feat!: use ShardingParams on subscriptions, make Decoder/Encoder auto sharding friendly by default (#1958)

* fix: use pubsubTopic from current ones if not set

* fix: improve type on dial method

* enforce same pubusb on filter.subscribe, make content topic to pubsub mapping default for decoder / encoder

* fix mapping problem

* update tests

* add error handling

* fix typo

* up lock

* rm lock

* up lock

* remove only

* fix content topic

* fix ephemeral test

* fix filter unsubscribe test

* up utils

* fix subscribe test

* up interfaces and filter api

* remove only

* up ping test

* fix subscribe test

* fix push test

* fix lightPush

* fix multiple pubsub

* remove only, fix subscribe filter test

* remove only

* fix cluster ID selection and named sharding subscription test

* fix unsubscribe test

* fix light push test

* fix light push test

* fix push test

* fix relay publish

* create runNode and fix relay tests

* generalize runNodes, fix some tests

* fix store tests

* fix toAsyncIterator tests

* remove only

* fix lightPush

* use generics

* try fix test

* run failing tests

* remove only

* address failed tests, remove DefaultPubsubTopic dependency in some tests
This commit is contained in:
Sasha 2024-04-28 11:15:17 +02:00 committed by GitHub
parent 86249dfe29
commit f3627c46a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 1475 additions and 1354 deletions

View File

@ -1,17 +1,17 @@
import type { IProtoMessage } from "@waku/interfaces"; import type { IProtoMessage } from "@waku/interfaces";
import { contentTopicToPubsubTopic } from "@waku/utils";
import { expect } from "chai"; import { expect } from "chai";
import fc from "fast-check"; import fc from "fast-check";
import { createDecoder, createEncoder, DecodedMessage } from "./version_0.js"; 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 () { describe("Waku Message version 0", function () {
it("Round trip binary serialization", async function () { it("Round trip binary serialization", async function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(fc.uint8Array({ minLength: 1 }), async (payload) => {
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ minLength: 1 }),
async (contentTopic, pubsubTopic, payload) => {
const encoder = createEncoder({ const encoder = createEncoder({
contentTopic contentTopic
}); });
@ -29,18 +29,13 @@ describe("Waku Message version 0", function () {
expect(result.ephemeral).to.be.false; expect(result.ephemeral).to.be.false;
expect(result.payload).to.deep.eq(payload); expect(result.payload).to.deep.eq(payload);
expect(result.timestamp).to.not.be.undefined; expect(result.timestamp).to.not.be.undefined;
} })
)
); );
}); });
it("Ephemeral field set to true", async function () { it("Ephemeral field set to true", async function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(fc.uint8Array({ minLength: 1 }), async (payload) => {
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ minLength: 1 }),
async (contentTopic, pubsubTopic, payload) => {
const encoder = createEncoder({ const encoder = createEncoder({
contentTopic, contentTopic,
ephemeral: true ephemeral: true
@ -54,18 +49,13 @@ describe("Waku Message version 0", function () {
)) as DecodedMessage; )) as DecodedMessage;
expect(result.ephemeral).to.be.true; expect(result.ephemeral).to.be.true;
} })
)
); );
}); });
it("Meta field set when metaSetter is specified", async function () { it("Meta field set when metaSetter is specified", async function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(fc.uint8Array({ minLength: 1 }), async (payload) => {
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ minLength: 1 }),
async (contentTopic, pubsubTopic, payload) => {
// Encode the length of the payload // Encode the length of the payload
// Not a relevant real life example // Not a relevant real life example
const metaSetter = ( const metaSetter = (
@ -101,8 +91,7 @@ describe("Waku Message version 0", function () {
}); });
expect(result.meta).to.deep.eq(expectedMeta); expect(result.meta).to.deep.eq(expectedMeta);
} })
)
); );
}); });
}); });

View File

@ -1,11 +1,10 @@
import type { PeerId } from "@libp2p/interface"; import type { IDecodedMessage, IDecoder } from "./message.js";
import type { IDecodedMessage, IDecoder, SingleShardInfo } from "./message.js";
import type { ContentTopic, PubsubTopic } from "./misc.js"; import type { ContentTopic, PubsubTopic } from "./misc.js";
import type { import type {
Callback, Callback,
IBaseProtocolCore, IBaseProtocolCore,
IBaseProtocolSDK IBaseProtocolSDK,
ShardingParams
} from "./protocols.js"; } from "./protocols.js";
import type { IReceiver } from "./receiver.js"; import type { IReceiver } from "./receiver.js";
@ -31,7 +30,6 @@ export type IFilter = IReceiver & IBaseProtocolCore;
export type IFilterSDK = IReceiver & export type IFilterSDK = IReceiver &
IBaseProtocolSDK & { protocol: IBaseProtocolCore } & { IBaseProtocolSDK & { protocol: IBaseProtocolCore } & {
createSubscription( createSubscription(
pubsubTopicShardInfo?: SingleShardInfo | PubsubTopic, pubsubTopicShardInfo?: ShardingParams | PubsubTopic
peerId?: PeerId
): Promise<IFilterSubscription>; ): Promise<IFilterSubscription>;
}; };

View File

@ -29,7 +29,7 @@ export type IBaseProtocolSDK = {
}; };
export type ContentTopicInfo = { export type ContentTopicInfo = {
clusterId: number; clusterId?: number;
contentTopics: string[]; contentTopics: string[];
}; };

View File

