diff --git a/packages/core/src/lib/message/version_0.spec.ts b/packages/core/src/lib/message/version_0.spec.ts index 7498c15f80..4cf6856154 100644 --- a/packages/core/src/lib/message/version_0.spec.ts +++ b/packages/core/src/lib/message/version_0.spec.ts @@ -1,108 +1,97 @@ import type { IProtoMessage } from "@waku/interfaces"; +import { contentTopicToPubsubTopic } from "@waku/utils"; import { expect } from "chai"; import fc from "fast-check"; import { createDecoder, createEncoder, DecodedMessage } from "./version_0.js"; +const contentTopic = "/js-waku/1/tests/bytes"; +const pubsubTopic = contentTopicToPubsubTopic(contentTopic); + describe("Waku Message version 0", function () { it("Round trip binary serialization", async function () { await fc.assert( - fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), - fc.uint8Array({ minLength: 1 }), - async (contentTopic, pubsubTopic, payload) => { - const encoder = createEncoder({ - contentTopic - }); - const bytes = await encoder.toWire({ payload }); - const decoder = createDecoder(contentTopic); - const protoResult = await decoder.fromWireToProtoObj(bytes); - const result = (await decoder.fromProtoObj( - pubsubTopic, - protoResult! - )) as DecodedMessage; + fc.asyncProperty(fc.uint8Array({ minLength: 1 }), async (payload) => { + const encoder = createEncoder({ + contentTopic + }); + const bytes = await encoder.toWire({ payload }); + const decoder = createDecoder(contentTopic); + const protoResult = await decoder.fromWireToProtoObj(bytes); + const result = (await decoder.fromProtoObj( + pubsubTopic, + protoResult! + )) as DecodedMessage; - expect(result.contentTopic).to.eq(contentTopic); - expect(result.pubsubTopic).to.eq(pubsubTopic); - expect(result.version).to.eq(0); - expect(result.ephemeral).to.be.false; - expect(result.payload).to.deep.eq(payload); - expect(result.timestamp).to.not.be.undefined; - } - ) + expect(result.contentTopic).to.eq(contentTopic); + expect(result.pubsubTopic).to.eq(pubsubTopic); + expect(result.version).to.eq(0); + expect(result.ephemeral).to.be.false; + expect(result.payload).to.deep.eq(payload); + expect(result.timestamp).to.not.be.undefined; + }) ); }); it("Ephemeral field set to true", async function () { await fc.assert( - fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), - fc.uint8Array({ minLength: 1 }), - async (contentTopic, pubsubTopic, payload) => { - const encoder = createEncoder({ - contentTopic, - ephemeral: true - }); - const bytes = await encoder.toWire({ payload }); - const decoder = createDecoder(contentTopic); - const protoResult = await decoder.fromWireToProtoObj(bytes); - const result = (await decoder.fromProtoObj( - pubsubTopic, - protoResult! - )) as DecodedMessage; + fc.asyncProperty(fc.uint8Array({ minLength: 1 }), async (payload) => { + const encoder = createEncoder({ + contentTopic, + ephemeral: true + }); + const bytes = await encoder.toWire({ payload }); + const decoder = createDecoder(contentTopic); + const protoResult = await decoder.fromWireToProtoObj(bytes); + const result = (await decoder.fromProtoObj( + pubsubTopic, + protoResult! + )) as DecodedMessage; - expect(result.ephemeral).to.be.true; - } - ) + expect(result.ephemeral).to.be.true; + }) ); }); it("Meta field set when metaSetter is specified", async function () { await fc.assert( - fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), - fc.uint8Array({ minLength: 1 }), - async (contentTopic, pubsubTopic, payload) => { - // Encode the length of the payload - // Not a relevant real life example - const metaSetter = ( - msg: IProtoMessage & { meta: undefined } - ): Uint8Array => { - const buffer = new ArrayBuffer(4); - const view = new DataView(buffer); - view.setUint32(0, msg.payload.length, false); - return new Uint8Array(buffer); - }; + fc.asyncProperty(fc.uint8Array({ minLength: 1 }), async (payload) => { + // Encode the length of the payload + // Not a relevant real life example + const metaSetter = ( + msg: IProtoMessage & { meta: undefined } + ): Uint8Array => { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + view.setUint32(0, msg.payload.length, false); + return new Uint8Array(buffer); + }; - const encoder = createEncoder({ - contentTopic, - ephemeral: true, - metaSetter - }); - const bytes = await encoder.toWire({ payload }); - const decoder = createDecoder(contentTopic); - const protoResult = await decoder.fromWireToProtoObj(bytes); - const result = (await decoder.fromProtoObj( - pubsubTopic, - protoResult! - )) as DecodedMessage; + const encoder = createEncoder({ + contentTopic, + ephemeral: true, + metaSetter + }); + const bytes = await encoder.toWire({ payload }); + const decoder = createDecoder(contentTopic); + const protoResult = await decoder.fromWireToProtoObj(bytes); + const result = (await decoder.fromProtoObj( + pubsubTopic, + protoResult! + )) as DecodedMessage; - const expectedMeta = metaSetter({ - payload, - timestamp: undefined, - contentTopic: "", - ephemeral: undefined, - meta: undefined, - rateLimitProof: undefined, - version: undefined - }); + const expectedMeta = metaSetter({ + payload, + timestamp: undefined, + contentTopic: "", + ephemeral: undefined, + meta: undefined, + rateLimitProof: undefined, + version: undefined + }); - expect(result.meta).to.deep.eq(expectedMeta); - } - ) + expect(result.meta).to.deep.eq(expectedMeta); + }) ); }); }); diff --git a/packages/interfaces/src/filter.ts b/packages/interfaces/src/filter.ts index 1565ec482d..b167493930 100644 --- a/packages/interfaces/src/filter.ts +++ b/packages/interfaces/src/filter.ts @@ -1,11 +1,10 @@ -import type { PeerId } from "@libp2p/interface"; - -import type { IDecodedMessage, IDecoder, SingleShardInfo } from "./message.js"; +import type { IDecodedMessage, IDecoder } from "./message.js"; import type { ContentTopic, PubsubTopic } from "./misc.js"; import type { Callback, IBaseProtocolCore, - IBaseProtocolSDK + IBaseProtocolSDK, + ShardingParams } from "./protocols.js"; import type { IReceiver } from "./receiver.js"; @@ -31,7 +30,6 @@ export type IFilter = IReceiver & IBaseProtocolCore; export type IFilterSDK = IReceiver & IBaseProtocolSDK & { protocol: IBaseProtocolCore } & { createSubscription( - pubsubTopicShardInfo?: SingleShardInfo | PubsubTopic, - peerId?: PeerId + pubsubTopicShardInfo?: ShardingParams | PubsubTopic ): Promise; }; diff --git a/packages/interfaces/src/protocols.ts b/packages/interfaces/src/protocols.ts index 012a7834af..a4ae7082c0 100644 --- a/packages/interfaces/src/protocols.ts +++ b/packages/interfaces/src/protocols.ts @@ -29,7 +29,7 @@ export type IBaseProtocolSDK = { }; export type ContentTopicInfo = { - clusterId: number; + clusterId?: number; contentTopics: string[]; }; diff --git a/packages/interfaces/src/waku.ts b/packages/interfaces/src/waku.ts index a14680c4a6..5b54b0080a 100644 --- a/packages/interfaces/src/waku.ts +++ b/packages/interfaces/src/waku.ts @@ -1,5 +1,5 @@ import type { PeerId, Stream } from "@libp2p/interface"; -import type { Multiaddr } from "@multiformats/multiaddr"; +import type { MultiaddrInput } from "@multiformats/multiaddr"; import { IConnectionManager } from "./connection_manager.js"; import type { IFilterSDK } from "./filter.js"; @@ -18,7 +18,7 @@ export interface Waku { connectionManager: IConnectionManager; - dial(peer: PeerId | Multiaddr, protocols?: Protocols[]): Promise; + dial(peer: PeerId | MultiaddrInput, protocols?: Protocols[]): Promise; start(): Promise; diff --git a/packages/message-encryption/src/ecies.spec.ts b/packages/message-encryption/src/ecies.spec.ts index eeb05b7ecd..55743820a0 100644 --- a/packages/message-encryption/src/ecies.spec.ts +++ b/packages/message-encryption/src/ecies.spec.ts @@ -1,20 +1,22 @@ import { IProtoMessage } from "@waku/interfaces"; +import { contentTopicToPubsubTopic } from "@waku/utils"; import { expect } from "chai"; import fc from "fast-check"; import { getPublicKey } from "./crypto/index.js"; import { createDecoder, createEncoder } from "./ecies.js"; +const contentTopic = "/js-waku/1/tests/bytes"; +const pubsubTopic = contentTopicToPubsubTopic(contentTopic); + describe("Ecies Encryption", function () { this.timeout(20000); it("Round trip binary encryption [ecies, no signature]", async function () { await fc.assert( fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), fc.uint8Array({ minLength: 1 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), - async (pubsubTopic, contentTopic, payload, privateKey) => { + async (payload, privateKey) => { const publicKey = getPublicKey(privateKey); const encoder = createEncoder({ @@ -46,18 +48,10 @@ describe("Ecies Encryption", function () { await fc.assert( fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), fc.uint8Array({ minLength: 1 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), - async ( - pubsubTopic, - contentTopic, - payload, - alicePrivateKey, - bobPrivateKey - ) => { + async (payload, alicePrivateKey, bobPrivateKey) => { const alicePublicKey = getPublicKey(alicePrivateKey); const bobPublicKey = getPublicKey(bobPrivateKey); @@ -89,11 +83,9 @@ describe("Ecies Encryption", function () { it("Check meta is set [ecies]", async function () { await fc.assert( fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), fc.uint8Array({ minLength: 1 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), - async (pubsubTopic, contentTopic, payload, privateKey) => { + async (payload, privateKey) => { const publicKey = getPublicKey(privateKey); const metaSetter = ( msg: IProtoMessage & { meta: undefined } diff --git a/packages/message-encryption/src/ecies.ts b/packages/message-encryption/src/ecies.ts index 31c9069656..b084c6a9bc 100644 --- a/packages/message-encryption/src/ecies.ts +++ b/packages/message-encryption/src/ecies.ts @@ -1,7 +1,6 @@ import { Decoder as DecoderV0 } from "@waku/core/lib/message/version_0"; import { type EncoderOptions as BaseEncoderOptions, - DefaultPubsubTopic, type IDecoder, type IEncoder, type IMessage, @@ -200,7 +199,7 @@ class Decoder extends DecoderV0 implements IDecoder { export function createDecoder( contentTopic: string, privateKey: Uint8Array, - pubsubTopicShardInfo: SingleShardInfo | PubsubTopic = DefaultPubsubTopic + pubsubTopicShardInfo?: SingleShardInfo | PubsubTopic ): Decoder { return new Decoder( determinePubsubTopic(contentTopic, pubsubTopicShardInfo), diff --git a/packages/message-encryption/src/symmetric.spec.ts b/packages/message-encryption/src/symmetric.spec.ts index cd604eb7d0..9016f66604 100644 --- a/packages/message-encryption/src/symmetric.spec.ts +++ b/packages/message-encryption/src/symmetric.spec.ts @@ -1,19 +1,21 @@ import { IProtoMessage } from "@waku/interfaces"; +import { contentTopicToPubsubTopic } from "@waku/utils"; import { expect } from "chai"; import fc from "fast-check"; import { getPublicKey } from "./crypto/index.js"; import { createDecoder, createEncoder } from "./symmetric.js"; +const contentTopic = "/js-waku/1/tests/bytes"; +const pubsubTopic = contentTopicToPubsubTopic(contentTopic); + describe("Symmetric Encryption", function () { it("Round trip binary encryption [symmetric, no signature]", async function () { await fc.assert( fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), fc.uint8Array({ minLength: 1 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), - async (pubsubTopic, contentTopic, payload, symKey) => { + async (payload, symKey) => { const encoder = createEncoder({ contentTopic, symKey @@ -41,12 +43,10 @@ describe("Symmetric Encryption", function () { it("Round trip binary encryption [symmetric, signature]", async function () { await fc.assert( fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), fc.uint8Array({ minLength: 1 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), - async (pubsubTopic, contentTopic, payload, sigPrivKey, symKey) => { + async (payload, sigPrivKey, symKey) => { const sigPubKey = getPublicKey(sigPrivKey); const encoder = createEncoder({ @@ -77,11 +77,9 @@ describe("Symmetric Encryption", function () { it("Check meta is set [symmetric]", async function () { await fc.assert( fc.asyncProperty( - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), fc.uint8Array({ minLength: 1 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), - async (pubsubTopic, contentTopic, payload, symKey) => { + async (payload, symKey) => { const metaSetter = ( msg: IProtoMessage & { meta: undefined } ): Uint8Array => { diff --git a/packages/relay/src/message_validator.spec.ts b/packages/relay/src/message_validator.spec.ts index a26f4ad27b..c5fb36a444 100644 --- a/packages/relay/src/message_validator.spec.ts +++ b/packages/relay/src/message_validator.spec.ts @@ -2,57 +2,55 @@ import { TopicValidatorResult } from "@libp2p/interface"; import type { UnsignedMessage } from "@libp2p/interface"; import { createSecp256k1PeerId } from "@libp2p/peer-id-factory"; import { createEncoder } from "@waku/core"; +import { determinePubsubTopic } from "@waku/utils"; import { expect } from "chai"; import fc from "fast-check"; import { messageValidator } from "./message_validator.js"; +const TestContentTopic = "/app/1/topic/utf8"; +const TestPubsubTopic = determinePubsubTopic(TestContentTopic); + describe("Message Validator", () => { it("Accepts a valid Waku Message", async () => { await fc.assert( - fc.asyncProperty( - fc.uint8Array({ minLength: 1 }), - fc.string({ minLength: 1 }), - fc.string({ minLength: 1 }), - async (payload, pubsubTopic, contentTopic) => { - const peerId = await createSecp256k1PeerId(); + fc.asyncProperty(fc.uint8Array({ minLength: 1 }), async (payload) => { + const peerId = await createSecp256k1PeerId(); - const encoder = createEncoder({ contentTopic }); - const bytes = await encoder.toWire({ payload }); + const encoder = createEncoder({ + contentTopic: TestContentTopic, + pubsubTopic: TestPubsubTopic + }); + const bytes = await encoder.toWire({ payload }); - const message: UnsignedMessage = { - type: "unsigned", - topic: pubsubTopic, - data: bytes - }; + const message: UnsignedMessage = { + type: "unsigned", + topic: TestPubsubTopic, + data: bytes + }; - const result = messageValidator(peerId, message); + const result = messageValidator(peerId, message); - expect(result).to.eq(TopicValidatorResult.Accept); - } - ) + expect(result).to.eq(TopicValidatorResult.Accept); + }) ); }); it("Rejects garbage", async () => { await fc.assert( - fc.asyncProperty( - fc.uint8Array(), - fc.string(), - async (data, pubsubTopic) => { - const peerId = await createSecp256k1PeerId(); + fc.asyncProperty(fc.uint8Array(), async (data) => { + const peerId = await createSecp256k1PeerId(); - const message: UnsignedMessage = { - type: "unsigned", - topic: pubsubTopic, - data - }; + const message: UnsignedMessage = { + type: "unsigned", + topic: TestPubsubTopic, + data + }; - const result = messageValidator(peerId, message); + const result = messageValidator(peerId, message); - expect(result).to.eq(TopicValidatorResult.Reject); - } - ) + expect(result).to.eq(TopicValidatorResult.Reject); + }) ); }); }); diff --git a/packages/sdk/src/protocols/filter.ts b/packages/sdk/src/protocols/filter.ts index 83883f5cae..134b5083c6 100644 --- a/packages/sdk/src/protocols/filter.ts +++ b/packages/sdk/src/protocols/filter.ts @@ -1,19 +1,18 @@ import type { Peer } from "@libp2p/interface"; import { FilterCore } from "@waku/core"; -import { - type Callback, +import type { + Callback, ContentTopic, - DefaultPubsubTopic, - type IAsyncIterator, - type IDecodedMessage, - type IDecoder, - type IFilterSDK, + IAsyncIterator, + IDecodedMessage, + IDecoder, + IFilterSDK, IProtoMessage, - type Libp2p, - type ProtocolCreateOptions, - type PubsubTopic, - type SingleShardInfo, - type Unsubscribe + Libp2p, + ProtocolCreateOptions, + PubsubTopic, + ShardingParams, + Unsubscribe } from "@waku/interfaces"; import { messageHashStr } from "@waku/message-hash"; import { WakuMessage } from "@waku/proto"; @@ -21,7 +20,7 @@ import { ensurePubsubTopicIsConfigured, groupByContentTopic, Logger, - singleShardInfoToPubsubTopic, + shardInfoToPubsubTopics, toAsyncIterator } from "@waku/utils"; @@ -245,12 +244,12 @@ class FilterSDK extends BaseProtocolSDK implements IFilterSDK { * @returns The subscription object. */ async createSubscription( - pubsubTopicShardInfo: SingleShardInfo | PubsubTopic = DefaultPubsubTopic + pubsubTopicShardInfo: ShardingParams | PubsubTopic ): Promise { const pubsubTopic = typeof pubsubTopicShardInfo == "string" ? pubsubTopicShardInfo - : singleShardInfoToPubsubTopic(pubsubTopicShardInfo); + : shardInfoToPubsubTopics(pubsubTopicShardInfo)?.[0]; ensurePubsubTopicIsConfigured(pubsubTopic, this.protocol.pubsubTopics); @@ -294,7 +293,21 @@ class FilterSDK extends BaseProtocolSDK implements IFilterSDK { decoders: IDecoder | IDecoder[], callback: Callback ): Promise { - const subscription = await this.createSubscription(); + const pubsubTopics = this.getPubsubTopics(decoders); + + if (pubsubTopics.length === 0) { + throw Error( + "Failed to subscribe: no pubsubTopic found on decoders provided." + ); + } + + if (pubsubTopics.length > 1) { + throw Error( + "Failed to subscribe: all decoders should have the same pubsub topic. Use createSubscription to be more agile." + ); + } + + const subscription = await this.createSubscription(pubsubTopics[0]); await subscription.subscribe(decoders, callback); @@ -314,6 +327,22 @@ class FilterSDK extends BaseProtocolSDK implements IFilterSDK { ): Promise> { return toAsyncIterator(this, decoders); } + + private getPubsubTopics( + decoders: IDecoder | IDecoder[] + ): string[] { + if (!Array.isArray(decoders)) { + return [decoders.pubsubTopic]; + } + + if (decoders.length === 0) { + return []; + } + + const pubsubTopics = new Set(decoders.map((d) => d.pubsubTopic)); + + return [...pubsubTopics]; + } } export function wakuFilter( diff --git a/packages/tests/src/lib/index.ts b/packages/tests/src/lib/index.ts index 5bcc9c947c..924febf82a 100644 --- a/packages/tests/src/lib/index.ts +++ b/packages/tests/src/lib/index.ts @@ -2,7 +2,6 @@ import { DecodedMessage } from "@waku/core"; import { DefaultPubsubTopic, PubsubTopic, - ShardInfo, ShardingParams } from "@waku/interfaces"; import { ensureShardingConfigured, Logger } from "@waku/utils"; @@ -12,9 +11,11 @@ import { Args, MessageRpcQuery, MessageRpcResponse } from "../types"; import { delay, makeLogFileName } from "../utils/index.js"; import { MessageCollector } from "./message_collector.js"; +import { runNodes } from "./runNodes.js"; import { defaultArgs, ServiceNode } from "./service_node.js"; export { ServiceNode, MessageCollector, defaultArgs }; +export { runNodes }; const log = new Logger("test:message-collector"); @@ -28,7 +29,7 @@ export class ServiceNodesFleet { pubsubTopics: PubsubTopic[], nodesToCreate: number = 3, strictChecking: boolean = false, - shardInfo?: ShardInfo, + shardInfo?: ShardingParams, _args?: Args, withoutFilter = false ): Promise { diff --git a/packages/tests/src/lib/message_collector.ts b/packages/tests/src/lib/message_collector.ts index b8d1b408c6..154c0b7284 100644 --- a/packages/tests/src/lib/message_collector.ts +++ b/packages/tests/src/lib/message_collector.ts @@ -73,7 +73,7 @@ export class MessageCollector { } ): Promise { const startTime = Date.now(); - const pubsubTopic = options?.pubsubTopic || DefaultPubsubTopic; + const pubsubTopic = this.getPubsubTopicToUse(options?.pubsubTopic); const timeoutDuration = options?.timeoutDuration || 400; const exact = options?.exact || false; @@ -237,12 +237,13 @@ export class MessageCollector { `Message text mismatch. Expected: ${options.expectedMessageText}. Got: ${receivedMessageText}` ); } else { + const pubsubTopicToUse = this.getPubsubTopicToUse( + options.expectedPubsubTopic + ); // js-waku message specific assertions expect(message.pubsubTopic).to.eq( - options.expectedPubsubTopic || DefaultPubsubTopic, - `Message pub/sub topic mismatch. Expected: ${ - options.expectedPubsubTopic || DefaultPubsubTopic - }. Got: ${message.pubsubTopic}` + pubsubTopicToUse, + `Message pub/sub topic mismatch. Expected: ${pubsubTopicToUse}. Got: ${message.pubsubTopic}` ); expect(bytesToUtf8(message.payload)).to.eq( @@ -266,4 +267,8 @@ export class MessageCollector { ); } } + + private getPubsubTopicToUse(pubsubTopic: string | undefined): string { + return pubsubTopic || this.nwaku?.pubsubTopics?.[0] || DefaultPubsubTopic; + } } diff --git a/packages/tests/src/lib/runNodes.ts b/packages/tests/src/lib/runNodes.ts new file mode 100644 index 0000000000..908b4e274d --- /dev/null +++ b/packages/tests/src/lib/runNodes.ts @@ -0,0 +1,78 @@ +import { waitForRemotePeer } from "@waku/core"; +import { + ContentTopicInfo, + ProtocolCreateOptions, + Protocols, + ShardingParams +} from "@waku/interfaces"; +import { createLightNode, WakuNode } from "@waku/sdk"; +import { createRelayNode } from "@waku/sdk/relay"; +import { Logger, shardInfoToPubsubTopics } from "@waku/utils"; +import { Context } from "mocha"; + +import { NOISE_KEY_1 } from "../constants.js"; +import { makeLogFileName } from "../utils/index.js"; + +import { ServiceNode } from "./service_node.js"; + +export const log = new Logger("test:runNodes"); + +type RunNodesOptions = { + context: Context; + shardInfo: ShardingParams; + protocols: Protocols[]; + createNode: typeof createLightNode | typeof createRelayNode; +}; + +export async function runNodes( + options: RunNodesOptions +): Promise<[ServiceNode, T]> { + const { context, shardInfo, createNode, protocols } = options; + + const nwaku = new ServiceNode(makeLogFileName(context)); + const pubsubTopics = shardInfoToPubsubTopics(shardInfo); + + function isContentTopicInfo(info: ShardingParams): info is ContentTopicInfo { + return (info as ContentTopicInfo).contentTopics !== undefined; + } + + await nwaku.start( + { + filter: true, + lightpush: true, + relay: true, + store: true, + pubsubTopic: pubsubTopics, + // Conditionally include clusterId if shardInfo exists + ...(shardInfo && { clusterId: shardInfo.clusterId }), + // Conditionally include contentTopic if shardInfo exists and clusterId is 1 + ...(shardInfo && + isContentTopicInfo(shardInfo) && + shardInfo.clusterId === 1 && { contentTopic: shardInfo.contentTopics }) + }, + { retries: 3 } + ); + const waku_options: ProtocolCreateOptions = { + staticNoiseKey: NOISE_KEY_1, + libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }, + shardInfo + }; + + log.info("Starting js waku node with :", JSON.stringify(waku_options)); + let waku: WakuNode | undefined; + try { + waku = (await createNode(waku_options)) as WakuNode; + await waku.start(); + } catch (error) { + log.error("jswaku node failed to start:", error); + } + + if (waku) { + await waku.dial(await nwaku.getMultiaddrWithId()); + await waitForRemotePeer(waku, protocols); + await nwaku.ensureSubscriptions(pubsubTopics); + return [nwaku, waku as T]; + } else { + throw new Error("Failed to initialize waku"); + } +} diff --git a/packages/tests/src/lib/service_node.ts b/packages/tests/src/lib/service_node.ts index d8a483858c..db9b620ee6 100644 --- a/packages/tests/src/lib/service_node.ts +++ b/packages/tests/src/lib/service_node.ts @@ -48,6 +48,7 @@ export class ServiceNode { private websocketPort?: number; private readonly logPath: string; private restPort?: number; + private args?: Args; /** * Convert a [[WakuMessage]] to a [[WakuRelayMessage]]. The latter is used @@ -166,6 +167,8 @@ export class ServiceNode { this.logPath, WAKU_SERVICE_NODE_PARAMS ); + + this.args = mergedArgs; } catch (error) { log.error("Nwaku node failed to start:", error); await this.stop(); @@ -237,11 +240,9 @@ export class ServiceNode { ); } - async messages( - pubsubTopic: string = DefaultPubsubTopic - ): Promise { + async messages(pubsubTopic?: string): Promise { return this.restCall( - `/relay/v1/messages/${encodeURIComponent(pubsubTopic)}`, + `/relay/v1/messages/${encodeURIComponent(pubsubTopic || this?.args?.pubsubTopic?.[0] || DefaultPubsubTopic)}`, "GET", null, async (response) => { @@ -266,7 +267,7 @@ export class ServiceNode { async sendMessage( message: MessageRpcQuery, - pubsubTopic: string = DefaultPubsubTopic + pubsubTopic?: string ): Promise { this.checkProcess(); @@ -275,7 +276,7 @@ export class ServiceNode { } return this.restCall( - `/relay/v1/messages/${encodeURIComponent(pubsubTopic)}`, + `/relay/v1/messages/${encodeURIComponent(pubsubTopic || this.args?.pubsubTopic?.[0] || DefaultPubsubTopic)}`, "POST", message, async (response) => response.status === 200 @@ -350,6 +351,10 @@ export class ServiceNode { return `http://127.0.0.1:${this.restPort}`; } + get pubsubTopics(): string[] { + return this.args?.pubsubTopic ?? []; + } + async restCall( endpoint: string, method: "GET" | "POST", diff --git a/packages/tests/src/utils/generate_test_data.ts b/packages/tests/src/utils/generate_test_data.ts index 8644e26437..cd1b6ed61b 100644 --- a/packages/tests/src/utils/generate_test_data.ts +++ b/packages/tests/src/utils/generate_test_data.ts @@ -1,19 +1,28 @@ import { createDecoder, createEncoder, Decoder, Encoder } from "@waku/core"; +type TestDataOptions = { + pubsubTopic: string; +}; + // Utility to generate test data for multiple topics tests. -export function generateTestData(topicCount: number): { +export function generateTestData( + topicCount: number, + options?: TestDataOptions +): { contentTopics: string[]; encoders: Encoder[]; decoders: Decoder[]; } { const contentTopics = Array.from( { length: topicCount }, - (_, i) => `/test/${i + 1}/waku-multi` + (_, i) => `/test/${i + 1}/waku-multi/default` ); const encoders = contentTopics.map((topic) => - createEncoder({ contentTopic: topic }) + createEncoder({ contentTopic: topic, pubsubTopic: options?.pubsubTopic }) + ); + const decoders = contentTopics.map((topic) => + createDecoder(topic, options?.pubsubTopic) ); - const decoders = contentTopics.map((topic) => createDecoder(topic)); return { contentTopics, encoders, diff --git a/packages/tests/tests/connection-mananger/connection_state.spec.ts b/packages/tests/tests/connection-mananger/connection_state.spec.ts index 0fd8394ab9..a4e3ba640e 100644 --- a/packages/tests/tests/connection-mananger/connection_state.spec.ts +++ b/packages/tests/tests/connection-mananger/connection_state.spec.ts @@ -87,7 +87,7 @@ describe("Connection state", function () { expect(eventCount).to.be.eq(1); }); - it("`waku:online` bwtween 2 js-waku relay nodes", async function () { + it("`waku:online` between 2 js-waku relay nodes", async function () { const waku1 = await createRelayNode({ staticNoiseKey: NOISE_KEY_1 }); @@ -159,7 +159,7 @@ describe("Connection state", function () { expect(waku.isConnected()).to.be.false; }); - it("isConnected bwtween 2 js-waku relay nodes", async function () { + it("isConnected between 2 js-waku relay nodes", async function () { const waku1 = await createRelayNode({ staticNoiseKey: NOISE_KEY_1 }); diff --git a/packages/tests/tests/ephemeral.node.spec.ts b/packages/tests/tests/ephemeral.node.spec.ts index fe0d5b075b..7020322bcd 100644 --- a/packages/tests/tests/ephemeral.node.spec.ts +++ b/packages/tests/tests/ephemeral.node.spec.ts @@ -12,15 +12,15 @@ import { getPublicKey } from "@waku/message-encryption"; import { - createDecoder as eciesDecoder, - createEncoder as eciesEncoder + createDecoder as createEciesDecoder, + createEncoder as createEciesEncoder } from "@waku/message-encryption/ecies"; import { - createDecoder as symDecoder, - createEncoder as symEncoder + createDecoder as createSymDecoder, + createEncoder as createSymEncoder } from "@waku/message-encryption/symmetric"; import { createLightNode } from "@waku/sdk"; -import { Logger } from "@waku/utils"; +import { contentTopicToPubsubTopic, Logger } from "@waku/utils"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; @@ -37,11 +37,47 @@ import { const log = new Logger("test:ephemeral"); +const ClusterId = 2; const TestContentTopic = "/test/1/ephemeral/utf8"; +const PubsubTopic = contentTopicToPubsubTopic(TestContentTopic, ClusterId); + const TestEncoder = createEncoder({ - contentTopic: TestContentTopic + contentTopic: TestContentTopic, + pubsubTopic: PubsubTopic }); -const TestDecoder = createDecoder(TestContentTopic); +const TestDecoder = createDecoder(TestContentTopic, PubsubTopic); + +const privateKey = generatePrivateKey(); +const symKey = generateSymmetricKey(); +const publicKey = getPublicKey(privateKey); + +const AsymContentTopic = "/test/1/ephemeral-asym/utf8"; +const SymContentTopic = "/test/1/ephemeral-sym/utf8"; + +const AsymEncoder = createEciesEncoder({ + contentTopic: AsymContentTopic, + publicKey, + ephemeral: true, + pubsubTopic: PubsubTopic +}); +const SymEncoder = createSymEncoder({ + contentTopic: SymContentTopic, + symKey, + ephemeral: true, + pubsubTopic: PubsubTopic +}); +const ClearEncoder = createEncoder({ + contentTopic: TestContentTopic, + ephemeral: true, + pubsubTopic: PubsubTopic +}); + +const AsymDecoder = createEciesDecoder( + AsymContentTopic, + privateKey, + PubsubTopic +); +const SymDecoder = createSymDecoder(SymContentTopic, symKey, PubsubTopic); describe("Waku Message Ephemeral field", function () { let waku: LightNode; @@ -59,11 +95,24 @@ describe("Waku Message Ephemeral field", function () { filter: true, lightpush: true, store: true, - relay: true + relay: true, + pubsubTopic: [PubsubTopic], + contentTopic: [TestContentTopic, AsymContentTopic, SymContentTopic], + clusterId: ClusterId }); + await nwaku.ensureSubscriptionsAutosharding([ + TestContentTopic, + AsymContentTopic, + SymContentTopic + ]); + waku = await createLightNode({ staticNoiseKey: NOISE_KEY_1, - libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } } + libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }, + shardInfo: { + contentTopics: [TestContentTopic, AsymContentTopic, SymContentTopic], + clusterId: ClusterId + } }); await waku.start(); await waku.dial(await nwaku.getMultiaddrWithId()); @@ -74,7 +123,9 @@ describe("Waku Message Ephemeral field", function () { Protocols.Store ]); - subscription = await waku.filter.createSubscription(); + subscription = await waku.filter.createSubscription( + TestEncoder.pubsubTopic + ); }); it("Ephemeral messages are not stored", async function () { @@ -94,37 +145,20 @@ describe("Waku Message Ephemeral field", function () { payload: utf8ToBytes(clearText) }; - const privateKey = generatePrivateKey(); - const symKey = generateSymmetricKey(); - const publicKey = getPublicKey(privateKey); - - const AsymContentTopic = "/test/1/ephemeral-asym/utf8"; - const SymContentTopic = "/test/1/ephemeral-sym/utf8"; - - const asymEncoder = eciesEncoder({ - contentTopic: AsymContentTopic, - publicKey, - ephemeral: true - }); - const symEncoder = eciesEncoder({ - contentTopic: SymContentTopic, - publicKey: symKey, - ephemeral: true - }); - const clearEncoder = createEncoder({ - contentTopic: TestContentTopic, - ephemeral: true - }); - - const asymDecoder = eciesDecoder(AsymContentTopic, privateKey); - const symDecoder = eciesDecoder(SymContentTopic, symKey); - const [waku1, waku2, nimWakuMultiaddr] = await Promise.all([ createLightNode({ - staticNoiseKey: NOISE_KEY_1 + staticNoiseKey: NOISE_KEY_1, + shardInfo: { + contentTopics: [TestContentTopic, AsymContentTopic, SymContentTopic], + clusterId: ClusterId + } }).then((waku) => waku.start().then(() => waku)), createLightNode({ - staticNoiseKey: NOISE_KEY_2 + staticNoiseKey: NOISE_KEY_2, + shardInfo: { + contentTopics: [TestContentTopic, AsymContentTopic, SymContentTopic], + clusterId: ClusterId + } }).then((waku) => waku.start().then(() => waku)), nwaku.getMultiaddrWithId() ]); @@ -142,9 +176,9 @@ describe("Waku Message Ephemeral field", function () { log.info("Sending messages using light push"); await Promise.all([ - waku1.lightPush.send(asymEncoder, asymMsg), - waku1.lightPush.send(symEncoder, symMsg), - waku1.lightPush.send(clearEncoder, clearMsg) + waku1.lightPush.send(AsymEncoder, asymMsg), + waku1.lightPush.send(SymEncoder, symMsg), + waku1.lightPush.send(ClearEncoder, clearMsg) ]); await waitForRemotePeer(waku2, [Protocols.Store]); @@ -153,8 +187,8 @@ describe("Waku Message Ephemeral field", function () { log.info("Retrieving messages from store"); for await (const msgPromises of waku2.store.queryGenerator([ - asymDecoder, - symDecoder, + AsymDecoder, + SymDecoder, TestDecoder ])) { for (const promise of msgPromises) { @@ -175,7 +209,8 @@ describe("Waku Message Ephemeral field", function () { const ephemeralEncoder = createEncoder({ contentTopic: TestContentTopic, - ephemeral: true + ephemeral: true, + pubsubTopic: PubsubTopic }); const messages: DecodedMessage[] = []; @@ -187,12 +222,16 @@ describe("Waku Message Ephemeral field", function () { await delay(200); const normalTxt = "Normal message"; const ephemeralTxt = "Ephemeral Message"; - await waku.lightPush.send(TestEncoder, { - payload: utf8ToBytes(normalTxt) - }); - await waku.lightPush.send(ephemeralEncoder, { - payload: utf8ToBytes(ephemeralTxt) - }); + + await Promise.all([ + waku.lightPush.send(TestEncoder, { + payload: utf8ToBytes(normalTxt) + }), + waku.lightPush.send(ephemeralEncoder, { + payload: utf8ToBytes(ephemeralTxt) + }) + ]); + while (messages.length < 2) { await delay(250); } @@ -214,18 +253,12 @@ describe("Waku Message Ephemeral field", function () { it("Ephemeral field is preserved - symmetric encryption", async function () { this.timeout(10000); - const symKey = generateSymmetricKey(); - - const ephemeralEncoder = symEncoder({ - contentTopic: TestContentTopic, + const encoder = createSymEncoder({ + contentTopic: SymContentTopic, symKey, - ephemeral: true + pubsubTopic: PubsubTopic }); - const encoder = symEncoder({ - contentTopic: TestContentTopic, - symKey - }); - const decoder = symDecoder(TestContentTopic, symKey); + const decoder = createSymDecoder(SymContentTopic, symKey, PubsubTopic); const messages: DecodedMessage[] = []; const callback = (msg: DecodedMessage): void => { @@ -236,12 +269,16 @@ describe("Waku Message Ephemeral field", function () { await delay(200); const normalTxt = "Normal message"; const ephemeralTxt = "Ephemeral Message"; - await waku.lightPush.send(encoder, { - payload: utf8ToBytes(normalTxt) - }); - await waku.lightPush.send(ephemeralEncoder, { - payload: utf8ToBytes(ephemeralTxt) - }); + + await Promise.all([ + waku.lightPush.send(encoder, { + payload: utf8ToBytes(normalTxt) + }), + waku.lightPush.send(SymEncoder, { + payload: utf8ToBytes(ephemeralTxt) + }) + ]); + while (messages.length < 2) { await delay(250); } @@ -263,19 +300,16 @@ describe("Waku Message Ephemeral field", function () { it("Ephemeral field is preserved - asymmetric encryption", async function () { this.timeout(10000); - const privKey = generatePrivateKey(); - const pubKey = getPublicKey(privKey); - - const ephemeralEncoder = eciesEncoder({ - contentTopic: TestContentTopic, - publicKey: pubKey, - ephemeral: true + const encoder = createEciesEncoder({ + contentTopic: AsymContentTopic, + publicKey: publicKey, + pubsubTopic: PubsubTopic }); - const encoder = eciesEncoder({ - contentTopic: TestContentTopic, - publicKey: pubKey - }); - const decoder = eciesDecoder(TestContentTopic, privKey); + const decoder = createEciesDecoder( + AsymContentTopic, + privateKey, + PubsubTopic + ); const messages: DecodedMessage[] = []; const callback = (msg: DecodedMessage): void => { @@ -286,12 +320,16 @@ describe("Waku Message Ephemeral field", function () { await delay(200); const normalTxt = "Normal message"; const ephemeralTxt = "Ephemeral Message"; - await waku.lightPush.send(encoder, { - payload: utf8ToBytes(normalTxt) - }); - await waku.lightPush.send(ephemeralEncoder, { - payload: utf8ToBytes(ephemeralTxt) - }); + + await Promise.all([ + waku.lightPush.send(encoder, { + payload: utf8ToBytes(normalTxt) + }), + waku.lightPush.send(AsymEncoder, { + payload: utf8ToBytes(ephemeralTxt) + }) + ]); + while (messages.length < 2) { await delay(250); } diff --git a/packages/tests/tests/filter/ping.node.spec.ts b/packages/tests/tests/filter/ping.node.spec.ts index 4604bd5d2b..4a7dbcd320 100644 --- a/packages/tests/tests/filter/ping.node.spec.ts +++ b/packages/tests/tests/filter/ping.node.spec.ts @@ -1,8 +1,4 @@ -import { - DefaultPubsubTopic, - IFilterSubscription, - LightNode -} from "@waku/interfaces"; +import { IFilterSubscription, LightNode } from "@waku/interfaces"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; @@ -18,6 +14,7 @@ import { TestContentTopic, TestDecoder, TestEncoder, + TestShardInfo, validatePingError } from "./utils"; @@ -30,10 +27,8 @@ const runTests = (strictCheckNodes: boolean): void => { let subscription: IFilterSubscription; beforeEachCustom(this, async () => { - [serviceNodes, waku] = await runMultipleNodes(this.ctx, [ - DefaultPubsubTopic - ]); - subscription = await waku.filter.createSubscription(); + [serviceNodes, waku] = await runMultipleNodes(this.ctx, TestShardInfo); + subscription = await waku.filter.createSubscription(TestShardInfo); }); afterEachCustom(this, async () => { diff --git a/packages/tests/tests/filter/push.node.spec.ts b/packages/tests/tests/filter/push.node.spec.ts index 67a862071e..4653c56e24 100644 --- a/packages/tests/tests/filter/push.node.spec.ts +++ b/packages/tests/tests/filter/push.node.spec.ts @@ -1,10 +1,5 @@ import { waitForRemotePeer } from "@waku/core"; -import { - DefaultPubsubTopic, - IFilterSubscription, - LightNode, - Protocols -} from "@waku/interfaces"; +import { IFilterSubscription, LightNode, Protocols } from "@waku/interfaces"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; @@ -23,7 +18,9 @@ import { teardownNodesWithRedundancy, TestContentTopic, TestDecoder, - TestEncoder + TestEncoder, + TestPubsubTopic, + TestShardInfo } from "./utils.js"; const runTests = (strictCheckNodes: boolean): void => { @@ -35,10 +32,8 @@ const runTests = (strictCheckNodes: boolean): void => { let subscription: IFilterSubscription; beforeEachCustom(this, async () => { - [serviceNodes, waku] = await runMultipleNodes(this.ctx, [ - DefaultPubsubTopic - ]); - subscription = await waku.filter.createSubscription(); + [serviceNodes, waku] = await runMultipleNodes(this.ctx, TestShardInfo); + subscription = await waku.filter.createSubscription(TestShardInfo); }); afterEachCustom(this, async () => { @@ -60,7 +55,8 @@ const runTests = (strictCheckNodes: boolean): void => { ); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: testItem.value, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -79,7 +75,7 @@ const runTests = (strictCheckNodes: boolean): void => { payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"), timestamp: testItem as any }, - DefaultPubsubTopic + TestPubsubTopic ); expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( @@ -88,7 +84,8 @@ const runTests = (strictCheckNodes: boolean): void => { serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, checkTimestamp: false, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); // Check if the timestamp matches @@ -117,7 +114,7 @@ const runTests = (strictCheckNodes: boolean): void => { payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"), timestamp: "2023-09-06T12:05:38.609Z" as any }, - DefaultPubsubTopic + TestPubsubTopic ); // Verify that no message was received @@ -139,12 +136,14 @@ const runTests = (strictCheckNodes: boolean): void => { payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"), timestamp: BigInt(Date.now()) * BigInt(1000000) }, - "DefaultPubsubTopic" + "WrongContentTopic" ); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - false - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(false); }); it("Check message with no content topic is not received", async function () { @@ -159,7 +158,7 @@ const runTests = (strictCheckNodes: boolean): void => { payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"), timestamp: BigInt(Date.now()) * BigInt(1000000) }, - DefaultPubsubTopic + TestPubsubTopic ); expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( @@ -180,7 +179,7 @@ const runTests = (strictCheckNodes: boolean): void => { timestamp: BigInt(Date.now()) * BigInt(1000000), payload: undefined as any }, - DefaultPubsubTopic + TestPubsubTopic ); // For go-waku the message is received (it is possible to send a message with no payload) @@ -208,7 +207,7 @@ const runTests = (strictCheckNodes: boolean): void => { payload: 12345 as unknown as string, timestamp: BigInt(Date.now()) * BigInt(1000000) }, - DefaultPubsubTopic + TestPubsubTopic ); expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( @@ -239,7 +238,7 @@ const runTests = (strictCheckNodes: boolean): void => { await waku.dial(await node.getMultiaddrWithId()); await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); } - subscription = await waku.filter.createSubscription(); + subscription = await waku.filter.createSubscription(TestShardInfo); await subscription.subscribe( [TestDecoder], serviceNodes.messageCollector.callback @@ -253,11 +252,13 @@ const runTests = (strictCheckNodes: boolean): void => { ); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: "M1", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); serviceNodes.messageCollector.verifyReceivedMessage(1, { expectedMessageText: "M2", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); @@ -285,11 +286,13 @@ const runTests = (strictCheckNodes: boolean): void => { ); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: "M1", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); serviceNodes.messageCollector.verifyReceivedMessage(1, { expectedMessageText: "M2", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); }); diff --git a/packages/tests/tests/filter/single_node/multiple_pubsub.node.spec.ts b/packages/tests/tests/filter/single_node/multiple_pubsub.node.spec.ts index 072d994c6b..687d41d8ad 100644 --- a/packages/tests/tests/filter/single_node/multiple_pubsub.node.spec.ts +++ b/packages/tests/tests/filter/single_node/multiple_pubsub.node.spec.ts @@ -10,7 +10,6 @@ import { Protocols } from "@waku/interfaces"; import { contentTopicToPubsubTopic, contentTopicToShardIndex, - pubsubTopicToSingleShardInfo, singleShardInfoToPubsubTopic } from "@waku/utils"; import { utf8ToBytes } from "@waku/utils/bytes"; @@ -61,14 +60,8 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () { const customDecoder2 = createDecoder(customContentTopic2, singleShardInfo2); beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes( - this.ctx, - [customPubsubTopic1, customPubsubTopic2], - shardInfo - ); - subscription = await waku.filter.createSubscription( - pubsubTopicToSingleShardInfo(customPubsubTopic1) - ); + [nwaku, waku] = await runNodes(this.ctx, shardInfo); + subscription = await waku.filter.createSubscription(shardInfo); messageCollector = new MessageCollector(); }); @@ -91,9 +84,8 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () { await subscription.subscribe([customDecoder1], messageCollector.callback); // Subscribe from the same lightnode to the 2nd pubsubtopic - const subscription2 = await waku.filter.createSubscription( - pubsubTopicToSingleShardInfo(customPubsubTopic2) - ); + const subscription2 = + await waku.filter.createSubscription(customPubsubTopic2); const messageCollector2 = new MessageCollector(); @@ -134,10 +126,8 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () { await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); // Subscribe from the same lightnode to the new nwaku on the new pubsubtopic - const subscription2 = await waku.filter.createSubscription( - pubsubTopicToSingleShardInfo(customPubsubTopic2), - await nwaku2.getPeerId() - ); + const subscription2 = + await waku.filter.createSubscription(customPubsubTopic2); await nwaku2.ensureSubscriptions([customPubsubTopic2]); const messageCollector2 = new MessageCollector(); @@ -172,7 +162,7 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () { }); it("Should fail to subscribe with decoder with wrong pubsubTopic", async function () { - // this subscription object is set up with the `customPubsubTopic` but we're passing it a Decoder with the `DefaultPubsubTopic` + // this subscription object is set up with the `customPubsubTopic1` but we're passing it a Decoder with the `customPubsubTopic2` try { await subscription.subscribe([customDecoder2], messageCollector.callback); } catch (error) { @@ -231,13 +221,9 @@ describe("Waku Filter V2 (Autosharding): Multiple PubsubTopics", function () { }); beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes( - this.ctx, - [autoshardingPubsubTopic1, autoshardingPubsubTopic2], - contentTopicInfo - ); + [nwaku, waku] = await runNodes(this.ctx, contentTopicInfo); subscription = await waku.filter.createSubscription( - pubsubTopicToSingleShardInfo(autoshardingPubsubTopic1) + autoshardingPubsubTopic1 ); messageCollector = new MessageCollector(); }); @@ -266,7 +252,7 @@ describe("Waku Filter V2 (Autosharding): Multiple PubsubTopics", function () { // Subscribe from the same lightnode to the 2nd pubsubtopic const subscription2 = await waku.filter.createSubscription( - pubsubTopicToSingleShardInfo(autoshardingPubsubTopic2) + autoshardingPubsubTopic2 ); const messageCollector2 = new MessageCollector(); @@ -318,8 +304,7 @@ describe("Waku Filter V2 (Autosharding): Multiple PubsubTopics", function () { // Subscribe from the same lightnode to the new nwaku on the new pubsubtopic const subscription2 = await waku.filter.createSubscription( - pubsubTopicToSingleShardInfo(autoshardingPubsubTopic2), - await nwaku2.getPeerId() + autoshardingPubsubTopic2 ); await nwaku2.ensureSubscriptionsAutosharding([customContentTopic2]); @@ -355,7 +340,7 @@ describe("Waku Filter V2 (Autosharding): Multiple PubsubTopics", function () { }); it("Should fail to subscribe with decoder with wrong pubsubTopic", async function () { - // this subscription object is set up with the `customPubsubTopic` but we're passing it a Decoder with the `DefaultPubsubTopic` + // this subscription object is set up with the `customPubsubTopic1` but we're passing it a Decoder with the `customPubsubTopic2` try { await subscription.subscribe([customDecoder2], messageCollector.callback); } catch (error) { @@ -383,6 +368,10 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () { clusterId: 3, shard: 2 }); + const shardInfo = { + clusterId: 3, + shards: [1, 2] + }; const customContentTopic1 = "/test/2/waku-filter"; const customContentTopic2 = "/test/3/waku-filter"; const customEncoder1 = createEncoder({ @@ -397,14 +386,7 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () { const customDecoder2 = createDecoder(customContentTopic2, customPubsubTopic2); beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes( - this.ctx, - [customPubsubTopic1, customPubsubTopic2], - { - clusterId: 3, - shards: [1, 2] - } - ); + [nwaku, waku] = await runNodes(this.ctx, shardInfo); subscription = await waku.filter.createSubscription(customPubsubTopic1); messageCollector = new MessageCollector(); }); @@ -428,9 +410,8 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () { await subscription.subscribe([customDecoder1], messageCollector.callback); // Subscribe from the same lightnode to the 2nd pubsubtopic - const subscription2 = await waku.filter.createSubscription( - pubsubTopicToSingleShardInfo(customPubsubTopic2) - ); + const subscription2 = + await waku.filter.createSubscription(customPubsubTopic2); const messageCollector2 = new MessageCollector(); @@ -471,10 +452,8 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () { await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); // Subscribe from the same lightnode to the new nwaku on the new pubsubtopic - const subscription2 = await waku.filter.createSubscription( - pubsubTopicToSingleShardInfo(customPubsubTopic2), - await nwaku2.getPeerId() - ); + const subscription2 = + await waku.filter.createSubscription(customPubsubTopic2); await nwaku2.ensureSubscriptions([customPubsubTopic2]); const messageCollector2 = new MessageCollector(); @@ -509,7 +488,7 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () { }); it("Should fail to subscribe with decoder with wrong pubsubTopic", async function () { - // this subscription object is set up with the `customPubsubTopic` but we're passing it a Decoder with the `DefaultPubsubTopic` + // this subscription object is set up with the `customPubsubTopic1` but we're passing it a Decoder with the `customPubsubTopic2` try { await subscription.subscribe([customDecoder2], messageCollector.callback); } catch (error) { diff --git a/packages/tests/tests/filter/single_node/ping.node.spec.ts b/packages/tests/tests/filter/single_node/ping.node.spec.ts index 14f9bf0b4f..59ca6c4130 100644 --- a/packages/tests/tests/filter/single_node/ping.node.spec.ts +++ b/packages/tests/tests/filter/single_node/ping.node.spec.ts @@ -1,8 +1,4 @@ -import { - DefaultPubsubTopic, - IFilterSubscription, - LightNode -} from "@waku/interfaces"; +import { IFilterSubscription, LightNode } from "@waku/interfaces"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; @@ -17,6 +13,7 @@ import { TestContentTopic, TestDecoder, TestEncoder, + TestShardInfo, validatePingError } from "../utils.js"; @@ -31,8 +28,8 @@ describe("Waku Filter V2: Ping", function () { let messageCollector: MessageCollector; beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); - subscription = await waku.filter.createSubscription(); + [nwaku, waku] = await runNodes(this.ctx, TestShardInfo); + subscription = await waku.filter.createSubscription(TestShardInfo); messageCollector = new MessageCollector(); }); diff --git a/packages/tests/tests/filter/single_node/push.node.spec.ts b/packages/tests/tests/filter/single_node/push.node.spec.ts index e905a0fdd0..5467402afb 100644 --- a/packages/tests/tests/filter/single_node/push.node.spec.ts +++ b/packages/tests/tests/filter/single_node/push.node.spec.ts @@ -1,10 +1,5 @@ import { waitForRemotePeer } from "@waku/core"; -import { - DefaultPubsubTopic, - IFilterSubscription, - LightNode, - Protocols -} from "@waku/interfaces"; +import { IFilterSubscription, LightNode, Protocols } from "@waku/interfaces"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; @@ -23,7 +18,9 @@ import { messageText, TestContentTopic, TestDecoder, - TestEncoder + TestEncoder, + TestPubsubTopic, + TestShardInfo } from "../utils.js"; describe("Waku Filter V2: FilterPush", function () { @@ -35,9 +32,9 @@ describe("Waku Filter V2: FilterPush", function () { let messageCollector: MessageCollector; beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); - subscription = await waku.filter.createSubscription(); - messageCollector = new MessageCollector(); + [nwaku, waku] = await runNodes(this.ctx, TestShardInfo); + subscription = await waku.filter.createSubscription(TestShardInfo); + messageCollector = new MessageCollector(nwaku); }); afterEachCustom(this, async () => { @@ -65,7 +62,7 @@ describe("Waku Filter V2: FilterPush", function () { await delay(400); await nwaku.restCall( - `/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, + `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`, "POST", { contentTopic: TestContentTopic, @@ -99,7 +96,7 @@ describe("Waku Filter V2: FilterPush", function () { await delay(400); await nwaku.restCall( - `/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, + `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`, "POST", { contentTopic: TestContentTopic, @@ -154,7 +151,7 @@ describe("Waku Filter V2: FilterPush", function () { await delay(400); await nwaku.restCall( - `/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, + `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`, "POST", { payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"), @@ -171,7 +168,7 @@ describe("Waku Filter V2: FilterPush", function () { await delay(400); await nwaku.restCall( - `/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, + `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`, "POST", { contentTopic: TestContentTopic, @@ -193,7 +190,7 @@ describe("Waku Filter V2: FilterPush", function () { await delay(400); await nwaku.restCall( - `/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, + `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`, "POST", { contentTopic: TestContentTopic, diff --git a/packages/tests/tests/filter/single_node/subscribe.node.spec.ts b/packages/tests/tests/filter/single_node/subscribe.node.spec.ts index e3b81843da..421f7d5755 100644 --- a/packages/tests/tests/filter/single_node/subscribe.node.spec.ts +++ b/packages/tests/tests/filter/single_node/subscribe.node.spec.ts @@ -1,10 +1,5 @@ import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core"; -import { - DefaultPubsubTopic, - IFilterSubscription, - LightNode, - Protocols -} from "@waku/interfaces"; +import { IFilterSubscription, LightNode, Protocols } from "@waku/interfaces"; import { ecies, generatePrivateKey, @@ -14,13 +9,13 @@ import { } from "@waku/message-encryption"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; +import type { Context } from "mocha"; import { afterEachCustom, beforeEachCustom, delay, generateTestData, - makeLogFileName, MessageCollector, ServiceNode, tearDownNodes, @@ -31,7 +26,9 @@ import { messageText, TestContentTopic, TestDecoder, - TestEncoder + TestEncoder, + TestPubsubTopic, + TestShardInfo } from "../utils.js"; import { runNodes } from "./utils.js"; @@ -40,20 +37,23 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { // Set the timeout for all tests in this suite. Can be overwritten at test level this.timeout(10000); let waku: LightNode; + let waku2: LightNode; let nwaku: ServiceNode; let nwaku2: ServiceNode; let subscription: IFilterSubscription; let messageCollector: MessageCollector; + let ctx: Context; beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); - subscription = await waku.filter.createSubscription(); + ctx = this.ctx; + [nwaku, waku] = await runNodes(this.ctx, TestShardInfo); + subscription = await waku.filter.createSubscription(TestShardInfo); messageCollector = new MessageCollector(); - await nwaku.ensureSubscriptions(); + await nwaku.ensureSubscriptions([TestPubsubTopic]); }); afterEachCustom(this, async () => { - await tearDownNodes([nwaku, nwaku2], waku); + await tearDownNodes([nwaku, nwaku2], [waku, waku2]); }); it("Subscribe and receive messages via lightPush", async function () { @@ -64,7 +64,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(1)).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); expect((await nwaku.messages()).length).to.eq(1); }); @@ -74,9 +75,14 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { const publicKey = getPublicKey(privateKey); const encoder = ecies.createEncoder({ contentTopic: TestContentTopic, - publicKey + publicKey, + pubsubTopic: TestPubsubTopic }); - const decoder = ecies.createDecoder(TestContentTopic, privateKey); + const decoder = ecies.createDecoder( + TestContentTopic, + privateKey, + TestPubsubTopic + ); await subscription.subscribe([decoder], messageCollector.callback); @@ -86,7 +92,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, expectedContentTopic: TestContentTopic, - expectedVersion: 1 + expectedVersion: 1, + expectedPubsubTopic: TestPubsubTopic }); expect((await nwaku.messages()).length).to.eq(1); }); @@ -95,9 +102,14 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { const symKey = generateSymmetricKey(); const encoder = symmetric.createEncoder({ contentTopic: TestContentTopic, - symKey + symKey, + pubsubTopic: TestPubsubTopic }); - const decoder = symmetric.createDecoder(TestContentTopic, symKey); + const decoder = symmetric.createDecoder( + TestContentTopic, + symKey, + TestPubsubTopic + ); await subscription.subscribe([decoder], messageCollector.callback); @@ -107,7 +119,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, expectedContentTopic: TestContentTopic, - expectedVersion: 1 + expectedVersion: 1, + expectedPubsubTopic: TestPubsubTopic }); expect((await nwaku.messages()).length).to.eq(1); }); @@ -128,7 +141,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(1)).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); expect((await nwaku.messages()).length).to.eq(1); }); @@ -141,7 +155,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(1)).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); // Send another message on the same topic. @@ -154,7 +169,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(2)).to.eq(true); messageCollector.verifyReceivedMessage(1, { expectedMessageText: newMessageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); expect((await nwaku.messages()).length).to.eq(2); }); @@ -166,15 +182,19 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(1)).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); // Modify subscription to include a new content topic and send a message. const newMessageText = "Filtering still works!"; const newMessagePayload = { payload: utf8ToBytes(newMessageText) }; - const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newContentTopic = "/test/2/waku-filter/default"; + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription.subscribe([newDecoder], messageCollector.callback); await waku.lightPush.send(newEncoder, { payload: utf8ToBytes(newMessageText) @@ -182,7 +202,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(2)).to.eq(true); messageCollector.verifyReceivedMessage(1, { expectedContentTopic: newContentTopic, - expectedMessageText: newMessageText + expectedMessageText: newMessageText, + expectedPubsubTopic: TestPubsubTopic }); // Send another message on the initial content topic to verify it still works. @@ -190,14 +211,15 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(3)).to.eq(true); messageCollector.verifyReceivedMessage(2, { expectedMessageText: newMessageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); expect((await nwaku.messages()).length).to.eq(3); }); it("Subscribe and receives messages on 20 topics", async function () { const topicCount = 20; - const td = generateTestData(topicCount); + const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic }); // Subscribe to all 20 topics. for (let i = 0; i < topicCount; i++) { @@ -216,7 +238,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { td.contentTopics.forEach((topic, index) => { messageCollector.verifyReceivedMessage(index, { expectedContentTopic: topic, - expectedMessageText: `Message for Topic ${index + 1}` + expectedMessageText: `Message for Topic ${index + 1}`, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -224,7 +247,7 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { it("Subscribe to 100 topics (new limit) at once and receives messages", async function () { this.timeout(50000); const topicCount = 100; - const td = generateTestData(topicCount); + const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic }); await subscription.subscribe(td.decoders, messageCollector.callback); @@ -243,7 +266,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { td.contentTopics.forEach((topic, index) => { messageCollector.verifyReceivedMessage(index, { expectedContentTopic: topic, - expectedMessageText: `Message for Topic ${index + 1}` + expectedMessageText: `Message for Topic ${index + 1}`, + expectedPubsubTopic: TestPubsubTopic }); }); } catch (error) { @@ -255,7 +279,7 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { it("Error when try to subscribe to more than 101 topics (new limit)", async function () { const topicCount = 101; - const td = generateTestData(topicCount); + const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic }); try { await subscription.subscribe(td.decoders, messageCollector.callback); @@ -279,9 +303,9 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { it("Overlapping topic subscription", async function () { // Define two sets of test data with overlapping topics. const topicCount1 = 2; - const td1 = generateTestData(topicCount1); + const td1 = generateTestData(topicCount1, { pubsubTopic: TestPubsubTopic }); const topicCount2 = 4; - const td2 = generateTestData(topicCount2); + const td2 = generateTestData(topicCount2, { pubsubTopic: TestPubsubTopic }); // Subscribe to the first set of topics. await subscription.subscribe(td1.decoders, messageCollector.callback); @@ -327,19 +351,24 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { ); messageCollector.verifyReceivedMessage(0, { expectedMessageText: "M1", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); messageCollector.verifyReceivedMessage(1, { expectedMessageText: "M2", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); TEST_STRING.forEach((testItem) => { it(`Subscribe to topic containing ${testItem.description} and receive message`, async function () { const newContentTopic = testItem.value; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription.subscribe([newDecoder], messageCollector.callback); await waku.lightPush.send(newEncoder, messagePayload); @@ -347,7 +376,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(1)).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: newContentTopic + expectedContentTopic: newContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -357,10 +387,13 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") }); // Create a second subscription on a different topic - const subscription2 = await waku.filter.createSubscription(); - const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const subscription2 = await waku.filter.createSubscription(TestShardInfo); + const newContentTopic = "/test/2/waku-filter/default"; + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription2.subscribe([newDecoder], messageCollector.callback); await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M2") }); @@ -369,11 +402,13 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { expect(await messageCollector.waitForMessages(2)).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: "M1", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); messageCollector.verifyReceivedMessage(1, { expectedContentTopic: newContentTopic, - expectedMessageText: "M2" + expectedMessageText: "M2", + expectedPubsubTopic: TestPubsubTopic }); }); @@ -381,23 +416,18 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () { await subscription.subscribe([TestDecoder], messageCollector.callback); // Set up and start a new nwaku node - nwaku2 = new ServiceNode(makeLogFileName(this) + "2"); - await nwaku2.start({ - filter: true, - lightpush: true, - relay: true - }); + [nwaku2, waku2] = await runNodes(ctx, TestShardInfo); await waku.dial(await nwaku2.getMultiaddrWithId()); await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); - const subscription2 = await waku.filter.createSubscription( - undefined, - await nwaku2.getPeerId() - ); - await nwaku2.ensureSubscriptions([DefaultPubsubTopic]); + const subscription2 = await waku.filter.createSubscription(TestShardInfo); + await nwaku2.ensureSubscriptions([TestPubsubTopic]); // Send a message using the new subscription - const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newContentTopic = "/test/2/waku-filter/default"; + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription2.subscribe([newDecoder], messageCollector.callback); // Making sure that messages are send and reveiced for both subscriptions diff --git a/packages/tests/tests/filter/single_node/unsubscribe.node.spec.ts b/packages/tests/tests/filter/single_node/unsubscribe.node.spec.ts index c0c95c6258..44d3b3bd47 100644 --- a/packages/tests/tests/filter/single_node/unsubscribe.node.spec.ts +++ b/packages/tests/tests/filter/single_node/unsubscribe.node.spec.ts @@ -1,5 +1,5 @@ import { createDecoder, createEncoder } from "@waku/core"; -import { DefaultPubsubTopic, IFilterSubscription } from "@waku/interfaces"; +import { IFilterSubscription } from "@waku/interfaces"; import { LightNode } from "@waku/interfaces"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; @@ -18,7 +18,9 @@ import { messageText, TestContentTopic, TestDecoder, - TestEncoder + TestEncoder, + TestPubsubTopic, + TestShardInfo } from "../utils.js"; describe("Waku Filter V2: Unsubscribe", function () { @@ -30,12 +32,10 @@ describe("Waku Filter V2: Unsubscribe", function () { let messageCollector: MessageCollector; beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); - subscription = await waku.filter.createSubscription(); + [nwaku, waku] = await runNodes(this.ctx, TestShardInfo); + subscription = await waku.filter.createSubscription(TestShardInfo); messageCollector = new MessageCollector(); - - // Nwaku subscribe to the default pubsub topic - await nwaku.ensureSubscriptions(); + await nwaku.ensureSubscriptions([TestPubsubTopic]); }); afterEachCustom(this, async () => { @@ -55,7 +55,8 @@ describe("Waku Filter V2: Unsubscribe", function () { // Check that from 2 messages send only the 1st was received messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); expect(messageCollector.count).to.eq(1); expect((await nwaku.messages()).length).to.eq(2); @@ -65,8 +66,11 @@ describe("Waku Filter V2: Unsubscribe", function () { // Subscribe to 2 topics and send messages await subscription.subscribe([TestDecoder], messageCollector.callback); const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription.subscribe([newDecoder], messageCollector.callback); await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") }); await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M2") }); @@ -86,9 +90,12 @@ describe("Waku Filter V2: Unsubscribe", function () { it("Unsubscribe 2 topics - node subscribed to 2 topics", async function () { // Subscribe to 2 topics and send messages await subscription.subscribe([TestDecoder], messageCollector.callback); - const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newContentTopic = "/test/2/waku-filter/default"; + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription.subscribe([newDecoder], messageCollector.callback); await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") }); await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M2") }); @@ -115,7 +122,7 @@ describe("Waku Filter V2: Unsubscribe", function () { // Unsubscribe from topics that the node is not not subscribed to and send again await subscription.unsubscribe([]); - await subscription.unsubscribe(["/test/2/waku-filter"]); + await subscription.unsubscribe(["/test/2/waku-filter/default"]); await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M2") }); expect(await messageCollector.waitForMessages(2)).to.eq(true); @@ -143,7 +150,7 @@ describe("Waku Filter V2: Unsubscribe", function () { it("Unsubscribes all - node subscribed to 10 topics", async function () { // Subscribe to 10 topics and send message const topicCount = 10; - const td = generateTestData(topicCount); + const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic }); await subscription.subscribe(td.decoders, messageCollector.callback); for (let i = 0; i < topicCount; i++) { await waku.lightPush.send(td.encoders[i], { diff --git a/packages/tests/tests/filter/single_node/utils.ts b/packages/tests/tests/filter/single_node/utils.ts index 59195f0302..da2bf7b328 100644 --- a/packages/tests/tests/filter/single_node/utils.ts +++ b/packages/tests/tests/filter/single_node/utils.ts @@ -1,76 +1,22 @@ -import { waitForRemotePeer } from "@waku/core"; -import { - ContentTopicInfo, - DefaultPubsubTopic, - LightNode, - ProtocolCreateOptions, - Protocols, - ShardingParams -} from "@waku/interfaces"; +import { LightNode, Protocols, ShardingParams } from "@waku/interfaces"; import { createLightNode } from "@waku/sdk"; import { Logger } from "@waku/utils"; import { Context } from "mocha"; import { - makeLogFileName, - NOISE_KEY_1, + runNodes as runNodesBuilder, ServiceNode } from "../../../src/index.js"; export const log = new Logger("test:filter:single_node"); -export async function runNodes( +export const runNodes = ( context: Context, - //TODO: change this to use `ShardInfo` instead of `string[]` - pubsubTopics: string[], - shardInfo?: ShardingParams -): Promise<[ServiceNode, LightNode]> { - const nwaku = new ServiceNode(makeLogFileName(context)); - - function isContentTopicInfo(info: ShardingParams): info is ContentTopicInfo { - return (info as ContentTopicInfo).contentTopics !== undefined; - } - - await nwaku.start( - { - filter: true, - lightpush: true, - relay: true, - pubsubTopic: pubsubTopics, - // Conditionally include clusterId if shardInfo exists - ...(shardInfo && { clusterId: shardInfo.clusterId }), - // Conditionally include contentTopic if shardInfo exists and clusterId is 1 - ...(shardInfo && - isContentTopicInfo(shardInfo) && - shardInfo.clusterId === 1 && { contentTopic: shardInfo.contentTopics }) - }, - { retries: 3 } - ); - const waku_options: ProtocolCreateOptions = { - staticNoiseKey: NOISE_KEY_1, - libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }, - pubsubTopics: shardInfo ? undefined : pubsubTopics, - ...((pubsubTopics.length !== 1 || - pubsubTopics[0] !== DefaultPubsubTopic) && { - shardInfo: shardInfo - }) - }; - - log.info("Starting js waku node with :", JSON.stringify(waku_options)); - let waku: LightNode | undefined; - try { - waku = await createLightNode(waku_options); - await waku.start(); - } catch (error) { - log.error("jswaku node failed to start:", error); - } - - if (waku) { - await waku.dial(await nwaku.getMultiaddrWithId()); - await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); - await nwaku.ensureSubscriptions(pubsubTopics); - return [nwaku, waku]; - } else { - throw new Error("Failed to initialize waku"); - } -} + shardInfo: ShardingParams +): Promise<[ServiceNode, LightNode]> => + runNodesBuilder({ + context, + createNode: createLightNode, + protocols: [Protocols.LightPush, Protocols.Filter], + shardInfo + }); diff --git a/packages/tests/tests/filter/subscribe.node.spec.ts b/packages/tests/tests/filter/subscribe.node.spec.ts index 3ba9a634fb..833358baab 100644 --- a/packages/tests/tests/filter/subscribe.node.spec.ts +++ b/packages/tests/tests/filter/subscribe.node.spec.ts @@ -1,9 +1,5 @@ import { createDecoder, createEncoder } from "@waku/core"; -import { - DefaultPubsubTopic, - IFilterSubscription, - LightNode -} from "@waku/interfaces"; +import { IFilterSubscription, LightNode } from "@waku/interfaces"; import { ecies, generatePrivateKey, @@ -30,7 +26,9 @@ import { teardownNodesWithRedundancy, TestContentTopic, TestDecoder, - TestEncoder + TestEncoder, + TestPubsubTopic, + TestShardInfo } from "./utils.js"; const runTests = (strictCheckNodes: boolean): void => { @@ -43,10 +41,10 @@ const runTests = (strictCheckNodes: boolean): void => { beforeEachCustom(this, async () => { [serviceNodes, waku] = await runMultipleNodes( this.ctx, - [DefaultPubsubTopic], + TestShardInfo, strictCheckNodes ); - subscription = await waku.filter.createSubscription(); + subscription = await waku.filter.createSubscription(TestShardInfo); }); afterEachCustom(this, async () => { @@ -79,9 +77,14 @@ const runTests = (strictCheckNodes: boolean): void => { const publicKey = getPublicKey(privateKey); const encoder = ecies.createEncoder({ contentTopic: TestContentTopic, - publicKey + publicKey, + pubsubTopic: TestPubsubTopic }); - const decoder = ecies.createDecoder(TestContentTopic, privateKey); + const decoder = ecies.createDecoder( + TestContentTopic, + privateKey, + TestPubsubTopic + ); await subscription.subscribe( [decoder], @@ -96,7 +99,8 @@ const runTests = (strictCheckNodes: boolean): void => { serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, expectedContentTopic: TestContentTopic, - expectedVersion: 1 + expectedVersion: 1, + expectedPubsubTopic: TestPubsubTopic }); await serviceNodes.confirmMessageLength(1); @@ -106,9 +110,14 @@ const runTests = (strictCheckNodes: boolean): void => { const symKey = generateSymmetricKey(); const encoder = symmetric.createEncoder({ contentTopic: TestContentTopic, - symKey + symKey, + pubsubTopic: TestPubsubTopic }); - const decoder = symmetric.createDecoder(TestContentTopic, symKey); + const decoder = symmetric.createDecoder( + TestContentTopic, + symKey, + TestPubsubTopic + ); await subscription.subscribe( [decoder], @@ -123,7 +132,8 @@ const runTests = (strictCheckNodes: boolean): void => { serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, expectedContentTopic: TestContentTopic, - expectedVersion: 1 + expectedVersion: 1, + expectedPubsubTopic: TestPubsubTopic }); await serviceNodes.confirmMessageLength(1); @@ -142,14 +152,15 @@ const runTests = (strictCheckNodes: boolean): void => { contentTopic: TestContentTopic, payload: utf8ToBytes(messageText) }); - await serviceNodes.sendRelayMessage(relayMessage); + await serviceNodes.sendRelayMessage(relayMessage, TestPubsubTopic); expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( true ); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); await serviceNodes.confirmMessageLength(1); @@ -201,15 +212,19 @@ const runTests = (strictCheckNodes: boolean): void => { ); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); // Modify subscription to include a new content topic and send a message. const newMessageText = "Filtering still works!"; const newMessagePayload = { payload: utf8ToBytes(newMessageText) }; - const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newContentTopic = "/test/2/waku-filter/default"; + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription.subscribe( [newDecoder], serviceNodes.messageCollector.callback @@ -222,7 +237,8 @@ const runTests = (strictCheckNodes: boolean): void => { ); serviceNodes.messageCollector.verifyReceivedMessage(1, { expectedContentTopic: newContentTopic, - expectedMessageText: newMessageText + expectedMessageText: newMessageText, + expectedPubsubTopic: TestPubsubTopic }); // Send another message on the initial content topic to verify it still works. @@ -232,7 +248,8 @@ const runTests = (strictCheckNodes: boolean): void => { ); serviceNodes.messageCollector.verifyReceivedMessage(2, { expectedMessageText: newMessageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); await serviceNodes.confirmMessageLength(3); @@ -240,7 +257,7 @@ const runTests = (strictCheckNodes: boolean): void => { it("Subscribe and receives messages on 20 topics", async function () { const topicCount = 20; - const td = generateTestData(topicCount); + const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic }); // Subscribe to all 20 topics. for (let i = 0; i < topicCount; i++) { @@ -264,7 +281,8 @@ const runTests = (strictCheckNodes: boolean): void => { td.contentTopics.forEach((topic, index) => { serviceNodes.messageCollector.verifyReceivedMessage(index, { expectedContentTopic: topic, - expectedMessageText: `Message for Topic ${index + 1}` + expectedMessageText: `Message for Topic ${index + 1}`, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -272,7 +290,7 @@ const runTests = (strictCheckNodes: boolean): void => { it("Subscribe to 100 topics (new limit) at once and receives messages", async function () { this.timeout(50000); const topicCount = 100; - const td = generateTestData(topicCount); + const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic }); await subscription.subscribe( td.decoders, @@ -296,7 +314,8 @@ const runTests = (strictCheckNodes: boolean): void => { td.contentTopics.forEach((topic, index) => { serviceNodes.messageCollector.verifyReceivedMessage(index, { expectedContentTopic: topic, - expectedMessageText: `Message for Topic ${index + 1}` + expectedMessageText: `Message for Topic ${index + 1}`, + expectedPubsubTopic: TestPubsubTopic }); }); } catch (error) { @@ -308,7 +327,7 @@ const runTests = (strictCheckNodes: boolean): void => { it("Error when try to subscribe to more than 101 topics (new limit)", async function () { const topicCount = 101; - const td = generateTestData(topicCount); + const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic }); try { await subscription.subscribe( @@ -335,9 +354,13 @@ const runTests = (strictCheckNodes: boolean): void => { it("Overlapping topic subscription", async function () { // Define two sets of test data with overlapping topics. const topicCount1 = 2; - const td1 = generateTestData(topicCount1); + const td1 = generateTestData(topicCount1, { + pubsubTopic: TestPubsubTopic + }); const topicCount2 = 4; - const td2 = generateTestData(topicCount2); + const td2 = generateTestData(topicCount2, { + pubsubTopic: TestPubsubTopic + }); // Subscribe to the first set of topics. await subscription.subscribe( @@ -394,19 +417,24 @@ const runTests = (strictCheckNodes: boolean): void => { ).to.eq(true); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: "M1", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); serviceNodes.messageCollector.verifyReceivedMessage(1, { expectedMessageText: "M2", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); TEST_STRING.forEach((testItem) => { it(`Subscribe to topic containing ${testItem.description} and receive message`, async function () { const newContentTopic = testItem.value; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription.subscribe( [newDecoder], @@ -419,7 +447,8 @@ const runTests = (strictCheckNodes: boolean): void => { ); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: newContentTopic + expectedContentTopic: newContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -432,10 +461,13 @@ const runTests = (strictCheckNodes: boolean): void => { await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") }); // Create a second subscription on a different topic - const subscription2 = await waku.filter.createSubscription(); - const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const subscription2 = await waku.filter.createSubscription(TestShardInfo); + const newContentTopic = "/test/2/waku-filter/default"; + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription2.subscribe( [newDecoder], serviceNodes.messageCollector.callback @@ -449,11 +481,13 @@ const runTests = (strictCheckNodes: boolean): void => { ); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: "M1", - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); serviceNodes.messageCollector.verifyReceivedMessage(1, { expectedContentTopic: newContentTopic, - expectedMessageText: "M2" + expectedMessageText: "M2", + expectedPubsubTopic: TestPubsubTopic }); }); }); diff --git a/packages/tests/tests/filter/unsubscribe.node.spec.ts b/packages/tests/tests/filter/unsubscribe.node.spec.ts index dffacf3a1b..ff130190c6 100644 --- a/packages/tests/tests/filter/unsubscribe.node.spec.ts +++ b/packages/tests/tests/filter/unsubscribe.node.spec.ts @@ -1,9 +1,5 @@ import { createDecoder, createEncoder } from "@waku/core"; -import { - DefaultPubsubTopic, - IFilterSubscription, - LightNode -} from "@waku/interfaces"; +import { IFilterSubscription, LightNode } from "@waku/interfaces"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; @@ -15,13 +11,15 @@ import { } from "../../src/index.js"; import { + ClusterId, messagePayload, messageText, runMultipleNodes, teardownNodesWithRedundancy, TestContentTopic, TestDecoder, - TestEncoder + TestEncoder, + TestPubsubTopic } from "./utils.js"; const runTests = (strictCheckNodes: boolean): void => { @@ -33,10 +31,15 @@ const runTests = (strictCheckNodes: boolean): void => { let subscription: IFilterSubscription; beforeEachCustom(this, async () => { - [serviceNodes, waku] = await runMultipleNodes(this.ctx, [ - DefaultPubsubTopic - ]); - subscription = await waku.filter.createSubscription(); + [serviceNodes, waku] = await runMultipleNodes(this.ctx, { + contentTopics: [TestContentTopic], + clusterId: ClusterId + }); + + subscription = await waku.filter.createSubscription({ + contentTopics: [TestContentTopic], + clusterId: ClusterId + }); }); afterEachCustom(this, async () => { @@ -77,8 +80,11 @@ const runTests = (strictCheckNodes: boolean): void => { serviceNodes.messageCollector.callback ); const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription.subscribe( [newDecoder], serviceNodes.messageCollector.callback @@ -109,8 +115,11 @@ const runTests = (strictCheckNodes: boolean): void => { serviceNodes.messageCollector.callback ); const newContentTopic = "/test/2/waku-filter"; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); await subscription.subscribe( [newDecoder], serviceNodes.messageCollector.callback @@ -186,7 +195,7 @@ const runTests = (strictCheckNodes: boolean): void => { it("Unsubscribes all - node subscribed to 10 topics", async function () { // Subscribe to 10 topics and send message const topicCount = 10; - const td = generateTestData(topicCount); + const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic }); await subscription.subscribe( td.decoders, serviceNodes.messageCollector.callback diff --git a/packages/tests/tests/filter/utils.ts b/packages/tests/tests/filter/utils.ts index d7aec2fab9..8341bd6211 100644 --- a/packages/tests/tests/filter/utils.ts +++ b/packages/tests/tests/filter/utils.ts @@ -1,6 +1,5 @@ import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core"; import { - DefaultPubsubTopic, IFilterSubscription, LightNode, ProtocolCreateOptions, @@ -10,7 +9,7 @@ import { } from "@waku/interfaces"; import { createLightNode } from "@waku/sdk"; import { - ensureShardingConfigured, + contentTopicToPubsubTopic, Logger, shardInfoToPubsubTopics } from "@waku/utils"; @@ -26,9 +25,21 @@ import { // Constants for test configuration. export const log = new Logger("test:filter"); -export const TestContentTopic = "/test/1/waku-filter"; -export const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); -export const TestDecoder = createDecoder(TestContentTopic); +export const TestContentTopic = "/test/1/waku-filter/default"; +export const ClusterId = 2; +export const TestShardInfo = { + contentTopics: [TestContentTopic], + clusterId: ClusterId +}; +export const TestPubsubTopic = contentTopicToPubsubTopic( + TestContentTopic, + ClusterId +); +export const TestEncoder = createEncoder({ + contentTopic: TestContentTopic, + pubsubTopic: TestPubsubTopic +}); +export const TestDecoder = createDecoder(TestContentTopic, TestPubsubTopic); export const messageText = "Filtering works!"; export const messagePayload = { payload: utf8ToBytes(messageText) }; @@ -55,20 +66,19 @@ export async function validatePingError( export async function runMultipleNodes( context: Context, - //TODO: change this to use `ShardInfo` instead of `string[]` - pubsubTopics: string[], + shardInfo: ShardingParams, strictChecking: boolean = false, - shardInfo?: ShardingParams, numServiceNodes = 3, withoutFilter = false ): Promise<[ServiceNodesFleet, LightNode]> { + const pubsubTopics = shardInfoToPubsubTopics(shardInfo); // create numServiceNodes nodes const serviceNodes = await ServiceNodesFleet.createAndRun( context, pubsubTopics, numServiceNodes, strictChecking, - shardInfo ? ensureShardingConfigured(shardInfo).shardInfo : shardInfo, + shardInfo, undefined, withoutFilter ); @@ -78,11 +88,8 @@ export async function runMultipleNodes( libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }, - pubsubTopics: shardInfo ? shardInfoToPubsubTopics(shardInfo) : pubsubTopics, - ...((pubsubTopics.length !== 1 || - pubsubTopics[0] !== DefaultPubsubTopic) && { - shardInfo: shardInfo - }) + pubsubTopics, + shardInfo }; log.info("Starting js waku node with :", JSON.stringify(waku_options)); diff --git a/packages/tests/tests/light-push/index.node.spec.ts b/packages/tests/tests/light-push/index.node.spec.ts index 896a9b27fe..ae12db79a4 100644 --- a/packages/tests/tests/light-push/index.node.spec.ts +++ b/packages/tests/tests/light-push/index.node.spec.ts @@ -1,10 +1,5 @@ import { createEncoder } from "@waku/core"; -import { - DefaultPubsubTopic, - IRateLimitProof, - LightNode, - ProtocolError -} from "@waku/interfaces"; +import { IRateLimitProof, LightNode, ProtocolError } from "@waku/interfaces"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; @@ -24,8 +19,10 @@ import { messagePayload, messageText, TestContentTopic, - TestEncoder -} from "./utils"; + TestEncoder, + TestPubsubTopic, + TestShardInfo +} from "./utils.js"; const runTests = (strictNodeCheck: boolean): void => { const numServiceNodes = 3; @@ -38,9 +35,8 @@ const runTests = (strictNodeCheck: boolean): void => { beforeEachCustom(this, async () => { [serviceNodes, waku] = await runMultipleNodes( this.ctx, - [DefaultPubsubTopic], + TestShardInfo, strictNodeCheck, - undefined, numServiceNodes, true ); @@ -57,12 +53,15 @@ const runTests = (strictNodeCheck: boolean): void => { }); expect(pushResponse.successes.length).to.eq(numServiceNodes); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - true - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: testItem.value, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -77,14 +76,17 @@ const runTests = (strictNodeCheck: boolean): void => { expect(pushResponse.successes.length).to.eq(numServiceNodes); } - expect(await serviceNodes.messageCollector.waitForMessages(30)).to.eq( - true - ); + expect( + await serviceNodes.messageCollector.waitForMessages(30, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); for (let i = 0; i < 30; i++) { serviceNodes.messageCollector.verifyReceivedMessage(i, { expectedMessageText: generateMessageText(i), - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); } }); @@ -95,21 +97,23 @@ const runTests = (strictNodeCheck: boolean): void => { }); expect(pushResponse.successes.length).to.eq(0); - console.log("validated 1"); + expect(pushResponse.failures?.map((failure) => failure.error)).to.include( ProtocolError.EMPTY_PAYLOAD ); - console.log("validated 2"); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - false - ); - console.log("validated 3"); + + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(false); }); TEST_STRING.forEach((testItem) => { it(`Push message with content topic containing ${testItem.description}`, async function () { const customEncoder = createEncoder({ - contentTopic: testItem.value + contentTopic: testItem.value, + pubsubTopic: TestPubsubTopic }); const pushResponse = await waku.lightPush.send( customEncoder, @@ -117,12 +121,15 @@ const runTests = (strictNodeCheck: boolean): void => { ); expect(pushResponse.successes.length).to.eq(numServiceNodes); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - true - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: testItem.value + expectedContentTopic: testItem.value, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -141,7 +148,8 @@ const runTests = (strictNodeCheck: boolean): void => { it("Push message with meta", async function () { const customTestEncoder = createEncoder({ contentTopic: TestContentTopic, - metaSetter: () => new Uint8Array(10) + metaSetter: () => new Uint8Array(10), + pubsubTopic: TestPubsubTopic }); const pushResponse = await waku.lightPush.send( @@ -150,18 +158,22 @@ const runTests = (strictNodeCheck: boolean): void => { ); expect(pushResponse.successes.length).to.eq(numServiceNodes); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - true - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); it("Fails to push message with large meta", async function () { const customTestEncoder = createEncoder({ contentTopic: TestContentTopic, + pubsubTopic: TestPubsubTopic, metaSetter: () => new Uint8Array(105024) // see the note below *** }); @@ -179,21 +191,26 @@ const runTests = (strictNodeCheck: boolean): void => { if (serviceNodes.type == "go-waku") { expect(pushResponse.successes.length).to.eq(numServiceNodes); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - true - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); } else { expect(pushResponse.successes.length).to.eq(0); expect( pushResponse.failures?.map((failure) => failure.error) ).to.include(ProtocolError.REMOTE_PEER_REJECTED); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - false - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(false); } }); @@ -214,12 +231,15 @@ const runTests = (strictNodeCheck: boolean): void => { }); expect(pushResponse.successes.length).to.eq(numServiceNodes); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - true - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); @@ -235,13 +255,16 @@ const runTests = (strictNodeCheck: boolean): void => { }); expect(pushResponse.successes.length).to.eq(numServiceNodes); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - true - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); serviceNodes.messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, expectedTimestamp: testItem, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -264,9 +287,11 @@ const runTests = (strictNodeCheck: boolean): void => { expect(pushResponse.failures?.map((failure) => failure.error)).to.include( ProtocolError.SIZE_TOO_BIG ); - expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( - false - ); + expect( + await serviceNodes.messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(false); }); }); }; diff --git a/packages/tests/tests/light-push/single_node/index.node.spec.ts b/packages/tests/tests/light-push/single_node/index.node.spec.ts index f6d5c02b59..a8b8835264 100644 --- a/packages/tests/tests/light-push/single_node/index.node.spec.ts +++ b/packages/tests/tests/light-push/single_node/index.node.spec.ts @@ -1,10 +1,5 @@ import { createEncoder } from "@waku/core"; -import { - DefaultPubsubTopic, - IRateLimitProof, - LightNode, - ProtocolError -} from "@waku/interfaces"; +import { IRateLimitProof, LightNode, ProtocolError } from "@waku/interfaces"; import { utf8ToBytes } from "@waku/sdk"; import { expect } from "chai"; @@ -22,7 +17,9 @@ import { messageText, runNodes, TestContentTopic, - TestEncoder + TestEncoder, + TestPubsubTopic, + TestShardInfo } from "../utils.js"; describe("Waku Light Push: Single Node", function () { @@ -33,10 +30,10 @@ describe("Waku Light Push: Single Node", function () { let messageCollector: MessageCollector; beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); + [nwaku, waku] = await runNodes(this.ctx, TestShardInfo); messageCollector = new MessageCollector(nwaku); - await nwaku.ensureSubscriptions(); + await nwaku.ensureSubscriptions([TestPubsubTopic]); }); afterEachCustom(this, async () => { @@ -50,10 +47,15 @@ describe("Waku Light Push: Single Node", function () { }); expect(pushResponse.successes.length).to.eq(1); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: testItem.value, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -68,12 +70,17 @@ describe("Waku Light Push: Single Node", function () { expect(pushResponse.successes.length).to.eq(1); } - expect(await messageCollector.waitForMessages(30)).to.eq(true); + expect( + await messageCollector.waitForMessages(30, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); for (let i = 0; i < 30; i++) { messageCollector.verifyReceivedMessage(i, { expectedMessageText: generateMessageText(i), - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); } }); @@ -87,13 +94,18 @@ describe("Waku Light Push: Single Node", function () { expect(pushResponse.failures?.map((failure) => failure.error)).to.include( ProtocolError.EMPTY_PAYLOAD ); - expect(await messageCollector.waitForMessages(1)).to.eq(false); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(false); }); TEST_STRING.forEach((testItem) => { it(`Push message with content topic containing ${testItem.description}`, async function () { const customEncoder = createEncoder({ - contentTopic: testItem.value + contentTopic: testItem.value, + pubsubTopic: TestPubsubTopic }); const pushResponse = await waku.lightPush.send( customEncoder, @@ -101,10 +113,15 @@ describe("Waku Light Push: Single Node", function () { ); expect(pushResponse.successes.length).to.eq(1); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: testItem.value + expectedContentTopic: testItem.value, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -123,7 +140,8 @@ describe("Waku Light Push: Single Node", function () { it("Push message with meta", async function () { const customTestEncoder = createEncoder({ contentTopic: TestContentTopic, - metaSetter: () => new Uint8Array(10) + metaSetter: () => new Uint8Array(10), + pubsubTopic: TestPubsubTopic }); const pushResponse = await waku.lightPush.send( @@ -132,16 +150,22 @@ describe("Waku Light Push: Single Node", function () { ); expect(pushResponse.successes.length).to.eq(1); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); it("Fails to push message with large meta", async function () { const customTestEncoder = createEncoder({ contentTopic: TestContentTopic, + pubsubTopic: TestPubsubTopic, metaSetter: () => new Uint8Array(105024) // see the note below *** }); @@ -159,17 +183,26 @@ describe("Waku Light Push: Single Node", function () { if (nwaku.type == "go-waku") { expect(pushResponse.successes.length).to.eq(1); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); } else { expect(pushResponse.successes.length).to.eq(0); expect(pushResponse.failures?.map((failure) => failure.error)).to.include( ProtocolError.REMOTE_PEER_REJECTED ); - expect(await messageCollector.waitForMessages(1)).to.eq(false); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(false); } }); @@ -190,10 +223,15 @@ describe("Waku Light Push: Single Node", function () { }); expect(pushResponse.successes.length).to.eq(1); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); @@ -209,11 +247,16 @@ describe("Waku Light Push: Single Node", function () { }); expect(pushResponse.successes.length).to.eq(1); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { expectedMessageText: messageText, expectedTimestamp: testItem, - expectedContentTopic: TestContentTopic + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic }); }); }); @@ -236,6 +279,10 @@ describe("Waku Light Push: Single Node", function () { expect(pushResponse.failures?.map((failure) => failure.error)).to.include( ProtocolError.SIZE_TOO_BIG ); - expect(await messageCollector.waitForMessages(1)).to.eq(false); + expect( + await messageCollector.waitForMessages(1, { + pubsubTopic: TestPubsubTopic + }) + ).to.eq(false); }); }); diff --git a/packages/tests/tests/light-push/single_node/multiple_pubsub.node.spec.ts b/packages/tests/tests/light-push/single_node/multiple_pubsub.node.spec.ts index b4e810a16a..be2b6fdec8 100644 --- a/packages/tests/tests/light-push/single_node/multiple_pubsub.node.spec.ts +++ b/packages/tests/tests/light-push/single_node/multiple_pubsub.node.spec.ts @@ -5,6 +5,7 @@ import { LightNode, Protocols, ShardInfo, + ShardingParams, SingleShardInfo } from "@waku/interfaces"; import { @@ -15,6 +16,7 @@ import { } from "@waku/utils"; import { utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; +import { Context } from "mocha"; import { afterEachCustom, @@ -32,14 +34,13 @@ describe("Waku Light Push : Multiple PubsubTopics", function () { let nwaku: ServiceNode; let nwaku2: ServiceNode; let messageCollector: MessageCollector; - const customPubsubTopic1 = singleShardInfoToPubsubTopic({ - clusterId: 3, - shard: 1 - }); const shardInfo: ShardInfo = { clusterId: 3, shards: [1, 2] }; const singleShardInfo1: SingleShardInfo = { clusterId: 3, shard: 1 }; const singleShardInfo2: SingleShardInfo = { clusterId: 3, shard: 2 }; + + const customPubsubTopic1 = singleShardInfoToPubsubTopic(singleShardInfo1); + const customPubsubTopic2 = singleShardInfoToPubsubTopic(singleShardInfo2); const customContentTopic1 = "/test/2/waku-light-push/utf8"; const customContentTopic2 = "/test/3/waku-light-push/utf8"; const customEncoder1 = createEncoder({ @@ -54,14 +55,7 @@ describe("Waku Light Push : Multiple PubsubTopics", function () { let nimPeerId: PeerId; beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes( - this.ctx, - [ - singleShardInfoToPubsubTopic(singleShardInfo1), - singleShardInfoToPubsubTopic(singleShardInfo2) - ], - shardInfo - ); + [nwaku, waku] = await runNodes(this.ctx, shardInfo); messageCollector = new MessageCollector(nwaku); nimPeerId = await nwaku.getPeerId(); }); @@ -108,7 +102,7 @@ describe("Waku Light Push : Multiple PubsubTopics", function () { expect( await messageCollector2.waitForMessages(1, { - pubsubTopic: singleShardInfoToPubsubTopic(singleShardInfo2) + pubsubTopic: customPubsubTopic2 }) ).to.eq(true); @@ -120,7 +114,7 @@ describe("Waku Light Push : Multiple PubsubTopics", function () { messageCollector2.verifyReceivedMessage(0, { expectedMessageText: "M2", expectedContentTopic: customContentTopic2, - expectedPubsubTopic: customPubsubTopic1 + expectedPubsubTopic: customPubsubTopic2 }); }); @@ -204,11 +198,7 @@ describe("Waku Light Push (Autosharding): Multiple PubsubTopics", function () { let nimPeerId: PeerId; beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes( - this.ctx, - [autoshardingPubsubTopic1, autoshardingPubsubTopic2], - shardInfo - ); + [nwaku, waku] = await runNodes(this.ctx, shardInfo); messageCollector = new MessageCollector(nwaku); nimPeerId = await nwaku.getPeerId(); }); @@ -318,11 +308,13 @@ describe("Waku Light Push (Autosharding): Multiple PubsubTopics", function () { describe("Waku Light Push (named sharding): Multiple PubsubTopics", function () { this.timeout(30000); let waku: LightNode; + let waku2: LightNode; let nwaku: ServiceNode; let nwaku2: ServiceNode; let messageCollector: MessageCollector; + let ctx: Context; - const clusterId = 0; + const clusterId = 3; const customContentTopic1 = "/waku/2/content/utf8"; const customContentTopic2 = "/myapp/1/latest/proto"; const autoshardingPubsubTopic1 = contentTopicToPubsubTopic( @@ -333,34 +325,44 @@ describe("Waku Light Push (named sharding): Multiple PubsubTopics", function () customContentTopic2, clusterId ); + + const shardInfo1 = { + clusterId, + shards: [contentTopicToShardIndex(customContentTopic1)] + }; const customEncoder1 = createEncoder({ contentTopic: customContentTopic1, - pubsubTopicShardInfo: { - clusterId, - shard: contentTopicToShardIndex(customContentTopic1) - } + pubsubTopicShardInfo: shardInfo1 }); + + const shardInfo2 = { + clusterId, + shards: [contentTopicToShardIndex(customContentTopic2)] + }; const customEncoder2 = createEncoder({ contentTopic: customContentTopic2, - pubsubTopicShardInfo: { - clusterId, - shard: contentTopicToShardIndex(customContentTopic2) - } + pubsubTopicShardInfo: shardInfo2 }); + const testShardInfo: ShardingParams = { + clusterId, + shards: [ + contentTopicToShardIndex(customContentTopic1), + contentTopicToShardIndex(customContentTopic2) + ] + }; + let nimPeerId: PeerId; beforeEachCustom(this, async () => { - [nwaku, waku] = await runNodes(this.ctx, [ - autoshardingPubsubTopic1, - autoshardingPubsubTopic2 - ]); + ctx = this.ctx; + [nwaku, waku] = await runNodes(ctx, testShardInfo); messageCollector = new MessageCollector(nwaku); nimPeerId = await nwaku.getPeerId(); }); afterEachCustom(this, async () => { - await tearDownNodes([nwaku, nwaku2], waku); + await tearDownNodes([nwaku, nwaku2], [waku, waku2]); }); it("Push message on custom pubsubTopic", async function () { @@ -419,13 +421,7 @@ describe("Waku Light Push (named sharding): Multiple PubsubTopics", function () it("Light push messages to 2 nwaku nodes each with different pubsubtopics", async function () { // Set up and start a new nwaku node with Default PubsubTopic - nwaku2 = new ServiceNode(makeLogFileName(this) + "2"); - await nwaku2.start({ - filter: true, - lightpush: true, - relay: true, - pubsubTopic: [autoshardingPubsubTopic2] - }); + [nwaku2, waku2] = await runNodes(ctx, shardInfo2); await nwaku2.ensureSubscriptions([autoshardingPubsubTopic2]); await waku.dial(await nwaku2.getMultiaddrWithId()); await waitForRemotePeer(waku, [Protocols.LightPush]); diff --git a/packages/tests/tests/light-push/utils.ts b/packages/tests/tests/light-push/utils.ts index 04a6ccc055..43f1a6dbb9 100644 --- a/packages/tests/tests/light-push/utils.ts +++ b/packages/tests/tests/light-push/utils.ts @@ -1,78 +1,26 @@ -import { createEncoder, waitForRemotePeer } from "@waku/core"; -import { - ContentTopicInfo, - DefaultPubsubTopic, - LightNode, - Protocols, - ShardingParams -} from "@waku/interfaces"; -import { createLightNode, utf8ToBytes } from "@waku/sdk"; -import { Logger } from "@waku/utils"; +import { createEncoder } from "@waku/core"; +import { utf8ToBytes } from "@waku/sdk"; +import { contentTopicToPubsubTopic, Logger } from "@waku/utils"; -import { makeLogFileName, NOISE_KEY_1, ServiceNode } from "../../src/index.js"; +import { runNodes } from "../filter/single_node/utils.js"; // Constants for test configuration. export const log = new Logger("test:lightpush"); export const TestContentTopic = "/test/1/waku-light-push/utf8"; -export const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); +export const ClusterId = 3; +export const TestPubsubTopic = contentTopicToPubsubTopic( + TestContentTopic, + ClusterId +); +export const TestShardInfo = { + contentTopics: [TestContentTopic], + clusterId: ClusterId +}; +export const TestEncoder = createEncoder({ + contentTopic: TestContentTopic, + pubsubTopic: TestPubsubTopic +}); export const messageText = "Light Push works!"; export const messagePayload = { payload: utf8ToBytes(messageText) }; -export async function runNodes( - context: Mocha.Context, - pubsubTopics: string[], - shardInfo?: ShardingParams -): Promise<[ServiceNode, LightNode]> { - const nwaku = new ServiceNode(makeLogFileName(context)); - - function isContentTopicInfo(info: ShardingParams): info is ContentTopicInfo { - return (info as ContentTopicInfo).contentTopics !== undefined; - } - - await nwaku.start( - { - lightpush: true, - filter: true, - relay: true, - pubsubTopic: pubsubTopics, - // Conditionally include clusterId if shardInfo exists - ...(shardInfo && { clusterId: shardInfo.clusterId }), - // Conditionally include contentTopic if shardInfo exists and clusterId is 1 - ...(shardInfo && - isContentTopicInfo(shardInfo) && - shardInfo.clusterId === 1 && { contentTopic: shardInfo.contentTopics }) - }, - { retries: 3 } - ); - - let waku: LightNode | undefined; - try { - waku = await createLightNode({ - ...((pubsubTopics.length !== 1 || - pubsubTopics[0] !== DefaultPubsubTopic) && { - shardInfo: shardInfo - }), - pubsubTopics: shardInfo ? undefined : pubsubTopics, - staticNoiseKey: NOISE_KEY_1 - }); - await waku.start(); - } catch (error) { - log.error("jswaku node failed to start:", error); - } - - if (waku) { - await waku.dial(await nwaku.getMultiaddrWithId()); - await waitForRemotePeer(waku, [Protocols.LightPush]); - if ( - shardInfo && - "contentTopics" in shardInfo && - shardInfo.contentTopics.length > 0 - ) { - await nwaku.ensureSubscriptionsAutosharding(shardInfo.contentTopics); - } - await nwaku.ensureSubscriptions(pubsubTopics); - return [nwaku, waku]; - } else { - throw new Error("Failed to initialize waku"); - } -} +export { runNodes }; diff --git a/packages/tests/tests/relay/index.node.spec.ts b/packages/tests/tests/relay/index.node.spec.ts index e964d0b77e..f9f4175f21 100644 --- a/packages/tests/tests/relay/index.node.spec.ts +++ b/packages/tests/tests/relay/index.node.spec.ts @@ -13,7 +13,6 @@ import { createDecoder as createSymDecoder, createEncoder as createSymEncoder } from "@waku/message-encryption/symmetric"; -import { createRelayNode } from "@waku/sdk/relay"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; @@ -21,12 +20,10 @@ import { afterEachCustom, beforeEachCustom, delay, - NOISE_KEY_1, - NOISE_KEY_2, tearDownNodes } from "../../src/index.js"; -import { log, waitForAllRemotePeers } from "./utils.js"; +import { runJSNodes, TestPubsubTopic } from "./utils.js"; describe("Waku Relay", function () { this.timeout(15000); @@ -34,24 +31,7 @@ describe("Waku Relay", function () { let waku2: RelayNode; beforeEachCustom(this, async () => { - log.info("Starting JS Waku instances"); - [waku1, waku2] = await Promise.all([ - createRelayNode({ staticNoiseKey: NOISE_KEY_1 }).then((waku) => - waku.start().then(() => waku) - ), - createRelayNode({ - staticNoiseKey: NOISE_KEY_2, - libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } } - }).then((waku) => waku.start().then(() => waku)) - ]); - log.info("Instances started, adding waku2 to waku1's address book"); - await waku1.libp2p.peerStore.merge(waku2.libp2p.peerId, { - multiaddrs: waku2.libp2p.getMultiaddrs() - }); - await waku1.dial(waku2.libp2p.peerId); - - await waitForAllRemotePeers(waku1, waku2); - log.info("before each hook done"); + [waku1, waku2] = await runJSNodes(); }); afterEachCustom(this, async () => { @@ -70,15 +50,21 @@ describe("Waku Relay", function () { const eciesEncoder = createEciesEncoder({ contentTopic: asymTopic, - publicKey + publicKey, + pubsubTopic: TestPubsubTopic }); const symEncoder = createSymEncoder({ contentTopic: symTopic, - symKey + symKey, + pubsubTopic: TestPubsubTopic }); - const eciesDecoder = createEciesDecoder(asymTopic, privateKey); - const symDecoder = createSymDecoder(symTopic, symKey); + const eciesDecoder = createEciesDecoder( + asymTopic, + privateKey, + TestPubsubTopic + ); + const symDecoder = createSymDecoder(symTopic, symKey, TestPubsubTopic); const msgs: DecodedMessage[] = []; void waku2.relay.subscribe([eciesDecoder], (wakuMsg) => { @@ -106,7 +92,7 @@ describe("Waku Relay", function () { const messageText = "Published on content topic with added then deleted observer"; - const contentTopic = "added-then-deleted-observer"; + const contentTopic = "/test/1/observer/proto"; // The promise **fails** if we receive a message on this observer. const receivedMsgPromise: Promise = new Promise( diff --git a/packages/tests/tests/relay/interop.node.spec.ts b/packages/tests/tests/relay/interop.node.spec.ts index b3cd5a40f9..09909bb673 100644 --- a/packages/tests/tests/relay/interop.node.spec.ts +++ b/packages/tests/tests/relay/interop.node.spec.ts @@ -1,6 +1,6 @@ import type { PeerId } from "@libp2p/interface"; import { DecodedMessage, waitForRemotePeer } from "@waku/core"; -import { DefaultPubsubTopic, Protocols, RelayNode } from "@waku/interfaces"; +import { Protocols, RelayNode } from "@waku/interfaces"; import { createRelayNode } from "@waku/sdk/relay"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; @@ -10,15 +10,20 @@ import { base64ToUtf8, beforeEachCustom, delay, - makeLogFileName, - NOISE_KEY_1, NOISE_KEY_2, ServiceNode, tearDownNodes } from "../../src/index.js"; import { MessageRpcResponse } from "../../src/types.js"; -import { TestContentTopic, TestDecoder, TestEncoder } from "./utils.js"; +import { + TestContentTopic, + TestDecoder, + TestEncoder, + TestPubsubTopic, + TestShardInfo +} from "./utils.js"; +import { runRelayNodes } from "./utils.js"; describe("Waku Relay, Interop", function () { this.timeout(15000); @@ -26,19 +31,7 @@ describe("Waku Relay, Interop", function () { let nwaku: ServiceNode; beforeEachCustom(this, async () => { - waku = await createRelayNode({ - staticNoiseKey: NOISE_KEY_1 - }); - await waku.start(); - - nwaku = new ServiceNode(this.ctx.test?.ctx?.currentTest?.title + ""); - await nwaku.start({ relay: true }); - - await waku.dial(await nwaku.getMultiaddrWithId()); - await waitForRemotePeer(waku, [Protocols.Relay]); - - // Nwaku subscribe to the default pubsub topic - await nwaku.ensureSubscriptions(); + [nwaku, waku] = await runRelayNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -51,7 +44,7 @@ describe("Waku Relay, Interop", function () { while (subscribers.length === 0) { await delay(200); subscribers = - waku.libp2p.services.pubsub!.getSubscribers(DefaultPubsubTopic); + waku.libp2p.services.pubsub!.getSubscribers(TestPubsubTopic); } const nimPeerId = await nwaku.getPeerId(); @@ -103,63 +96,38 @@ describe("Waku Relay, Interop", function () { expect(bytesToUtf8(receivedMsg.payload!)).to.eq(messageText); }); - describe("Two nodes connected to nwaku", function () { - let waku1: RelayNode; - let waku2: RelayNode; - let nwaku: ServiceNode; - - afterEachCustom(this, async () => { - await tearDownNodes(nwaku, [waku1, waku2]); + it("Js publishes, other Js receives", async function () { + const waku2 = await createRelayNode({ + staticNoiseKey: NOISE_KEY_2, + emitSelf: true, + shardInfo: TestShardInfo }); + await waku2.start(); - it("Js publishes, other Js receives", async function () { - [waku1, waku2] = await Promise.all([ - createRelayNode({ - staticNoiseKey: NOISE_KEY_1, - emitSelf: true - }).then((waku) => waku.start().then(() => waku)), - createRelayNode({ - staticNoiseKey: NOISE_KEY_2 - }).then((waku) => waku.start().then(() => waku)) - ]); + const nwakuMultiaddr = await nwaku.getMultiaddrWithId(); + await waku2.dial(nwakuMultiaddr); - nwaku = new ServiceNode(makeLogFileName(this)); - await nwaku.start({ relay: true }); + await waitForRemotePeer(waku2, [Protocols.Relay]); - const nwakuMultiaddr = await nwaku.getMultiaddrWithId(); - await Promise.all([ - waku1.dial(nwakuMultiaddr), - waku2.dial(nwakuMultiaddr) - ]); + await delay(2000); + // Check that the two JS peers are NOT directly connected + expect(await waku.libp2p.peerStore.has(waku2.libp2p.peerId)).to.eq(false); + expect(await waku2.libp2p.peerStore.has(waku.libp2p.peerId)).to.eq(false); - // Wait for identify protocol to finish - await Promise.all([ - waitForRemotePeer(waku1, [Protocols.Relay]), - waitForRemotePeer(waku2, [Protocols.Relay]) - ]); + const msgStr = "Hello there!"; + const message = { payload: utf8ToBytes(msgStr) }; - await delay(2000); - // Check that the two JS peers are NOT directly connected - expect(await waku1.libp2p.peerStore.has(waku2.libp2p.peerId)).to.eq( - false - ); - expect(await waku2.libp2p.peerStore.has(waku1.libp2p.peerId)).to.eq( - false - ); + const waku2ReceivedMsgPromise: Promise = new Promise( + (resolve) => { + void waku2.relay.subscribe(TestDecoder, resolve); + } + ); - const msgStr = "Hello there!"; - const message = { payload: utf8ToBytes(msgStr) }; + await waku.relay.send(TestEncoder, message); + const waku2ReceivedMsg = await waku2ReceivedMsgPromise; - const waku2ReceivedMsgPromise: Promise = new Promise( - (resolve) => { - void waku2.relay.subscribe(TestDecoder, resolve); - } - ); + expect(bytesToUtf8(waku2ReceivedMsg.payload)).to.eq(msgStr); - await waku1.relay.send(TestEncoder, message); - const waku2ReceivedMsg = await waku2ReceivedMsgPromise; - - expect(bytesToUtf8(waku2ReceivedMsg.payload)).to.eq(msgStr); - }); + await tearDownNodes([], waku); }); }); diff --git a/packages/tests/tests/relay/publish.node.spec.ts b/packages/tests/tests/relay/publish.node.spec.ts index 86caea8fb8..f93c4ea609 100644 --- a/packages/tests/tests/relay/publish.node.spec.ts +++ b/packages/tests/tests/relay/publish.node.spec.ts @@ -1,6 +1,5 @@ import { createEncoder } from "@waku/core"; import { IRateLimitProof, ProtocolError, RelayNode } from "@waku/interfaces"; -import { createRelayNode } from "@waku/sdk/relay"; import { utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; @@ -10,18 +9,20 @@ import { delay, generateRandomUint8Array, MessageCollector, - NOISE_KEY_1, - NOISE_KEY_2, tearDownNodes, TEST_STRING } from "../../src/index.js"; import { - log, messageText, + runJSNodes, TestContentTopic, TestDecoder, TestEncoder, + TestExpectOptions, + TestPubsubTopic, + TestShardInfo, + TestWaitMessageOptions, waitForAllRemotePeers } from "./utils.js"; @@ -32,23 +33,7 @@ describe("Waku Relay, Publish", function () { let messageCollector: MessageCollector; beforeEachCustom(this, async () => { - log.info("Starting JS Waku instances"); - [waku1, waku2] = await Promise.all([ - createRelayNode({ - staticNoiseKey: NOISE_KEY_1 - }).then((waku) => waku.start().then(() => waku)), - createRelayNode({ - staticNoiseKey: NOISE_KEY_2, - libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } } - }).then((waku) => waku.start().then(() => waku)) - ]); - log.info("Instances started, adding waku2 to waku1's address book"); - await waku1.libp2p.peerStore.merge(waku2.libp2p.peerId, { - multiaddrs: waku2.libp2p.getMultiaddrs() - }); - await waku1.dial(waku2.libp2p.peerId); - log.info("before each hook done"); - await waitForAllRemotePeers(waku1, waku2); + [waku1, waku2] = await runJSNodes(); messageCollector = new MessageCollector(); await waku2.relay.subscribe([TestDecoder], messageCollector.callback); }); @@ -66,10 +51,12 @@ describe("Waku Relay, Publish", function () { expect(pushResponse.successes[0].toString()).to.eq( waku2.libp2p.peerId.toString() ); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { - expectedMessageText: testItem.value, - expectedContentTopic: TestContentTopic + ...TestExpectOptions, + expectedMessageText: testItem.value }); }); }); @@ -91,11 +78,13 @@ describe("Waku Relay, Publish", function () { waku2.libp2p.peerId.toString() ); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { + ...TestExpectOptions, expectedMessageText: messageText, - expectedContentTopic: TestContentTopic, expectedTimestamp: testItem.valueOf() }); }); @@ -115,20 +104,30 @@ describe("Waku Relay, Publish", function () { it("Fails to publish message with empty text", async function () { await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("") }); await delay(400); - expect(await messageCollector.waitForMessages(1)).to.eq(false); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(false); }); it("Fails to publish message with wrong content topic", async function () { - const wrong_encoder = createEncoder({ contentTopic: "wrong" }); + const wrong_encoder = createEncoder({ + contentTopic: "/test/1/wrong/utf8", + pubsubTopic: TestPubsubTopic + }); await waku1.relay.send(wrong_encoder, { payload: utf8ToBytes("") }); - expect(await messageCollector.waitForMessages(1)).to.eq(false); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(false); }); it("Fails to publish message with wrong pubsubtopic", async function () { const wrong_encoder = createEncoder({ - pubsubTopicShardInfo: { clusterId: 3, shard: 1 }, + pubsubTopicShardInfo: { + clusterId: TestShardInfo.clusterId, + shard: TestShardInfo.shards[0] + 1 + }, contentTopic: TestContentTopic }); const pushResponse = await waku1.relay.send(wrong_encoder, { @@ -138,7 +137,9 @@ describe("Waku Relay, Publish", function () { ProtocolError.TOPIC_NOT_CONFIGURED ); await delay(400); - expect(await messageCollector.waitForMessages(1)).to.eq(false); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(false); }); [1024 ** 2 + 65536, 2 * 1024 ** 2].forEach((testItem) => { @@ -151,7 +152,9 @@ describe("Waku Relay, Publish", function () { ProtocolError.SIZE_TOO_BIG ); await delay(400); - expect(await messageCollector.waitForMessages(1)).to.eq(false); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(false); }); }); @@ -177,7 +180,9 @@ describe("Waku Relay, Publish", function () { expect(pushResponse.successes[0].toString()).to.eq( waku2.libp2p.peerId.toString() ); - expect(await messageCollector.waitForMessages(2)).to.eq(true); + expect( + await messageCollector.waitForMessages(2, TestWaitMessageOptions) + ).to.eq(true); }); // Will be skipped until https://github.com/waku-org/js-waku/issues/1464 si done @@ -202,12 +207,15 @@ describe("Waku Relay, Publish", function () { expect(pushResponse.successes[0].toString()).to.eq( waku2.libp2p.peerId.toString() ); - expect(await messageCollector.waitForMessages(2)).to.eq(true); + expect( + await messageCollector.waitForMessages(2, TestWaitMessageOptions) + ).to.eq(true); }); it("Publish message with large meta", async function () { const customTestEncoder = createEncoder({ contentTopic: TestContentTopic, + pubsubTopic: TestPubsubTopic, metaSetter: () => new Uint8Array(10 ** 6) }); @@ -218,7 +226,9 @@ describe("Waku Relay, Publish", function () { expect(pushResponse.successes[0].toString()).to.eq( waku2.libp2p.peerId.toString() ); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(true); }); it("Publish message with rate limit", async function () { @@ -238,10 +248,12 @@ describe("Waku Relay, Publish", function () { }); expect(pushResponse.successes.length).to.eq(1); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { - expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + ...TestExpectOptions, + expectedMessageText: messageText }); }); }); diff --git a/packages/tests/tests/relay/subscribe.node.spec.ts b/packages/tests/tests/relay/subscribe.node.spec.ts index 804d3a39b8..b234acd53b 100644 --- a/packages/tests/tests/relay/subscribe.node.spec.ts +++ b/packages/tests/tests/relay/subscribe.node.spec.ts @@ -1,5 +1,5 @@ import { createDecoder, createEncoder } from "@waku/core"; -import { DefaultPubsubTopic, RelayNode } from "@waku/interfaces"; +import { RelayNode } from "@waku/interfaces"; import { createRelayNode } from "@waku/sdk/relay"; import { utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; @@ -10,17 +10,19 @@ import { generateTestData, MessageCollector, NOISE_KEY_1, - NOISE_KEY_2, tearDownNodes, TEST_STRING } from "../../src/index.js"; import { - log, messageText, - TestContentTopic, + runJSNodes, TestDecoder, TestEncoder, + TestExpectOptions, + TestPubsubTopic, + TestShardInfo, + TestWaitMessageOptions, waitForAllRemotePeers } from "./utils.js"; @@ -31,22 +33,7 @@ describe("Waku Relay, Subscribe", function () { let messageCollector: MessageCollector; beforeEachCustom(this, async () => { - log.info("Starting JS Waku instances"); - [waku1, waku2] = await Promise.all([ - createRelayNode({ - staticNoiseKey: NOISE_KEY_1 - }).then((waku) => waku.start().then(() => waku)), - createRelayNode({ - staticNoiseKey: NOISE_KEY_2, - libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } } - }).then((waku) => waku.start().then(() => waku)) - ]); - log.info("Instances started, adding waku2 to waku1's address book"); - await waku1.libp2p.peerStore.merge(waku2.libp2p.peerId, { - multiaddrs: waku2.libp2p.getMultiaddrs() - }); - await waku1.dial(waku2.libp2p.peerId); - log.info("before each hook done"); + [waku1, waku2] = await runJSNodes(); messageCollector = new MessageCollector(this.ctx.nwaku); }); @@ -57,10 +44,10 @@ describe("Waku Relay, Subscribe", function () { it("Mutual subscription", async function () { await waitForAllRemotePeers(waku1, waku2); const subscribers1 = waku1.libp2p.services - .pubsub!.getSubscribers(DefaultPubsubTopic) + .pubsub!.getSubscribers(TestPubsubTopic) .map((p) => p.toString()); const subscribers2 = waku2.libp2p.services - .pubsub!.getSubscribers(DefaultPubsubTopic) + .pubsub!.getSubscribers(TestPubsubTopic) .map((p) => p.toString()); expect(subscribers1).to.contain(waku2.libp2p.peerId.toString()); @@ -76,9 +63,16 @@ describe("Waku Relay, Subscribe", function () { it("Publish without waiting for remote peer", async function () { try { - await waku1.relay.send(TestEncoder, { + const waku = await createRelayNode({ + staticNoiseKey: NOISE_KEY_1, + shardInfo: TestShardInfo + }); + await waku.start(); + + await waku.relay.send(TestEncoder, { payload: utf8ToBytes(messageText) }); + throw new Error("Publish was successful but was expected to fail"); } catch (err) { if ( @@ -91,19 +85,19 @@ describe("Waku Relay, Subscribe", function () { }); it("Subscribe and publish message", async function () { - await waitForAllRemotePeers(waku1, waku2); await waku2.relay.subscribe([TestDecoder], messageCollector.callback); await waku1.relay.send(TestEncoder, { payload: utf8ToBytes(messageText) }); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { - expectedMessageText: messageText, - expectedContentTopic: TestContentTopic + ...TestExpectOptions, + expectedMessageText: messageText }); }); it("Subscribe and publish 10000 messages on the same topic", async function () { const messageCount = 10000; - await waitForAllRemotePeers(waku1, waku2); await waku2.relay.subscribe([TestDecoder], messageCollector.callback); // Send a unique message on each topic. for (let i = 0; i < messageCount; i++) { @@ -114,13 +108,16 @@ describe("Waku Relay, Subscribe", function () { // Verify that each message was received on the corresponding topic. expect( - await messageCollector.waitForMessages(messageCount, { exact: true }) + await messageCollector.waitForMessages(messageCount, { + ...TestWaitMessageOptions, + exact: true + }) ).to.eq(true); for (let i = 0; i < messageCount; i++) { messageCollector.verifyReceivedMessage(i, { + ...TestExpectOptions, expectedMessageText: `M${i + 1}`, - expectedContentTopic: TestContentTopic, checkTimestamp: false }); } @@ -128,31 +125,36 @@ describe("Waku Relay, Subscribe", function () { it("Subscribe and publish messages on 2 different content topics", async function () { const secondContentTopic = "/test/2/waku-relay/utf8"; - const secondEncoder = createEncoder({ contentTopic: secondContentTopic }); - const secondDecoder = createDecoder(secondContentTopic); + const secondEncoder = createEncoder({ + contentTopic: secondContentTopic, + pubsubTopic: TestPubsubTopic + }); + const secondDecoder = createDecoder(secondContentTopic, TestPubsubTopic); - await waitForAllRemotePeers(waku1, waku2); await waku2.relay.subscribe([TestDecoder], messageCollector.callback); await waku2.relay.subscribe([secondDecoder], messageCollector.callback); await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("M1") }); await waku1.relay.send(secondEncoder, { payload: utf8ToBytes("M2") }); - expect(await messageCollector.waitForMessages(2, { exact: true })).to.eq( - true - ); + expect( + await messageCollector.waitForMessages(2, { + ...TestWaitMessageOptions, + exact: true + }) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { - expectedMessageText: "M1", - expectedContentTopic: TestContentTopic + ...TestExpectOptions, + expectedMessageText: "M1" }); messageCollector.verifyReceivedMessage(1, { - expectedMessageText: "M2", - expectedContentTopic: secondContentTopic + ...TestExpectOptions, + expectedContentTopic: secondEncoder.contentTopic, + expectedMessageText: "M2" }); }); it("Subscribe one by one to 100 topics and publish messages", async function () { const topicCount = 100; - const td = generateTestData(topicCount); - await waitForAllRemotePeers(waku1, waku2); + const td = generateTestData(topicCount, TestWaitMessageOptions); // Subscribe to topics one by one for (let i = 0; i < topicCount; i++) { @@ -168,10 +170,14 @@ describe("Waku Relay, Subscribe", function () { // Verify that each message was received on the corresponding topic. expect( - await messageCollector.waitForMessages(topicCount, { exact: true }) + await messageCollector.waitForMessages(topicCount, { + ...TestWaitMessageOptions, + exact: true + }) ).to.eq(true); td.contentTopics.forEach((topic, index) => { messageCollector.verifyReceivedMessage(index, { + ...TestExpectOptions, expectedContentTopic: topic, expectedMessageText: `Message for Topic ${index + 1}` }); @@ -180,8 +186,7 @@ describe("Waku Relay, Subscribe", function () { it("Subscribe at once to 10000 topics and publish messages", async function () { const topicCount = 10000; - const td = generateTestData(topicCount); - await waitForAllRemotePeers(waku1, waku2); + const td = generateTestData(topicCount, TestWaitMessageOptions); // Subscribe to all topics at once await waku2.relay.subscribe(td.decoders, messageCollector.callback); @@ -195,10 +200,14 @@ describe("Waku Relay, Subscribe", function () { // Verify that each message was received on the corresponding topic. expect( - await messageCollector.waitForMessages(topicCount, { exact: true }) + await messageCollector.waitForMessages(topicCount, { + ...TestWaitMessageOptions, + exact: true + }) ).to.eq(true); td.contentTopics.forEach((topic, index) => { messageCollector.verifyReceivedMessage(index, { + ...TestExpectOptions, expectedContentTopic: topic, expectedMessageText: `Message for Topic ${index + 1}`, checkTimestamp: false @@ -208,26 +217,26 @@ describe("Waku Relay, Subscribe", function () { // Will be skipped until https://github.com/waku-org/js-waku/issues/1678 is fixed it.skip("Refresh subscription", async function () { - await waitForAllRemotePeers(waku1, waku2); - await waku2.relay.subscribe([TestDecoder], messageCollector.callback); await waku2.relay.subscribe([TestDecoder], messageCollector.callback); await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("M1") }); - expect(await messageCollector.waitForMessages(1, { exact: true })).to.eq( - true - ); + expect( + await messageCollector.waitForMessages(1, { + ...TestWaitMessageOptions, + exact: true + }) + ).to.eq(true); }); // Will be skipped until https://github.com/waku-org/js-waku/issues/1678 is fixed it.skip("Overlapping topic subscription", async function () { // Define two sets of test data with overlapping topics. const topicCount1 = 2; - const td1 = generateTestData(topicCount1); + const td1 = generateTestData(topicCount1, TestWaitMessageOptions); const topicCount2 = 4; - const td2 = generateTestData(topicCount2); - await waitForAllRemotePeers(waku1, waku2); + const td2 = generateTestData(topicCount2, TestWaitMessageOptions); // Subscribe to the first set of topics. await waku2.relay.subscribe(td1.decoders, messageCollector.callback); @@ -252,23 +261,33 @@ describe("Waku Relay, Subscribe", function () { // Check if all messages were received. // Since there are overlapping topics, there should be 6 messages in total (2 from the first set + 4 from the second set). - expect(await messageCollector.waitForMessages(6, { exact: true })).to.eq( - true - ); + expect( + await messageCollector.waitForMessages(6, { + ...TestWaitMessageOptions, + exact: true + }) + ).to.eq(true); }); TEST_STRING.forEach((testItem) => { it(`Subscribe to topic containing ${testItem.description} and publish message`, async function () { const newContentTopic = testItem.value; - const newEncoder = createEncoder({ contentTopic: newContentTopic }); - const newDecoder = createDecoder(newContentTopic); - await waitForAllRemotePeers(waku1, waku2); + const newEncoder = createEncoder({ + contentTopic: newContentTopic, + pubsubTopic: TestPubsubTopic + }); + const newDecoder = createDecoder(newContentTopic, TestPubsubTopic); + await waku2.relay.subscribe([newDecoder], messageCollector.callback); await waku1.relay.send(newEncoder, { payload: utf8ToBytes(messageText) }); - expect(await messageCollector.waitForMessages(1)).to.eq(true); + + expect( + await messageCollector.waitForMessages(1, TestWaitMessageOptions) + ).to.eq(true); messageCollector.verifyReceivedMessage(0, { + ...TestExpectOptions, expectedMessageText: messageText, expectedContentTopic: newContentTopic }); diff --git a/packages/tests/tests/relay/utils.ts b/packages/tests/tests/relay/utils.ts index e35110fd67..df8cfeee2f 100644 --- a/packages/tests/tests/relay/utils.ts +++ b/packages/tests/tests/relay/utils.ts @@ -1,18 +1,85 @@ import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core"; -import { Protocols, RelayNode } from "@waku/interfaces"; -import { Logger } from "@waku/utils"; +import { + Protocols, + RelayNode, + ShardInfo, + ShardingParams +} from "@waku/interfaces"; +import { createRelayNode } from "@waku/sdk/relay"; +import { contentTopicToPubsubTopic, Logger } from "@waku/utils"; +import { Context } from "mocha"; + +import { + NOISE_KEY_1, + NOISE_KEY_2, + runNodes, + ServiceNode +} from "../../src/index.js"; export const messageText = "Relay works!"; export const TestContentTopic = "/test/1/waku-relay/utf8"; -export const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); -export const TestDecoder = createDecoder(TestContentTopic); +export const TestShardInfo: ShardInfo = { + clusterId: 2, + shards: [4] +}; +export const TestPubsubTopic = contentTopicToPubsubTopic( + TestContentTopic, + TestShardInfo.clusterId +); +export const TestEncoder = createEncoder({ + contentTopic: TestContentTopic, + pubsubTopic: TestPubsubTopic +}); +export const TestDecoder = createDecoder(TestContentTopic, TestPubsubTopic); +export const TestWaitMessageOptions = { pubsubTopic: TestPubsubTopic }; +export const TestExpectOptions = { + expectedContentTopic: TestContentTopic, + expectedPubsubTopic: TestPubsubTopic +}; export const log = new Logger("test:relay"); +const RELAY_PROTOCOLS = [Protocols.Relay]; + export async function waitForAllRemotePeers( ...nodes: RelayNode[] ): Promise { log.info("Wait for mutual pubsub subscription"); await Promise.all( - nodes.map((node) => waitForRemotePeer(node, [Protocols.Relay])) + nodes.map((node): Promise => waitForRemotePeer(node, RELAY_PROTOCOLS)) ); } + +export const runRelayNodes = ( + context: Context, + shardInfo: ShardingParams +): Promise<[ServiceNode, RelayNode]> => + runNodes({ + shardInfo, + context, + protocols: RELAY_PROTOCOLS, + createNode: createRelayNode + }); + +export async function runJSNodes(): Promise<[RelayNode, RelayNode]> { + log.info("Starting JS Waku instances"); + const [waku1, waku2] = await Promise.all([ + createRelayNode({ + staticNoiseKey: NOISE_KEY_1, + shardInfo: TestShardInfo + }).then((waku) => waku.start().then(() => waku)), + createRelayNode({ + staticNoiseKey: NOISE_KEY_2, + shardInfo: TestShardInfo, + libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } } + }).then((waku) => waku.start().then(() => waku)) + ]); + log.info("Instances started, adding waku2 to waku1's address book"); + await waku1.libp2p.peerStore.merge(waku2.libp2p.peerId, { + multiaddrs: waku2.libp2p.getMultiaddrs() + }); + await waku1.dial(waku2.libp2p.peerId); + log.info("before each hook done"); + await waitForAllRemotePeers(waku1, waku2); + + return [waku1, waku2]; +} diff --git a/packages/tests/tests/store/cursor.node.spec.ts b/packages/tests/tests/store/cursor.node.spec.ts index e6a76bf189..60be3f1869 100644 --- a/packages/tests/tests/store/cursor.node.spec.ts +++ b/packages/tests/tests/store/cursor.node.spec.ts @@ -1,23 +1,22 @@ import { DecodedMessage } from "@waku/core"; import type { LightNode } from "@waku/interfaces"; -import { DefaultPubsubTopic } from "@waku/interfaces"; import { bytesToUtf8 } from "@waku/utils/bytes"; import { expect } from "chai"; import { afterEachCustom, beforeEachCustom, - makeLogFileName, ServiceNode, tearDownNodes } from "../../src/index.js"; import { - customShardedPubsubTopic1, + runStoreNodes, sendMessages, startAndConnectLightNode, - TestContentTopic, TestDecoder, + TestDecoder2, + TestShardInfo, totalMsgs } from "./utils.js"; @@ -28,9 +27,7 @@ describe("Waku Store, cursor", function () { let nwaku: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ store: true, lightpush: true, relay: true }); - await nwaku.ensureSubscriptions(); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -49,10 +46,9 @@ describe("Waku Store, cursor", function () { await sendMessages( nwaku, messageCount, - TestContentTopic, - DefaultPubsubTopic + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku); // messages in reversed order (first message at last index) const messages: DecodedMessage[] = []; @@ -95,9 +91,13 @@ describe("Waku Store, cursor", function () { }); it("Reusing cursor across nodes", async function () { - await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); - waku2 = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + totalMsgs, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); + waku2 = await startAndConnectLightNode(nwaku, TestShardInfo); // messages in reversed order (first message at last index) const messages: DecodedMessage[] = []; @@ -133,8 +133,12 @@ describe("Waku Store, cursor", function () { }); it("Passing cursor with wrong message digest", async function () { - await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + totalMsgs, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); const messages: DecodedMessage[] = []; for await (const page of waku.store.queryGenerator([TestDecoder])) { @@ -175,8 +179,12 @@ describe("Waku Store, cursor", function () { }); it("Passing cursor with wrong pubsubTopic", async function () { - await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + totalMsgs, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); const messages: DecodedMessage[] = []; for await (const page of waku.store.queryGenerator([TestDecoder])) { @@ -184,7 +192,7 @@ describe("Waku Store, cursor", function () { messages.push(msg as DecodedMessage); } } - messages[5].pubsubTopic = customShardedPubsubTopic1; + messages[5].pubsubTopic = TestDecoder2.pubsubTopic; const cursor = waku.store.createCursor(messages[5]); try { @@ -198,7 +206,7 @@ describe("Waku Store, cursor", function () { if ( !(err instanceof Error) || !err.message.includes( - `Cursor pubsub topic (${customShardedPubsubTopic1}) does not match decoder pubsub topic (${DefaultPubsubTopic})` + `Cursor pubsub topic (${TestDecoder2.pubsubTopic}) does not match decoder pubsub topic (${TestDecoder.pubsubTopic})` ) ) { throw err; diff --git a/packages/tests/tests/store/error_handling.node.spec.ts b/packages/tests/tests/store/error_handling.node.spec.ts index 1146a7cfdd..9a921163e2 100644 --- a/packages/tests/tests/store/error_handling.node.spec.ts +++ b/packages/tests/tests/store/error_handling.node.spec.ts @@ -1,21 +1,22 @@ -import { DefaultPubsubTopic } from "@waku/interfaces"; +import { createDecoder } from "@waku/core"; import { IMessage, type LightNode } from "@waku/interfaces"; +import { determinePubsubTopic } from "@waku/utils"; import { expect } from "chai"; import { afterEachCustom, beforeEachCustom, - makeLogFileName, ServiceNode, tearDownNodes } from "../../src/index.js"; import { - customDecoder1, - customShardedPubsubTopic1, processQueriedMessages, - startAndConnectLightNode, - TestDecoder + runStoreNodes, + TestContentTopic1, + TestDecoder, + TestDecoder2, + TestShardInfo } from "./utils.js"; describe("Waku Store, error handling", function () { @@ -24,10 +25,7 @@ describe("Waku Store, error handling", function () { let nwaku: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ store: true, lightpush: true, relay: true }); - await nwaku.ensureSubscriptions(); - waku = await startAndConnectLightNode(nwaku); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -35,9 +33,11 @@ describe("Waku Store, error handling", function () { }); it("Query Generator, Wrong PubsubTopic", async function () { + const wrongDecoder = createDecoder(TestContentTopic1, "WrongPubsubTopic"); + try { for await (const msgPromises of waku.store.queryGenerator([ - customDecoder1 + wrongDecoder ])) { void msgPromises; } @@ -46,7 +46,7 @@ describe("Waku Store, error handling", function () { if ( !(err instanceof Error) || !err.message.includes( - `Pubsub topic ${customShardedPubsubTopic1} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}` + `Pubsub topic ${wrongDecoder.pubsubTopic} has not been configured on this instance. Configured topics are: ${TestDecoder.pubsubTopic}` ) ) { throw err; @@ -58,7 +58,7 @@ describe("Waku Store, error handling", function () { try { for await (const msgPromises of waku.store.queryGenerator([ TestDecoder, - customDecoder1 + TestDecoder2 ])) { void msgPromises; } @@ -92,26 +92,25 @@ describe("Waku Store, error handling", function () { }); it("Query Generator, No message returned", async function () { + const WrongTestPubsubTopic = determinePubsubTopic("/test/1/wrong/utf8"); const messages = await processQueriedMessages( waku, [TestDecoder], - DefaultPubsubTopic + WrongTestPubsubTopic ); expect(messages?.length).eq(0); }); it("Query with Ordered Callback, Wrong PubsubTopic", async function () { + const wrongDecoder = createDecoder(TestContentTopic1, "WrongPubsubTopic"); try { - await waku.store.queryWithOrderedCallback( - [customDecoder1], - async () => {} - ); + await waku.store.queryWithOrderedCallback([wrongDecoder], async () => {}); throw new Error("QueryGenerator was successful but was expected to fail"); } catch (err) { if ( !(err instanceof Error) || !err.message.includes( - `Pubsub topic ${customShardedPubsubTopic1} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}` + `Pubsub topic ${wrongDecoder.pubsubTopic} has not been configured on this instance. Configured topics are: ${TestDecoder.pubsubTopic}` ) ) { throw err; @@ -122,7 +121,7 @@ describe("Waku Store, error handling", function () { it("Query with Ordered Callback, Multiple PubsubTopics", async function () { try { await waku.store.queryWithOrderedCallback( - [TestDecoder, customDecoder1], + [TestDecoder, TestDecoder2], async () => {} ); throw new Error("QueryGenerator was successful but was expected to fail"); @@ -161,17 +160,15 @@ describe("Waku Store, error handling", function () { }); it("Query with Promise Callback, Wrong PubsubTopic", async function () { + const wrongDecoder = createDecoder(TestContentTopic1, "WrongPubsubTopic"); try { - await waku.store.queryWithPromiseCallback( - [customDecoder1], - async () => {} - ); + await waku.store.queryWithPromiseCallback([wrongDecoder], async () => {}); throw new Error("QueryGenerator was successful but was expected to fail"); } catch (err) { if ( !(err instanceof Error) || !err.message.includes( - `Pubsub topic ${customShardedPubsubTopic1} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}` + `Pubsub topic ${wrongDecoder.pubsubTopic} has not been configured on this instance. Configured topics are: ${TestDecoder.pubsubTopic}` ) ) { throw err; @@ -182,7 +179,7 @@ describe("Waku Store, error handling", function () { it("Query with Promise Callback, Multiple PubsubTopics", async function () { try { await waku.store.queryWithPromiseCallback( - [TestDecoder, customDecoder1], + [TestDecoder, TestDecoder2], async () => {} ); throw new Error("QueryGenerator was successful but was expected to fail"); diff --git a/packages/tests/tests/store/index.node.spec.ts b/packages/tests/tests/store/index.node.spec.ts index 1c4229109f..595c0abc2d 100644 --- a/packages/tests/tests/store/index.node.spec.ts +++ b/packages/tests/tests/store/index.node.spec.ts @@ -1,6 +1,6 @@ import { createDecoder, DecodedMessage, waitForRemotePeer } from "@waku/core"; import type { IMessage, LightNode } from "@waku/interfaces"; -import { DefaultPubsubTopic, Protocols } from "@waku/interfaces"; +import { Protocols } from "@waku/interfaces"; import { generatePrivateKey, generateSymmetricKey, @@ -22,7 +22,6 @@ import { afterEachCustom, beforeEachCustom, delay, - makeLogFileName, MessageCollector, ServiceNode, tearDownNodes, @@ -30,20 +29,21 @@ import { } from "../../src/index.js"; import { - customContentTopic1, log, messageText, processQueriedMessages, + runStoreNodes, sendMessages, startAndConnectLightNode, - TestContentTopic, + TestContentTopic1, TestDecoder, + TestDecoder2, TestEncoder, + TestPubsubTopic1, + TestShardInfo, totalMsgs } from "./utils.js"; -const secondDecoder = createDecoder(customContentTopic1); - describe("Waku Store, general", function () { this.timeout(15000); let waku: LightNode; @@ -51,9 +51,7 @@ describe("Waku Store, general", function () { let nwaku: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ store: true, lightpush: true, relay: true }); - await nwaku.ensureSubscriptions(); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -61,12 +59,17 @@ describe("Waku Store, general", function () { }); it("Query generator for multiple messages", async function () { - await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + totalMsgs, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); + const messages = await processQueriedMessages( waku, [TestDecoder], - DefaultPubsubTopic + TestDecoder.pubsubTopic ); expect(messages?.length).eq(totalMsgs); @@ -84,55 +87,62 @@ describe("Waku Store, general", function () { await nwaku.sendMessage( ServiceNode.toMessageRpcQuery({ payload: utf8ToBytes(testItem["value"]), - contentTopic: TestContentTopic + contentTopic: TestDecoder.contentTopic }), - DefaultPubsubTopic + TestDecoder.pubsubTopic ) ).to.eq(true); await delay(1); // to ensure each timestamp is unique. } - waku = await startAndConnectLightNode(nwaku); const messageCollector = new MessageCollector(nwaku); messageCollector.list = await processQueriedMessages( waku, [TestDecoder], - DefaultPubsubTopic + TestDecoder.pubsubTopic ); // checking that all message sent were retrieved TEST_STRING.forEach((testItem) => { expect( - messageCollector.hasMessage(TestContentTopic, testItem["value"]) + messageCollector.hasMessage(TestDecoder.contentTopic, testItem["value"]) ).to.eq(true); }); }); it("Query generator for multiple messages with multiple decoders", async function () { + const SecondDecoder = createDecoder( + TestDecoder2.contentTopic, + TestDecoder.pubsubTopic + ); + await nwaku.sendMessage( ServiceNode.toMessageRpcQuery({ payload: utf8ToBytes("M1"), - contentTopic: TestContentTopic + contentTopic: TestDecoder.contentTopic }), - DefaultPubsubTopic + TestDecoder.pubsubTopic ); await nwaku.sendMessage( ServiceNode.toMessageRpcQuery({ payload: utf8ToBytes("M2"), - contentTopic: customContentTopic1 + contentTopic: SecondDecoder.contentTopic }), - DefaultPubsubTopic + SecondDecoder.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku); const messageCollector = new MessageCollector(nwaku); messageCollector.list = await processQueriedMessages( waku, - [TestDecoder, secondDecoder], - DefaultPubsubTopic + [TestDecoder, SecondDecoder], + TestDecoder.pubsubTopic + ); + expect(messageCollector.hasMessage(TestDecoder.contentTopic, "M1")).to.eq( + true + ); + expect(messageCollector.hasMessage(SecondDecoder.contentTopic, "M2")).to.eq( + true ); - expect(messageCollector.hasMessage(TestContentTopic, "M1")).to.eq(true); - expect(messageCollector.hasMessage(customContentTopic1, "M2")).to.eq(true); }); it("Query generator for multiple messages with different content topic format", async function () { @@ -143,17 +153,15 @@ describe("Waku Store, general", function () { payload: utf8ToBytes(messageText), contentTopic: testItem["value"] }), - DefaultPubsubTopic + TestDecoder.pubsubTopic ) ).to.eq(true); await delay(1); // to ensure each timestamp is unique. } - waku = await startAndConnectLightNode(nwaku); - for (const testItem of TEST_STRING) { for await (const query of waku.store.queryGenerator([ - createDecoder(testItem["value"]) + createDecoder(testItem["value"], TestDecoder.pubsubTopic) ])) { for await (const msg of query) { expect(equals(msg!.payload, utf8ToBytes(messageText))).to.eq(true); @@ -163,8 +171,12 @@ describe("Waku Store, general", function () { }); it("Callback on promise", async function () { - await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + totalMsgs, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); const messages: IMessage[] = []; await waku.store.queryWithPromiseCallback( @@ -185,8 +197,12 @@ describe("Waku Store, general", function () { }); it("Callback on promise, aborts when callback returns true", async function () { - await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + totalMsgs, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); const desiredMsgs = 14; const messages: IMessage[] = []; @@ -237,33 +253,35 @@ describe("Waku Store, general", function () { const eciesEncoder = createEciesEncoder({ contentTopic: asymTopic, - publicKey + publicKey, + pubsubTopic: TestPubsubTopic1 }); const symEncoder = createSymEncoder({ contentTopic: symTopic, - symKey + symKey, + pubsubTopic: TestPubsubTopic1 }); const otherEncoder = createEciesEncoder({ - contentTopic: TestContentTopic, + contentTopic: TestContentTopic1, + pubsubTopic: TestPubsubTopic1, publicKey: getPublicKey(generatePrivateKey()) }); - const eciesDecoder = createEciesDecoder(asymTopic, privateKey); - const symDecoder = createSymDecoder(symTopic, symKey); + const eciesDecoder = createEciesDecoder( + asymTopic, + privateKey, + TestDecoder.pubsubTopic + ); + const symDecoder = createSymDecoder( + symTopic, + symKey, + TestDecoder.pubsubTopic + ); - waku = await startAndConnectLightNode(nwaku); - waku2 = await startAndConnectLightNode(nwaku); + waku2 = await startAndConnectLightNode(nwaku, TestShardInfo); const nimWakuMultiaddr = await nwaku.getMultiaddrWithId(); - - await Promise.all([ - waku.dial(nimWakuMultiaddr), - waku2.dial(nimWakuMultiaddr) - ]); - - log.info("Waku nodes connected to nwaku"); - - await waitForRemotePeer(waku, [Protocols.LightPush]); + await waku2.dial(nimWakuMultiaddr); log.info("Sending messages using light push"); await Promise.all([ @@ -298,8 +316,12 @@ describe("Waku Store, general", function () { }); it("Ordered callback, aborts when callback returns true", async function () { - await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + totalMsgs, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); const desiredMsgs = 14; const messages: IMessage[] = []; @@ -317,12 +339,17 @@ describe("Waku Store, general", function () { it("Query generator for 2000 messages", async function () { this.timeout(40000); - await sendMessages(nwaku, 2000, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + 2000, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); + const messages = await processQueriedMessages( waku, [TestDecoder], - DefaultPubsubTopic + TestDecoder.pubsubTopic ); expect(messages?.length).eq(2000); diff --git a/packages/tests/tests/store/multiple_pubsub.spec.ts b/packages/tests/tests/store/multiple_pubsub.spec.ts index c4cbc9a1a2..e2f42df56e 100644 --- a/packages/tests/tests/store/multiple_pubsub.spec.ts +++ b/packages/tests/tests/store/multiple_pubsub.spec.ts @@ -3,8 +3,7 @@ import type { ContentTopicInfo, IMessage, LightNode } from "@waku/interfaces"; import { createLightNode, Protocols } from "@waku/sdk"; import { contentTopicToPubsubTopic, - pubsubTopicToSingleShardInfo, - singleShardInfosToShardInfo + pubsubTopicToSingleShardInfo } from "@waku/utils"; import { expect } from "chai"; @@ -18,20 +17,13 @@ import { } from "../../src/index.js"; import { - customContentTopic1, - customContentTopic2, - customDecoder1, - customDecoder2, - customShardedPubsubTopic1, - customShardedPubsubTopic2, - customShardInfo1, - customShardInfo2, processQueriedMessages, + runStoreNodes, sendMessages, sendMessagesAutosharding, - shardInfo1, - shardInfoBothShards, - startAndConnectLightNode, + TestDecoder, + TestDecoder2, + TestShardInfo, totalMsgs } from "./utils.js"; @@ -42,17 +34,7 @@ describe("Waku Store, custom pubsub topic", function () { let nwaku2: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ - store: true, - pubsubTopic: [customShardedPubsubTopic1, customShardedPubsubTopic2], - clusterId: customShardInfo1.clusterId, - relay: true - }); - await nwaku.ensureSubscriptions([ - customShardedPubsubTopic1, - customShardedPubsubTopic2 - ]); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -63,14 +45,14 @@ describe("Waku Store, custom pubsub topic", function () { await sendMessages( nwaku, totalMsgs, - customContentTopic1, - customShardedPubsubTopic1 + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku, [], shardInfo1); + const messages = await processQueriedMessages( waku, - [customDecoder1], - customShardedPubsubTopic1 + [TestDecoder], + TestDecoder.pubsubTopic ); expect(messages?.length).eq(totalMsgs); @@ -87,22 +69,20 @@ describe("Waku Store, custom pubsub topic", function () { await sendMessages( nwaku, totalMsgs, - customContentTopic1, - customShardedPubsubTopic1 + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); await sendMessages( nwaku, totalMsgs, - customContentTopic2, - customShardedPubsubTopic2 + TestDecoder2.contentTopic, + TestDecoder2.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku, [], shardInfoBothShards); - const customMessages = await processQueriedMessages( waku, - [customDecoder1], - customShardedPubsubTopic1 + [TestDecoder], + TestDecoder.pubsubTopic ); expect(customMessages?.length).eq(totalMsgs); const result1 = customMessages?.findIndex((msg) => { @@ -112,8 +92,8 @@ describe("Waku Store, custom pubsub topic", function () { const testMessages = await processQueriedMessages( waku, - [customDecoder2], - customShardedPubsubTopic2 + [TestDecoder2], + TestDecoder2.pubsubTopic ); expect(testMessages?.length).eq(totalMsgs); const result2 = testMessages?.findIndex((msg) => { @@ -129,33 +109,26 @@ describe("Waku Store, custom pubsub topic", function () { nwaku2 = new ServiceNode(makeLogFileName(this) + "2"); await nwaku2.start({ store: true, - pubsubTopic: [customShardedPubsubTopic2], - clusterId: customShardInfo2.clusterId, + pubsubTopic: [TestDecoder2.pubsubTopic], + clusterId: TestShardInfo.clusterId, relay: true }); - await nwaku2.ensureSubscriptions([customShardedPubsubTopic2]); + await nwaku2.ensureSubscriptions([TestDecoder2.pubsubTopic]); const totalMsgs = 10; await sendMessages( nwaku, totalMsgs, - customContentTopic1, - customShardedPubsubTopic1 + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); await sendMessages( nwaku2, totalMsgs, - customContentTopic2, - customShardedPubsubTopic2 + TestDecoder2.contentTopic, + TestDecoder2.pubsubTopic ); - waku = await createLightNode({ - staticNoiseKey: NOISE_KEY_1, - shardInfo: shardInfoBothShards - }); - await waku.start(); - - await waku.dial(await nwaku.getMultiaddrWithId()); await waku.dial(await nwaku2.getMultiaddrWithId()); await waitForRemotePeer(waku, [Protocols.Store]); @@ -168,13 +141,13 @@ describe("Waku Store, custom pubsub topic", function () { ) { customMessages = await processQueriedMessages( waku, - [customDecoder1], - customShardedPubsubTopic1 + [TestDecoder], + TestDecoder.pubsubTopic ); testMessages = await processQueriedMessages( waku, - [customDecoder2], - customShardedPubsubTopic2 + [TestDecoder2], + TestDecoder2.pubsubTopic ); } }); @@ -197,10 +170,6 @@ describe("Waku Store (Autosharding), custom pubsub topic", function () { customContentTopic2, clusterId ); - const contentTopicInfo1: ContentTopicInfo = { - clusterId, - contentTopics: [customContentTopic1] - }; const customDecoder1 = createDecoder( customContentTopic1, pubsubTopicToSingleShardInfo(autoshardingPubsubTopic1) @@ -215,18 +184,7 @@ describe("Waku Store (Autosharding), custom pubsub topic", function () { }; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ - store: true, - pubsubTopic: [autoshardingPubsubTopic1, autoshardingPubsubTopic2], - contentTopic: [customContentTopic1, customContentTopic2], - relay: true, - clusterId - }); - await nwaku.ensureSubscriptionsAutosharding([ - customContentTopic1, - customContentTopic2 - ]); + [nwaku, waku] = await runStoreNodes(this.ctx, contentTopicInfoBothShards); }); afterEachCustom(this, async () => { @@ -235,7 +193,7 @@ describe("Waku Store (Autosharding), custom pubsub topic", function () { it("Generator, custom pubsub topic", async function () { await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic1); - waku = await startAndConnectLightNode(nwaku, [], contentTopicInfo1); + const messages = await processQueriedMessages( waku, [customDecoder1], @@ -256,12 +214,6 @@ describe("Waku Store (Autosharding), custom pubsub topic", function () { await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic1); await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic2); - waku = await startAndConnectLightNode( - nwaku, - [], - contentTopicInfoBothShards - ); - const customMessages = await processQueriedMessages( waku, [customDecoder1], @@ -340,38 +292,8 @@ describe("Waku Store (named sharding), custom pubsub topic", function () { let nwaku: ServiceNode; let nwaku2: ServiceNode; - const customDecoder1 = createDecoder( - customContentTopic1, - customShardedPubsubTopic1 - ); - const customDecoder2 = createDecoder( - customContentTopic2, - customShardedPubsubTopic2 - ); - beforeEachCustom(this, async () => { - const shardInfo = singleShardInfosToShardInfo([ - customShardInfo1, - customShardInfo2 - ]); - - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ - store: true, - relay: true, - pubsubTopic: [customShardedPubsubTopic1, customShardedPubsubTopic2], - clusterId: shardInfo.clusterId - }); - await nwaku.ensureSubscriptions([ - customShardedPubsubTopic1, - customShardedPubsubTopic2 - ]); - - waku = await startAndConnectLightNode( - nwaku, - [customShardedPubsubTopic1, customShardedPubsubTopic2], - shardInfo - ); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -382,14 +304,14 @@ describe("Waku Store (named sharding), custom pubsub topic", function () { await sendMessages( nwaku, totalMsgs, - customContentTopic1, - customShardedPubsubTopic1 + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); const messages = await processQueriedMessages( waku, - [customDecoder1], - customShardedPubsubTopic1 + [TestDecoder], + TestDecoder.pubsubTopic ); expect(messages?.length).eq(totalMsgs); @@ -406,20 +328,20 @@ describe("Waku Store (named sharding), custom pubsub topic", function () { await sendMessages( nwaku, totalMsgs, - customContentTopic1, - customShardedPubsubTopic1 + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); await sendMessages( nwaku, totalMsgs, - customContentTopic2, - customShardedPubsubTopic2 + TestDecoder2.contentTopic, + TestDecoder2.pubsubTopic ); const customMessages = await processQueriedMessages( waku, - [customDecoder1], - customShardedPubsubTopic1 + [TestDecoder], + TestDecoder.pubsubTopic ); expect(customMessages?.length).eq(totalMsgs); const result1 = customMessages?.findIndex((msg) => { @@ -429,8 +351,8 @@ describe("Waku Store (named sharding), custom pubsub topic", function () { const testMessages = await processQueriedMessages( waku, - [customDecoder2], - customShardedPubsubTopic2 + [TestDecoder2], + TestDecoder2.pubsubTopic ); expect(testMessages?.length).eq(totalMsgs); const result2 = testMessages?.findIndex((msg) => { @@ -446,24 +368,24 @@ describe("Waku Store (named sharding), custom pubsub topic", function () { nwaku2 = new ServiceNode(makeLogFileName(this) + "2"); await nwaku2.start({ store: true, - pubsubTopic: [customShardedPubsubTopic2], + pubsubTopic: [TestDecoder2.pubsubTopic], relay: true, - clusterId: customShardInfo2.clusterId + clusterId: TestShardInfo.clusterId }); - await nwaku2.ensureSubscriptions([customShardedPubsubTopic2]); + await nwaku2.ensureSubscriptions([TestDecoder2.pubsubTopic]); const totalMsgs = 10; await sendMessages( nwaku, totalMsgs, - customContentTopic1, - customShardedPubsubTopic1 + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); await sendMessages( nwaku2, totalMsgs, - customContentTopic2, - customShardedPubsubTopic2 + TestDecoder2.contentTopic, + TestDecoder2.pubsubTopic ); await waku.dial(await nwaku2.getMultiaddrWithId()); @@ -478,13 +400,13 @@ describe("Waku Store (named sharding), custom pubsub topic", function () { ) { customMessages = await processQueriedMessages( waku, - [customDecoder1], - customShardedPubsubTopic1 + [TestDecoder], + TestDecoder.pubsubTopic ); testMessages = await processQueriedMessages( waku, - [customDecoder2], - customShardedPubsubTopic2 + [TestDecoder2], + TestDecoder2.pubsubTopic ); } }); diff --git a/packages/tests/tests/store/order.node.spec.ts b/packages/tests/tests/store/order.node.spec.ts index bb83142a33..e99785a2bd 100644 --- a/packages/tests/tests/store/order.node.spec.ts +++ b/packages/tests/tests/store/order.node.spec.ts @@ -1,22 +1,20 @@ import { DecodedMessage, PageDirection } from "@waku/core"; import type { IMessage, LightNode } from "@waku/interfaces"; -import { DefaultPubsubTopic } from "@waku/interfaces"; import { expect } from "chai"; import { afterEachCustom, beforeEachCustom, - makeLogFileName, ServiceNode, tearDownNodes } from "../../src/index.js"; import { chunkAndReverseArray, + runStoreNodes, sendMessages, - startAndConnectLightNode, - TestContentTopic, TestDecoder, + TestShardInfo, totalMsgs } from "./utils.js"; @@ -26,9 +24,7 @@ describe("Waku Store, order", function () { let nwaku: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ store: true, lightpush: true, relay: true }); - await nwaku.ensureSubscriptions(); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -40,10 +36,9 @@ describe("Waku Store, order", function () { await sendMessages( nwaku, totalMsgs, - TestContentTopic, - DefaultPubsubTopic + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku); const messages: IMessage[] = []; for await (const query of waku.store.queryGenerator([TestDecoder], { @@ -72,10 +67,9 @@ describe("Waku Store, order", function () { await sendMessages( nwaku, totalMsgs, - TestContentTopic, - DefaultPubsubTopic + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku); const messages: IMessage[] = []; await waku.store.queryWithPromiseCallback( @@ -107,10 +101,9 @@ describe("Waku Store, order", function () { await sendMessages( nwaku, totalMsgs, - TestContentTopic, - DefaultPubsubTopic + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku); const messages: IMessage[] = []; await waku.store.queryWithOrderedCallback( diff --git a/packages/tests/tests/store/page_size.node.spec.ts b/packages/tests/tests/store/page_size.node.spec.ts index f19e38ea53..fab0185d35 100644 --- a/packages/tests/tests/store/page_size.node.spec.ts +++ b/packages/tests/tests/store/page_size.node.spec.ts @@ -1,20 +1,18 @@ -import { DefaultPubsubTopic } from "@waku/interfaces"; import type { LightNode } from "@waku/interfaces"; import { expect } from "chai"; import { afterEachCustom, beforeEachCustom, - makeLogFileName, ServiceNode, tearDownNodes } from "../../src/index.js"; import { + runStoreNodes, sendMessages, - startAndConnectLightNode, - TestContentTopic, - TestDecoder + TestDecoder, + TestShardInfo } from "./utils.js"; describe("Waku Store, page size", function () { @@ -23,9 +21,7 @@ describe("Waku Store, page size", function () { let nwaku: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ store: true, lightpush: true, relay: true }); - await nwaku.ensureSubscriptions(); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -45,8 +41,8 @@ describe("Waku Store, page size", function () { await sendMessages( nwaku, messageCount, - TestContentTopic, - DefaultPubsubTopic + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); // Determine effectivePageSize for test expectations @@ -61,7 +57,6 @@ describe("Waku Store, page size", function () { } } - waku = await startAndConnectLightNode(nwaku); let messagesRetrieved = 0; for await (const query of waku.store.queryGenerator([TestDecoder], { pageSize: pageSize @@ -86,8 +81,12 @@ describe("Waku Store, page size", function () { // Possible issue here because pageSize differs across implementations it("Default pageSize", async function () { - await sendMessages(nwaku, 20, TestContentTopic, DefaultPubsubTopic); - waku = await startAndConnectLightNode(nwaku); + await sendMessages( + nwaku, + 20, + TestDecoder.contentTopic, + TestDecoder.pubsubTopic + ); let messagesRetrieved = 0; for await (const query of waku.store.queryGenerator([TestDecoder])) { diff --git a/packages/tests/tests/store/sorting.node.spec.ts b/packages/tests/tests/store/sorting.node.spec.ts index aa1e63c60b..e8cc45d59e 100644 --- a/packages/tests/tests/store/sorting.node.spec.ts +++ b/packages/tests/tests/store/sorting.node.spec.ts @@ -1,20 +1,18 @@ import { DecodedMessage, PageDirection } from "@waku/core"; import type { IMessage, LightNode } from "@waku/interfaces"; -import { DefaultPubsubTopic } from "@waku/interfaces"; import { afterEachCustom, beforeEachCustom, - makeLogFileName, ServiceNode, tearDownNodes } from "../../src/index.js"; import { + runStoreNodes, sendMessages, - startAndConnectLightNode, - TestContentTopic, TestDecoder, + TestShardInfo, totalMsgs } from "./utils.js"; @@ -24,9 +22,7 @@ describe("Waku Store, sorting", function () { let nwaku: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ store: true, lightpush: true, relay: true }); - await nwaku.ensureSubscriptions(); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -38,10 +34,9 @@ describe("Waku Store, sorting", function () { await sendMessages( nwaku, totalMsgs, - TestContentTopic, - DefaultPubsubTopic + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku); for await (const query of waku.store.queryGenerator([TestDecoder], { pageDirection: PageDirection.FORWARD @@ -73,10 +68,9 @@ describe("Waku Store, sorting", function () { await sendMessages( nwaku, totalMsgs, - TestContentTopic, - DefaultPubsubTopic + TestDecoder.contentTopic, + TestDecoder.pubsubTopic ); - waku = await startAndConnectLightNode(nwaku); const messages: IMessage[] = []; await waku.store.queryWithOrderedCallback( diff --git a/packages/tests/tests/store/time_filter.node.spec.ts b/packages/tests/tests/store/time_filter.node.spec.ts index 38a6ced612..17687407b0 100644 --- a/packages/tests/tests/store/time_filter.node.spec.ts +++ b/packages/tests/tests/store/time_filter.node.spec.ts @@ -4,16 +4,15 @@ import { expect } from "chai"; import { afterEachCustom, beforeEachCustom, - makeLogFileName, ServiceNode, tearDownNodes } from "../../src/index.js"; import { adjustDate, - startAndConnectLightNode, - TestContentTopic, - TestDecoder + runStoreNodes, + TestDecoder, + TestShardInfo } from "./utils.js"; describe("Waku Store, time filter", function () { @@ -22,9 +21,7 @@ describe("Waku Store, time filter", function () { let nwaku: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ store: true, lightpush: true, relay: true }); - await nwaku.ensureSubscriptions(); + [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -48,14 +45,12 @@ describe("Waku Store, time filter", function () { await nwaku.sendMessage( ServiceNode.toMessageRpcQuery({ payload: new Uint8Array([0]), - contentTopic: TestContentTopic, + contentTopic: TestDecoder.contentTopic, timestamp: msgTimestamp }) ) ).to.eq(true); - waku = await startAndConnectLightNode(nwaku); - const messages: IMessage[] = []; await waku.store.queryWithOrderedCallback( [TestDecoder], @@ -93,14 +88,12 @@ describe("Waku Store, time filter", function () { await nwaku.sendMessage( ServiceNode.toMessageRpcQuery({ payload: new Uint8Array([0]), - contentTopic: TestContentTopic, + contentTopic: TestDecoder.contentTopic, timestamp: msgTimestamp }) ) ).to.eq(true); - waku = await startAndConnectLightNode(nwaku); - const messages: IMessage[] = []; await waku.store.queryWithOrderedCallback( [TestDecoder], diff --git a/packages/tests/tests/store/utils.ts b/packages/tests/tests/store/utils.ts index d1b88161d0..4e7fddb993 100644 --- a/packages/tests/tests/store/utils.ts +++ b/packages/tests/tests/store/utils.ts @@ -2,47 +2,46 @@ import { createDecoder, createEncoder, DecodedMessage, - Decoder, - waitForRemotePeer + Decoder } from "@waku/core"; import { - DefaultPubsubTopic, LightNode, Protocols, ShardInfo, ShardingParams, type SingleShardInfo } from "@waku/interfaces"; -import { createLightNode } from "@waku/sdk"; +import { createLightNode, waitForRemotePeer } from "@waku/sdk"; import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils"; import { expect } from "chai"; +import { Context } from "mocha"; -import { delay, NOISE_KEY_1, ServiceNode } from "../../src"; +import { delay, NOISE_KEY_1, runNodes, ServiceNode } from "../../src"; export const log = new Logger("test:store"); -export const TestContentTopic = "/test/1/waku-store/utf8"; -export const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); -export const TestDecoder = createDecoder(TestContentTopic); -export const customShardInfo1: SingleShardInfo = { clusterId: 3, shard: 1 }; -export const customShardedPubsubTopic1 = - singleShardInfoToPubsubTopic(customShardInfo1); +export const TestClusterId = 3; +export const TestShardInfo: ShardInfo = { + clusterId: TestClusterId, + shards: [1, 2] +}; -export const customShardInfo2: SingleShardInfo = { clusterId: 3, shard: 2 }; -export const customShardedPubsubTopic2 = - singleShardInfoToPubsubTopic(customShardInfo2); -export const shardInfo1: ShardInfo = { clusterId: 3, shards: [1] }; -export const customContentTopic1 = "/test/2/waku-store/utf8"; -export const customContentTopic2 = "/test/3/waku-store/utf8"; -export const customDecoder1 = createDecoder(customContentTopic1, { - clusterId: 3, - shard: 1 +export const TestShardInfo1: SingleShardInfo = { clusterId: 3, shard: 1 }; +export const TestPubsubTopic1 = singleShardInfoToPubsubTopic(TestShardInfo1); + +export const TestShardInfo2: SingleShardInfo = { clusterId: 3, shard: 2 }; +export const TestPubsubTopic2 = singleShardInfoToPubsubTopic(TestShardInfo2); + +export const TestContentTopic1 = "/test/1/waku-store/utf8"; +export const TestEncoder = createEncoder({ + contentTopic: TestContentTopic1, + pubsubTopicShardInfo: TestShardInfo1 }); -export const customDecoder2 = createDecoder(customContentTopic2, { - clusterId: 3, - shard: 2 -}); -export const shardInfoBothShards: ShardInfo = { clusterId: 3, shards: [1, 2] }; +export const TestDecoder = createDecoder(TestContentTopic1, TestPubsubTopic1); + +export const TestContentTopic2 = "/test/3/waku-store/utf8"; +export const TestDecoder2 = createDecoder(TestContentTopic2, TestPubsubTopic2); + export const totalMsgs = 20; export const messageText = "Store Push works!"; @@ -103,17 +102,12 @@ export async function processQueriedMessages( export async function startAndConnectLightNode( instance: ServiceNode, - pubsubTopics: string[] = [DefaultPubsubTopic], - shardInfo?: ShardingParams + shardInfo: ShardingParams ): Promise { const waku = await createLightNode({ - pubsubTopics: shardInfo ? undefined : pubsubTopics, staticNoiseKey: NOISE_KEY_1, libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }, - ...((pubsubTopics.length !== 1 || - pubsubTopics[0] !== DefaultPubsubTopic) && { - shardInfo: shardInfo - }) + shardInfo: shardInfo }); await waku.start(); await waku.dial(await instance.getMultiaddrWithId()); @@ -148,3 +142,14 @@ export const adjustDate = (baseDate: Date, adjustMs: number): Date => { adjusted.setTime(adjusted.getTime() + adjustMs); return adjusted; }; + +export const runStoreNodes = ( + context: Context, + shardInfo: ShardingParams +): Promise<[ServiceNode, LightNode]> => + runNodes({ + context, + shardInfo, + createNode: createLightNode, + protocols: [Protocols.Store] + }); diff --git a/packages/tests/tests/utils.spec.ts b/packages/tests/tests/utils.spec.ts index eb2e6d4a3e..ee2765b199 100644 --- a/packages/tests/tests/utils.spec.ts +++ b/packages/tests/tests/utils.spec.ts @@ -1,10 +1,5 @@ -import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core"; -import { - DefaultPubsubTopic, - type LightNode, - Protocols -} from "@waku/interfaces"; -import { createLightNode } from "@waku/sdk"; +import { createDecoder, createEncoder } from "@waku/core"; +import { type LightNode } from "@waku/interfaces"; import { toAsyncIterator } from "@waku/utils"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import chai, { expect } from "chai"; @@ -14,36 +9,32 @@ import { afterEachCustom, beforeEachCustom, delay, - makeLogFileName, - NOISE_KEY_1, ServiceNode, tearDownNodes } from "../src/index.js"; +import { runNodes } from "./filter/single_node/utils.js"; + chai.use(chaiAsPromised); -const TestContentTopic = "/test/1/waku-filter"; -const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); -const TestDecoder = createDecoder(TestContentTopic); +const TestContentTopic = "/test/1/waku-filter/default"; +const TestShardInfo = { + contentTopics: [TestContentTopic], + clusterId: 3 +}; + +const TestEncoder = createEncoder({ + contentTopic: TestContentTopic, + pubsubTopicShardInfo: TestShardInfo +}); +const TestDecoder = createDecoder(TestContentTopic, TestShardInfo); describe("Util: toAsyncIterator: Filter", function () { let waku: LightNode; let nwaku: ServiceNode; beforeEachCustom(this, async () => { - nwaku = new ServiceNode(makeLogFileName(this.ctx)); - await nwaku.start({ - filter: true, - lightpush: true, - relay: true - }); - waku = await createLightNode({ - staticNoiseKey: NOISE_KEY_1, - libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } } - }); - await waku.start(); - await waku.dial(await nwaku.getMultiaddrWithId()); - await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); + [nwaku, waku] = await runNodes(this.ctx, TestShardInfo); }); afterEachCustom(this, async () => { @@ -63,7 +54,7 @@ describe("Util: toAsyncIterator: Filter", function () { const { value } = await iterator.next(); expect(value.contentTopic).to.eq(TestContentTopic); - expect(value.pubsubTopic).to.eq(DefaultPubsubTopic); + expect(value.pubsubTopic).to.eq(TestDecoder.pubsubTopic); expect(bytesToUtf8(value.payload)).to.eq(messageText); }); diff --git a/packages/tests/tests/wait_for_remote_peer.node.spec.ts b/packages/tests/tests/wait_for_remote_peer.node.spec.ts index c345ea1d40..2e50b036d3 100644 --- a/packages/tests/tests/wait_for_remote_peer.node.spec.ts +++ b/packages/tests/tests/wait_for_remote_peer.node.spec.ts @@ -1,6 +1,6 @@ import { waitForRemotePeer } from "@waku/core"; import type { LightNode, RelayNode } from "@waku/interfaces"; -import { DefaultPubsubTopic, Protocols } from "@waku/interfaces"; +import { Protocols } from "@waku/interfaces"; import { createLightNode } from "@waku/sdk"; import { createRelayNode } from "@waku/sdk/relay"; import { expect } from "chai"; @@ -14,6 +14,12 @@ import { tearDownNodes } from "../src/index.js"; +import { + runRelayNodes, + TestPubsubTopic, + TestShardInfo +} from "./relay/utils.js"; + describe("Wait for remote peer", function () { let waku1: RelayNode; let waku2: LightNode; @@ -25,23 +31,10 @@ describe("Wait for remote peer", function () { it("Relay - dialed first", async function () { this.timeout(20_000); - nwaku = new ServiceNode(makeLogFileName(this)); - await nwaku.start({ - relay: true, - store: false, - filter: false, - lightpush: false - }); + [nwaku, waku1] = await runRelayNodes(this, TestShardInfo); const multiAddrWithId = await nwaku.getMultiaddrWithId(); - waku1 = await createRelayNode({ - staticNoiseKey: NOISE_KEY_1 - }); - await waku1.start(); - await waku1.dial(multiAddrWithId); - await delay(1000); - await waitForRemotePeer(waku1, [Protocols.Relay]); - const peers = waku1.relay.getMeshPeers(DefaultPubsubTopic); + const peers = waku1.relay.getMeshPeers(TestPubsubTopic); const nimPeerId = multiAddrWithId.getPeerId(); expect(nimPeerId).to.not.be.undefined; @@ -252,23 +245,10 @@ describe("Wait for remote peer", function () { it("Privacy Node - default protocol", async function () { this.timeout(20_000); - nwaku = new ServiceNode(makeLogFileName(this)); - await nwaku.start({ - filter: false, - lightpush: false, - relay: true, - store: false - }); + [nwaku, waku1] = await runRelayNodes(this, TestShardInfo); const multiAddrWithId = await nwaku.getMultiaddrWithId(); - waku1 = await createRelayNode({ - staticNoiseKey: NOISE_KEY_1 - }); - await waku1.start(); - await waku1.dial(multiAddrWithId); - await waitForRemotePeer(waku1); - - const peers = waku1.relay.getMeshPeers(DefaultPubsubTopic); + const peers = waku1.relay.getMeshPeers(TestPubsubTopic); const nimPeerId = multiAddrWithId.getPeerId(); diff --git a/packages/utils/src/common/sharding.spec.ts b/packages/utils/src/common/sharding.spec.ts index cc5ea223ca..8e4e10e00f 100644 --- a/packages/utils/src/common/sharding.spec.ts +++ b/packages/utils/src/common/sharding.spec.ts @@ -1,4 +1,4 @@ -import { DEFAULT_CLUSTER_ID, DefaultPubsubTopic } from "@waku/interfaces"; +import { DEFAULT_CLUSTER_ID } from "@waku/interfaces"; import { expect } from "chai"; import { @@ -404,7 +404,7 @@ describe("determinePubsubTopic", () => { }); it("should fall back to default pubsub topic when pubsubTopicShardInfo is not provided", () => { - expect(determinePubsubTopic(contentTopic)).to.equal(DefaultPubsubTopic); + expect(determinePubsubTopic(contentTopic)).to.equal("/waku/2/rs/1/6"); }); it("should process correctly when SingleShardInfo has no clusterId but has a shard", () => { diff --git a/packages/utils/src/common/sharding.ts b/packages/utils/src/common/sharding.ts index 79be1e6d36..a542721b0c 100644 --- a/packages/utils/src/common/sharding.ts +++ b/packages/utils/src/common/sharding.ts @@ -1,7 +1,6 @@ import { sha256 } from "@noble/hashes/sha256"; import { DEFAULT_CLUSTER_ID, - DefaultPubsubTopic, PubsubTopic, ShardInfo, ShardingParams, @@ -190,6 +189,10 @@ export function contentTopicToPubsubTopic( clusterId: number = DEFAULT_CLUSTER_ID, networkShards: number = 8 ): string { + if (!contentTopic) { + throw Error("Content topic must be specified"); + } + const shardIndex = contentTopicToShardIndex(contentTopic, networkShards); return `/waku/2/rs/${clusterId}/${shardIndex}`; } @@ -225,20 +228,18 @@ export function contentTopicsByPubsubTopic( */ export function determinePubsubTopic( contentTopic: string, - pubsubTopicShardInfo: SingleShardInfo | PubsubTopic = DefaultPubsubTopic + pubsubTopicShardInfo?: SingleShardInfo | PubsubTopic ): string { if (typeof pubsubTopicShardInfo == "string") { return pubsubTopicShardInfo; - } else { - return pubsubTopicShardInfo - ? pubsubTopicShardInfo.shard !== undefined - ? singleShardInfoToPubsubTopic(pubsubTopicShardInfo) - : contentTopicToPubsubTopic( - contentTopic, - pubsubTopicShardInfo.clusterId - ) - : DefaultPubsubTopic; } + + return pubsubTopicShardInfo?.shard !== undefined + ? singleShardInfoToPubsubTopic(pubsubTopicShardInfo) + : contentTopicToPubsubTopic( + contentTopic, + pubsubTopicShardInfo?.clusterId ?? DEFAULT_CLUSTER_ID + ); } /**