fryorcraken 3842d84b55
feat!: Introduce routing info concept
Concepts are being mixed up between the global network config (static vs auto sharding), that needs to be the same of all nodes in the network, individual node configuration (eg relay node subscribing to a given shard), and the routing characteristic of a specific message (eg pubsub topic, shard).

This stops proper configuration of nwaku post 0.36.0 because we know need to be deliberate on whether nwaku nodes are running with auto or static sharding.

It also included various back and forth conversions between shards, pubsub topics, etc.

With this change, we tidy up the network configuration, and make it explicit whether it is static or auto sharded.
We also introduce the concept of routing info, which is specific to a message, and tied to the overall network configuration.

Routing info abstract pubsub topic, shard, and autosharding needs. Which should lead to easier tidy up of the pubsub concept at a later stage.

# Conflicts:
#	packages/core/src/lib/connection_manager/connection_manager.ts
#	packages/core/src/lib/metadata/metadata.ts
#	packages/interfaces/src/metadata.ts
#	packages/interfaces/src/sharding.ts
#	packages/relay/src/create.ts
#	packages/sdk/src/filter/filter.ts
#	packages/sdk/src/filter/types.ts
#	packages/sdk/src/light_push/light_push.spec.ts
#	packages/tests/tests/sharding/auto_sharding.spec.ts
#	packages/tests/tests/sharding/static_sharding.spec.ts

# Conflicts:
#	packages/sdk/src/store/store.ts
2025-07-19 13:22:45 +10:00

125 lines
3.1 KiB
TypeScript

import {
CreateNodeOptions,
IWaku,
LightNode,
Protocols
} from "@waku/interfaces";
import { createLightNode } from "@waku/sdk";
import { RoutingInfo } from "@waku/utils";
import { Context } from "mocha";
import pRetry from "p-retry";
import { NOISE_KEY_1 } from "../constants.js";
import { ServiceNodesFleet } from "../lib/index.js";
import { DEFAULT_DISCOVERIES_ENABLED } from "../lib/runNodes.js";
import { Args } from "../types.js";
import { waitForConnections } from "./waitForConnections.js";
/**
* Runs both js-waku and nwaku nodes.
*
* @param context
* @param routingInfo
* @param customArgs passed to nwaku service nodes
* @param strictChecking
* @param numServiceNodes
* @param withoutFilter
* @param jsWakuParams
*/
export async function runMultipleNodes(
context: Context,
routingInfo: RoutingInfo,
customArgs?: Args,
strictChecking: boolean = false,
numServiceNodes = 2,
withoutFilter = false,
jsWakuParams: CreateNodeOptions = {}
): Promise<[ServiceNodesFleet, LightNode]> {
// create numServiceNodes nodes
const serviceNodes = await ServiceNodesFleet.createAndRun(
context,
numServiceNodes,
strictChecking,
routingInfo,
customArgs,
withoutFilter
);
const wakuOptions: CreateNodeOptions = {
staticNoiseKey: NOISE_KEY_1,
libp2p: {
addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] }
},
networkConfig: routingInfo.networkConfig,
lightPush: { numPeersToUse: numServiceNodes },
discovery: DEFAULT_DISCOVERIES_ENABLED,
...jsWakuParams
};
const waku = await createLightNode(wakuOptions);
if (!waku) {
throw new Error("Failed to initialize waku");
}
for (const node of serviceNodes.nodes) {
await waku.dial(await node.getMultiaddrWithId());
await waku.waitForPeers([Protocols.Filter, Protocols.LightPush]);
// TODO
// await node.ensureSubscriptions(
// derivePubsubTopicsFromNetworkConfig(networkConfig)
// );
const wakuConnections = waku.libp2p.getConnections();
if (wakuConnections.length < 1) {
throw new Error(`Expected at least 1 connection for js-waku.`);
}
await node.waitForLog(waku.libp2p.peerId.toString(), 100);
}
await waitForConnections(numServiceNodes, waku);
for (let i = 0; i < serviceNodes.nodes.length; i++) {
const node = serviceNodes.nodes[i];
const peers = await node.peers();
if (peers.length < 1) {
throw new Error(`Expected at least 1 connection for nwaku.`);
}
}
return [serviceNodes, waku];
}
export async function teardownNodesWithRedundancy(
serviceNodes: ServiceNodesFleet,
wakuNodes: IWaku | IWaku[]
): Promise<void> {
const wNodes = Array.isArray(wakuNodes) ? wakuNodes : [wakuNodes];
const stopNwakuNodes = serviceNodes.nodes.map(async (node) => {
await pRetry(
async () => {
await node.stop();
},
{ retries: 3 }
);
});
const stopWakuNodes = wNodes.map(async (waku) => {
if (waku) {
await pRetry(
async () => {
await waku.stop();
},
{ retries: 3 }
);
}
});
await Promise.all([...stopNwakuNodes, ...stopWakuNodes]);
}