@ -1,5 +1,5 @@
import type { PeerId, Stream } from "@libp2p/interface"; 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 { IConnectionManager } from "./connection_manager.js";
import type { IFilterSDK } from "./filter.js"; import type { IFilterSDK } from "./filter.js";
@ -18,7 +18,7 @@ export interface Waku {
connectionManager: IConnectionManager; connectionManager: IConnectionManager;
dial(peer: PeerId | Multiaddr, protocols?: Protocols[]): Promise<Stream>; dial(peer: PeerId | MultiaddrInput, protocols?: Protocols[]): Promise<Stream>;
start(): Promise<void>; start(): Promise<void>;

View File

@ -1,20 +1,22 @@
import { IProtoMessage } from "@waku/interfaces"; import { IProtoMessage } from "@waku/interfaces";
import { contentTopicToPubsubTopic } from "@waku/utils";
import { expect } from "chai"; import { expect } from "chai";
import fc from "fast-check"; import fc from "fast-check";
import { getPublicKey } from "./crypto/index.js"; import { getPublicKey } from "./crypto/index.js";
import { createDecoder, createEncoder } from "./ecies.js"; import { createDecoder, createEncoder } from "./ecies.js";
const contentTopic = "/js-waku/1/tests/bytes";
const pubsubTopic = contentTopicToPubsubTopic(contentTopic);
describe("Ecies Encryption", function () { describe("Ecies Encryption", function () {
this.timeout(20000); this.timeout(20000);
it("Round trip binary encryption [ecies, no signature]", async function () { it("Round trip binary encryption [ecies, no signature]", async function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ 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, privateKey) => { async (payload, privateKey) => {
const publicKey = getPublicKey(privateKey); const publicKey = getPublicKey(privateKey);
const encoder = createEncoder({ const encoder = createEncoder({
@ -46,18 +48,10 @@ describe("Ecies Encryption", function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ minLength: 1 }), fc.uint8Array({ minLength: 1 }),
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
async ( async (payload, alicePrivateKey, bobPrivateKey) => {
pubsubTopic,
contentTopic,
payload,
alicePrivateKey,
bobPrivateKey
) => {
const alicePublicKey = getPublicKey(alicePrivateKey); const alicePublicKey = getPublicKey(alicePrivateKey);
const bobPublicKey = getPublicKey(bobPrivateKey); const bobPublicKey = getPublicKey(bobPrivateKey);
@ -89,11 +83,9 @@ describe("Ecies Encryption", function () {
it("Check meta is set [ecies]", async function () { it("Check meta is set [ecies]", async function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ 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, privateKey) => { async (payload, privateKey) => {
const publicKey = getPublicKey(privateKey); const publicKey = getPublicKey(privateKey);
const metaSetter = ( const metaSetter = (
msg: IProtoMessage & { meta: undefined } msg: IProtoMessage & { meta: undefined }

View File

@ -1,7 +1,6 @@
import { Decoder as DecoderV0 } from "@waku/core/lib/message/version_0"; import { Decoder as DecoderV0 } from "@waku/core/lib/message/version_0";
import { import {
type EncoderOptions as BaseEncoderOptions, type EncoderOptions as BaseEncoderOptions,
DefaultPubsubTopic,
type IDecoder, type IDecoder,
type IEncoder, type IEncoder,
type IMessage, type IMessage,
@ -200,7 +199,7 @@ class Decoder extends DecoderV0 implements IDecoder<DecodedMessage> {
export function createDecoder( export function createDecoder(
contentTopic: string, contentTopic: string,
privateKey: Uint8Array, privateKey: Uint8Array,
pubsubTopicShardInfo: SingleShardInfo | PubsubTopic = DefaultPubsubTopic pubsubTopicShardInfo?: SingleShardInfo | PubsubTopic
): Decoder { ): Decoder {
return new Decoder( return new Decoder(
determinePubsubTopic(contentTopic, pubsubTopicShardInfo), determinePubsubTopic(contentTopic, pubsubTopicShardInfo),

View File

@ -1,19 +1,21 @@
import { IProtoMessage } from "@waku/interfaces"; import { IProtoMessage } from "@waku/interfaces";
import { contentTopicToPubsubTopic } from "@waku/utils";
import { expect } from "chai"; import { expect } from "chai";
import fc from "fast-check"; import fc from "fast-check";
import { getPublicKey } from "./crypto/index.js"; import { getPublicKey } from "./crypto/index.js";
import { createDecoder, createEncoder } from "./symmetric.js"; import { createDecoder, createEncoder } from "./symmetric.js";
const contentTopic = "/js-waku/1/tests/bytes";
const pubsubTopic = contentTopicToPubsubTopic(contentTopic);
describe("Symmetric Encryption", function () { describe("Symmetric Encryption", function () {
it("Round trip binary encryption [symmetric, no signature]", async function () { it("Round trip binary encryption [symmetric, no signature]", async function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ 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, symKey) => { async (payload, symKey) => {
const encoder = createEncoder({ const encoder = createEncoder({
contentTopic, contentTopic,
symKey symKey
@ -41,12 +43,10 @@ describe("Symmetric Encryption", function () {
it("Round trip binary encryption [symmetric, signature]", async function () { it("Round trip binary encryption [symmetric, signature]", async function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ minLength: 1 }), fc.uint8Array({ minLength: 1 }),
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }), fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
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 sigPubKey = getPublicKey(sigPrivKey);
const encoder = createEncoder({ const encoder = createEncoder({
@ -77,11 +77,9 @@ describe("Symmetric Encryption", function () {
it("Check meta is set [symmetric]", async function () { it("Check meta is set [symmetric]", async function () {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.uint8Array({ 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, symKey) => { async (payload, symKey) => {
const metaSetter = ( const metaSetter = (
msg: IProtoMessage & { meta: undefined } msg: IProtoMessage & { meta: undefined }
): Uint8Array => { ): Uint8Array => {

View File

@ -2,57 +2,55 @@ import { TopicValidatorResult } from "@libp2p/interface";
import type { UnsignedMessage } from "@libp2p/interface"; import type { UnsignedMessage } from "@libp2p/interface";
import { createSecp256k1PeerId } from "@libp2p/peer-id-factory"; import { createSecp256k1PeerId } from "@libp2p/peer-id-factory";
import { createEncoder } from "@waku/core"; import { createEncoder } from "@waku/core";
import { determinePubsubTopic } from "@waku/utils";
import { expect } from "chai"; import { expect } from "chai";
import fc from "fast-check"; import fc from "fast-check";
import { messageValidator } from "./message_validator.js"; import { messageValidator } from "./message_validator.js";
const TestContentTopic = "/app/1/topic/utf8";
const TestPubsubTopic = determinePubsubTopic(TestContentTopic);
describe("Message Validator", () => { describe("Message Validator", () => {
it("Accepts a valid Waku Message", async () => { it("Accepts a valid Waku Message", async () => {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(fc.uint8Array({ minLength: 1 }), async (payload) => {
fc.uint8Array({ minLength: 1 }),
fc.string({ minLength: 1 }),
fc.string({ minLength: 1 }),
async (payload, pubsubTopic, contentTopic) => {
const peerId = await createSecp256k1PeerId(); const peerId = await createSecp256k1PeerId();
const encoder = createEncoder({ contentTopic }); const encoder = createEncoder({
contentTopic: TestContentTopic,
pubsubTopic: TestPubsubTopic
});
const bytes = await encoder.toWire({ payload }); const bytes = await encoder.toWire({ payload });
const message: UnsignedMessage = { const message: UnsignedMessage = {
type: "unsigned", type: "unsigned",
topic: pubsubTopic, topic: TestPubsubTopic,
data: bytes 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 () => { it("Rejects garbage", async () => {
await fc.assert( await fc.assert(
fc.asyncProperty( fc.asyncProperty(fc.uint8Array(), async (data) => {
fc.uint8Array(),
fc.string(),
async (data, pubsubTopic) => {
const peerId = await createSecp256k1PeerId(); const peerId = await createSecp256k1PeerId();
const message: UnsignedMessage = { const message: UnsignedMessage = {
type: "unsigned", type: "unsigned",
topic: pubsubTopic, topic: TestPubsubTopic,
data data
}; };
const result = messageValidator(peerId, message); const result = messageValidator(peerId, message);
expect(result).to.eq(TopicValidatorResult.Reject); expect(result).to.eq(TopicValidatorResult.Reject);
} })
)
); );
}); });
}); });

View File

@ -1,19 +1,18 @@
import type { Peer } from "@libp2p/interface"; import type { Peer } from "@libp2p/interface";
import { FilterCore } from "@waku/core"; import { FilterCore } from "@waku/core";
import { import type {
type Callback, Callback,
ContentTopic, ContentTopic,
DefaultPubsubTopic, IAsyncIterator,
type IAsyncIterator, IDecodedMessage,
type IDecodedMessage, IDecoder,
type IDecoder, IFilterSDK,
type IFilterSDK,
IProtoMessage, IProtoMessage,
type Libp2p, Libp2p,
type ProtocolCreateOptions, ProtocolCreateOptions,
type PubsubTopic, PubsubTopic,
type SingleShardInfo, ShardingParams,
type Unsubscribe Unsubscribe
} from "@waku/interfaces"; } from "@waku/interfaces";
import { messageHashStr } from "@waku/message-hash"; import { messageHashStr } from "@waku/message-hash";
import { WakuMessage } from "@waku/proto"; import { WakuMessage } from "@waku/proto";
@ -21,7 +20,7 @@ import {
ensurePubsubTopicIsConfigured, ensurePubsubTopicIsConfigured,
groupByContentTopic, groupByContentTopic,
Logger, Logger,
singleShardInfoToPubsubTopic, shardInfoToPubsubTopics,
toAsyncIterator toAsyncIterator
} from "@waku/utils"; } from "@waku/utils";
@ -245,12 +244,12 @@ class FilterSDK extends BaseProtocolSDK implements IFilterSDK {
* @returns The subscription object. * @returns The subscription object.
*/ */
async createSubscription( async createSubscription(
pubsubTopicShardInfo: SingleShardInfo | PubsubTopic = DefaultPubsubTopic pubsubTopicShardInfo: ShardingParams | PubsubTopic
): Promise<SubscriptionManager> { ): Promise<SubscriptionManager> {
const pubsubTopic = const pubsubTopic =
typeof pubsubTopicShardInfo == "string" typeof pubsubTopicShardInfo == "string"
? pubsubTopicShardInfo ? pubsubTopicShardInfo
: singleShardInfoToPubsubTopic(pubsubTopicShardInfo); : shardInfoToPubsubTopics(pubsubTopicShardInfo)?.[0];
ensurePubsubTopicIsConfigured(pubsubTopic, this.protocol.pubsubTopics); ensurePubsubTopicIsConfigured(pubsubTopic, this.protocol.pubsubTopics);
@ -294,7 +293,21 @@ class FilterSDK extends BaseProtocolSDK implements IFilterSDK {
decoders: IDecoder<T> | IDecoder<T>[], decoders: IDecoder<T> | IDecoder<T>[],
callback: Callback<T> callback: Callback<T>
): Promise<Unsubscribe> { ): Promise<Unsubscribe> {
const subscription = await this.createSubscription(); const pubsubTopics = this.getPubsubTopics<T>(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); await subscription.subscribe(decoders, callback);
@ -314,6 +327,22 @@ class FilterSDK extends BaseProtocolSDK implements IFilterSDK {
): Promise<IAsyncIterator<T>> { ): Promise<IAsyncIterator<T>> {
return toAsyncIterator(this, decoders); return toAsyncIterator(this, decoders);
} }
private getPubsubTopics<T extends IDecodedMessage>(
decoders: IDecoder<T> | IDecoder<T>[]
): 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( export function wakuFilter(

View File

@ -2,7 +2,6 @@ import { DecodedMessage } from "@waku/core";
import { import {
DefaultPubsubTopic, DefaultPubsubTopic,
PubsubTopic, PubsubTopic,
ShardInfo,
ShardingParams ShardingParams
} from "@waku/interfaces"; } from "@waku/interfaces";
import { ensureShardingConfigured, Logger } from "@waku/utils"; import { ensureShardingConfigured, Logger } from "@waku/utils";
@ -12,9 +11,11 @@ import { Args, MessageRpcQuery, MessageRpcResponse } from "../types";
import { delay, makeLogFileName } from "../utils/index.js"; import { delay, makeLogFileName } from "../utils/index.js";
import { MessageCollector } from "./message_collector.js"; import { MessageCollector } from "./message_collector.js";
import { runNodes } from "./runNodes.js";
import { defaultArgs, ServiceNode } from "./service_node.js"; import { defaultArgs, ServiceNode } from "./service_node.js";
export { ServiceNode, MessageCollector, defaultArgs }; export { ServiceNode, MessageCollector, defaultArgs };
export { runNodes };
const log = new Logger("test:message-collector"); const log = new Logger("test:message-collector");
@ -28,7 +29,7 @@ export class ServiceNodesFleet {
pubsubTopics: PubsubTopic[], pubsubTopics: PubsubTopic[],
nodesToCreate: number = 3, nodesToCreate: number = 3,
strictChecking: boolean = false, strictChecking: boolean = false,
shardInfo?: ShardInfo, shardInfo?: ShardingParams,
_args?: Args, _args?: Args,
withoutFilter = false withoutFilter = false
): Promise<ServiceNodesFleet> { ): Promise<ServiceNodesFleet> {

View File

@ -73,7 +73,7 @@ export class MessageCollector {
} }
): Promise<boolean> { ): Promise<boolean> {
const startTime = Date.now(); const startTime = Date.now();
const pubsubTopic = options?.pubsubTopic || DefaultPubsubTopic; const pubsubTopic = this.getPubsubTopicToUse(options?.pubsubTopic);
const timeoutDuration = options?.timeoutDuration || 400; const timeoutDuration = options?.timeoutDuration || 400;
const exact = options?.exact || false; const exact = options?.exact || false;
@ -237,12 +237,13 @@ export class MessageCollector {
`Message text mismatch. Expected: ${options.expectedMessageText}. Got: ${receivedMessageText}` `Message text mismatch. Expected: ${options.expectedMessageText}. Got: ${receivedMessageText}`
); );
} else { } else {
const pubsubTopicToUse = this.getPubsubTopicToUse(
options.expectedPubsubTopic
);
// js-waku message specific assertions // js-waku message specific assertions
expect(message.pubsubTopic).to.eq( expect(message.pubsubTopic).to.eq(
options.expectedPubsubTopic || DefaultPubsubTopic, pubsubTopicToUse,
`Message pub/sub topic mismatch. Expected: ${ `Message pub/sub topic mismatch. Expected: ${pubsubTopicToUse}. Got: ${message.pubsubTopic}`
options.expectedPubsubTopic || DefaultPubsubTopic
}. Got: ${message.pubsubTopic}`
); );
expect(bytesToUtf8(message.payload)).to.eq( 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;
}
} }

View File

@ -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<T>(
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");
}
}

View File

@ -48,6 +48,7 @@ export class ServiceNode {
private websocketPort?: number; private websocketPort?: number;
private readonly logPath: string; private readonly logPath: string;
private restPort?: number; private restPort?: number;
private args?: Args;
/** /**
* Convert a [[WakuMessage]] to a [[WakuRelayMessage]]. The latter is used * Convert a [[WakuMessage]] to a [[WakuRelayMessage]]. The latter is used
@ -166,6 +167,8 @@ export class ServiceNode {
this.logPath, this.logPath,
WAKU_SERVICE_NODE_PARAMS WAKU_SERVICE_NODE_PARAMS
); );
this.args = mergedArgs;
} catch (error) { } catch (error) {
log.error("Nwaku node failed to start:", error); log.error("Nwaku node failed to start:", error);
await this.stop(); await this.stop();
@ -237,11 +240,9 @@ export class ServiceNode {
); );
} }
async messages( async messages(pubsubTopic?: string): Promise<MessageRpcResponse[]> {
pubsubTopic: string = DefaultPubsubTopic
): Promise<MessageRpcResponse[]> {
return this.restCall<MessageRpcResponse[]>( return this.restCall<MessageRpcResponse[]>(
`/relay/v1/messages/${encodeURIComponent(pubsubTopic)}`, `/relay/v1/messages/${encodeURIComponent(pubsubTopic || this?.args?.pubsubTopic?.[0] || DefaultPubsubTopic)}`,
"GET", "GET",
null, null,
async (response) => { async (response) => {
@ -266,7 +267,7 @@ export class ServiceNode {
async sendMessage( async sendMessage(
message: MessageRpcQuery, message: MessageRpcQuery,
pubsubTopic: string = DefaultPubsubTopic pubsubTopic?: string
): Promise<boolean> { ): Promise<boolean> {
this.checkProcess(); this.checkProcess();
@ -275,7 +276,7 @@ export class ServiceNode {
} }
return this.restCall<boolean>( return this.restCall<boolean>(
`/relay/v1/messages/${encodeURIComponent(pubsubTopic)}`, `/relay/v1/messages/${encodeURIComponent(pubsubTopic || this.args?.pubsubTopic?.[0] || DefaultPubsubTopic)}`,
"POST", "POST",
message, message,
async (response) => response.status === 200 async (response) => response.status === 200
@ -350,6 +351,10 @@ export class ServiceNode {
return `http://127.0.0.1:${this.restPort}`; return `http://127.0.0.1:${this.restPort}`;
} }
get pubsubTopics(): string[] {
return this.args?.pubsubTopic ?? [];
}
async restCall<T>( async restCall<T>(
endpoint: string, endpoint: string,
method: "GET" | "POST", method: "GET" | "POST",

View File

@ -1,19 +1,28 @@
import { createDecoder, createEncoder, Decoder, Encoder } from "@waku/core"; import { createDecoder, createEncoder, Decoder, Encoder } from "@waku/core";
type TestDataOptions = {
pubsubTopic: string;
};
// Utility to generate test data for multiple topics tests. // Utility to generate test data for multiple topics tests.
export function generateTestData(topicCount: number): { export function generateTestData(
topicCount: number,
options?: TestDataOptions
): {
contentTopics: string[]; contentTopics: string[];
encoders: Encoder[]; encoders: Encoder[];
decoders: Decoder[]; decoders: Decoder[];
} { } {
const contentTopics = Array.from( const contentTopics = Array.from(
{ length: topicCount }, { length: topicCount },
(_, i) => `/test/${i + 1}/waku-multi` (_, i) => `/test/${i + 1}/waku-multi/default`
); );
const encoders = contentTopics.map((topic) => 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 { return {
contentTopics, contentTopics,
encoders, encoders,

View File

@ -87,7 +87,7 @@ describe("Connection state", function () {
expect(eventCount).to.be.eq(1); 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({ const waku1 = await createRelayNode({
staticNoiseKey: NOISE_KEY_1 staticNoiseKey: NOISE_KEY_1
}); });
@ -159,7 +159,7 @@ describe("Connection state", function () {
expect(waku.isConnected()).to.be.false; 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({ const waku1 = await createRelayNode({
staticNoiseKey: NOISE_KEY_1 staticNoiseKey: NOISE_KEY_1
}); });

View File

@ -12,15 +12,15 @@ import {
getPublicKey getPublicKey
} from "@waku/message-encryption"; } from "@waku/message-encryption";
import { import {
createDecoder as eciesDecoder, createDecoder as createEciesDecoder,
createEncoder as eciesEncoder createEncoder as createEciesEncoder
} from "@waku/message-encryption/ecies"; } from "@waku/message-encryption/ecies";
import { import {
createDecoder as symDecoder, createDecoder as createSymDecoder,
createEncoder as symEncoder createEncoder as createSymEncoder
} from "@waku/message-encryption/symmetric"; } from "@waku/message-encryption/symmetric";
import { createLightNode } from "@waku/sdk"; import { createLightNode } from "@waku/sdk";
import { Logger } from "@waku/utils"; import { contentTopicToPubsubTopic, Logger } from "@waku/utils";
import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes";
import { expect } from "chai"; import { expect } from "chai";
@ -37,11 +37,47 @@ import {
const log = new Logger("test:ephemeral"); const log = new Logger("test:ephemeral");
const ClusterId = 2;
const TestContentTopic = "/test/1/ephemeral/utf8"; const TestContentTopic = "/test/1/ephemeral/utf8";
const PubsubTopic = contentTopicToPubsubTopic(TestContentTopic, ClusterId);
const TestEncoder = createEncoder({ 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 () { describe("Waku Message Ephemeral field", function () {
let waku: LightNode; let waku: LightNode;
@ -59,11 +95,24 @@ describe("Waku Message Ephemeral field", function () {
filter: true, filter: true,
lightpush: true, lightpush: true,
store: true, store: true,
relay: true relay: true,
pubsubTopic: [PubsubTopic],
contentTopic: [TestContentTopic, AsymContentTopic, SymContentTopic],
clusterId: ClusterId
}); });
await nwaku.ensureSubscriptionsAutosharding([
TestContentTopic,
AsymContentTopic,
SymContentTopic
]);
waku = await createLightNode({ waku = await createLightNode({
staticNoiseKey: NOISE_KEY_1, 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.start();
await waku.dial(await nwaku.getMultiaddrWithId()); await waku.dial(await nwaku.getMultiaddrWithId());
@ -74,7 +123,9 @@ describe("Waku Message Ephemeral field", function () {
Protocols.Store Protocols.Store
]); ]);
subscription = await waku.filter.createSubscription(); subscription = await waku.filter.createSubscription(
TestEncoder.pubsubTopic
);
}); });
it("Ephemeral messages are not stored", async function () { it("Ephemeral messages are not stored", async function () {
@ -94,37 +145,20 @@ describe("Waku Message Ephemeral field", function () {
payload: utf8ToBytes(clearText) 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([ const [waku1, waku2, nimWakuMultiaddr] = await Promise.all([
createLightNode({ createLightNode({
staticNoiseKey: NOISE_KEY_1 staticNoiseKey: NOISE_KEY_1,
shardInfo: {
contentTopics: [TestContentTopic, AsymContentTopic, SymContentTopic],
clusterId: ClusterId
}
}).then((waku) => waku.start().then(() => waku)), }).then((waku) => waku.start().then(() => waku)),
createLightNode({ createLightNode({
staticNoiseKey: NOISE_KEY_2 staticNoiseKey: NOISE_KEY_2,
shardInfo: {
contentTopics: [TestContentTopic, AsymContentTopic, SymContentTopic],
clusterId: ClusterId
}
}).then((waku) => waku.start().then(() => waku)), }).then((waku) => waku.start().then(() => waku)),
nwaku.getMultiaddrWithId() nwaku.getMultiaddrWithId()
]); ]);
@ -142,9 +176,9 @@ describe("Waku Message Ephemeral field", function () {
log.info("Sending messages using light push"); log.info("Sending messages using light push");
await Promise.all([ await Promise.all([
waku1.lightPush.send(asymEncoder, asymMsg), waku1.lightPush.send(AsymEncoder, asymMsg),
waku1.lightPush.send(symEncoder, symMsg), waku1.lightPush.send(SymEncoder, symMsg),
waku1.lightPush.send(clearEncoder, clearMsg) waku1.lightPush.send(ClearEncoder, clearMsg)
]); ]);
await waitForRemotePeer(waku2, [Protocols.Store]); await waitForRemotePeer(waku2, [Protocols.Store]);
@ -153,8 +187,8 @@ describe("Waku Message Ephemeral field", function () {
log.info("Retrieving messages from store"); log.info("Retrieving messages from store");
for await (const msgPromises of waku2.store.queryGenerator([ for await (const msgPromises of waku2.store.queryGenerator([
asymDecoder, AsymDecoder,
symDecoder, SymDecoder,
TestDecoder TestDecoder
])) { ])) {
for (const promise of msgPromises) { for (const promise of msgPromises) {
@ -175,7 +209,8 @@ describe("Waku Message Ephemeral field", function () {
const ephemeralEncoder = createEncoder({ const ephemeralEncoder = createEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
ephemeral: true ephemeral: true,
pubsubTopic: PubsubTopic
}); });
const messages: DecodedMessage[] = []; const messages: DecodedMessage[] = [];
@ -187,12 +222,16 @@ describe("Waku Message Ephemeral field", function () {
await delay(200); await delay(200);
const normalTxt = "Normal message"; const normalTxt = "Normal message";
const ephemeralTxt = "Ephemeral Message"; const ephemeralTxt = "Ephemeral Message";
await waku.lightPush.send(TestEncoder, {
await Promise.all([
waku.lightPush.send(TestEncoder, {
payload: utf8ToBytes(normalTxt) payload: utf8ToBytes(normalTxt)
}); }),
await waku.lightPush.send(ephemeralEncoder, { waku.lightPush.send(ephemeralEncoder, {
payload: utf8ToBytes(ephemeralTxt) payload: utf8ToBytes(ephemeralTxt)
}); })
]);
while (messages.length < 2) { while (messages.length < 2) {
await delay(250); await delay(250);
} }
@ -214,18 +253,12 @@ describe("Waku Message Ephemeral field", function () {
it("Ephemeral field is preserved - symmetric encryption", async function () { it("Ephemeral field is preserved - symmetric encryption", async function () {
this.timeout(10000); this.timeout(10000);
const symKey = generateSymmetricKey(); const encoder = createSymEncoder({
contentTopic: SymContentTopic,
const ephemeralEncoder = symEncoder({
contentTopic: TestContentTopic,
symKey, symKey,
ephemeral: true pubsubTopic: PubsubTopic
}); });
const encoder = symEncoder({ const decoder = createSymDecoder(SymContentTopic, symKey, PubsubTopic);
contentTopic: TestContentTopic,
symKey
});
const decoder = symDecoder(TestContentTopic, symKey);
const messages: DecodedMessage[] = []; const messages: DecodedMessage[] = [];
const callback = (msg: DecodedMessage): void => { const callback = (msg: DecodedMessage): void => {
@ -236,12 +269,16 @@ describe("Waku Message Ephemeral field", function () {
await delay(200); await delay(200);
const normalTxt = "Normal message"; const normalTxt = "Normal message";
const ephemeralTxt = "Ephemeral Message"; const ephemeralTxt = "Ephemeral Message";
await waku.lightPush.send(encoder, {
await Promise.all([
waku.lightPush.send(encoder, {
payload: utf8ToBytes(normalTxt) payload: utf8ToBytes(normalTxt)
}); }),
await waku.lightPush.send(ephemeralEncoder, { waku.lightPush.send(SymEncoder, {
payload: utf8ToBytes(ephemeralTxt) payload: utf8ToBytes(ephemeralTxt)
}); })
]);
while (messages.length < 2) { while (messages.length < 2) {
await delay(250); await delay(250);
} }
@ -263,19 +300,16 @@ describe("Waku Message Ephemeral field", function () {
it("Ephemeral field is preserved - asymmetric encryption", async function () { it("Ephemeral field is preserved - asymmetric encryption", async function () {
this.timeout(10000); this.timeout(10000);
const privKey = generatePrivateKey(); const encoder = createEciesEncoder({
const pubKey = getPublicKey(privKey); contentTopic: AsymContentTopic,
publicKey: publicKey,
const ephemeralEncoder = eciesEncoder({ pubsubTopic: PubsubTopic
contentTopic: TestContentTopic,
publicKey: pubKey,
ephemeral: true
}); });
const encoder = eciesEncoder({ const decoder = createEciesDecoder(
contentTopic: TestContentTopic, AsymContentTopic,
publicKey: pubKey privateKey,
}); PubsubTopic
const decoder = eciesDecoder(TestContentTopic, privKey); );
const messages: DecodedMessage[] = []; const messages: DecodedMessage[] = [];
const callback = (msg: DecodedMessage): void => { const callback = (msg: DecodedMessage): void => {
@ -286,12 +320,16 @@ describe("Waku Message Ephemeral field", function () {
await delay(200); await delay(200);
const normalTxt = "Normal message"; const normalTxt = "Normal message";
const ephemeralTxt = "Ephemeral Message"; const ephemeralTxt = "Ephemeral Message";
await waku.lightPush.send(encoder, {
await Promise.all([
waku.lightPush.send(encoder, {
payload: utf8ToBytes(normalTxt) payload: utf8ToBytes(normalTxt)
}); }),
await waku.lightPush.send(ephemeralEncoder, { waku.lightPush.send(AsymEncoder, {
payload: utf8ToBytes(ephemeralTxt) payload: utf8ToBytes(ephemeralTxt)
}); })
]);
while (messages.length < 2) { while (messages.length < 2) {
await delay(250); await delay(250);
} }

View File

@ -1,8 +1,4 @@
import { import { IFilterSubscription, LightNode } from "@waku/interfaces";
DefaultPubsubTopic,
IFilterSubscription,
LightNode
} from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
@ -18,6 +14,7 @@ import {
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder, TestEncoder,
TestShardInfo,
validatePingError validatePingError
} from "./utils"; } from "./utils";
@ -30,10 +27,8 @@ const runTests = (strictCheckNodes: boolean): void => {
let subscription: IFilterSubscription; let subscription: IFilterSubscription;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[serviceNodes, waku] = await runMultipleNodes(this.ctx, [ [serviceNodes, waku] = await runMultipleNodes(this.ctx, TestShardInfo);
DefaultPubsubTopic subscription = await waku.filter.createSubscription(TestShardInfo);
]);
subscription = await waku.filter.createSubscription();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {

View File

@ -1,10 +1,5 @@
import { waitForRemotePeer } from "@waku/core"; import { waitForRemotePeer } from "@waku/core";
import { import { IFilterSubscription, LightNode, Protocols } from "@waku/interfaces";
DefaultPubsubTopic,
IFilterSubscription,
LightNode,
Protocols
} from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
@ -23,7 +18,9 @@ import {
teardownNodesWithRedundancy, teardownNodesWithRedundancy,
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder TestEncoder,
TestPubsubTopic,
TestShardInfo
} from "./utils.js"; } from "./utils.js";
const runTests = (strictCheckNodes: boolean): void => { const runTests = (strictCheckNodes: boolean): void => {
@ -35,10 +32,8 @@ const runTests = (strictCheckNodes: boolean): void => {
let subscription: IFilterSubscription; let subscription: IFilterSubscription;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[serviceNodes, waku] = await runMultipleNodes(this.ctx, [ [serviceNodes, waku] = await runMultipleNodes(this.ctx, TestShardInfo);
DefaultPubsubTopic subscription = await waku.filter.createSubscription(TestShardInfo);
]);
subscription = await waku.filter.createSubscription();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -60,7 +55,8 @@ const runTests = (strictCheckNodes: boolean): void => {
); );
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: testItem.value, 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"), payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"),
timestamp: testItem as any timestamp: testItem as any
}, },
DefaultPubsubTopic TestPubsubTopic
); );
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq(
@ -88,7 +84,8 @@ const runTests = (strictCheckNodes: boolean): void => {
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
checkTimestamp: false, checkTimestamp: false,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
// Check if the timestamp matches // Check if the timestamp matches
@ -117,7 +114,7 @@ const runTests = (strictCheckNodes: boolean): void => {
payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"), payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"),
timestamp: "2023-09-06T12:05:38.609Z" as any timestamp: "2023-09-06T12:05:38.609Z" as any
}, },
DefaultPubsubTopic TestPubsubTopic
); );
// Verify that no message was received // Verify that no message was received
@ -139,12 +136,14 @@ const runTests = (strictCheckNodes: boolean): void => {
payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"), payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"),
timestamp: BigInt(Date.now()) * BigInt(1000000) timestamp: BigInt(Date.now()) * BigInt(1000000)
}, },
"DefaultPubsubTopic" "WrongContentTopic"
); );
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
false await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(false);
}); });
it("Check message with no content topic is not received", async function () { 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"), payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"),
timestamp: BigInt(Date.now()) * BigInt(1000000) timestamp: BigInt(Date.now()) * BigInt(1000000)
}, },
DefaultPubsubTopic TestPubsubTopic
); );
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq(
@ -180,7 +179,7 @@ const runTests = (strictCheckNodes: boolean): void => {
timestamp: BigInt(Date.now()) * BigInt(1000000), timestamp: BigInt(Date.now()) * BigInt(1000000),
payload: undefined as any payload: undefined as any
}, },
DefaultPubsubTopic TestPubsubTopic
); );
// For go-waku the message is received (it is possible to send a message with no payload) // 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, payload: 12345 as unknown as string,
timestamp: BigInt(Date.now()) * BigInt(1000000) timestamp: BigInt(Date.now()) * BigInt(1000000)
}, },
DefaultPubsubTopic TestPubsubTopic
); );
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq(
@ -239,7 +238,7 @@ const runTests = (strictCheckNodes: boolean): void => {
await waku.dial(await node.getMultiaddrWithId()); await waku.dial(await node.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]);
} }
subscription = await waku.filter.createSubscription(); subscription = await waku.filter.createSubscription(TestShardInfo);
await subscription.subscribe( await subscription.subscribe(
[TestDecoder], [TestDecoder],
serviceNodes.messageCollector.callback serviceNodes.messageCollector.callback
@ -253,11 +252,13 @@ const runTests = (strictCheckNodes: boolean): void => {
); );
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: "M1", expectedMessageText: "M1",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
serviceNodes.messageCollector.verifyReceivedMessage(1, { serviceNodes.messageCollector.verifyReceivedMessage(1, {
expectedMessageText: "M2", expectedMessageText: "M2",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
@ -285,11 +286,13 @@ const runTests = (strictCheckNodes: boolean): void => {
); );
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: "M1", expectedMessageText: "M1",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
serviceNodes.messageCollector.verifyReceivedMessage(1, { serviceNodes.messageCollector.verifyReceivedMessage(1, {
expectedMessageText: "M2", expectedMessageText: "M2",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
}); });

View File

@ -10,7 +10,6 @@ import { Protocols } from "@waku/interfaces";
import { import {
contentTopicToPubsubTopic, contentTopicToPubsubTopic,
contentTopicToShardIndex, contentTopicToShardIndex,
pubsubTopicToSingleShardInfo,
singleShardInfoToPubsubTopic singleShardInfoToPubsubTopic
} from "@waku/utils"; } from "@waku/utils";
import { utf8ToBytes } from "@waku/utils/bytes"; import { utf8ToBytes } from "@waku/utils/bytes";
@ -61,14 +60,8 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () {
const customDecoder2 = createDecoder(customContentTopic2, singleShardInfo2); const customDecoder2 = createDecoder(customContentTopic2, singleShardInfo2);
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes( [nwaku, waku] = await runNodes(this.ctx, shardInfo);
this.ctx, subscription = await waku.filter.createSubscription(shardInfo);
[customPubsubTopic1, customPubsubTopic2],
shardInfo
);
subscription = await waku.filter.createSubscription(
pubsubTopicToSingleShardInfo(customPubsubTopic1)
);
messageCollector = new MessageCollector(); messageCollector = new MessageCollector();
}); });
@ -91,9 +84,8 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () {
await subscription.subscribe([customDecoder1], messageCollector.callback); await subscription.subscribe([customDecoder1], messageCollector.callback);
// Subscribe from the same lightnode to the 2nd pubsubtopic // Subscribe from the same lightnode to the 2nd pubsubtopic
const subscription2 = await waku.filter.createSubscription( const subscription2 =
pubsubTopicToSingleShardInfo(customPubsubTopic2) await waku.filter.createSubscription(customPubsubTopic2);
);
const messageCollector2 = new MessageCollector(); const messageCollector2 = new MessageCollector();
@ -134,10 +126,8 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () {
await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]);
// Subscribe from the same lightnode to the new nwaku on the new pubsubtopic // Subscribe from the same lightnode to the new nwaku on the new pubsubtopic
const subscription2 = await waku.filter.createSubscription( const subscription2 =
pubsubTopicToSingleShardInfo(customPubsubTopic2), await waku.filter.createSubscription(customPubsubTopic2);
await nwaku2.getPeerId()
);
await nwaku2.ensureSubscriptions([customPubsubTopic2]); await nwaku2.ensureSubscriptions([customPubsubTopic2]);
const messageCollector2 = new MessageCollector(); 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 () { 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 { try {
await subscription.subscribe([customDecoder2], messageCollector.callback); await subscription.subscribe([customDecoder2], messageCollector.callback);
} catch (error) { } catch (error) {
@ -231,13 +221,9 @@ describe("Waku Filter V2 (Autosharding): Multiple PubsubTopics", function () {
}); });
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes( [nwaku, waku] = await runNodes(this.ctx, contentTopicInfo);
this.ctx,
[autoshardingPubsubTopic1, autoshardingPubsubTopic2],
contentTopicInfo
);
subscription = await waku.filter.createSubscription( subscription = await waku.filter.createSubscription(
pubsubTopicToSingleShardInfo(autoshardingPubsubTopic1) autoshardingPubsubTopic1
); );
messageCollector = new MessageCollector(); messageCollector = new MessageCollector();
}); });
@ -266,7 +252,7 @@ describe("Waku Filter V2 (Autosharding): Multiple PubsubTopics", function () {
// Subscribe from the same lightnode to the 2nd pubsubtopic // Subscribe from the same lightnode to the 2nd pubsubtopic
const subscription2 = await waku.filter.createSubscription( const subscription2 = await waku.filter.createSubscription(
pubsubTopicToSingleShardInfo(autoshardingPubsubTopic2) autoshardingPubsubTopic2
); );
const messageCollector2 = new MessageCollector(); 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 // Subscribe from the same lightnode to the new nwaku on the new pubsubtopic
const subscription2 = await waku.filter.createSubscription( const subscription2 = await waku.filter.createSubscription(
pubsubTopicToSingleShardInfo(autoshardingPubsubTopic2), autoshardingPubsubTopic2
await nwaku2.getPeerId()
); );
await nwaku2.ensureSubscriptionsAutosharding([customContentTopic2]); 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 () { 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 { try {
await subscription.subscribe([customDecoder2], messageCollector.callback); await subscription.subscribe([customDecoder2], messageCollector.callback);
} catch (error) { } catch (error) {
@ -383,6 +368,10 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () {
clusterId: 3, clusterId: 3,
shard: 2 shard: 2
}); });
const shardInfo = {
clusterId: 3,
shards: [1, 2]
};
const customContentTopic1 = "/test/2/waku-filter"; const customContentTopic1 = "/test/2/waku-filter";
const customContentTopic2 = "/test/3/waku-filter"; const customContentTopic2 = "/test/3/waku-filter";
const customEncoder1 = createEncoder({ const customEncoder1 = createEncoder({
@ -397,14 +386,7 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () {
const customDecoder2 = createDecoder(customContentTopic2, customPubsubTopic2); const customDecoder2 = createDecoder(customContentTopic2, customPubsubTopic2);
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes( [nwaku, waku] = await runNodes(this.ctx, shardInfo);
this.ctx,
[customPubsubTopic1, customPubsubTopic2],
{
clusterId: 3,
shards: [1, 2]
}
);
subscription = await waku.filter.createSubscription(customPubsubTopic1); subscription = await waku.filter.createSubscription(customPubsubTopic1);
messageCollector = new MessageCollector(); messageCollector = new MessageCollector();
}); });
@ -428,9 +410,8 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () {
await subscription.subscribe([customDecoder1], messageCollector.callback); await subscription.subscribe([customDecoder1], messageCollector.callback);
// Subscribe from the same lightnode to the 2nd pubsubtopic // Subscribe from the same lightnode to the 2nd pubsubtopic
const subscription2 = await waku.filter.createSubscription( const subscription2 =
pubsubTopicToSingleShardInfo(customPubsubTopic2) await waku.filter.createSubscription(customPubsubTopic2);
);
const messageCollector2 = new MessageCollector(); const messageCollector2 = new MessageCollector();
@ -471,10 +452,8 @@ describe("Waku Filter V2 (Named sharding): Multiple PubsubTopics", function () {
await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]);
// Subscribe from the same lightnode to the new nwaku on the new pubsubtopic // Subscribe from the same lightnode to the new nwaku on the new pubsubtopic
const subscription2 = await waku.filter.createSubscription( const subscription2 =
pubsubTopicToSingleShardInfo(customPubsubTopic2), await waku.filter.createSubscription(customPubsubTopic2);
await nwaku2.getPeerId()
);
await nwaku2.ensureSubscriptions([customPubsubTopic2]); await nwaku2.ensureSubscriptions([customPubsubTopic2]);
const messageCollector2 = new MessageCollector(); 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 () { 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 { try {
await subscription.subscribe([customDecoder2], messageCollector.callback); await subscription.subscribe([customDecoder2], messageCollector.callback);
} catch (error) { } catch (error) {

View File

@ -1,8 +1,4 @@
import { import { IFilterSubscription, LightNode } from "@waku/interfaces";
DefaultPubsubTopic,
IFilterSubscription,
LightNode
} from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
@ -17,6 +13,7 @@ import {
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder, TestEncoder,
TestShardInfo,
validatePingError validatePingError
} from "../utils.js"; } from "../utils.js";
@ -31,8 +28,8 @@ describe("Waku Filter V2: Ping", function () {
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); [nwaku, waku] = await runNodes(this.ctx, TestShardInfo);
subscription = await waku.filter.createSubscription(); subscription = await waku.filter.createSubscription(TestShardInfo);
messageCollector = new MessageCollector(); messageCollector = new MessageCollector();
}); });

View File

@ -1,10 +1,5 @@
import { waitForRemotePeer } from "@waku/core"; import { waitForRemotePeer } from "@waku/core";
import { import { IFilterSubscription, LightNode, Protocols } from "@waku/interfaces";
DefaultPubsubTopic,
IFilterSubscription,
LightNode,
Protocols
} from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
@ -23,7 +18,9 @@ import {
messageText, messageText,
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder TestEncoder,
TestPubsubTopic,
TestShardInfo
} from "../utils.js"; } from "../utils.js";
describe("Waku Filter V2: FilterPush", function () { describe("Waku Filter V2: FilterPush", function () {
@ -35,9 +32,9 @@ describe("Waku Filter V2: FilterPush", function () {
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); [nwaku, waku] = await runNodes(this.ctx, TestShardInfo);
subscription = await waku.filter.createSubscription(); subscription = await waku.filter.createSubscription(TestShardInfo);
messageCollector = new MessageCollector(); messageCollector = new MessageCollector(nwaku);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -65,7 +62,7 @@ describe("Waku Filter V2: FilterPush", function () {
await delay(400); await delay(400);
await nwaku.restCall<boolean>( await nwaku.restCall<boolean>(
`/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`,
"POST", "POST",
{ {
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
@ -99,7 +96,7 @@ describe("Waku Filter V2: FilterPush", function () {
await delay(400); await delay(400);
await nwaku.restCall<boolean>( await nwaku.restCall<boolean>(
`/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`,
"POST", "POST",
{ {
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
@ -154,7 +151,7 @@ describe("Waku Filter V2: FilterPush", function () {
await delay(400); await delay(400);
await nwaku.restCall<boolean>( await nwaku.restCall<boolean>(
`/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`,
"POST", "POST",
{ {
payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"), payload: Buffer.from(utf8ToBytes(messageText)).toString("base64"),
@ -171,7 +168,7 @@ describe("Waku Filter V2: FilterPush", function () {
await delay(400); await delay(400);
await nwaku.restCall<boolean>( await nwaku.restCall<boolean>(
`/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`,
"POST", "POST",
{ {
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
@ -193,7 +190,7 @@ describe("Waku Filter V2: FilterPush", function () {
await delay(400); await delay(400);
await nwaku.restCall<boolean>( await nwaku.restCall<boolean>(
`/relay/v1/messages/${encodeURIComponent(DefaultPubsubTopic)}`, `/relay/v1/messages/${encodeURIComponent(TestPubsubTopic)}`,
"POST", "POST",
{ {
contentTopic: TestContentTopic, contentTopic: TestContentTopic,

View File

@ -1,10 +1,5 @@
import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core"; import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core";
import { import { IFilterSubscription, LightNode, Protocols } from "@waku/interfaces";
DefaultPubsubTopic,
IFilterSubscription,
LightNode,
Protocols
} from "@waku/interfaces";
import { import {
ecies, ecies,
generatePrivateKey, generatePrivateKey,
@ -14,13 +9,13 @@ import {
} from "@waku/message-encryption"; } from "@waku/message-encryption";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
import type { Context } from "mocha";
import { import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
delay, delay,
generateTestData, generateTestData,
makeLogFileName,
MessageCollector, MessageCollector,
ServiceNode, ServiceNode,
tearDownNodes, tearDownNodes,
@ -31,7 +26,9 @@ import {
messageText, messageText,
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder TestEncoder,
TestPubsubTopic,
TestShardInfo
} from "../utils.js"; } from "../utils.js";
import { runNodes } 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 // Set the timeout for all tests in this suite. Can be overwritten at test level
this.timeout(10000); this.timeout(10000);
let waku: LightNode; let waku: LightNode;
let waku2: LightNode;
let nwaku: ServiceNode; let nwaku: ServiceNode;
let nwaku2: ServiceNode; let nwaku2: ServiceNode;
let subscription: IFilterSubscription; let subscription: IFilterSubscription;
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
let ctx: Context;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); ctx = this.ctx;
subscription = await waku.filter.createSubscription(); [nwaku, waku] = await runNodes(this.ctx, TestShardInfo);
subscription = await waku.filter.createSubscription(TestShardInfo);
messageCollector = new MessageCollector(); messageCollector = new MessageCollector();
await nwaku.ensureSubscriptions(); await nwaku.ensureSubscriptions([TestPubsubTopic]);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
await tearDownNodes([nwaku, nwaku2], waku); await tearDownNodes([nwaku, nwaku2], [waku, waku2]);
}); });
it("Subscribe and receive messages via lightPush", async function () { 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); expect(await messageCollector.waitForMessages(1)).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
expect((await nwaku.messages()).length).to.eq(1); 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 publicKey = getPublicKey(privateKey);
const encoder = ecies.createEncoder({ const encoder = ecies.createEncoder({
contentTopic: TestContentTopic, 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); await subscription.subscribe([decoder], messageCollector.callback);
@ -86,7 +92,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () {
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic, expectedContentTopic: TestContentTopic,
expectedVersion: 1 expectedVersion: 1,
expectedPubsubTopic: TestPubsubTopic
}); });
expect((await nwaku.messages()).length).to.eq(1); 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 symKey = generateSymmetricKey();
const encoder = symmetric.createEncoder({ const encoder = symmetric.createEncoder({
contentTopic: TestContentTopic, 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); await subscription.subscribe([decoder], messageCollector.callback);
@ -107,7 +119,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () {
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic, expectedContentTopic: TestContentTopic,
expectedVersion: 1 expectedVersion: 1,
expectedPubsubTopic: TestPubsubTopic
}); });
expect((await nwaku.messages()).length).to.eq(1); 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); expect(await messageCollector.waitForMessages(1)).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
expect((await nwaku.messages()).length).to.eq(1); 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); expect(await messageCollector.waitForMessages(1)).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
// Send another message on the same topic. // 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); expect(await messageCollector.waitForMessages(2)).to.eq(true);
messageCollector.verifyReceivedMessage(1, { messageCollector.verifyReceivedMessage(1, {
expectedMessageText: newMessageText, expectedMessageText: newMessageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
expect((await nwaku.messages()).length).to.eq(2); 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); expect(await messageCollector.waitForMessages(1)).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
// Modify subscription to include a new content topic and send a message. // Modify subscription to include a new content topic and send a message.
const newMessageText = "Filtering still works!"; const newMessageText = "Filtering still works!";
const newMessagePayload = { payload: utf8ToBytes(newMessageText) }; const newMessagePayload = { payload: utf8ToBytes(newMessageText) };
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter/default";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription.subscribe([newDecoder], messageCollector.callback); await subscription.subscribe([newDecoder], messageCollector.callback);
await waku.lightPush.send(newEncoder, { await waku.lightPush.send(newEncoder, {
payload: utf8ToBytes(newMessageText) payload: utf8ToBytes(newMessageText)
@ -182,7 +202,8 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () {
expect(await messageCollector.waitForMessages(2)).to.eq(true); expect(await messageCollector.waitForMessages(2)).to.eq(true);
messageCollector.verifyReceivedMessage(1, { messageCollector.verifyReceivedMessage(1, {
expectedContentTopic: newContentTopic, expectedContentTopic: newContentTopic,
expectedMessageText: newMessageText expectedMessageText: newMessageText,
expectedPubsubTopic: TestPubsubTopic
}); });
// Send another message on the initial content topic to verify it still works. // 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); expect(await messageCollector.waitForMessages(3)).to.eq(true);
messageCollector.verifyReceivedMessage(2, { messageCollector.verifyReceivedMessage(2, {
expectedMessageText: newMessageText, expectedMessageText: newMessageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
expect((await nwaku.messages()).length).to.eq(3); expect((await nwaku.messages()).length).to.eq(3);
}); });
it("Subscribe and receives messages on 20 topics", async function () { it("Subscribe and receives messages on 20 topics", async function () {
const topicCount = 20; const topicCount = 20;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic });
// Subscribe to all 20 topics. // Subscribe to all 20 topics.
for (let i = 0; i < topicCount; i++) { 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) => { td.contentTopics.forEach((topic, index) => {
messageCollector.verifyReceivedMessage(index, { messageCollector.verifyReceivedMessage(index, {
expectedContentTopic: topic, 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 () { it("Subscribe to 100 topics (new limit) at once and receives messages", async function () {
this.timeout(50000); this.timeout(50000);
const topicCount = 100; const topicCount = 100;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic });
await subscription.subscribe(td.decoders, messageCollector.callback); 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) => { td.contentTopics.forEach((topic, index) => {
messageCollector.verifyReceivedMessage(index, { messageCollector.verifyReceivedMessage(index, {
expectedContentTopic: topic, expectedContentTopic: topic,
expectedMessageText: `Message for Topic ${index + 1}` expectedMessageText: `Message for Topic ${index + 1}`,
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
} catch (error) { } 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 () { it("Error when try to subscribe to more than 101 topics (new limit)", async function () {
const topicCount = 101; const topicCount = 101;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic });
try { try {
await subscription.subscribe(td.decoders, messageCollector.callback); 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 () { it("Overlapping topic subscription", async function () {
// Define two sets of test data with overlapping topics. // Define two sets of test data with overlapping topics.
const topicCount1 = 2; const topicCount1 = 2;
const td1 = generateTestData(topicCount1); const td1 = generateTestData(topicCount1, { pubsubTopic: TestPubsubTopic });
const topicCount2 = 4; const topicCount2 = 4;
const td2 = generateTestData(topicCount2); const td2 = generateTestData(topicCount2, { pubsubTopic: TestPubsubTopic });
// Subscribe to the first set of topics. // Subscribe to the first set of topics.
await subscription.subscribe(td1.decoders, messageCollector.callback); await subscription.subscribe(td1.decoders, messageCollector.callback);
@ -327,19 +351,24 @@ describe("Waku Filter V2: Subscribe: Single Service Node", function () {
); );
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: "M1", expectedMessageText: "M1",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
messageCollector.verifyReceivedMessage(1, { messageCollector.verifyReceivedMessage(1, {
expectedMessageText: "M2", expectedMessageText: "M2",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
TEST_STRING.forEach((testItem) => { TEST_STRING.forEach((testItem) => {
it(`Subscribe to topic containing ${testItem.description} and receive message`, async function () { it(`Subscribe to topic containing ${testItem.description} and receive message`, async function () {
const newContentTopic = testItem.value; const newContentTopic = testItem.value;
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription.subscribe([newDecoder], messageCollector.callback); await subscription.subscribe([newDecoder], messageCollector.callback);
await waku.lightPush.send(newEncoder, messagePayload); 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); expect(await messageCollector.waitForMessages(1)).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, 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") }); await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") });
// Create a second subscription on a different topic // Create a second subscription on a different topic
const subscription2 = await waku.filter.createSubscription(); const subscription2 = await waku.filter.createSubscription(TestShardInfo);
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter/default";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription2.subscribe([newDecoder], messageCollector.callback); await subscription2.subscribe([newDecoder], messageCollector.callback);
await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M2") }); 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); expect(await messageCollector.waitForMessages(2)).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: "M1", expectedMessageText: "M1",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
messageCollector.verifyReceivedMessage(1, { messageCollector.verifyReceivedMessage(1, {
expectedContentTopic: newContentTopic, 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); await subscription.subscribe([TestDecoder], messageCollector.callback);
// Set up and start a new nwaku node // Set up and start a new nwaku node
nwaku2 = new ServiceNode(makeLogFileName(this) + "2"); [nwaku2, waku2] = await runNodes(ctx, TestShardInfo);
await nwaku2.start({
filter: true,
lightpush: true,
relay: true
});
await waku.dial(await nwaku2.getMultiaddrWithId()); await waku.dial(await nwaku2.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]); await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]);
const subscription2 = await waku.filter.createSubscription( const subscription2 = await waku.filter.createSubscription(TestShardInfo);
undefined, await nwaku2.ensureSubscriptions([TestPubsubTopic]);
await nwaku2.getPeerId()
);
await nwaku2.ensureSubscriptions([DefaultPubsubTopic]);
// Send a message using the new subscription // Send a message using the new subscription
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter/default";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription2.subscribe([newDecoder], messageCollector.callback); await subscription2.subscribe([newDecoder], messageCollector.callback);
// Making sure that messages are send and reveiced for both subscriptions // Making sure that messages are send and reveiced for both subscriptions

View File

@ -1,5 +1,5 @@
import { createDecoder, createEncoder } from "@waku/core"; import { createDecoder, createEncoder } from "@waku/core";
import { DefaultPubsubTopic, IFilterSubscription } from "@waku/interfaces"; import { IFilterSubscription } from "@waku/interfaces";
import { LightNode } from "@waku/interfaces"; import { LightNode } from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
@ -18,7 +18,9 @@ import {
messageText, messageText,
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder TestEncoder,
TestPubsubTopic,
TestShardInfo
} from "../utils.js"; } from "../utils.js";
describe("Waku Filter V2: Unsubscribe", function () { describe("Waku Filter V2: Unsubscribe", function () {
@ -30,12 +32,10 @@ describe("Waku Filter V2: Unsubscribe", function () {
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); [nwaku, waku] = await runNodes(this.ctx, TestShardInfo);
subscription = await waku.filter.createSubscription(); subscription = await waku.filter.createSubscription(TestShardInfo);
messageCollector = new MessageCollector(); messageCollector = new MessageCollector();
await nwaku.ensureSubscriptions([TestPubsubTopic]);
// Nwaku subscribe to the default pubsub topic
await nwaku.ensureSubscriptions();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -55,7 +55,8 @@ describe("Waku Filter V2: Unsubscribe", function () {
// Check that from 2 messages send only the 1st was received // Check that from 2 messages send only the 1st was received
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
expect(messageCollector.count).to.eq(1); expect(messageCollector.count).to.eq(1);
expect((await nwaku.messages()).length).to.eq(2); 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 // Subscribe to 2 topics and send messages
await subscription.subscribe([TestDecoder], messageCollector.callback); await subscription.subscribe([TestDecoder], messageCollector.callback);
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription.subscribe([newDecoder], messageCollector.callback); await subscription.subscribe([newDecoder], messageCollector.callback);
await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") }); await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") });
await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M2") }); 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 () { it("Unsubscribe 2 topics - node subscribed to 2 topics", async function () {
// Subscribe to 2 topics and send messages // Subscribe to 2 topics and send messages
await subscription.subscribe([TestDecoder], messageCollector.callback); await subscription.subscribe([TestDecoder], messageCollector.callback);
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter/default";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription.subscribe([newDecoder], messageCollector.callback); await subscription.subscribe([newDecoder], messageCollector.callback);
await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") }); await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") });
await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M2") }); 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 // Unsubscribe from topics that the node is not not subscribed to and send again
await subscription.unsubscribe([]); 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") }); await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M2") });
expect(await messageCollector.waitForMessages(2)).to.eq(true); 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 () { it("Unsubscribes all - node subscribed to 10 topics", async function () {
// Subscribe to 10 topics and send message // Subscribe to 10 topics and send message
const topicCount = 10; const topicCount = 10;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic });
await subscription.subscribe(td.decoders, messageCollector.callback); await subscription.subscribe(td.decoders, messageCollector.callback);
for (let i = 0; i < topicCount; i++) { for (let i = 0; i < topicCount; i++) {
await waku.lightPush.send(td.encoders[i], { await waku.lightPush.send(td.encoders[i], {

View File

@ -1,76 +1,22 @@
import { waitForRemotePeer } from "@waku/core"; import { LightNode, Protocols, ShardingParams } from "@waku/interfaces";
import {
ContentTopicInfo,
DefaultPubsubTopic,
LightNode,
ProtocolCreateOptions,
Protocols,
ShardingParams
} from "@waku/interfaces";
import { createLightNode } from "@waku/sdk"; import { createLightNode } from "@waku/sdk";
import { Logger } from "@waku/utils"; import { Logger } from "@waku/utils";
import { Context } from "mocha"; import { Context } from "mocha";
import { import {
makeLogFileName, runNodes as runNodesBuilder,
NOISE_KEY_1,
ServiceNode ServiceNode
} from "../../../src/index.js"; } from "../../../src/index.js";
export const log = new Logger("test:filter:single_node"); export const log = new Logger("test:filter:single_node");
export async function runNodes( export const runNodes = (
context: Context, context: Context,
//TODO: change this to use `ShardInfo` instead of `string[]` shardInfo: ShardingParams
pubsubTopics: string[], ): Promise<[ServiceNode, LightNode]> =>
shardInfo?: ShardingParams runNodesBuilder<LightNode>({
): Promise<[ServiceNode, LightNode]> { context,
const nwaku = new ServiceNode(makeLogFileName(context)); createNode: createLightNode,
protocols: [Protocols.LightPush, Protocols.Filter],
function isContentTopicInfo(info: ShardingParams): info is ContentTopicInfo { shardInfo
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");
}
}

View File

@ -1,9 +1,5 @@
import { createDecoder, createEncoder } from "@waku/core"; import { createDecoder, createEncoder } from "@waku/core";
import { import { IFilterSubscription, LightNode } from "@waku/interfaces";
DefaultPubsubTopic,
IFilterSubscription,
LightNode
} from "@waku/interfaces";
import { import {
ecies, ecies,
generatePrivateKey, generatePrivateKey,
@ -30,7 +26,9 @@ import {
teardownNodesWithRedundancy, teardownNodesWithRedundancy,
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder TestEncoder,
TestPubsubTopic,
TestShardInfo
} from "./utils.js"; } from "./utils.js";
const runTests = (strictCheckNodes: boolean): void => { const runTests = (strictCheckNodes: boolean): void => {
@ -43,10 +41,10 @@ const runTests = (strictCheckNodes: boolean): void => {
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[serviceNodes, waku] = await runMultipleNodes( [serviceNodes, waku] = await runMultipleNodes(
this.ctx, this.ctx,
[DefaultPubsubTopic], TestShardInfo,
strictCheckNodes strictCheckNodes
); );
subscription = await waku.filter.createSubscription(); subscription = await waku.filter.createSubscription(TestShardInfo);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -79,9 +77,14 @@ const runTests = (strictCheckNodes: boolean): void => {
const publicKey = getPublicKey(privateKey); const publicKey = getPublicKey(privateKey);
const encoder = ecies.createEncoder({ const encoder = ecies.createEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
publicKey publicKey,
pubsubTopic: TestPubsubTopic
}); });
const decoder = ecies.createDecoder(TestContentTopic, privateKey); const decoder = ecies.createDecoder(
TestContentTopic,
privateKey,
TestPubsubTopic
);
await subscription.subscribe( await subscription.subscribe(
[decoder], [decoder],
@ -96,7 +99,8 @@ const runTests = (strictCheckNodes: boolean): void => {
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic, expectedContentTopic: TestContentTopic,
expectedVersion: 1 expectedVersion: 1,
expectedPubsubTopic: TestPubsubTopic
}); });
await serviceNodes.confirmMessageLength(1); await serviceNodes.confirmMessageLength(1);
@ -106,9 +110,14 @@ const runTests = (strictCheckNodes: boolean): void => {
const symKey = generateSymmetricKey(); const symKey = generateSymmetricKey();
const encoder = symmetric.createEncoder({ const encoder = symmetric.createEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
symKey symKey,
pubsubTopic: TestPubsubTopic
}); });
const decoder = symmetric.createDecoder(TestContentTopic, symKey); const decoder = symmetric.createDecoder(
TestContentTopic,
symKey,
TestPubsubTopic
);
await subscription.subscribe( await subscription.subscribe(
[decoder], [decoder],
@ -123,7 +132,8 @@ const runTests = (strictCheckNodes: boolean): void => {
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic, expectedContentTopic: TestContentTopic,
expectedVersion: 1 expectedVersion: 1,
expectedPubsubTopic: TestPubsubTopic
}); });
await serviceNodes.confirmMessageLength(1); await serviceNodes.confirmMessageLength(1);
@ -142,14 +152,15 @@ const runTests = (strictCheckNodes: boolean): void => {
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
payload: utf8ToBytes(messageText) payload: utf8ToBytes(messageText)
}); });
await serviceNodes.sendRelayMessage(relayMessage); await serviceNodes.sendRelayMessage(relayMessage, TestPubsubTopic);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq(
true true
); );
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
await serviceNodes.confirmMessageLength(1); await serviceNodes.confirmMessageLength(1);
@ -201,15 +212,19 @@ const runTests = (strictCheckNodes: boolean): void => {
); );
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
// Modify subscription to include a new content topic and send a message. // Modify subscription to include a new content topic and send a message.
const newMessageText = "Filtering still works!"; const newMessageText = "Filtering still works!";
const newMessagePayload = { payload: utf8ToBytes(newMessageText) }; const newMessagePayload = { payload: utf8ToBytes(newMessageText) };
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter/default";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription.subscribe( await subscription.subscribe(
[newDecoder], [newDecoder],
serviceNodes.messageCollector.callback serviceNodes.messageCollector.callback
@ -222,7 +237,8 @@ const runTests = (strictCheckNodes: boolean): void => {
); );
serviceNodes.messageCollector.verifyReceivedMessage(1, { serviceNodes.messageCollector.verifyReceivedMessage(1, {
expectedContentTopic: newContentTopic, expectedContentTopic: newContentTopic,
expectedMessageText: newMessageText expectedMessageText: newMessageText,
expectedPubsubTopic: TestPubsubTopic
}); });
// Send another message on the initial content topic to verify it still works. // 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, { serviceNodes.messageCollector.verifyReceivedMessage(2, {
expectedMessageText: newMessageText, expectedMessageText: newMessageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
await serviceNodes.confirmMessageLength(3); await serviceNodes.confirmMessageLength(3);
@ -240,7 +257,7 @@ const runTests = (strictCheckNodes: boolean): void => {
it("Subscribe and receives messages on 20 topics", async function () { it("Subscribe and receives messages on 20 topics", async function () {
const topicCount = 20; const topicCount = 20;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic });
// Subscribe to all 20 topics. // Subscribe to all 20 topics.
for (let i = 0; i < topicCount; i++) { for (let i = 0; i < topicCount; i++) {
@ -264,7 +281,8 @@ const runTests = (strictCheckNodes: boolean): void => {
td.contentTopics.forEach((topic, index) => { td.contentTopics.forEach((topic, index) => {
serviceNodes.messageCollector.verifyReceivedMessage(index, { serviceNodes.messageCollector.verifyReceivedMessage(index, {
expectedContentTopic: topic, 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 () { it("Subscribe to 100 topics (new limit) at once and receives messages", async function () {
this.timeout(50000); this.timeout(50000);
const topicCount = 100; const topicCount = 100;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic });
await subscription.subscribe( await subscription.subscribe(
td.decoders, td.decoders,
@ -296,7 +314,8 @@ const runTests = (strictCheckNodes: boolean): void => {
td.contentTopics.forEach((topic, index) => { td.contentTopics.forEach((topic, index) => {
serviceNodes.messageCollector.verifyReceivedMessage(index, { serviceNodes.messageCollector.verifyReceivedMessage(index, {
expectedContentTopic: topic, expectedContentTopic: topic,
expectedMessageText: `Message for Topic ${index + 1}` expectedMessageText: `Message for Topic ${index + 1}`,
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
} catch (error) { } 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 () { it("Error when try to subscribe to more than 101 topics (new limit)", async function () {
const topicCount = 101; const topicCount = 101;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic });
try { try {
await subscription.subscribe( await subscription.subscribe(
@ -335,9 +354,13 @@ const runTests = (strictCheckNodes: boolean): void => {
it("Overlapping topic subscription", async function () { it("Overlapping topic subscription", async function () {
// Define two sets of test data with overlapping topics. // Define two sets of test data with overlapping topics.
const topicCount1 = 2; const topicCount1 = 2;
const td1 = generateTestData(topicCount1); const td1 = generateTestData(topicCount1, {
pubsubTopic: TestPubsubTopic
});
const topicCount2 = 4; const topicCount2 = 4;
const td2 = generateTestData(topicCount2); const td2 = generateTestData(topicCount2, {
pubsubTopic: TestPubsubTopic
});
// Subscribe to the first set of topics. // Subscribe to the first set of topics.
await subscription.subscribe( await subscription.subscribe(
@ -394,19 +417,24 @@ const runTests = (strictCheckNodes: boolean): void => {
).to.eq(true); ).to.eq(true);
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: "M1", expectedMessageText: "M1",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
serviceNodes.messageCollector.verifyReceivedMessage(1, { serviceNodes.messageCollector.verifyReceivedMessage(1, {
expectedMessageText: "M2", expectedMessageText: "M2",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
TEST_STRING.forEach((testItem) => { TEST_STRING.forEach((testItem) => {
it(`Subscribe to topic containing ${testItem.description} and receive message`, async function () { it(`Subscribe to topic containing ${testItem.description} and receive message`, async function () {
const newContentTopic = testItem.value; const newContentTopic = testItem.value;
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription.subscribe( await subscription.subscribe(
[newDecoder], [newDecoder],
@ -419,7 +447,8 @@ const runTests = (strictCheckNodes: boolean): void => {
); );
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, 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") }); await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M1") });
// Create a second subscription on a different topic // Create a second subscription on a different topic
const subscription2 = await waku.filter.createSubscription(); const subscription2 = await waku.filter.createSubscription(TestShardInfo);
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter/default";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription2.subscribe( await subscription2.subscribe(
[newDecoder], [newDecoder],
serviceNodes.messageCollector.callback serviceNodes.messageCollector.callback
@ -449,11 +481,13 @@ const runTests = (strictCheckNodes: boolean): void => {
); );
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: "M1", expectedMessageText: "M1",
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
serviceNodes.messageCollector.verifyReceivedMessage(1, { serviceNodes.messageCollector.verifyReceivedMessage(1, {
expectedContentTopic: newContentTopic, expectedContentTopic: newContentTopic,
expectedMessageText: "M2" expectedMessageText: "M2",
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
}); });

View File

@ -1,9 +1,5 @@
import { createDecoder, createEncoder } from "@waku/core"; import { createDecoder, createEncoder } from "@waku/core";
import { import { IFilterSubscription, LightNode } from "@waku/interfaces";
DefaultPubsubTopic,
IFilterSubscription,
LightNode
} from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
@ -15,13 +11,15 @@ import {
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
ClusterId,
messagePayload, messagePayload,
messageText, messageText,
runMultipleNodes, runMultipleNodes,
teardownNodesWithRedundancy, teardownNodesWithRedundancy,
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder TestEncoder,
TestPubsubTopic
} from "./utils.js"; } from "./utils.js";
const runTests = (strictCheckNodes: boolean): void => { const runTests = (strictCheckNodes: boolean): void => {
@ -33,10 +31,15 @@ const runTests = (strictCheckNodes: boolean): void => {
let subscription: IFilterSubscription; let subscription: IFilterSubscription;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[serviceNodes, waku] = await runMultipleNodes(this.ctx, [ [serviceNodes, waku] = await runMultipleNodes(this.ctx, {
DefaultPubsubTopic contentTopics: [TestContentTopic],
]); clusterId: ClusterId
subscription = await waku.filter.createSubscription(); });
subscription = await waku.filter.createSubscription({
contentTopics: [TestContentTopic],
clusterId: ClusterId
});
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -77,8 +80,11 @@ const runTests = (strictCheckNodes: boolean): void => {
serviceNodes.messageCollector.callback serviceNodes.messageCollector.callback
); );
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription.subscribe( await subscription.subscribe(
[newDecoder], [newDecoder],
serviceNodes.messageCollector.callback serviceNodes.messageCollector.callback
@ -109,8 +115,11 @@ const runTests = (strictCheckNodes: boolean): void => {
serviceNodes.messageCollector.callback serviceNodes.messageCollector.callback
); );
const newContentTopic = "/test/2/waku-filter"; const newContentTopic = "/test/2/waku-filter";
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await subscription.subscribe( await subscription.subscribe(
[newDecoder], [newDecoder],
serviceNodes.messageCollector.callback serviceNodes.messageCollector.callback
@ -186,7 +195,7 @@ const runTests = (strictCheckNodes: boolean): void => {
it("Unsubscribes all - node subscribed to 10 topics", async function () { it("Unsubscribes all - node subscribed to 10 topics", async function () {
// Subscribe to 10 topics and send message // Subscribe to 10 topics and send message
const topicCount = 10; const topicCount = 10;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, { pubsubTopic: TestPubsubTopic });
await subscription.subscribe( await subscription.subscribe(
td.decoders, td.decoders,
serviceNodes.messageCollector.callback serviceNodes.messageCollector.callback

View File

@ -1,6 +1,5 @@
import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core"; import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core";
import { import {
DefaultPubsubTopic,
IFilterSubscription, IFilterSubscription,
LightNode, LightNode,
ProtocolCreateOptions, ProtocolCreateOptions,
@ -10,7 +9,7 @@ import {
} from "@waku/interfaces"; } from "@waku/interfaces";
import { createLightNode } from "@waku/sdk"; import { createLightNode } from "@waku/sdk";
import { import {
ensureShardingConfigured, contentTopicToPubsubTopic,
Logger, Logger,
shardInfoToPubsubTopics shardInfoToPubsubTopics
} from "@waku/utils"; } from "@waku/utils";
@ -26,9 +25,21 @@ import {
// Constants for test configuration. // Constants for test configuration.
export const log = new Logger("test:filter"); export const log = new Logger("test:filter");
export const TestContentTopic = "/test/1/waku-filter"; export const TestContentTopic = "/test/1/waku-filter/default";
export const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); export const ClusterId = 2;
export const TestDecoder = createDecoder(TestContentTopic); 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 messageText = "Filtering works!";
export const messagePayload = { payload: utf8ToBytes(messageText) }; export const messagePayload = { payload: utf8ToBytes(messageText) };
@ -55,20 +66,19 @@ export async function validatePingError(
export async function runMultipleNodes( export async function runMultipleNodes(
context: Context, context: Context,
//TODO: change this to use `ShardInfo` instead of `string[]` shardInfo: ShardingParams,
pubsubTopics: string[],
strictChecking: boolean = false, strictChecking: boolean = false,
shardInfo?: ShardingParams,
numServiceNodes = 3, numServiceNodes = 3,
withoutFilter = false withoutFilter = false
): Promise<[ServiceNodesFleet, LightNode]> { ): Promise<[ServiceNodesFleet, LightNode]> {
const pubsubTopics = shardInfoToPubsubTopics(shardInfo);
// create numServiceNodes nodes // create numServiceNodes nodes
const serviceNodes = await ServiceNodesFleet.createAndRun( const serviceNodes = await ServiceNodesFleet.createAndRun(
context, context,
pubsubTopics, pubsubTopics,
numServiceNodes, numServiceNodes,
strictChecking, strictChecking,
shardInfo ? ensureShardingConfigured(shardInfo).shardInfo : shardInfo, shardInfo,
undefined, undefined,
withoutFilter withoutFilter
); );
@ -78,11 +88,8 @@ export async function runMultipleNodes(
libp2p: { libp2p: {
addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] }
}, },
pubsubTopics: shardInfo ? shardInfoToPubsubTopics(shardInfo) : pubsubTopics, pubsubTopics,
...((pubsubTopics.length !== 1 || shardInfo
pubsubTopics[0] !== DefaultPubsubTopic) && {
shardInfo: shardInfo
})
}; };
log.info("Starting js waku node with :", JSON.stringify(waku_options)); log.info("Starting js waku node with :", JSON.stringify(waku_options));

View File

@ -1,10 +1,5 @@
import { createEncoder } from "@waku/core"; import { createEncoder } from "@waku/core";
import { import { IRateLimitProof, LightNode, ProtocolError } from "@waku/interfaces";
DefaultPubsubTopic,
IRateLimitProof,
LightNode,
ProtocolError
} from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
@ -24,8 +19,10 @@ import {
messagePayload, messagePayload,
messageText, messageText,
TestContentTopic, TestContentTopic,
TestEncoder TestEncoder,
} from "./utils"; TestPubsubTopic,
TestShardInfo
} from "./utils.js";
const runTests = (strictNodeCheck: boolean): void => { const runTests = (strictNodeCheck: boolean): void => {
const numServiceNodes = 3; const numServiceNodes = 3;
@ -38,9 +35,8 @@ const runTests = (strictNodeCheck: boolean): void => {
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[serviceNodes, waku] = await runMultipleNodes( [serviceNodes, waku] = await runMultipleNodes(
this.ctx, this.ctx,
[DefaultPubsubTopic], TestShardInfo,
strictNodeCheck, strictNodeCheck,
undefined,
numServiceNodes, numServiceNodes,
true true
); );
@ -57,12 +53,15 @@ const runTests = (strictNodeCheck: boolean): void => {
}); });
expect(pushResponse.successes.length).to.eq(numServiceNodes); expect(pushResponse.successes.length).to.eq(numServiceNodes);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
true await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(true);
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: testItem.value, 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(pushResponse.successes.length).to.eq(numServiceNodes);
} }
expect(await serviceNodes.messageCollector.waitForMessages(30)).to.eq( expect(
true await serviceNodes.messageCollector.waitForMessages(30, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(true);
for (let i = 0; i < 30; i++) { for (let i = 0; i < 30; i++) {
serviceNodes.messageCollector.verifyReceivedMessage(i, { serviceNodes.messageCollector.verifyReceivedMessage(i, {
expectedMessageText: generateMessageText(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); expect(pushResponse.successes.length).to.eq(0);
console.log("validated 1");
expect(pushResponse.failures?.map((failure) => failure.error)).to.include( expect(pushResponse.failures?.map((failure) => failure.error)).to.include(
ProtocolError.EMPTY_PAYLOAD ProtocolError.EMPTY_PAYLOAD
); );
console.log("validated 2");
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
false await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
console.log("validated 3"); })
).to.eq(false);
}); });
TEST_STRING.forEach((testItem) => { TEST_STRING.forEach((testItem) => {
it(`Push message with content topic containing ${testItem.description}`, async function () { it(`Push message with content topic containing ${testItem.description}`, async function () {
const customEncoder = createEncoder({ const customEncoder = createEncoder({
contentTopic: testItem.value contentTopic: testItem.value,
pubsubTopic: TestPubsubTopic
}); });
const pushResponse = await waku.lightPush.send( const pushResponse = await waku.lightPush.send(
customEncoder, customEncoder,
@ -117,12 +121,15 @@ const runTests = (strictNodeCheck: boolean): void => {
); );
expect(pushResponse.successes.length).to.eq(numServiceNodes); expect(pushResponse.successes.length).to.eq(numServiceNodes);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
true await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(true);
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, 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 () { it("Push message with meta", async function () {
const customTestEncoder = createEncoder({ const customTestEncoder = createEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
metaSetter: () => new Uint8Array(10) metaSetter: () => new Uint8Array(10),
pubsubTopic: TestPubsubTopic
}); });
const pushResponse = await waku.lightPush.send( const pushResponse = await waku.lightPush.send(
@ -150,18 +158,22 @@ const runTests = (strictNodeCheck: boolean): void => {
); );
expect(pushResponse.successes.length).to.eq(numServiceNodes); expect(pushResponse.successes.length).to.eq(numServiceNodes);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
true await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(true);
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
it("Fails to push message with large meta", async function () { it("Fails to push message with large meta", async function () {
const customTestEncoder = createEncoder({ const customTestEncoder = createEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
pubsubTopic: TestPubsubTopic,
metaSetter: () => new Uint8Array(105024) // see the note below *** metaSetter: () => new Uint8Array(105024) // see the note below ***
}); });
@ -179,21 +191,26 @@ const runTests = (strictNodeCheck: boolean): void => {
if (serviceNodes.type == "go-waku") { if (serviceNodes.type == "go-waku") {
expect(pushResponse.successes.length).to.eq(numServiceNodes); expect(pushResponse.successes.length).to.eq(numServiceNodes);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
true await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(true);
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
} else { } else {
expect(pushResponse.successes.length).to.eq(0); expect(pushResponse.successes.length).to.eq(0);
expect( expect(
pushResponse.failures?.map((failure) => failure.error) pushResponse.failures?.map((failure) => failure.error)
).to.include(ProtocolError.REMOTE_PEER_REJECTED); ).to.include(ProtocolError.REMOTE_PEER_REJECTED);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
false 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(pushResponse.successes.length).to.eq(numServiceNodes);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
true await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(true);
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, 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(pushResponse.successes.length).to.eq(numServiceNodes);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
true await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(true);
serviceNodes.messageCollector.verifyReceivedMessage(0, { serviceNodes.messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedTimestamp: testItem, 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( expect(pushResponse.failures?.map((failure) => failure.error)).to.include(
ProtocolError.SIZE_TOO_BIG ProtocolError.SIZE_TOO_BIG
); );
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq( expect(
false await serviceNodes.messageCollector.waitForMessages(1, {
); pubsubTopic: TestPubsubTopic
})
).to.eq(false);
}); });
}); });
}; };

View File

@ -1,10 +1,5 @@
import { createEncoder } from "@waku/core"; import { createEncoder } from "@waku/core";
import { import { IRateLimitProof, LightNode, ProtocolError } from "@waku/interfaces";
DefaultPubsubTopic,
IRateLimitProof,
LightNode,
ProtocolError
} from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk"; import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai"; import { expect } from "chai";
@ -22,7 +17,9 @@ import {
messageText, messageText,
runNodes, runNodes,
TestContentTopic, TestContentTopic,
TestEncoder TestEncoder,
TestPubsubTopic,
TestShardInfo
} from "../utils.js"; } from "../utils.js";
describe("Waku Light Push: Single Node", function () { describe("Waku Light Push: Single Node", function () {
@ -33,10 +30,10 @@ describe("Waku Light Push: Single Node", function () {
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes(this.ctx, [DefaultPubsubTopic]); [nwaku, waku] = await runNodes(this.ctx, TestShardInfo);
messageCollector = new MessageCollector(nwaku); messageCollector = new MessageCollector(nwaku);
await nwaku.ensureSubscriptions(); await nwaku.ensureSubscriptions([TestPubsubTopic]);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -50,10 +47,15 @@ describe("Waku Light Push: Single Node", function () {
}); });
expect(pushResponse.successes.length).to.eq(1); 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, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: testItem.value, 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(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++) { for (let i = 0; i < 30; i++) {
messageCollector.verifyReceivedMessage(i, { messageCollector.verifyReceivedMessage(i, {
expectedMessageText: generateMessageText(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( expect(pushResponse.failures?.map((failure) => failure.error)).to.include(
ProtocolError.EMPTY_PAYLOAD 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) => { TEST_STRING.forEach((testItem) => {
it(`Push message with content topic containing ${testItem.description}`, async function () { it(`Push message with content topic containing ${testItem.description}`, async function () {
const customEncoder = createEncoder({ const customEncoder = createEncoder({
contentTopic: testItem.value contentTopic: testItem.value,
pubsubTopic: TestPubsubTopic
}); });
const pushResponse = await waku.lightPush.send( const pushResponse = await waku.lightPush.send(
customEncoder, customEncoder,
@ -101,10 +113,15 @@ describe("Waku Light Push: Single Node", function () {
); );
expect(pushResponse.successes.length).to.eq(1); 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, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, 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 () { it("Push message with meta", async function () {
const customTestEncoder = createEncoder({ const customTestEncoder = createEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
metaSetter: () => new Uint8Array(10) metaSetter: () => new Uint8Array(10),
pubsubTopic: TestPubsubTopic
}); });
const pushResponse = await waku.lightPush.send( 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(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, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
}); });
it("Fails to push message with large meta", async function () { it("Fails to push message with large meta", async function () {
const customTestEncoder = createEncoder({ const customTestEncoder = createEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
pubsubTopic: TestPubsubTopic,
metaSetter: () => new Uint8Array(105024) // see the note below *** metaSetter: () => new Uint8Array(105024) // see the note below ***
}); });
@ -159,17 +183,26 @@ describe("Waku Light Push: Single Node", function () {
if (nwaku.type == "go-waku") { if (nwaku.type == "go-waku") {
expect(pushResponse.successes.length).to.eq(1); 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, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic expectedContentTopic: TestContentTopic,
expectedPubsubTopic: TestPubsubTopic
}); });
} else { } else {
expect(pushResponse.successes.length).to.eq(0); expect(pushResponse.successes.length).to.eq(0);
expect(pushResponse.failures?.map((failure) => failure.error)).to.include( expect(pushResponse.failures?.map((failure) => failure.error)).to.include(
ProtocolError.REMOTE_PEER_REJECTED 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(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, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, 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(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, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, expectedMessageText: messageText,
expectedTimestamp: testItem, 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( expect(pushResponse.failures?.map((failure) => failure.error)).to.include(
ProtocolError.SIZE_TOO_BIG ProtocolError.SIZE_TOO_BIG
); );
expect(await messageCollector.waitForMessages(1)).to.eq(false); expect(
await messageCollector.waitForMessages(1, {
pubsubTopic: TestPubsubTopic
})
).to.eq(false);
}); });
}); });

View File

@ -5,6 +5,7 @@ import {
LightNode, LightNode,
Protocols, Protocols,
ShardInfo, ShardInfo,
ShardingParams,
SingleShardInfo SingleShardInfo
} from "@waku/interfaces"; } from "@waku/interfaces";
import { import {
@ -15,6 +16,7 @@ import {
} from "@waku/utils"; } from "@waku/utils";
import { utf8ToBytes } from "@waku/utils/bytes"; import { utf8ToBytes } from "@waku/utils/bytes";
import { expect } from "chai"; import { expect } from "chai";
import { Context } from "mocha";
import { import {
afterEachCustom, afterEachCustom,
@ -32,14 +34,13 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
let nwaku2: ServiceNode; let nwaku2: ServiceNode;
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
const customPubsubTopic1 = singleShardInfoToPubsubTopic({
clusterId: 3,
shard: 1
});
const shardInfo: ShardInfo = { clusterId: 3, shards: [1, 2] }; const shardInfo: ShardInfo = { clusterId: 3, shards: [1, 2] };
const singleShardInfo1: SingleShardInfo = { clusterId: 3, shard: 1 }; const singleShardInfo1: SingleShardInfo = { clusterId: 3, shard: 1 };
const singleShardInfo2: SingleShardInfo = { clusterId: 3, shard: 2 }; const singleShardInfo2: SingleShardInfo = { clusterId: 3, shard: 2 };
const customPubsubTopic1 = singleShardInfoToPubsubTopic(singleShardInfo1);
const customPubsubTopic2 = singleShardInfoToPubsubTopic(singleShardInfo2);
const customContentTopic1 = "/test/2/waku-light-push/utf8"; const customContentTopic1 = "/test/2/waku-light-push/utf8";
const customContentTopic2 = "/test/3/waku-light-push/utf8"; const customContentTopic2 = "/test/3/waku-light-push/utf8";
const customEncoder1 = createEncoder({ const customEncoder1 = createEncoder({
@ -54,14 +55,7 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
let nimPeerId: PeerId; let nimPeerId: PeerId;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes( [nwaku, waku] = await runNodes(this.ctx, shardInfo);
this.ctx,
[
singleShardInfoToPubsubTopic(singleShardInfo1),
singleShardInfoToPubsubTopic(singleShardInfo2)
],
shardInfo
);
messageCollector = new MessageCollector(nwaku); messageCollector = new MessageCollector(nwaku);
nimPeerId = await nwaku.getPeerId(); nimPeerId = await nwaku.getPeerId();
}); });
@ -108,7 +102,7 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
expect( expect(
await messageCollector2.waitForMessages(1, { await messageCollector2.waitForMessages(1, {
pubsubTopic: singleShardInfoToPubsubTopic(singleShardInfo2) pubsubTopic: customPubsubTopic2
}) })
).to.eq(true); ).to.eq(true);
@ -120,7 +114,7 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
messageCollector2.verifyReceivedMessage(0, { messageCollector2.verifyReceivedMessage(0, {
expectedMessageText: "M2", expectedMessageText: "M2",
expectedContentTopic: customContentTopic2, expectedContentTopic: customContentTopic2,
expectedPubsubTopic: customPubsubTopic1 expectedPubsubTopic: customPubsubTopic2
}); });
}); });
@ -204,11 +198,7 @@ describe("Waku Light Push (Autosharding): Multiple PubsubTopics", function () {
let nimPeerId: PeerId; let nimPeerId: PeerId;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes( [nwaku, waku] = await runNodes(this.ctx, shardInfo);
this.ctx,
[autoshardingPubsubTopic1, autoshardingPubsubTopic2],
shardInfo
);
messageCollector = new MessageCollector(nwaku); messageCollector = new MessageCollector(nwaku);
nimPeerId = await nwaku.getPeerId(); 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 () { describe("Waku Light Push (named sharding): Multiple PubsubTopics", function () {
this.timeout(30000); this.timeout(30000);
let waku: LightNode; let waku: LightNode;
let waku2: LightNode;
let nwaku: ServiceNode; let nwaku: ServiceNode;
let nwaku2: ServiceNode; let nwaku2: ServiceNode;
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
let ctx: Context;
const clusterId = 0; const clusterId = 3;
const customContentTopic1 = "/waku/2/content/utf8"; const customContentTopic1 = "/waku/2/content/utf8";
const customContentTopic2 = "/myapp/1/latest/proto"; const customContentTopic2 = "/myapp/1/latest/proto";
const autoshardingPubsubTopic1 = contentTopicToPubsubTopic( const autoshardingPubsubTopic1 = contentTopicToPubsubTopic(
@ -333,34 +325,44 @@ describe("Waku Light Push (named sharding): Multiple PubsubTopics", function ()
customContentTopic2, customContentTopic2,
clusterId clusterId
); );
const shardInfo1 = {
clusterId,
shards: [contentTopicToShardIndex(customContentTopic1)]
};
const customEncoder1 = createEncoder({ const customEncoder1 = createEncoder({
contentTopic: customContentTopic1, contentTopic: customContentTopic1,
pubsubTopicShardInfo: { pubsubTopicShardInfo: shardInfo1
clusterId,
shard: contentTopicToShardIndex(customContentTopic1)
}
}); });
const shardInfo2 = {
clusterId,
shards: [contentTopicToShardIndex(customContentTopic2)]
};
const customEncoder2 = createEncoder({ const customEncoder2 = createEncoder({
contentTopic: customContentTopic2, contentTopic: customContentTopic2,
pubsubTopicShardInfo: { pubsubTopicShardInfo: shardInfo2
clusterId,
shard: contentTopicToShardIndex(customContentTopic2)
}
}); });
const testShardInfo: ShardingParams = {
clusterId,
shards: [
contentTopicToShardIndex(customContentTopic1),
contentTopicToShardIndex(customContentTopic2)
]
};
let nimPeerId: PeerId; let nimPeerId: PeerId;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
[nwaku, waku] = await runNodes(this.ctx, [ ctx = this.ctx;
autoshardingPubsubTopic1, [nwaku, waku] = await runNodes(ctx, testShardInfo);
autoshardingPubsubTopic2
]);
messageCollector = new MessageCollector(nwaku); messageCollector = new MessageCollector(nwaku);
nimPeerId = await nwaku.getPeerId(); nimPeerId = await nwaku.getPeerId();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
await tearDownNodes([nwaku, nwaku2], waku); await tearDownNodes([nwaku, nwaku2], [waku, waku2]);
}); });
it("Push message on custom pubsubTopic", async function () { 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 () { 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 // Set up and start a new nwaku node with Default PubsubTopic
nwaku2 = new ServiceNode(makeLogFileName(this) + "2"); [nwaku2, waku2] = await runNodes(ctx, shardInfo2);
await nwaku2.start({
filter: true,
lightpush: true,
relay: true,
pubsubTopic: [autoshardingPubsubTopic2]
});
await nwaku2.ensureSubscriptions([autoshardingPubsubTopic2]); await nwaku2.ensureSubscriptions([autoshardingPubsubTopic2]);
await waku.dial(await nwaku2.getMultiaddrWithId()); await waku.dial(await nwaku2.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.LightPush]); await waitForRemotePeer(waku, [Protocols.LightPush]);

View File

@ -1,78 +1,26 @@
import { createEncoder, waitForRemotePeer } from "@waku/core"; import { createEncoder } from "@waku/core";
import { import { utf8ToBytes } from "@waku/sdk";
ContentTopicInfo, import { contentTopicToPubsubTopic, Logger } from "@waku/utils";
DefaultPubsubTopic,
LightNode,
Protocols,
ShardingParams
} from "@waku/interfaces";
import { createLightNode, utf8ToBytes } from "@waku/sdk";
import { 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. // Constants for test configuration.
export const log = new Logger("test:lightpush"); export const log = new Logger("test:lightpush");
export const TestContentTopic = "/test/1/waku-light-push/utf8"; 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 messageText = "Light Push works!";
export const messagePayload = { payload: utf8ToBytes(messageText) }; export const messagePayload = { payload: utf8ToBytes(messageText) };
export async function runNodes( export { 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");
}
}

View File

@ -13,7 +13,6 @@ import {
createDecoder as createSymDecoder, createDecoder as createSymDecoder,
createEncoder as createSymEncoder createEncoder as createSymEncoder
} from "@waku/message-encryption/symmetric"; } from "@waku/message-encryption/symmetric";
import { createRelayNode } from "@waku/sdk/relay";
import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes";
import { expect } from "chai"; import { expect } from "chai";
@ -21,12 +20,10 @@ import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
delay, delay,
NOISE_KEY_1,
NOISE_KEY_2,
tearDownNodes tearDownNodes
} from "../../src/index.js"; } from "../../src/index.js";
import { log, waitForAllRemotePeers } from "./utils.js"; import { runJSNodes, TestPubsubTopic } from "./utils.js";
describe("Waku Relay", function () { describe("Waku Relay", function () {
this.timeout(15000); this.timeout(15000);
@ -34,24 +31,7 @@ describe("Waku Relay", function () {
let waku2: RelayNode; let waku2: RelayNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
log.info("Starting JS Waku instances"); [waku1, waku2] = await runJSNodes();
[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");
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -70,15 +50,21 @@ describe("Waku Relay", function () {
const eciesEncoder = createEciesEncoder({ const eciesEncoder = createEciesEncoder({
contentTopic: asymTopic, contentTopic: asymTopic,
publicKey publicKey,
pubsubTopic: TestPubsubTopic
}); });
const symEncoder = createSymEncoder({ const symEncoder = createSymEncoder({
contentTopic: symTopic, contentTopic: symTopic,
symKey symKey,
pubsubTopic: TestPubsubTopic
}); });
const eciesDecoder = createEciesDecoder(asymTopic, privateKey); const eciesDecoder = createEciesDecoder(
const symDecoder = createSymDecoder(symTopic, symKey); asymTopic,
privateKey,
TestPubsubTopic
);
const symDecoder = createSymDecoder(symTopic, symKey, TestPubsubTopic);
const msgs: DecodedMessage[] = []; const msgs: DecodedMessage[] = [];
void waku2.relay.subscribe([eciesDecoder], (wakuMsg) => { void waku2.relay.subscribe([eciesDecoder], (wakuMsg) => {
@ -106,7 +92,7 @@ describe("Waku Relay", function () {
const messageText = const messageText =
"Published on content topic with added then deleted observer"; "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. // The promise **fails** if we receive a message on this observer.
const receivedMsgPromise: Promise<DecodedMessage> = new Promise( const receivedMsgPromise: Promise<DecodedMessage> = new Promise(

View File

@ -1,6 +1,6 @@
import type { PeerId } from "@libp2p/interface"; import type { PeerId } from "@libp2p/interface";
import { DecodedMessage, waitForRemotePeer } from "@waku/core"; 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 { createRelayNode } from "@waku/sdk/relay";
import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes";
import { expect } from "chai"; import { expect } from "chai";
@ -10,15 +10,20 @@ import {
base64ToUtf8, base64ToUtf8,
beforeEachCustom, beforeEachCustom,
delay, delay,
makeLogFileName,
NOISE_KEY_1,
NOISE_KEY_2, NOISE_KEY_2,
ServiceNode, ServiceNode,
tearDownNodes tearDownNodes
} from "../../src/index.js"; } from "../../src/index.js";
import { MessageRpcResponse } from "../../src/types.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 () { describe("Waku Relay, Interop", function () {
this.timeout(15000); this.timeout(15000);
@ -26,19 +31,7 @@ describe("Waku Relay, Interop", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
waku = await createRelayNode({ [nwaku, waku] = await runRelayNodes(this.ctx, TestShardInfo);
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();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -51,7 +44,7 @@ describe("Waku Relay, Interop", function () {
while (subscribers.length === 0) { while (subscribers.length === 0) {
await delay(200); await delay(200);
subscribers = subscribers =
waku.libp2p.services.pubsub!.getSubscribers(DefaultPubsubTopic); waku.libp2p.services.pubsub!.getSubscribers(TestPubsubTopic);
} }
const nimPeerId = await nwaku.getPeerId(); const nimPeerId = await nwaku.getPeerId();
@ -103,49 +96,23 @@ describe("Waku Relay, Interop", function () {
expect(bytesToUtf8(receivedMsg.payload!)).to.eq(messageText); 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 () { it("Js publishes, other Js receives", async function () {
[waku1, waku2] = await Promise.all([ const waku2 = await createRelayNode({
createRelayNode({ staticNoiseKey: NOISE_KEY_2,
staticNoiseKey: NOISE_KEY_1, emitSelf: true,
emitSelf: true shardInfo: TestShardInfo
}).then((waku) => waku.start().then(() => waku)), });
createRelayNode({ await waku2.start();
staticNoiseKey: NOISE_KEY_2
}).then((waku) => waku.start().then(() => waku))
]);
nwaku = new ServiceNode(makeLogFileName(this));
await nwaku.start({ relay: true });
const nwakuMultiaddr = await nwaku.getMultiaddrWithId(); const nwakuMultiaddr = await nwaku.getMultiaddrWithId();
await Promise.all([ await waku2.dial(nwakuMultiaddr);
waku1.dial(nwakuMultiaddr),
waku2.dial(nwakuMultiaddr)
]);
// Wait for identify protocol to finish await waitForRemotePeer(waku2, [Protocols.Relay]);
await Promise.all([
waitForRemotePeer(waku1, [Protocols.Relay]),
waitForRemotePeer(waku2, [Protocols.Relay])
]);
await delay(2000); await delay(2000);
// Check that the two JS peers are NOT directly connected // Check that the two JS peers are NOT directly connected
expect(await waku1.libp2p.peerStore.has(waku2.libp2p.peerId)).to.eq( expect(await waku.libp2p.peerStore.has(waku2.libp2p.peerId)).to.eq(false);
false expect(await waku2.libp2p.peerStore.has(waku.libp2p.peerId)).to.eq(false);
);
expect(await waku2.libp2p.peerStore.has(waku1.libp2p.peerId)).to.eq(
false
);
const msgStr = "Hello there!"; const msgStr = "Hello there!";
const message = { payload: utf8ToBytes(msgStr) }; const message = { payload: utf8ToBytes(msgStr) };
@ -156,10 +123,11 @@ describe("Waku Relay, Interop", function () {
} }
); );
await waku1.relay.send(TestEncoder, message); await waku.relay.send(TestEncoder, message);
const waku2ReceivedMsg = await waku2ReceivedMsgPromise; const waku2ReceivedMsg = await waku2ReceivedMsgPromise;
expect(bytesToUtf8(waku2ReceivedMsg.payload)).to.eq(msgStr); expect(bytesToUtf8(waku2ReceivedMsg.payload)).to.eq(msgStr);
});
await tearDownNodes([], waku);
}); });
}); });

View File

@ -1,6 +1,5 @@
import { createEncoder } from "@waku/core"; import { createEncoder } from "@waku/core";
import { IRateLimitProof, ProtocolError, RelayNode } from "@waku/interfaces"; import { IRateLimitProof, ProtocolError, RelayNode } from "@waku/interfaces";
import { createRelayNode } from "@waku/sdk/relay";
import { utf8ToBytes } from "@waku/utils/bytes"; import { utf8ToBytes } from "@waku/utils/bytes";
import { expect } from "chai"; import { expect } from "chai";
@ -10,18 +9,20 @@ import {
delay, delay,
generateRandomUint8Array, generateRandomUint8Array,
MessageCollector, MessageCollector,
NOISE_KEY_1,
NOISE_KEY_2,
tearDownNodes, tearDownNodes,
TEST_STRING TEST_STRING
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
log,
messageText, messageText,
runJSNodes,
TestContentTopic, TestContentTopic,
TestDecoder, TestDecoder,
TestEncoder, TestEncoder,
TestExpectOptions,
TestPubsubTopic,
TestShardInfo,
TestWaitMessageOptions,
waitForAllRemotePeers waitForAllRemotePeers
} from "./utils.js"; } from "./utils.js";
@ -32,23 +33,7 @@ describe("Waku Relay, Publish", function () {
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
log.info("Starting JS Waku instances"); [waku1, waku2] = await runJSNodes();
[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);
messageCollector = new MessageCollector(); messageCollector = new MessageCollector();
await waku2.relay.subscribe([TestDecoder], messageCollector.callback); await waku2.relay.subscribe([TestDecoder], messageCollector.callback);
}); });
@ -66,10 +51,12 @@ describe("Waku Relay, Publish", function () {
expect(pushResponse.successes[0].toString()).to.eq( expect(pushResponse.successes[0].toString()).to.eq(
waku2.libp2p.peerId.toString() waku2.libp2p.peerId.toString()
); );
expect(await messageCollector.waitForMessages(1)).to.eq(true); expect(
await messageCollector.waitForMessages(1, TestWaitMessageOptions)
).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: testItem.value, ...TestExpectOptions,
expectedContentTopic: TestContentTopic expectedMessageText: testItem.value
}); });
}); });
}); });
@ -91,11 +78,13 @@ describe("Waku Relay, Publish", function () {
waku2.libp2p.peerId.toString() waku2.libp2p.peerId.toString()
); );
expect(await messageCollector.waitForMessages(1)).to.eq(true); expect(
await messageCollector.waitForMessages(1, TestWaitMessageOptions)
).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
...TestExpectOptions,
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: TestContentTopic,
expectedTimestamp: testItem.valueOf() expectedTimestamp: testItem.valueOf()
}); });
}); });
@ -115,20 +104,30 @@ describe("Waku Relay, Publish", function () {
it("Fails to publish message with empty text", async function () { it("Fails to publish message with empty text", async function () {
await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("") }); await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("") });
await delay(400); 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 () { 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, { await waku1.relay.send(wrong_encoder, {
payload: utf8ToBytes("") 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 () { it("Fails to publish message with wrong pubsubtopic", async function () {
const wrong_encoder = createEncoder({ const wrong_encoder = createEncoder({
pubsubTopicShardInfo: { clusterId: 3, shard: 1 }, pubsubTopicShardInfo: {
clusterId: TestShardInfo.clusterId,
shard: TestShardInfo.shards[0] + 1
},
contentTopic: TestContentTopic contentTopic: TestContentTopic
}); });
const pushResponse = await waku1.relay.send(wrong_encoder, { const pushResponse = await waku1.relay.send(wrong_encoder, {
@ -138,7 +137,9 @@ describe("Waku Relay, Publish", function () {
ProtocolError.TOPIC_NOT_CONFIGURED ProtocolError.TOPIC_NOT_CONFIGURED
); );
await delay(400); 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) => { [1024 ** 2 + 65536, 2 * 1024 ** 2].forEach((testItem) => {
@ -151,7 +152,9 @@ describe("Waku Relay, Publish", function () {
ProtocolError.SIZE_TOO_BIG ProtocolError.SIZE_TOO_BIG
); );
await delay(400); 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( expect(pushResponse.successes[0].toString()).to.eq(
waku2.libp2p.peerId.toString() 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 // 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( expect(pushResponse.successes[0].toString()).to.eq(
waku2.libp2p.peerId.toString() 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 () { it("Publish message with large meta", async function () {
const customTestEncoder = createEncoder({ const customTestEncoder = createEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic,
pubsubTopic: TestPubsubTopic,
metaSetter: () => new Uint8Array(10 ** 6) metaSetter: () => new Uint8Array(10 ** 6)
}); });
@ -218,7 +226,9 @@ describe("Waku Relay, Publish", function () {
expect(pushResponse.successes[0].toString()).to.eq( expect(pushResponse.successes[0].toString()).to.eq(
waku2.libp2p.peerId.toString() 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 () { 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(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, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, ...TestExpectOptions,
expectedContentTopic: TestContentTopic expectedMessageText: messageText
}); });
}); });
}); });

View File

@ -1,5 +1,5 @@
import { createDecoder, createEncoder } from "@waku/core"; import { createDecoder, createEncoder } from "@waku/core";
import { DefaultPubsubTopic, RelayNode } from "@waku/interfaces"; import { RelayNode } from "@waku/interfaces";
import { createRelayNode } from "@waku/sdk/relay"; import { createRelayNode } from "@waku/sdk/relay";
import { utf8ToBytes } from "@waku/utils/bytes"; import { utf8ToBytes } from "@waku/utils/bytes";
import { expect } from "chai"; import { expect } from "chai";
@ -10,17 +10,19 @@ import {
generateTestData, generateTestData,
MessageCollector, MessageCollector,
NOISE_KEY_1, NOISE_KEY_1,
NOISE_KEY_2,
tearDownNodes, tearDownNodes,
TEST_STRING TEST_STRING
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
log,
messageText, messageText,
TestContentTopic, runJSNodes,
TestDecoder, TestDecoder,
TestEncoder, TestEncoder,
TestExpectOptions,
TestPubsubTopic,
TestShardInfo,
TestWaitMessageOptions,
waitForAllRemotePeers waitForAllRemotePeers
} from "./utils.js"; } from "./utils.js";
@ -31,22 +33,7 @@ describe("Waku Relay, Subscribe", function () {
let messageCollector: MessageCollector; let messageCollector: MessageCollector;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
log.info("Starting JS Waku instances"); [waku1, waku2] = await runJSNodes();
[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");
messageCollector = new MessageCollector(this.ctx.nwaku); messageCollector = new MessageCollector(this.ctx.nwaku);
}); });
@ -57,10 +44,10 @@ describe("Waku Relay, Subscribe", function () {
it("Mutual subscription", async function () { it("Mutual subscription", async function () {
await waitForAllRemotePeers(waku1, waku2); await waitForAllRemotePeers(waku1, waku2);
const subscribers1 = waku1.libp2p.services const subscribers1 = waku1.libp2p.services
.pubsub!.getSubscribers(DefaultPubsubTopic) .pubsub!.getSubscribers(TestPubsubTopic)
.map((p) => p.toString()); .map((p) => p.toString());
const subscribers2 = waku2.libp2p.services const subscribers2 = waku2.libp2p.services
.pubsub!.getSubscribers(DefaultPubsubTopic) .pubsub!.getSubscribers(TestPubsubTopic)
.map((p) => p.toString()); .map((p) => p.toString());
expect(subscribers1).to.contain(waku2.libp2p.peerId.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 () { it("Publish without waiting for remote peer", async function () {
try { 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) payload: utf8ToBytes(messageText)
}); });
throw new Error("Publish was successful but was expected to fail"); throw new Error("Publish was successful but was expected to fail");
} catch (err) { } catch (err) {
if ( if (
@ -91,19 +85,19 @@ describe("Waku Relay, Subscribe", function () {
}); });
it("Subscribe and publish message", async function () { it("Subscribe and publish message", 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(messageText) }); 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, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: messageText, ...TestExpectOptions,
expectedContentTopic: TestContentTopic expectedMessageText: messageText
}); });
}); });
it("Subscribe and publish 10000 messages on the same topic", async function () { it("Subscribe and publish 10000 messages on the same topic", async function () {
const messageCount = 10000; const messageCount = 10000;
await waitForAllRemotePeers(waku1, waku2);
await waku2.relay.subscribe([TestDecoder], messageCollector.callback); await waku2.relay.subscribe([TestDecoder], messageCollector.callback);
// Send a unique message on each topic. // Send a unique message on each topic.
for (let i = 0; i < messageCount; i++) { 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. // Verify that each message was received on the corresponding topic.
expect( expect(
await messageCollector.waitForMessages(messageCount, { exact: true }) await messageCollector.waitForMessages(messageCount, {
...TestWaitMessageOptions,
exact: true
})
).to.eq(true); ).to.eq(true);
for (let i = 0; i < messageCount; i++) { for (let i = 0; i < messageCount; i++) {
messageCollector.verifyReceivedMessage(i, { messageCollector.verifyReceivedMessage(i, {
...TestExpectOptions,
expectedMessageText: `M${i + 1}`, expectedMessageText: `M${i + 1}`,
expectedContentTopic: TestContentTopic,
checkTimestamp: false checkTimestamp: false
}); });
} }
@ -128,31 +125,36 @@ describe("Waku Relay, Subscribe", function () {
it("Subscribe and publish messages on 2 different content topics", async function () { it("Subscribe and publish messages on 2 different content topics", async function () {
const secondContentTopic = "/test/2/waku-relay/utf8"; const secondContentTopic = "/test/2/waku-relay/utf8";
const secondEncoder = createEncoder({ contentTopic: secondContentTopic }); const secondEncoder = createEncoder({
const secondDecoder = createDecoder(secondContentTopic); contentTopic: secondContentTopic,
pubsubTopic: TestPubsubTopic
});
const secondDecoder = createDecoder(secondContentTopic, TestPubsubTopic);
await waitForAllRemotePeers(waku1, waku2);
await waku2.relay.subscribe([TestDecoder], messageCollector.callback); await waku2.relay.subscribe([TestDecoder], messageCollector.callback);
await waku2.relay.subscribe([secondDecoder], messageCollector.callback); await waku2.relay.subscribe([secondDecoder], messageCollector.callback);
await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("M1") }); await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("M1") });
await waku1.relay.send(secondEncoder, { payload: utf8ToBytes("M2") }); await waku1.relay.send(secondEncoder, { payload: utf8ToBytes("M2") });
expect(await messageCollector.waitForMessages(2, { exact: true })).to.eq( expect(
true await messageCollector.waitForMessages(2, {
); ...TestWaitMessageOptions,
exact: true
})
).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
expectedMessageText: "M1", ...TestExpectOptions,
expectedContentTopic: TestContentTopic expectedMessageText: "M1"
}); });
messageCollector.verifyReceivedMessage(1, { messageCollector.verifyReceivedMessage(1, {
expectedMessageText: "M2", ...TestExpectOptions,
expectedContentTopic: secondContentTopic expectedContentTopic: secondEncoder.contentTopic,
expectedMessageText: "M2"
}); });
}); });
it("Subscribe one by one to 100 topics and publish messages", async function () { it("Subscribe one by one to 100 topics and publish messages", async function () {
const topicCount = 100; const topicCount = 100;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, TestWaitMessageOptions);
await waitForAllRemotePeers(waku1, waku2);
// Subscribe to topics one by one // Subscribe to topics one by one
for (let i = 0; i < topicCount; i++) { 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. // Verify that each message was received on the corresponding topic.
expect( expect(
await messageCollector.waitForMessages(topicCount, { exact: true }) await messageCollector.waitForMessages(topicCount, {
...TestWaitMessageOptions,
exact: true
})
).to.eq(true); ).to.eq(true);
td.contentTopics.forEach((topic, index) => { td.contentTopics.forEach((topic, index) => {
messageCollector.verifyReceivedMessage(index, { messageCollector.verifyReceivedMessage(index, {
...TestExpectOptions,
expectedContentTopic: topic, expectedContentTopic: topic,
expectedMessageText: `Message for Topic ${index + 1}` 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 () { it("Subscribe at once to 10000 topics and publish messages", async function () {
const topicCount = 10000; const topicCount = 10000;
const td = generateTestData(topicCount); const td = generateTestData(topicCount, TestWaitMessageOptions);
await waitForAllRemotePeers(waku1, waku2);
// Subscribe to all topics at once // Subscribe to all topics at once
await waku2.relay.subscribe(td.decoders, messageCollector.callback); 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. // Verify that each message was received on the corresponding topic.
expect( expect(
await messageCollector.waitForMessages(topicCount, { exact: true }) await messageCollector.waitForMessages(topicCount, {
...TestWaitMessageOptions,
exact: true
})
).to.eq(true); ).to.eq(true);
td.contentTopics.forEach((topic, index) => { td.contentTopics.forEach((topic, index) => {
messageCollector.verifyReceivedMessage(index, { messageCollector.verifyReceivedMessage(index, {
...TestExpectOptions,
expectedContentTopic: topic, expectedContentTopic: topic,
expectedMessageText: `Message for Topic ${index + 1}`, expectedMessageText: `Message for Topic ${index + 1}`,
checkTimestamp: false 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 // Will be skipped until https://github.com/waku-org/js-waku/issues/1678 is fixed
it.skip("Refresh subscription", async function () { 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 waku2.relay.subscribe([TestDecoder], messageCollector.callback); await waku2.relay.subscribe([TestDecoder], messageCollector.callback);
await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("M1") }); await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("M1") });
expect(await messageCollector.waitForMessages(1, { exact: true })).to.eq( expect(
true 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 // Will be skipped until https://github.com/waku-org/js-waku/issues/1678 is fixed
it.skip("Overlapping topic subscription", async function () { it.skip("Overlapping topic subscription", async function () {
// Define two sets of test data with overlapping topics. // Define two sets of test data with overlapping topics.
const topicCount1 = 2; const topicCount1 = 2;
const td1 = generateTestData(topicCount1); const td1 = generateTestData(topicCount1, TestWaitMessageOptions);
const topicCount2 = 4; const topicCount2 = 4;
const td2 = generateTestData(topicCount2); const td2 = generateTestData(topicCount2, TestWaitMessageOptions);
await waitForAllRemotePeers(waku1, waku2);
// Subscribe to the first set of topics. // Subscribe to the first set of topics.
await waku2.relay.subscribe(td1.decoders, messageCollector.callback); await waku2.relay.subscribe(td1.decoders, messageCollector.callback);
@ -252,23 +261,33 @@ describe("Waku Relay, Subscribe", function () {
// Check if all messages were received. // 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). // 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( expect(
true await messageCollector.waitForMessages(6, {
); ...TestWaitMessageOptions,
exact: true
})
).to.eq(true);
}); });
TEST_STRING.forEach((testItem) => { TEST_STRING.forEach((testItem) => {
it(`Subscribe to topic containing ${testItem.description} and publish message`, async function () { it(`Subscribe to topic containing ${testItem.description} and publish message`, async function () {
const newContentTopic = testItem.value; const newContentTopic = testItem.value;
const newEncoder = createEncoder({ contentTopic: newContentTopic }); const newEncoder = createEncoder({
const newDecoder = createDecoder(newContentTopic); contentTopic: newContentTopic,
await waitForAllRemotePeers(waku1, waku2); pubsubTopic: TestPubsubTopic
});
const newDecoder = createDecoder(newContentTopic, TestPubsubTopic);
await waku2.relay.subscribe([newDecoder], messageCollector.callback); await waku2.relay.subscribe([newDecoder], messageCollector.callback);
await waku1.relay.send(newEncoder, { await waku1.relay.send(newEncoder, {
payload: utf8ToBytes(messageText) payload: utf8ToBytes(messageText)
}); });
expect(await messageCollector.waitForMessages(1)).to.eq(true);
expect(
await messageCollector.waitForMessages(1, TestWaitMessageOptions)
).to.eq(true);
messageCollector.verifyReceivedMessage(0, { messageCollector.verifyReceivedMessage(0, {
...TestExpectOptions,
expectedMessageText: messageText, expectedMessageText: messageText,
expectedContentTopic: newContentTopic expectedContentTopic: newContentTopic
}); });

View File

@ -1,18 +1,85 @@
import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core"; import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core";
import { Protocols, RelayNode } from "@waku/interfaces"; import {
import { Logger } from "@waku/utils"; 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 messageText = "Relay works!";
export const TestContentTopic = "/test/1/waku-relay/utf8"; export const TestContentTopic = "/test/1/waku-relay/utf8";
export const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); export const TestShardInfo: ShardInfo = {
export const TestDecoder = createDecoder(TestContentTopic); 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"); export const log = new Logger("test:relay");
const RELAY_PROTOCOLS = [Protocols.Relay];
export async function waitForAllRemotePeers( export async function waitForAllRemotePeers(
...nodes: RelayNode[] ...nodes: RelayNode[]
): Promise<void> { ): Promise<void> {
log.info("Wait for mutual pubsub subscription"); log.info("Wait for mutual pubsub subscription");
await Promise.all( await Promise.all(
nodes.map((node) => waitForRemotePeer(node, [Protocols.Relay])) nodes.map((node): Promise<void> => waitForRemotePeer(node, RELAY_PROTOCOLS))
); );
} }
export const runRelayNodes = (
context: Context,
shardInfo: ShardingParams
): Promise<[ServiceNode, RelayNode]> =>
runNodes<RelayNode>({
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];
}

View File

@ -1,23 +1,22 @@
import { DecodedMessage } from "@waku/core"; import { DecodedMessage } from "@waku/core";
import type { LightNode } from "@waku/interfaces"; import type { LightNode } from "@waku/interfaces";
import { DefaultPubsubTopic } from "@waku/interfaces";
import { bytesToUtf8 } from "@waku/utils/bytes"; import { bytesToUtf8 } from "@waku/utils/bytes";
import { expect } from "chai"; import { expect } from "chai";
import { import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
makeLogFileName,
ServiceNode, ServiceNode,
tearDownNodes tearDownNodes
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
customShardedPubsubTopic1, runStoreNodes,
sendMessages, sendMessages,
startAndConnectLightNode, startAndConnectLightNode,
TestContentTopic,
TestDecoder, TestDecoder,
TestDecoder2,
TestShardInfo,
totalMsgs totalMsgs
} from "./utils.js"; } from "./utils.js";
@ -28,9 +27,7 @@ describe("Waku Store, cursor", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
await nwaku.start({ store: true, lightpush: true, relay: true });
await nwaku.ensureSubscriptions();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -49,10 +46,9 @@ describe("Waku Store, cursor", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
messageCount, messageCount,
TestContentTopic, TestDecoder.contentTopic,
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku);
// messages in reversed order (first message at last index) // messages in reversed order (first message at last index)
const messages: DecodedMessage[] = []; const messages: DecodedMessage[] = [];
@ -95,9 +91,13 @@ describe("Waku Store, cursor", function () {
}); });
it("Reusing cursor across nodes", async function () { it("Reusing cursor across nodes", async function () {
await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
waku2 = await startAndConnectLightNode(nwaku); totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
waku2 = await startAndConnectLightNode(nwaku, TestShardInfo);
// messages in reversed order (first message at last index) // messages in reversed order (first message at last index)
const messages: DecodedMessage[] = []; const messages: DecodedMessage[] = [];
@ -133,8 +133,12 @@ describe("Waku Store, cursor", function () {
}); });
it("Passing cursor with wrong message digest", async function () { it("Passing cursor with wrong message digest", async function () {
await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const messages: DecodedMessage[] = []; const messages: DecodedMessage[] = [];
for await (const page of waku.store.queryGenerator([TestDecoder])) { 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 () { it("Passing cursor with wrong pubsubTopic", async function () {
await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const messages: DecodedMessage[] = []; const messages: DecodedMessage[] = [];
for await (const page of waku.store.queryGenerator([TestDecoder])) { for await (const page of waku.store.queryGenerator([TestDecoder])) {
@ -184,7 +192,7 @@ describe("Waku Store, cursor", function () {
messages.push(msg as DecodedMessage); messages.push(msg as DecodedMessage);
} }
} }
messages[5].pubsubTopic = customShardedPubsubTopic1; messages[5].pubsubTopic = TestDecoder2.pubsubTopic;
const cursor = waku.store.createCursor(messages[5]); const cursor = waku.store.createCursor(messages[5]);
try { try {
@ -198,7 +206,7 @@ describe("Waku Store, cursor", function () {
if ( if (
!(err instanceof Error) || !(err instanceof Error) ||
!err.message.includes( !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; throw err;

View File

@ -1,21 +1,22 @@
import { DefaultPubsubTopic } from "@waku/interfaces"; import { createDecoder } from "@waku/core";
import { IMessage, type LightNode } from "@waku/interfaces"; import { IMessage, type LightNode } from "@waku/interfaces";
import { determinePubsubTopic } from "@waku/utils";
import { expect } from "chai"; import { expect } from "chai";
import { import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
makeLogFileName,
ServiceNode, ServiceNode,
tearDownNodes tearDownNodes
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
customDecoder1,
customShardedPubsubTopic1,
processQueriedMessages, processQueriedMessages,
startAndConnectLightNode, runStoreNodes,
TestDecoder TestContentTopic1,
TestDecoder,
TestDecoder2,
TestShardInfo
} from "./utils.js"; } from "./utils.js";
describe("Waku Store, error handling", function () { describe("Waku Store, error handling", function () {
@ -24,10 +25,7 @@ describe("Waku Store, error handling", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
await nwaku.start({ store: true, lightpush: true, relay: true });
await nwaku.ensureSubscriptions();
waku = await startAndConnectLightNode(nwaku);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -35,9 +33,11 @@ describe("Waku Store, error handling", function () {
}); });
it("Query Generator, Wrong PubsubTopic", async function () { it("Query Generator, Wrong PubsubTopic", async function () {
const wrongDecoder = createDecoder(TestContentTopic1, "WrongPubsubTopic");
try { try {
for await (const msgPromises of waku.store.queryGenerator([ for await (const msgPromises of waku.store.queryGenerator([
customDecoder1 wrongDecoder
])) { ])) {
void msgPromises; void msgPromises;
} }
@ -46,7 +46,7 @@ describe("Waku Store, error handling", function () {
if ( if (
!(err instanceof Error) || !(err instanceof Error) ||
!err.message.includes( !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; throw err;
@ -58,7 +58,7 @@ describe("Waku Store, error handling", function () {
try { try {
for await (const msgPromises of waku.store.queryGenerator([ for await (const msgPromises of waku.store.queryGenerator([
TestDecoder, TestDecoder,
customDecoder1 TestDecoder2
])) { ])) {
void msgPromises; void msgPromises;
} }
@ -92,26 +92,25 @@ describe("Waku Store, error handling", function () {
}); });
it("Query Generator, No message returned", async function () { it("Query Generator, No message returned", async function () {
const WrongTestPubsubTopic = determinePubsubTopic("/test/1/wrong/utf8");
const messages = await processQueriedMessages( const messages = await processQueriedMessages(
waku, waku,
[TestDecoder], [TestDecoder],
DefaultPubsubTopic WrongTestPubsubTopic
); );
expect(messages?.length).eq(0); expect(messages?.length).eq(0);
}); });
it("Query with Ordered Callback, Wrong PubsubTopic", async function () { it("Query with Ordered Callback, Wrong PubsubTopic", async function () {
const wrongDecoder = createDecoder(TestContentTopic1, "WrongPubsubTopic");
try { try {
await waku.store.queryWithOrderedCallback( await waku.store.queryWithOrderedCallback([wrongDecoder], async () => {});
[customDecoder1],
async () => {}
);
throw new Error("QueryGenerator was successful but was expected to fail"); throw new Error("QueryGenerator was successful but was expected to fail");
} catch (err) { } catch (err) {
if ( if (
!(err instanceof Error) || !(err instanceof Error) ||
!err.message.includes( !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; throw err;
@ -122,7 +121,7 @@ describe("Waku Store, error handling", function () {
it("Query with Ordered Callback, Multiple PubsubTopics", async function () { it("Query with Ordered Callback, Multiple PubsubTopics", async function () {
try { try {
await waku.store.queryWithOrderedCallback( await waku.store.queryWithOrderedCallback(
[TestDecoder, customDecoder1], [TestDecoder, TestDecoder2],
async () => {} async () => {}
); );
throw new Error("QueryGenerator was successful but was expected to fail"); 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 () { it("Query with Promise Callback, Wrong PubsubTopic", async function () {
const wrongDecoder = createDecoder(TestContentTopic1, "WrongPubsubTopic");
try { try {
await waku.store.queryWithPromiseCallback( await waku.store.queryWithPromiseCallback([wrongDecoder], async () => {});
[customDecoder1],
async () => {}
);
throw new Error("QueryGenerator was successful but was expected to fail"); throw new Error("QueryGenerator was successful but was expected to fail");
} catch (err) { } catch (err) {
if ( if (
!(err instanceof Error) || !(err instanceof Error) ||
!err.message.includes( !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; throw err;
@ -182,7 +179,7 @@ describe("Waku Store, error handling", function () {
it("Query with Promise Callback, Multiple PubsubTopics", async function () { it("Query with Promise Callback, Multiple PubsubTopics", async function () {
try { try {
await waku.store.queryWithPromiseCallback( await waku.store.queryWithPromiseCallback(
[TestDecoder, customDecoder1], [TestDecoder, TestDecoder2],
async () => {} async () => {}
); );
throw new Error("QueryGenerator was successful but was expected to fail"); throw new Error("QueryGenerator was successful but was expected to fail");

View File

@ -1,6 +1,6 @@
import { createDecoder, DecodedMessage, waitForRemotePeer } from "@waku/core"; import { createDecoder, DecodedMessage, waitForRemotePeer } from "@waku/core";
import type { IMessage, LightNode } from "@waku/interfaces"; import type { IMessage, LightNode } from "@waku/interfaces";
import { DefaultPubsubTopic, Protocols } from "@waku/interfaces"; import { Protocols } from "@waku/interfaces";
import { import {
generatePrivateKey, generatePrivateKey,
generateSymmetricKey, generateSymmetricKey,
@ -22,7 +22,6 @@ import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
delay, delay,
makeLogFileName,
MessageCollector, MessageCollector,
ServiceNode, ServiceNode,
tearDownNodes, tearDownNodes,
@ -30,20 +29,21 @@ import {
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
customContentTopic1,
log, log,
messageText, messageText,
processQueriedMessages, processQueriedMessages,
runStoreNodes,
sendMessages, sendMessages,
startAndConnectLightNode, startAndConnectLightNode,
TestContentTopic, TestContentTopic1,
TestDecoder, TestDecoder,
TestDecoder2,
TestEncoder, TestEncoder,
TestPubsubTopic1,
TestShardInfo,
totalMsgs totalMsgs
} from "./utils.js"; } from "./utils.js";
const secondDecoder = createDecoder(customContentTopic1);
describe("Waku Store, general", function () { describe("Waku Store, general", function () {
this.timeout(15000); this.timeout(15000);
let waku: LightNode; let waku: LightNode;
@ -51,9 +51,7 @@ describe("Waku Store, general", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
await nwaku.start({ store: true, lightpush: true, relay: true });
await nwaku.ensureSubscriptions();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -61,12 +59,17 @@ describe("Waku Store, general", function () {
}); });
it("Query generator for multiple messages", async function () { it("Query generator for multiple messages", async function () {
await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const messages = await processQueriedMessages( const messages = await processQueriedMessages(
waku, waku,
[TestDecoder], [TestDecoder],
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
expect(messages?.length).eq(totalMsgs); expect(messages?.length).eq(totalMsgs);
@ -84,55 +87,62 @@ describe("Waku Store, general", function () {
await nwaku.sendMessage( await nwaku.sendMessage(
ServiceNode.toMessageRpcQuery({ ServiceNode.toMessageRpcQuery({
payload: utf8ToBytes(testItem["value"]), payload: utf8ToBytes(testItem["value"]),
contentTopic: TestContentTopic contentTopic: TestDecoder.contentTopic
}), }),
DefaultPubsubTopic TestDecoder.pubsubTopic
) )
).to.eq(true); ).to.eq(true);
await delay(1); // to ensure each timestamp is unique. await delay(1); // to ensure each timestamp is unique.
} }
waku = await startAndConnectLightNode(nwaku);
const messageCollector = new MessageCollector(nwaku); const messageCollector = new MessageCollector(nwaku);
messageCollector.list = await processQueriedMessages( messageCollector.list = await processQueriedMessages(
waku, waku,
[TestDecoder], [TestDecoder],
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
// checking that all message sent were retrieved // checking that all message sent were retrieved
TEST_STRING.forEach((testItem) => { TEST_STRING.forEach((testItem) => {
expect( expect(
messageCollector.hasMessage(TestContentTopic, testItem["value"]) messageCollector.hasMessage(TestDecoder.contentTopic, testItem["value"])
).to.eq(true); ).to.eq(true);
}); });
}); });
it("Query generator for multiple messages with multiple decoders", async function () { it("Query generator for multiple messages with multiple decoders", async function () {
const SecondDecoder = createDecoder(
TestDecoder2.contentTopic,
TestDecoder.pubsubTopic
);
await nwaku.sendMessage( await nwaku.sendMessage(
ServiceNode.toMessageRpcQuery({ ServiceNode.toMessageRpcQuery({
payload: utf8ToBytes("M1"), payload: utf8ToBytes("M1"),
contentTopic: TestContentTopic contentTopic: TestDecoder.contentTopic
}), }),
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
await nwaku.sendMessage( await nwaku.sendMessage(
ServiceNode.toMessageRpcQuery({ ServiceNode.toMessageRpcQuery({
payload: utf8ToBytes("M2"), payload: utf8ToBytes("M2"),
contentTopic: customContentTopic1 contentTopic: SecondDecoder.contentTopic
}), }),
DefaultPubsubTopic SecondDecoder.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku);
const messageCollector = new MessageCollector(nwaku); const messageCollector = new MessageCollector(nwaku);
messageCollector.list = await processQueriedMessages( messageCollector.list = await processQueriedMessages(
waku, waku,
[TestDecoder, secondDecoder], [TestDecoder, SecondDecoder],
DefaultPubsubTopic 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 () { 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), payload: utf8ToBytes(messageText),
contentTopic: testItem["value"] contentTopic: testItem["value"]
}), }),
DefaultPubsubTopic TestDecoder.pubsubTopic
) )
).to.eq(true); ).to.eq(true);
await delay(1); // to ensure each timestamp is unique. await delay(1); // to ensure each timestamp is unique.
} }
waku = await startAndConnectLightNode(nwaku);
for (const testItem of TEST_STRING) { for (const testItem of TEST_STRING) {
for await (const query of waku.store.queryGenerator([ for await (const query of waku.store.queryGenerator([
createDecoder(testItem["value"]) createDecoder(testItem["value"], TestDecoder.pubsubTopic)
])) { ])) {
for await (const msg of query) { for await (const msg of query) {
expect(equals(msg!.payload, utf8ToBytes(messageText))).to.eq(true); expect(equals(msg!.payload, utf8ToBytes(messageText))).to.eq(true);
@ -163,8 +171,12 @@ describe("Waku Store, general", function () {
}); });
it("Callback on promise", async function () { it("Callback on promise", async function () {
await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const messages: IMessage[] = []; const messages: IMessage[] = [];
await waku.store.queryWithPromiseCallback( await waku.store.queryWithPromiseCallback(
@ -185,8 +197,12 @@ describe("Waku Store, general", function () {
}); });
it("Callback on promise, aborts when callback returns true", async function () { it("Callback on promise, aborts when callback returns true", async function () {
await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const desiredMsgs = 14; const desiredMsgs = 14;
const messages: IMessage[] = []; const messages: IMessage[] = [];
@ -237,33 +253,35 @@ describe("Waku Store, general", function () {
const eciesEncoder = createEciesEncoder({ const eciesEncoder = createEciesEncoder({
contentTopic: asymTopic, contentTopic: asymTopic,
publicKey publicKey,
pubsubTopic: TestPubsubTopic1
}); });
const symEncoder = createSymEncoder({ const symEncoder = createSymEncoder({
contentTopic: symTopic, contentTopic: symTopic,
symKey symKey,
pubsubTopic: TestPubsubTopic1
}); });
const otherEncoder = createEciesEncoder({ const otherEncoder = createEciesEncoder({
contentTopic: TestContentTopic, contentTopic: TestContentTopic1,
pubsubTopic: TestPubsubTopic1,
publicKey: getPublicKey(generatePrivateKey()) publicKey: getPublicKey(generatePrivateKey())
}); });
const eciesDecoder = createEciesDecoder(asymTopic, privateKey); const eciesDecoder = createEciesDecoder(
const symDecoder = createSymDecoder(symTopic, symKey); asymTopic,
privateKey,
TestDecoder.pubsubTopic
);
const symDecoder = createSymDecoder(
symTopic,
symKey,
TestDecoder.pubsubTopic
);
waku = await startAndConnectLightNode(nwaku); waku2 = await startAndConnectLightNode(nwaku, TestShardInfo);
waku2 = await startAndConnectLightNode(nwaku);
const nimWakuMultiaddr = await nwaku.getMultiaddrWithId(); const nimWakuMultiaddr = await nwaku.getMultiaddrWithId();
await waku2.dial(nimWakuMultiaddr);
await Promise.all([
waku.dial(nimWakuMultiaddr),
waku2.dial(nimWakuMultiaddr)
]);
log.info("Waku nodes connected to nwaku");
await waitForRemotePeer(waku, [Protocols.LightPush]);
log.info("Sending messages using light push"); log.info("Sending messages using light push");
await Promise.all([ await Promise.all([
@ -298,8 +316,12 @@ describe("Waku Store, general", function () {
}); });
it("Ordered callback, aborts when callback returns true", async function () { it("Ordered callback, aborts when callback returns true", async function () {
await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
totalMsgs,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const desiredMsgs = 14; const desiredMsgs = 14;
const messages: IMessage[] = []; const messages: IMessage[] = [];
@ -317,12 +339,17 @@ describe("Waku Store, general", function () {
it("Query generator for 2000 messages", async function () { it("Query generator for 2000 messages", async function () {
this.timeout(40000); this.timeout(40000);
await sendMessages(nwaku, 2000, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
2000,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
const messages = await processQueriedMessages( const messages = await processQueriedMessages(
waku, waku,
[TestDecoder], [TestDecoder],
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
expect(messages?.length).eq(2000); expect(messages?.length).eq(2000);

View File

@ -3,8 +3,7 @@ import type { ContentTopicInfo, IMessage, LightNode } from "@waku/interfaces";
import { createLightNode, Protocols } from "@waku/sdk"; import { createLightNode, Protocols } from "@waku/sdk";
import { import {
contentTopicToPubsubTopic, contentTopicToPubsubTopic,
pubsubTopicToSingleShardInfo, pubsubTopicToSingleShardInfo
singleShardInfosToShardInfo
} from "@waku/utils"; } from "@waku/utils";
import { expect } from "chai"; import { expect } from "chai";
@ -18,20 +17,13 @@ import {
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
customContentTopic1,
customContentTopic2,
customDecoder1,
customDecoder2,
customShardedPubsubTopic1,
customShardedPubsubTopic2,
customShardInfo1,
customShardInfo2,
processQueriedMessages, processQueriedMessages,
runStoreNodes,
sendMessages, sendMessages,
sendMessagesAutosharding, sendMessagesAutosharding,
shardInfo1, TestDecoder,
shardInfoBothShards, TestDecoder2,
startAndConnectLightNode, TestShardInfo,
totalMsgs totalMsgs
} from "./utils.js"; } from "./utils.js";
@ -42,17 +34,7 @@ describe("Waku Store, custom pubsub topic", function () {
let nwaku2: ServiceNode; let nwaku2: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
await nwaku.start({
store: true,
pubsubTopic: [customShardedPubsubTopic1, customShardedPubsubTopic2],
clusterId: customShardInfo1.clusterId,
relay: true
});
await nwaku.ensureSubscriptions([
customShardedPubsubTopic1,
customShardedPubsubTopic2
]);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -63,14 +45,14 @@ describe("Waku Store, custom pubsub topic", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
customContentTopic1, TestDecoder.contentTopic,
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku, [], shardInfo1);
const messages = await processQueriedMessages( const messages = await processQueriedMessages(
waku, waku,
[customDecoder1], [TestDecoder],
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
expect(messages?.length).eq(totalMsgs); expect(messages?.length).eq(totalMsgs);
@ -87,22 +69,20 @@ describe("Waku Store, custom pubsub topic", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
customContentTopic1, TestDecoder.contentTopic,
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
customContentTopic2, TestDecoder2.contentTopic,
customShardedPubsubTopic2 TestDecoder2.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku, [], shardInfoBothShards);
const customMessages = await processQueriedMessages( const customMessages = await processQueriedMessages(
waku, waku,
[customDecoder1], [TestDecoder],
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
expect(customMessages?.length).eq(totalMsgs); expect(customMessages?.length).eq(totalMsgs);
const result1 = customMessages?.findIndex((msg) => { const result1 = customMessages?.findIndex((msg) => {
@ -112,8 +92,8 @@ describe("Waku Store, custom pubsub topic", function () {
const testMessages = await processQueriedMessages( const testMessages = await processQueriedMessages(
waku, waku,
[customDecoder2], [TestDecoder2],
customShardedPubsubTopic2 TestDecoder2.pubsubTopic
); );
expect(testMessages?.length).eq(totalMsgs); expect(testMessages?.length).eq(totalMsgs);
const result2 = testMessages?.findIndex((msg) => { const result2 = testMessages?.findIndex((msg) => {
@ -129,33 +109,26 @@ describe("Waku Store, custom pubsub topic", function () {
nwaku2 = new ServiceNode(makeLogFileName(this) + "2"); nwaku2 = new ServiceNode(makeLogFileName(this) + "2");
await nwaku2.start({ await nwaku2.start({
store: true, store: true,
pubsubTopic: [customShardedPubsubTopic2], pubsubTopic: [TestDecoder2.pubsubTopic],
clusterId: customShardInfo2.clusterId, clusterId: TestShardInfo.clusterId,
relay: true relay: true
}); });
await nwaku2.ensureSubscriptions([customShardedPubsubTopic2]); await nwaku2.ensureSubscriptions([TestDecoder2.pubsubTopic]);
const totalMsgs = 10; const totalMsgs = 10;
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
customContentTopic1, TestDecoder.contentTopic,
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
await sendMessages( await sendMessages(
nwaku2, nwaku2,
totalMsgs, totalMsgs,
customContentTopic2, TestDecoder2.contentTopic,
customShardedPubsubTopic2 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 waku.dial(await nwaku2.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]); await waitForRemotePeer(waku, [Protocols.Store]);
@ -168,13 +141,13 @@ describe("Waku Store, custom pubsub topic", function () {
) { ) {
customMessages = await processQueriedMessages( customMessages = await processQueriedMessages(
waku, waku,
[customDecoder1], [TestDecoder],
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
testMessages = await processQueriedMessages( testMessages = await processQueriedMessages(
waku, waku,
[customDecoder2], [TestDecoder2],
customShardedPubsubTopic2 TestDecoder2.pubsubTopic
); );
} }
}); });
@ -197,10 +170,6 @@ describe("Waku Store (Autosharding), custom pubsub topic", function () {
customContentTopic2, customContentTopic2,
clusterId clusterId
); );
const contentTopicInfo1: ContentTopicInfo = {
clusterId,
contentTopics: [customContentTopic1]
};
const customDecoder1 = createDecoder( const customDecoder1 = createDecoder(
customContentTopic1, customContentTopic1,
pubsubTopicToSingleShardInfo(autoshardingPubsubTopic1) pubsubTopicToSingleShardInfo(autoshardingPubsubTopic1)
@ -215,18 +184,7 @@ describe("Waku Store (Autosharding), custom pubsub topic", function () {
}; };
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, contentTopicInfoBothShards);
await nwaku.start({
store: true,
pubsubTopic: [autoshardingPubsubTopic1, autoshardingPubsubTopic2],
contentTopic: [customContentTopic1, customContentTopic2],
relay: true,
clusterId
});
await nwaku.ensureSubscriptionsAutosharding([
customContentTopic1,
customContentTopic2
]);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -235,7 +193,7 @@ describe("Waku Store (Autosharding), custom pubsub topic", function () {
it("Generator, custom pubsub topic", async function () { it("Generator, custom pubsub topic", async function () {
await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic1); await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic1);
waku = await startAndConnectLightNode(nwaku, [], contentTopicInfo1);
const messages = await processQueriedMessages( const messages = await processQueriedMessages(
waku, waku,
[customDecoder1], [customDecoder1],
@ -256,12 +214,6 @@ describe("Waku Store (Autosharding), custom pubsub topic", function () {
await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic1); await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic1);
await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic2); await sendMessagesAutosharding(nwaku, totalMsgs, customContentTopic2);
waku = await startAndConnectLightNode(
nwaku,
[],
contentTopicInfoBothShards
);
const customMessages = await processQueriedMessages( const customMessages = await processQueriedMessages(
waku, waku,
[customDecoder1], [customDecoder1],
@ -340,38 +292,8 @@ describe("Waku Store (named sharding), custom pubsub topic", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
let nwaku2: ServiceNode; let nwaku2: ServiceNode;
const customDecoder1 = createDecoder(
customContentTopic1,
customShardedPubsubTopic1
);
const customDecoder2 = createDecoder(
customContentTopic2,
customShardedPubsubTopic2
);
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
const shardInfo = singleShardInfosToShardInfo([ [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
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
);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -382,14 +304,14 @@ describe("Waku Store (named sharding), custom pubsub topic", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
customContentTopic1, TestDecoder.contentTopic,
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
const messages = await processQueriedMessages( const messages = await processQueriedMessages(
waku, waku,
[customDecoder1], [TestDecoder],
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
expect(messages?.length).eq(totalMsgs); expect(messages?.length).eq(totalMsgs);
@ -406,20 +328,20 @@ describe("Waku Store (named sharding), custom pubsub topic", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
customContentTopic1, TestDecoder.contentTopic,
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
customContentTopic2, TestDecoder2.contentTopic,
customShardedPubsubTopic2 TestDecoder2.pubsubTopic
); );
const customMessages = await processQueriedMessages( const customMessages = await processQueriedMessages(
waku, waku,
[customDecoder1], [TestDecoder],
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
expect(customMessages?.length).eq(totalMsgs); expect(customMessages?.length).eq(totalMsgs);
const result1 = customMessages?.findIndex((msg) => { const result1 = customMessages?.findIndex((msg) => {
@ -429,8 +351,8 @@ describe("Waku Store (named sharding), custom pubsub topic", function () {
const testMessages = await processQueriedMessages( const testMessages = await processQueriedMessages(
waku, waku,
[customDecoder2], [TestDecoder2],
customShardedPubsubTopic2 TestDecoder2.pubsubTopic
); );
expect(testMessages?.length).eq(totalMsgs); expect(testMessages?.length).eq(totalMsgs);
const result2 = testMessages?.findIndex((msg) => { const result2 = testMessages?.findIndex((msg) => {
@ -446,24 +368,24 @@ describe("Waku Store (named sharding), custom pubsub topic", function () {
nwaku2 = new ServiceNode(makeLogFileName(this) + "2"); nwaku2 = new ServiceNode(makeLogFileName(this) + "2");
await nwaku2.start({ await nwaku2.start({
store: true, store: true,
pubsubTopic: [customShardedPubsubTopic2], pubsubTopic: [TestDecoder2.pubsubTopic],
relay: true, relay: true,
clusterId: customShardInfo2.clusterId clusterId: TestShardInfo.clusterId
}); });
await nwaku2.ensureSubscriptions([customShardedPubsubTopic2]); await nwaku2.ensureSubscriptions([TestDecoder2.pubsubTopic]);
const totalMsgs = 10; const totalMsgs = 10;
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
customContentTopic1, TestDecoder.contentTopic,
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
await sendMessages( await sendMessages(
nwaku2, nwaku2,
totalMsgs, totalMsgs,
customContentTopic2, TestDecoder2.contentTopic,
customShardedPubsubTopic2 TestDecoder2.pubsubTopic
); );
await waku.dial(await nwaku2.getMultiaddrWithId()); await waku.dial(await nwaku2.getMultiaddrWithId());
@ -478,13 +400,13 @@ describe("Waku Store (named sharding), custom pubsub topic", function () {
) { ) {
customMessages = await processQueriedMessages( customMessages = await processQueriedMessages(
waku, waku,
[customDecoder1], [TestDecoder],
customShardedPubsubTopic1 TestDecoder.pubsubTopic
); );
testMessages = await processQueriedMessages( testMessages = await processQueriedMessages(
waku, waku,
[customDecoder2], [TestDecoder2],
customShardedPubsubTopic2 TestDecoder2.pubsubTopic
); );
} }
}); });

View File

@ -1,22 +1,20 @@
import { DecodedMessage, PageDirection } from "@waku/core"; import { DecodedMessage, PageDirection } from "@waku/core";
import type { IMessage, LightNode } from "@waku/interfaces"; import type { IMessage, LightNode } from "@waku/interfaces";
import { DefaultPubsubTopic } from "@waku/interfaces";
import { expect } from "chai"; import { expect } from "chai";
import { import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
makeLogFileName,
ServiceNode, ServiceNode,
tearDownNodes tearDownNodes
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
chunkAndReverseArray, chunkAndReverseArray,
runStoreNodes,
sendMessages, sendMessages,
startAndConnectLightNode,
TestContentTopic,
TestDecoder, TestDecoder,
TestShardInfo,
totalMsgs totalMsgs
} from "./utils.js"; } from "./utils.js";
@ -26,9 +24,7 @@ describe("Waku Store, order", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
await nwaku.start({ store: true, lightpush: true, relay: true });
await nwaku.ensureSubscriptions();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -40,10 +36,9 @@ describe("Waku Store, order", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
TestContentTopic, TestDecoder.contentTopic,
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku);
const messages: IMessage[] = []; const messages: IMessage[] = [];
for await (const query of waku.store.queryGenerator([TestDecoder], { for await (const query of waku.store.queryGenerator([TestDecoder], {
@ -72,10 +67,9 @@ describe("Waku Store, order", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
TestContentTopic, TestDecoder.contentTopic,
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku);
const messages: IMessage[] = []; const messages: IMessage[] = [];
await waku.store.queryWithPromiseCallback( await waku.store.queryWithPromiseCallback(
@ -107,10 +101,9 @@ describe("Waku Store, order", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
TestContentTopic, TestDecoder.contentTopic,
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku);
const messages: IMessage[] = []; const messages: IMessage[] = [];
await waku.store.queryWithOrderedCallback( await waku.store.queryWithOrderedCallback(

View File

@ -1,20 +1,18 @@
import { DefaultPubsubTopic } from "@waku/interfaces";
import type { LightNode } from "@waku/interfaces"; import type { LightNode } from "@waku/interfaces";
import { expect } from "chai"; import { expect } from "chai";
import { import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
makeLogFileName,
ServiceNode, ServiceNode,
tearDownNodes tearDownNodes
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
runStoreNodes,
sendMessages, sendMessages,
startAndConnectLightNode, TestDecoder,
TestContentTopic, TestShardInfo
TestDecoder
} from "./utils.js"; } from "./utils.js";
describe("Waku Store, page size", function () { describe("Waku Store, page size", function () {
@ -23,9 +21,7 @@ describe("Waku Store, page size", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
await nwaku.start({ store: true, lightpush: true, relay: true });
await nwaku.ensureSubscriptions();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -45,8 +41,8 @@ describe("Waku Store, page size", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
messageCount, messageCount,
TestContentTopic, TestDecoder.contentTopic,
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
// Determine effectivePageSize for test expectations // Determine effectivePageSize for test expectations
@ -61,7 +57,6 @@ describe("Waku Store, page size", function () {
} }
} }
waku = await startAndConnectLightNode(nwaku);
let messagesRetrieved = 0; let messagesRetrieved = 0;
for await (const query of waku.store.queryGenerator([TestDecoder], { for await (const query of waku.store.queryGenerator([TestDecoder], {
pageSize: pageSize pageSize: pageSize
@ -86,8 +81,12 @@ describe("Waku Store, page size", function () {
// Possible issue here because pageSize differs across implementations // Possible issue here because pageSize differs across implementations
it("Default pageSize", async function () { it("Default pageSize", async function () {
await sendMessages(nwaku, 20, TestContentTopic, DefaultPubsubTopic); await sendMessages(
waku = await startAndConnectLightNode(nwaku); nwaku,
20,
TestDecoder.contentTopic,
TestDecoder.pubsubTopic
);
let messagesRetrieved = 0; let messagesRetrieved = 0;
for await (const query of waku.store.queryGenerator([TestDecoder])) { for await (const query of waku.store.queryGenerator([TestDecoder])) {

View File

@ -1,20 +1,18 @@
import { DecodedMessage, PageDirection } from "@waku/core"; import { DecodedMessage, PageDirection } from "@waku/core";
import type { IMessage, LightNode } from "@waku/interfaces"; import type { IMessage, LightNode } from "@waku/interfaces";
import { DefaultPubsubTopic } from "@waku/interfaces";
import { import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
makeLogFileName,
ServiceNode, ServiceNode,
tearDownNodes tearDownNodes
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
runStoreNodes,
sendMessages, sendMessages,
startAndConnectLightNode,
TestContentTopic,
TestDecoder, TestDecoder,
TestShardInfo,
totalMsgs totalMsgs
} from "./utils.js"; } from "./utils.js";
@ -24,9 +22,7 @@ describe("Waku Store, sorting", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
await nwaku.start({ store: true, lightpush: true, relay: true });
await nwaku.ensureSubscriptions();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -38,10 +34,9 @@ describe("Waku Store, sorting", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
TestContentTopic, TestDecoder.contentTopic,
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku);
for await (const query of waku.store.queryGenerator([TestDecoder], { for await (const query of waku.store.queryGenerator([TestDecoder], {
pageDirection: PageDirection.FORWARD pageDirection: PageDirection.FORWARD
@ -73,10 +68,9 @@ describe("Waku Store, sorting", function () {
await sendMessages( await sendMessages(
nwaku, nwaku,
totalMsgs, totalMsgs,
TestContentTopic, TestDecoder.contentTopic,
DefaultPubsubTopic TestDecoder.pubsubTopic
); );
waku = await startAndConnectLightNode(nwaku);
const messages: IMessage[] = []; const messages: IMessage[] = [];
await waku.store.queryWithOrderedCallback( await waku.store.queryWithOrderedCallback(

View File

@ -4,16 +4,15 @@ import { expect } from "chai";
import { import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
makeLogFileName,
ServiceNode, ServiceNode,
tearDownNodes tearDownNodes
} from "../../src/index.js"; } from "../../src/index.js";
import { import {
adjustDate, adjustDate,
startAndConnectLightNode, runStoreNodes,
TestContentTopic, TestDecoder,
TestDecoder TestShardInfo
} from "./utils.js"; } from "./utils.js";
describe("Waku Store, time filter", function () { describe("Waku Store, time filter", function () {
@ -22,9 +21,7 @@ describe("Waku Store, time filter", function () {
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runStoreNodes(this.ctx, TestShardInfo);
await nwaku.start({ store: true, lightpush: true, relay: true });
await nwaku.ensureSubscriptions();
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -48,14 +45,12 @@ describe("Waku Store, time filter", function () {
await nwaku.sendMessage( await nwaku.sendMessage(
ServiceNode.toMessageRpcQuery({ ServiceNode.toMessageRpcQuery({
payload: new Uint8Array([0]), payload: new Uint8Array([0]),
contentTopic: TestContentTopic, contentTopic: TestDecoder.contentTopic,
timestamp: msgTimestamp timestamp: msgTimestamp
}) })
) )
).to.eq(true); ).to.eq(true);
waku = await startAndConnectLightNode(nwaku);
const messages: IMessage[] = []; const messages: IMessage[] = [];
await waku.store.queryWithOrderedCallback( await waku.store.queryWithOrderedCallback(
[TestDecoder], [TestDecoder],
@ -93,14 +88,12 @@ describe("Waku Store, time filter", function () {
await nwaku.sendMessage( await nwaku.sendMessage(
ServiceNode.toMessageRpcQuery({ ServiceNode.toMessageRpcQuery({
payload: new Uint8Array([0]), payload: new Uint8Array([0]),
contentTopic: TestContentTopic, contentTopic: TestDecoder.contentTopic,
timestamp: msgTimestamp timestamp: msgTimestamp
}) })
) )
).to.eq(true); ).to.eq(true);
waku = await startAndConnectLightNode(nwaku);
const messages: IMessage[] = []; const messages: IMessage[] = [];
await waku.store.queryWithOrderedCallback( await waku.store.queryWithOrderedCallback(
[TestDecoder], [TestDecoder],

View File

@ -2,47 +2,46 @@ import {
createDecoder, createDecoder,
createEncoder, createEncoder,
DecodedMessage, DecodedMessage,
Decoder, Decoder
waitForRemotePeer
} from "@waku/core"; } from "@waku/core";
import { import {
DefaultPubsubTopic,
LightNode, LightNode,
Protocols, Protocols,
ShardInfo, ShardInfo,
ShardingParams, ShardingParams,
type SingleShardInfo type SingleShardInfo
} from "@waku/interfaces"; } from "@waku/interfaces";
import { createLightNode } from "@waku/sdk"; import { createLightNode, waitForRemotePeer } from "@waku/sdk";
import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils"; import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils";
import { expect } from "chai"; 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 log = new Logger("test:store");
export const TestContentTopic = "/test/1/waku-store/utf8"; export const TestClusterId = 3;
export const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); export const TestShardInfo: ShardInfo = {
export const TestDecoder = createDecoder(TestContentTopic); clusterId: TestClusterId,
export const customShardInfo1: SingleShardInfo = { clusterId: 3, shard: 1 }; shards: [1, 2]
export const customShardedPubsubTopic1 = };
singleShardInfoToPubsubTopic(customShardInfo1);
export const customShardInfo2: SingleShardInfo = { clusterId: 3, shard: 2 }; export const TestShardInfo1: SingleShardInfo = { clusterId: 3, shard: 1 };
export const customShardedPubsubTopic2 = export const TestPubsubTopic1 = singleShardInfoToPubsubTopic(TestShardInfo1);
singleShardInfoToPubsubTopic(customShardInfo2);
export const shardInfo1: ShardInfo = { clusterId: 3, shards: [1] }; export const TestShardInfo2: SingleShardInfo = { clusterId: 3, shard: 2 };
export const customContentTopic1 = "/test/2/waku-store/utf8"; export const TestPubsubTopic2 = singleShardInfoToPubsubTopic(TestShardInfo2);
export const customContentTopic2 = "/test/3/waku-store/utf8";
export const customDecoder1 = createDecoder(customContentTopic1, { export const TestContentTopic1 = "/test/1/waku-store/utf8";
clusterId: 3, export const TestEncoder = createEncoder({
shard: 1 contentTopic: TestContentTopic1,
pubsubTopicShardInfo: TestShardInfo1
}); });
export const customDecoder2 = createDecoder(customContentTopic2, { export const TestDecoder = createDecoder(TestContentTopic1, TestPubsubTopic1);
clusterId: 3,
shard: 2 export const TestContentTopic2 = "/test/3/waku-store/utf8";
}); export const TestDecoder2 = createDecoder(TestContentTopic2, TestPubsubTopic2);
export const shardInfoBothShards: ShardInfo = { clusterId: 3, shards: [1, 2] };
export const totalMsgs = 20; export const totalMsgs = 20;
export const messageText = "Store Push works!"; export const messageText = "Store Push works!";
@ -103,17 +102,12 @@ export async function processQueriedMessages(
export async function startAndConnectLightNode( export async function startAndConnectLightNode(
instance: ServiceNode, instance: ServiceNode,
pubsubTopics: string[] = [DefaultPubsubTopic], shardInfo: ShardingParams
shardInfo?: ShardingParams
): Promise<LightNode> { ): Promise<LightNode> {
const waku = await createLightNode({ const waku = await createLightNode({
pubsubTopics: shardInfo ? undefined : pubsubTopics,
staticNoiseKey: NOISE_KEY_1, 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"] } },
...((pubsubTopics.length !== 1 ||
pubsubTopics[0] !== DefaultPubsubTopic) && {
shardInfo: shardInfo shardInfo: shardInfo
})
}); });
await waku.start(); await waku.start();
await waku.dial(await instance.getMultiaddrWithId()); await waku.dial(await instance.getMultiaddrWithId());
@ -148,3 +142,14 @@ export const adjustDate = (baseDate: Date, adjustMs: number): Date => {
adjusted.setTime(adjusted.getTime() + adjustMs); adjusted.setTime(adjusted.getTime() + adjustMs);
return adjusted; return adjusted;
}; };
export const runStoreNodes = (
context: Context,
shardInfo: ShardingParams
): Promise<[ServiceNode, LightNode]> =>
runNodes({
context,
shardInfo,
createNode: createLightNode,
protocols: [Protocols.Store]
});

View File

@ -1,10 +1,5 @@
import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core"; import { createDecoder, createEncoder } from "@waku/core";
import { import { type LightNode } from "@waku/interfaces";
DefaultPubsubTopic,
type LightNode,
Protocols
} from "@waku/interfaces";
import { createLightNode } from "@waku/sdk";
import { toAsyncIterator } from "@waku/utils"; import { toAsyncIterator } from "@waku/utils";
import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes";
import chai, { expect } from "chai"; import chai, { expect } from "chai";
@ -14,36 +9,32 @@ import {
afterEachCustom, afterEachCustom,
beforeEachCustom, beforeEachCustom,
delay, delay,
makeLogFileName,
NOISE_KEY_1,
ServiceNode, ServiceNode,
tearDownNodes tearDownNodes
} from "../src/index.js"; } from "../src/index.js";
import { runNodes } from "./filter/single_node/utils.js";
chai.use(chaiAsPromised); chai.use(chaiAsPromised);
const TestContentTopic = "/test/1/waku-filter"; const TestContentTopic = "/test/1/waku-filter/default";
const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); const TestShardInfo = {
const TestDecoder = createDecoder(TestContentTopic); contentTopics: [TestContentTopic],
clusterId: 3
};
const TestEncoder = createEncoder({
contentTopic: TestContentTopic,
pubsubTopicShardInfo: TestShardInfo
});
const TestDecoder = createDecoder(TestContentTopic, TestShardInfo);
describe("Util: toAsyncIterator: Filter", function () { describe("Util: toAsyncIterator: Filter", function () {
let waku: LightNode; let waku: LightNode;
let nwaku: ServiceNode; let nwaku: ServiceNode;
beforeEachCustom(this, async () => { beforeEachCustom(this, async () => {
nwaku = new ServiceNode(makeLogFileName(this.ctx)); [nwaku, waku] = await runNodes(this.ctx, TestShardInfo);
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]);
}); });
afterEachCustom(this, async () => { afterEachCustom(this, async () => {
@ -63,7 +54,7 @@ describe("Util: toAsyncIterator: Filter", function () {
const { value } = await iterator.next(); const { value } = await iterator.next();
expect(value.contentTopic).to.eq(TestContentTopic); 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); expect(bytesToUtf8(value.payload)).to.eq(messageText);
}); });

View File

@ -1,6 +1,6 @@
import { waitForRemotePeer } from "@waku/core"; import { waitForRemotePeer } from "@waku/core";
import type { LightNode, RelayNode } from "@waku/interfaces"; import type { LightNode, RelayNode } from "@waku/interfaces";
import { DefaultPubsubTopic, Protocols } from "@waku/interfaces"; import { Protocols } from "@waku/interfaces";
import { createLightNode } from "@waku/sdk"; import { createLightNode } from "@waku/sdk";
import { createRelayNode } from "@waku/sdk/relay"; import { createRelayNode } from "@waku/sdk/relay";
import { expect } from "chai"; import { expect } from "chai";
@ -14,6 +14,12 @@ import {
tearDownNodes tearDownNodes
} from "../src/index.js"; } from "../src/index.js";
import {
runRelayNodes,
TestPubsubTopic,
TestShardInfo
} from "./relay/utils.js";
describe("Wait for remote peer", function () { describe("Wait for remote peer", function () {
let waku1: RelayNode; let waku1: RelayNode;
let waku2: LightNode; let waku2: LightNode;
@ -25,23 +31,10 @@ describe("Wait for remote peer", function () {
it("Relay - dialed first", async function () { it("Relay - dialed first", async function () {
this.timeout(20_000); this.timeout(20_000);
nwaku = new ServiceNode(makeLogFileName(this)); [nwaku, waku1] = await runRelayNodes(this, TestShardInfo);
await nwaku.start({
relay: true,
store: false,
filter: false,
lightpush: false
});
const multiAddrWithId = await nwaku.getMultiaddrWithId(); const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku1 = await createRelayNode({ const peers = waku1.relay.getMeshPeers(TestPubsubTopic);
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 nimPeerId = multiAddrWithId.getPeerId(); const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined; expect(nimPeerId).to.not.be.undefined;
@ -252,23 +245,10 @@ describe("Wait for remote peer", function () {
it("Privacy Node - default protocol", async function () { it("Privacy Node - default protocol", async function () {
this.timeout(20_000); this.timeout(20_000);
nwaku = new ServiceNode(makeLogFileName(this)); [nwaku, waku1] = await runRelayNodes(this, TestShardInfo);
await nwaku.start({
filter: false,
lightpush: false,
relay: true,
store: false
});
const multiAddrWithId = await nwaku.getMultiaddrWithId(); const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku1 = await createRelayNode({ const peers = waku1.relay.getMeshPeers(TestPubsubTopic);
staticNoiseKey: NOISE_KEY_1
});
await waku1.start();
await waku1.dial(multiAddrWithId);
await waitForRemotePeer(waku1);
const peers = waku1.relay.getMeshPeers(DefaultPubsubTopic);
const nimPeerId = multiAddrWithId.getPeerId(); const nimPeerId = multiAddrWithId.getPeerId();

View File

@ -1,4 +1,4 @@
import { DEFAULT_CLUSTER_ID, DefaultPubsubTopic } from "@waku/interfaces"; import { DEFAULT_CLUSTER_ID } from "@waku/interfaces";
import { expect } from "chai"; import { expect } from "chai";
import { import {
@ -404,7 +404,7 @@ describe("determinePubsubTopic", () => {
}); });
it("should fall back to default pubsub topic when pubsubTopicShardInfo is not provided", () => { 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", () => { it("should process correctly when SingleShardInfo has no clusterId but has a shard", () => {

View File

@ -1,7 +1,6 @@
import { sha256 } from "@noble/hashes/sha256"; import { sha256 } from "@noble/hashes/sha256";
import { import {
DEFAULT_CLUSTER_ID, DEFAULT_CLUSTER_ID,
DefaultPubsubTopic,
PubsubTopic, PubsubTopic,
ShardInfo, ShardInfo,
ShardingParams, ShardingParams,
@ -190,6 +189,10 @@ export function contentTopicToPubsubTopic(
clusterId: number = DEFAULT_CLUSTER_ID, clusterId: number = DEFAULT_CLUSTER_ID,
networkShards: number = 8 networkShards: number = 8
): string { ): string {
if (!contentTopic) {
throw Error("Content topic must be specified");
}
const shardIndex = contentTopicToShardIndex(contentTopic, networkShards); const shardIndex = contentTopicToShardIndex(contentTopic, networkShards);
return `/waku/2/rs/${clusterId}/${shardIndex}`; return `/waku/2/rs/${clusterId}/${shardIndex}`;
} }
@ -225,20 +228,18 @@ export function contentTopicsByPubsubTopic(
*/ */
export function determinePubsubTopic( export function determinePubsubTopic(
contentTopic: string, contentTopic: string,
pubsubTopicShardInfo: SingleShardInfo | PubsubTopic = DefaultPubsubTopic pubsubTopicShardInfo?: SingleShardInfo | PubsubTopic
): string { ): string {
if (typeof pubsubTopicShardInfo == "string") { if (typeof pubsubTopicShardInfo == "string") {
return pubsubTopicShardInfo; return pubsubTopicShardInfo;
} else { }
return pubsubTopicShardInfo
? pubsubTopicShardInfo.shard !== undefined return pubsubTopicShardInfo?.shard !== undefined
? singleShardInfoToPubsubTopic(pubsubTopicShardInfo) ? singleShardInfoToPubsubTopic(pubsubTopicShardInfo)
: contentTopicToPubsubTopic( : contentTopicToPubsubTopic(
contentTopic, contentTopic,
pubsubTopicShardInfo.clusterId pubsubTopicShardInfo?.clusterId ?? DEFAULT_CLUSTER_ID
) );
: DefaultPubsubTopic;
}
} }
/** /**