mirror of https://github.com/waku-org/js-waku.git
feat!: add support for sharded pubsub topics & remove support for named pubsub topics (#1697)
* merge branches * tests: use a generator for sharded pubsub topics * fix namespace edge case * move shardInfo to pubsubTopic logic in waku.ts * simplify encoder/decoder creation logic + update tests * sharding utils: add error handling * remove redundant test util * baseprotocol: create abstraction for initialising pubsub topics * fix: `createDecoder` interface * filter: createSubscription takes shardInfo instead of pubsubTopicStr * fix: sharding utils for error handling * SingleShardInfo: use a new interface instead of omitting and rename namespace * change redundant namespaces
This commit is contained in:
parent
7eb3375f50
commit
4cf2ffefa7
|
@ -2,9 +2,16 @@ import type { Libp2p } from "@libp2p/interface";
|
||||||
import type { Stream } from "@libp2p/interface/connection";
|
import type { Stream } from "@libp2p/interface/connection";
|
||||||
import type { PeerId } from "@libp2p/interface/peer-id";
|
import type { PeerId } from "@libp2p/interface/peer-id";
|
||||||
import { Peer, PeerStore } from "@libp2p/interface/peer-store";
|
import { Peer, PeerStore } from "@libp2p/interface/peer-store";
|
||||||
import type { IBaseProtocol, Libp2pComponents } from "@waku/interfaces";
|
import type {
|
||||||
|
IBaseProtocol,
|
||||||
|
Libp2pComponents,
|
||||||
|
PubsubTopic,
|
||||||
|
ShardInfo
|
||||||
|
} from "@waku/interfaces";
|
||||||
|
import { shardInfoToPubsubTopics } from "@waku/utils";
|
||||||
import { getPeersForProtocol, selectPeerForProtocol } from "@waku/utils/libp2p";
|
import { getPeersForProtocol, selectPeerForProtocol } from "@waku/utils/libp2p";
|
||||||
|
|
||||||
|
import { DefaultPubsubTopic } from "./constants.js";
|
||||||
import { filterPeers } from "./filterPeers.js";
|
import { filterPeers } from "./filterPeers.js";
|
||||||
import { StreamManager } from "./stream_manager.js";
|
import { StreamManager } from "./stream_manager.js";
|
||||||
|
|
||||||
|
@ -89,4 +96,10 @@ export class BaseProtocol implements IBaseProtocol {
|
||||||
// Filter the peers based on the specified criteria
|
// Filter the peers based on the specified criteria
|
||||||
return filterPeers(allPeersForProtocol, numPeers, maxBootstrapPeers);
|
return filterPeers(allPeersForProtocol, numPeers, maxBootstrapPeers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initializePubsubTopic(shardInfo?: ShardInfo): PubsubTopic[] {
|
||||||
|
return shardInfo
|
||||||
|
? shardInfoToPubsubTopics(shardInfo)
|
||||||
|
: [DefaultPubsubTopic];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,12 +14,14 @@ import type {
|
||||||
PeerIdStr,
|
PeerIdStr,
|
||||||
ProtocolCreateOptions,
|
ProtocolCreateOptions,
|
||||||
PubsubTopic,
|
PubsubTopic,
|
||||||
|
SingleShardInfo,
|
||||||
Unsubscribe
|
Unsubscribe
|
||||||
} from "@waku/interfaces";
|
} from "@waku/interfaces";
|
||||||
import { WakuMessage } from "@waku/proto";
|
import { WakuMessage } from "@waku/proto";
|
||||||
import {
|
import {
|
||||||
ensurePubsubTopicIsConfigured,
|
ensurePubsubTopicIsConfigured,
|
||||||
groupByContentTopic,
|
groupByContentTopic,
|
||||||
|
singleShardInfoToPubsubTopic,
|
||||||
toAsyncIterator
|
toAsyncIterator
|
||||||
} from "@waku/utils";
|
} from "@waku/utils";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger } from "@waku/utils";
|
||||||
|
@ -279,7 +281,7 @@ class Filter extends BaseProtocol implements IReceiver {
|
||||||
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
||||||
super(FilterCodecs.SUBSCRIBE, libp2p.components);
|
super(FilterCodecs.SUBSCRIBE, libp2p.components);
|
||||||
|
|
||||||
this.pubsubTopics = options?.pubsubTopics || [DefaultPubsubTopic];
|
this.pubsubTopics = this.initializePubsubTopic(options?.shardInfo);
|
||||||
|
|
||||||
libp2p.handle(FilterCodecs.PUSH, this.onRequest.bind(this)).catch((e) => {
|
libp2p.handle(FilterCodecs.PUSH, this.onRequest.bind(this)).catch((e) => {
|
||||||
log.error("Failed to register ", FilterCodecs.PUSH, e);
|
log.error("Failed to register ", FilterCodecs.PUSH, e);
|
||||||
|
@ -289,8 +291,12 @@ class Filter extends BaseProtocol implements IReceiver {
|
||||||
}
|
}
|
||||||
|
|
||||||
async createSubscription(
|
async createSubscription(
|
||||||
pubsubTopic: string = DefaultPubsubTopic
|
pubsubTopicShardInfo?: SingleShardInfo
|
||||||
): Promise<Subscription> {
|
): Promise<Subscription> {
|
||||||
|
const pubsubTopic = pubsubTopicShardInfo
|
||||||
|
? singleShardInfoToPubsubTopic(pubsubTopicShardInfo)
|
||||||
|
: DefaultPubsubTopic;
|
||||||
|
|
||||||
ensurePubsubTopicIsConfigured(pubsubTopic, this.pubsubTopics);
|
ensurePubsubTopicIsConfigured(pubsubTopic, this.pubsubTopics);
|
||||||
|
|
||||||
//TODO: get a relevant peer for the topic/shard
|
//TODO: get a relevant peer for the topic/shard
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type { PeerId } from "@libp2p/interface/peer-id";
|
||||||
import type { PeerStore } from "@libp2p/interface/peer-store";
|
import type { PeerStore } from "@libp2p/interface/peer-store";
|
||||||
import type { IRelay, PeerIdStr } from "@waku/interfaces";
|
import type { IRelay, PeerIdStr } from "@waku/interfaces";
|
||||||
import type { KeepAliveOptions } from "@waku/interfaces";
|
import type { KeepAliveOptions } from "@waku/interfaces";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger, pubsubTopicToSingleShardInfo } from "@waku/utils";
|
||||||
import { utf8ToBytes } from "@waku/utils/bytes";
|
import { utf8ToBytes } from "@waku/utils/bytes";
|
||||||
import type { PingService } from "libp2p/ping";
|
import type { PingService } from "libp2p/ping";
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ export class KeepAliveManager {
|
||||||
if (!meshPeers.includes(peerIdStr)) continue;
|
if (!meshPeers.includes(peerIdStr)) continue;
|
||||||
|
|
||||||
const encoder = createEncoder({
|
const encoder = createEncoder({
|
||||||
pubsubTopic: topic,
|
pubsubTopicShardInfo: pubsubTopicToSingleShardInfo(topic),
|
||||||
contentTopic: RelayPingContentTopic,
|
contentTopic: RelayPingContentTopic,
|
||||||
ephemeral: true
|
ephemeral: true
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,7 +22,6 @@ import { pipe } from "it-pipe";
|
||||||
import { Uint8ArrayList } from "uint8arraylist";
|
import { Uint8ArrayList } from "uint8arraylist";
|
||||||
|
|
||||||
import { BaseProtocol } from "../base_protocol.js";
|
import { BaseProtocol } from "../base_protocol.js";
|
||||||
import { DefaultPubsubTopic } from "../constants.js";
|
|
||||||
|
|
||||||
import { PushRpc } from "./push_rpc.js";
|
import { PushRpc } from "./push_rpc.js";
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ class LightPush extends BaseProtocol implements ILightPush {
|
||||||
|
|
||||||
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
||||||
super(LightPushCodec, libp2p.components);
|
super(LightPushCodec, libp2p.components);
|
||||||
this.pubsubTopics = options?.pubsubTopics ?? [DefaultPubsubTopic];
|
this.pubsubTopics = this.initializePubsubTopic(options?.shardInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async preparePushMessage(
|
private async preparePushMessage(
|
||||||
|
|
|
@ -7,10 +7,11 @@ import type {
|
||||||
IMetaSetter,
|
IMetaSetter,
|
||||||
IProtoMessage,
|
IProtoMessage,
|
||||||
IRateLimitProof,
|
IRateLimitProof,
|
||||||
PubsubTopic
|
PubsubTopic,
|
||||||
|
SingleShardInfo
|
||||||
} from "@waku/interfaces";
|
} from "@waku/interfaces";
|
||||||
import { proto_message as proto } from "@waku/proto";
|
import { proto_message as proto } from "@waku/proto";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils";
|
||||||
|
|
||||||
import { DefaultPubsubTopic } from "../constants.js";
|
import { DefaultPubsubTopic } from "../constants.js";
|
||||||
|
|
||||||
|
@ -119,12 +120,19 @@ export class Encoder implements IEncoder {
|
||||||
* messages.
|
* messages.
|
||||||
*/
|
*/
|
||||||
export function createEncoder({
|
export function createEncoder({
|
||||||
pubsubTopic = DefaultPubsubTopic,
|
pubsubTopicShardInfo,
|
||||||
contentTopic,
|
contentTopic,
|
||||||
ephemeral,
|
ephemeral,
|
||||||
metaSetter
|
metaSetter
|
||||||
}: EncoderOptions): Encoder {
|
}: EncoderOptions): Encoder {
|
||||||
return new Encoder(contentTopic, ephemeral, pubsubTopic, metaSetter);
|
return new Encoder(
|
||||||
|
contentTopic,
|
||||||
|
ephemeral,
|
||||||
|
pubsubTopicShardInfo?.index
|
||||||
|
? singleShardInfoToPubsubTopic(pubsubTopicShardInfo)
|
||||||
|
: DefaultPubsubTopic,
|
||||||
|
metaSetter
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Decoder implements IDecoder<DecodedMessage> {
|
export class Decoder implements IDecoder<DecodedMessage> {
|
||||||
|
@ -182,7 +190,12 @@ export class Decoder implements IDecoder<DecodedMessage> {
|
||||||
*/
|
*/
|
||||||
export function createDecoder(
|
export function createDecoder(
|
||||||
contentTopic: string,
|
contentTopic: string,
|
||||||
pubsubTopic: PubsubTopic = DefaultPubsubTopic
|
pubsubTopicShardInfo?: SingleShardInfo
|
||||||
): Decoder {
|
): Decoder {
|
||||||
return new Decoder(pubsubTopic, contentTopic);
|
return new Decoder(
|
||||||
|
pubsubTopicShardInfo?.index
|
||||||
|
? singleShardInfoToPubsubTopic(pubsubTopicShardInfo)
|
||||||
|
: DefaultPubsubTopic,
|
||||||
|
contentTopic
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import { pipe } from "it-pipe";
|
||||||
import { Uint8ArrayList } from "uint8arraylist";
|
import { Uint8ArrayList } from "uint8arraylist";
|
||||||
|
|
||||||
import { BaseProtocol } from "../base_protocol.js";
|
import { BaseProtocol } from "../base_protocol.js";
|
||||||
import { DefaultPubsubTopic } from "../constants.js";
|
|
||||||
import { toProtoMessage } from "../to_proto_message.js";
|
import { toProtoMessage } from "../to_proto_message.js";
|
||||||
|
|
||||||
import { HistoryRpc, PageDirection, Params } from "./history_rpc.js";
|
import { HistoryRpc, PageDirection, Params } from "./history_rpc.js";
|
||||||
|
@ -80,7 +79,7 @@ class Store extends BaseProtocol implements IStore {
|
||||||
|
|
||||||
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
||||||
super(StoreCodec, libp2p.components);
|
super(StoreCodec, libp2p.components);
|
||||||
this.pubsubTopics = options?.pubsubTopics ?? [DefaultPubsubTopic];
|
this.pubsubTopics = this.initializePubsubTopic(options?.shardInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,12 +8,14 @@ import type {
|
||||||
IStore,
|
IStore,
|
||||||
Libp2p,
|
Libp2p,
|
||||||
PubsubTopic,
|
PubsubTopic,
|
||||||
|
ShardInfo,
|
||||||
Waku
|
Waku
|
||||||
} from "@waku/interfaces";
|
} from "@waku/interfaces";
|
||||||
import { Protocols } from "@waku/interfaces";
|
import { Protocols } from "@waku/interfaces";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger, shardInfoToPubsubTopics } from "@waku/utils";
|
||||||
|
|
||||||
import { ConnectionManager } from "./connection_manager.js";
|
import { ConnectionManager } from "./connection_manager.js";
|
||||||
|
import { DefaultPubsubTopic } from "./constants.js";
|
||||||
|
|
||||||
export const DefaultPingKeepAliveValueSecs = 5 * 60;
|
export const DefaultPingKeepAliveValueSecs = 5 * 60;
|
||||||
export const DefaultRelayKeepAliveValueSecs = 5 * 60;
|
export const DefaultRelayKeepAliveValueSecs = 5 * 60;
|
||||||
|
@ -50,16 +52,23 @@ export class WakuNode implements Waku {
|
||||||
public filter?: IFilter;
|
public filter?: IFilter;
|
||||||
public lightPush?: ILightPush;
|
public lightPush?: ILightPush;
|
||||||
public connectionManager: ConnectionManager;
|
public connectionManager: ConnectionManager;
|
||||||
|
public readonly pubsubTopics: PubsubTopic[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
options: WakuOptions,
|
options: WakuOptions,
|
||||||
public readonly pubsubTopics: PubsubTopic[],
|
|
||||||
libp2p: Libp2p,
|
libp2p: Libp2p,
|
||||||
|
pubsubShardInfo?: ShardInfo,
|
||||||
store?: (libp2p: Libp2p) => IStore,
|
store?: (libp2p: Libp2p) => IStore,
|
||||||
lightPush?: (libp2p: Libp2p) => ILightPush,
|
lightPush?: (libp2p: Libp2p) => ILightPush,
|
||||||
filter?: (libp2p: Libp2p) => IFilter,
|
filter?: (libp2p: Libp2p) => IFilter,
|
||||||
relay?: (libp2p: Libp2p) => IRelay
|
relay?: (libp2p: Libp2p) => IRelay
|
||||||
) {
|
) {
|
||||||
|
if (!pubsubShardInfo) {
|
||||||
|
this.pubsubTopics = [DefaultPubsubTopic];
|
||||||
|
} else {
|
||||||
|
this.pubsubTopics = shardInfoToPubsubTopics(pubsubShardInfo);
|
||||||
|
}
|
||||||
|
|
||||||
this.libp2p = libp2p;
|
this.libp2p = libp2p;
|
||||||
|
|
||||||
if (store) {
|
if (store) {
|
||||||
|
@ -88,7 +97,7 @@ export class WakuNode implements Waku {
|
||||||
peerId,
|
peerId,
|
||||||
libp2p,
|
libp2p,
|
||||||
{ pingKeepAlive, relayKeepAlive },
|
{ pingKeepAlive, relayKeepAlive },
|
||||||
pubsubTopics,
|
this.pubsubTopics,
|
||||||
this.relay
|
this.relay
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { PeerId } from "@libp2p/interface/peer-id";
|
import type { PeerId } from "@libp2p/interface/peer-id";
|
||||||
|
|
||||||
import type { IDecodedMessage, IDecoder } from "./message.js";
|
import type { IDecodedMessage, IDecoder, SingleShardInfo } from "./message.js";
|
||||||
import type { ContentTopic } from "./misc.js";
|
import type { ContentTopic } from "./misc.js";
|
||||||
import type { Callback, IBaseProtocol } from "./protocols.js";
|
import type { Callback, IBaseProtocol } from "./protocols.js";
|
||||||
import type { IReceiver } from "./receiver.js";
|
import type { IReceiver } from "./receiver.js";
|
||||||
|
@ -25,7 +25,7 @@ export interface IFilterSubscription {
|
||||||
export type IFilter = IReceiver &
|
export type IFilter = IReceiver &
|
||||||
IBaseProtocol & {
|
IBaseProtocol & {
|
||||||
createSubscription(
|
createSubscription(
|
||||||
pubsubTopic?: string,
|
pubsubTopicShardInfo?: SingleShardInfo,
|
||||||
peerId?: PeerId
|
peerId?: PeerId
|
||||||
): Promise<IFilterSubscription>;
|
): Promise<IFilterSubscription>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import type { PubsubTopic } from "./misc.js";
|
import type { PubsubTopic } from "./misc.js";
|
||||||
|
|
||||||
|
export interface SingleShardInfo {
|
||||||
|
cluster: number;
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IRateLimitProof {
|
export interface IRateLimitProof {
|
||||||
proof: Uint8Array;
|
proof: Uint8Array;
|
||||||
merkleRoot: Uint8Array;
|
merkleRoot: Uint8Array;
|
||||||
|
@ -38,7 +43,7 @@ export interface IMetaSetter {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EncoderOptions {
|
export interface EncoderOptions {
|
||||||
pubsubTopic?: PubsubTopic;
|
pubsubTopicShardInfo?: SingleShardInfo;
|
||||||
/** The content topic to set on outgoing messages. */
|
/** The content topic to set on outgoing messages. */
|
||||||
contentTopic: string;
|
contentTopic: string;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,9 +2,9 @@ import type { Libp2p } from "@libp2p/interface";
|
||||||
import type { PeerId } from "@libp2p/interface/peer-id";
|
import type { PeerId } from "@libp2p/interface/peer-id";
|
||||||
import type { Peer, PeerStore } from "@libp2p/interface/peer-store";
|
import type { Peer, PeerStore } from "@libp2p/interface/peer-store";
|
||||||
|
|
||||||
|
import type { ShardInfo } from "./enr.js";
|
||||||
import type { CreateLibp2pOptions } from "./libp2p.js";
|
import type { CreateLibp2pOptions } from "./libp2p.js";
|
||||||
import type { IDecodedMessage } from "./message.js";
|
import type { IDecodedMessage } from "./message.js";
|
||||||
import type { PubsubTopic } from "./misc.js";
|
|
||||||
|
|
||||||
export enum Protocols {
|
export enum Protocols {
|
||||||
Relay = "relay",
|
Relay = "relay",
|
||||||
|
@ -23,9 +23,9 @@ export interface IBaseProtocol {
|
||||||
|
|
||||||
export type ProtocolCreateOptions = {
|
export type ProtocolCreateOptions = {
|
||||||
/**
|
/**
|
||||||
* Waku supports usage of multiple pubsub topics, but this is still in early stages.
|
* Waku supports usage of multiple pubsub topics. This is achieved through static sharding for now, and auto-sharding in the future.
|
||||||
* Waku implements sharding to achieve scalability
|
* The format to specify a shard is:
|
||||||
* The format of the sharded topic is `/waku/2/rs/<shard_cluster_index>/<shard_number>`
|
* clusterId: number, shards: number[]
|
||||||
* To learn more about the sharding specifications implemented, see [Relay Sharding](https://rfc.vac.dev/spec/51/).
|
* To learn more about the sharding specifications implemented, see [Relay Sharding](https://rfc.vac.dev/spec/51/).
|
||||||
* The Pubsub Topic to use. Defaults to {@link @waku/core!DefaultPubsubTopic }.
|
* The Pubsub Topic to use. Defaults to {@link @waku/core!DefaultPubsubTopic }.
|
||||||
*
|
*
|
||||||
|
@ -39,7 +39,7 @@ export type ProtocolCreateOptions = {
|
||||||
* See [Waku v2 Topic Usage Recommendations](https://rfc.vac.dev/spec/23/) for details.
|
* See [Waku v2 Topic Usage Recommendations](https://rfc.vac.dev/spec/23/) for details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
pubsubTopics?: PubsubTopic[];
|
shardInfo?: ShardInfo;
|
||||||
/**
|
/**
|
||||||
* You can pass options to the `Libp2p` instance used by {@link @waku/core!WakuNode} using the `libp2p` property.
|
* You can pass options to the `Libp2p` instance used by {@link @waku/core!WakuNode} using the `libp2p` property.
|
||||||
* This property is the same type as the one passed to [`Libp2p.create`](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#create)
|
* This property is the same type as the one passed to [`Libp2p.create`](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#create)
|
||||||
|
|
|
@ -7,10 +7,11 @@ import type {
|
||||||
IMessage,
|
IMessage,
|
||||||
IMetaSetter,
|
IMetaSetter,
|
||||||
IProtoMessage,
|
IProtoMessage,
|
||||||
PubsubTopic
|
PubsubTopic,
|
||||||
|
SingleShardInfo
|
||||||
} from "@waku/interfaces";
|
} from "@waku/interfaces";
|
||||||
import { WakuMessage } from "@waku/proto";
|
import { WakuMessage } from "@waku/proto";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils";
|
||||||
|
|
||||||
import { generatePrivateKey } from "./crypto/utils.js";
|
import { generatePrivateKey } from "./crypto/utils.js";
|
||||||
import { DecodedMessage } from "./decoded_message.js";
|
import { DecodedMessage } from "./decoded_message.js";
|
||||||
|
@ -98,7 +99,7 @@ export interface EncoderOptions extends BaseEncoderOptions {
|
||||||
* in [26/WAKU2-PAYLOAD](https://rfc.vac.dev/spec/26/).
|
* in [26/WAKU2-PAYLOAD](https://rfc.vac.dev/spec/26/).
|
||||||
*/
|
*/
|
||||||
export function createEncoder({
|
export function createEncoder({
|
||||||
pubsubTopic = DefaultPubsubTopic,
|
pubsubTopicShardInfo,
|
||||||
contentTopic,
|
contentTopic,
|
||||||
publicKey,
|
publicKey,
|
||||||
sigPrivKey,
|
sigPrivKey,
|
||||||
|
@ -106,7 +107,9 @@ export function createEncoder({
|
||||||
metaSetter
|
metaSetter
|
||||||
}: EncoderOptions): Encoder {
|
}: EncoderOptions): Encoder {
|
||||||
return new Encoder(
|
return new Encoder(
|
||||||
pubsubTopic,
|
pubsubTopicShardInfo?.index
|
||||||
|
? singleShardInfoToPubsubTopic(pubsubTopicShardInfo)
|
||||||
|
: DefaultPubsubTopic,
|
||||||
contentTopic,
|
contentTopic,
|
||||||
publicKey,
|
publicKey,
|
||||||
sigPrivKey,
|
sigPrivKey,
|
||||||
|
@ -194,7 +197,13 @@ class Decoder extends DecoderV0 implements IDecoder<DecodedMessage> {
|
||||||
export function createDecoder(
|
export function createDecoder(
|
||||||
contentTopic: string,
|
contentTopic: string,
|
||||||
privateKey: Uint8Array,
|
privateKey: Uint8Array,
|
||||||
pubsubTopic: PubsubTopic = DefaultPubsubTopic
|
pubsubTopicShardInfo?: SingleShardInfo
|
||||||
): Decoder {
|
): Decoder {
|
||||||
return new Decoder(pubsubTopic, contentTopic, privateKey);
|
return new Decoder(
|
||||||
|
pubsubTopicShardInfo?.index
|
||||||
|
? singleShardInfoToPubsubTopic(pubsubTopicShardInfo)
|
||||||
|
: DefaultPubsubTopic,
|
||||||
|
contentTopic,
|
||||||
|
privateKey
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,11 @@ import type {
|
||||||
IMessage,
|
IMessage,
|
||||||
IMetaSetter,
|
IMetaSetter,
|
||||||
IProtoMessage,
|
IProtoMessage,
|
||||||
PubsubTopic
|
PubsubTopic,
|
||||||
|
SingleShardInfo
|
||||||
} from "@waku/interfaces";
|
} from "@waku/interfaces";
|
||||||
import { WakuMessage } from "@waku/proto";
|
import { WakuMessage } from "@waku/proto";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils";
|
||||||
|
|
||||||
import { generateSymmetricKey } from "./crypto/utils.js";
|
import { generateSymmetricKey } from "./crypto/utils.js";
|
||||||
import { DecodedMessage } from "./decoded_message.js";
|
import { DecodedMessage } from "./decoded_message.js";
|
||||||
|
@ -98,7 +99,7 @@ export interface EncoderOptions extends BaseEncoderOptions {
|
||||||
* in [26/WAKU2-PAYLOAD](https://rfc.vac.dev/spec/26/).
|
* in [26/WAKU2-PAYLOAD](https://rfc.vac.dev/spec/26/).
|
||||||
*/
|
*/
|
||||||
export function createEncoder({
|
export function createEncoder({
|
||||||
pubsubTopic = DefaultPubsubTopic,
|
pubsubTopicShardInfo,
|
||||||
contentTopic,
|
contentTopic,
|
||||||
symKey,
|
symKey,
|
||||||
sigPrivKey,
|
sigPrivKey,
|
||||||
|
@ -106,7 +107,9 @@ export function createEncoder({
|
||||||
metaSetter
|
metaSetter
|
||||||
}: EncoderOptions): Encoder {
|
}: EncoderOptions): Encoder {
|
||||||
return new Encoder(
|
return new Encoder(
|
||||||
pubsubTopic,
|
pubsubTopicShardInfo?.index
|
||||||
|
? singleShardInfoToPubsubTopic(pubsubTopicShardInfo)
|
||||||
|
: DefaultPubsubTopic,
|
||||||
contentTopic,
|
contentTopic,
|
||||||
symKey,
|
symKey,
|
||||||
sigPrivKey,
|
sigPrivKey,
|
||||||
|
@ -194,7 +197,13 @@ class Decoder extends DecoderV0 implements IDecoder<DecodedMessage> {
|
||||||
export function createDecoder(
|
export function createDecoder(
|
||||||
contentTopic: string,
|
contentTopic: string,
|
||||||
symKey: Uint8Array,
|
symKey: Uint8Array,
|
||||||
pubsubTopic: PubsubTopic = DefaultPubsubTopic
|
pubsubTopicShardInfo?: SingleShardInfo
|
||||||
): Decoder {
|
): Decoder {
|
||||||
return new Decoder(pubsubTopic, contentTopic, symKey);
|
return new Decoder(
|
||||||
|
pubsubTopicShardInfo?.index
|
||||||
|
? singleShardInfoToPubsubTopic(pubsubTopicShardInfo)
|
||||||
|
: DefaultPubsubTopic,
|
||||||
|
contentTopic,
|
||||||
|
symKey
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,11 @@ import {
|
||||||
SendError,
|
SendError,
|
||||||
SendResult
|
SendResult
|
||||||
} from "@waku/interfaces";
|
} from "@waku/interfaces";
|
||||||
import { isWireSizeUnderCap, toAsyncIterator } from "@waku/utils";
|
import {
|
||||||
|
isWireSizeUnderCap,
|
||||||
|
shardInfoToPubsubTopics,
|
||||||
|
toAsyncIterator
|
||||||
|
} from "@waku/utils";
|
||||||
import { pushOrInitMapSet } from "@waku/utils";
|
import { pushOrInitMapSet } from "@waku/utils";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger } from "@waku/utils";
|
||||||
|
|
||||||
|
@ -68,7 +72,9 @@ class Relay implements IRelay {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.gossipSub = libp2p.services.pubsub as GossipSub;
|
this.gossipSub = libp2p.services.pubsub as GossipSub;
|
||||||
this.pubsubTopics = new Set(options?.pubsubTopics ?? [DefaultPubsubTopic]);
|
this.pubsubTopics = options?.shardInfo
|
||||||
|
? new Set(shardInfoToPubsubTopics(options.shardInfo))
|
||||||
|
: new Set([DefaultPubsubTopic]);
|
||||||
|
|
||||||
if (this.gossipSub.isStarted()) {
|
if (this.gossipSub.isStarted()) {
|
||||||
this.subscribeToAllTopics();
|
this.subscribeToAllTopics();
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { mplex } from "@libp2p/mplex";
|
||||||
import { webSockets } from "@libp2p/websockets";
|
import { webSockets } from "@libp2p/websockets";
|
||||||
import { all as filterAll } from "@libp2p/websockets/filters";
|
import { all as filterAll } from "@libp2p/websockets/filters";
|
||||||
import {
|
import {
|
||||||
DefaultPubsubTopic,
|
|
||||||
DefaultUserAgent,
|
DefaultUserAgent,
|
||||||
wakuFilter,
|
wakuFilter,
|
||||||
wakuLightPush,
|
wakuLightPush,
|
||||||
|
@ -47,10 +46,6 @@ export async function createLightNode(
|
||||||
): Promise<LightNode> {
|
): Promise<LightNode> {
|
||||||
options = options ?? {};
|
options = options ?? {};
|
||||||
|
|
||||||
if (!options.pubsubTopics) {
|
|
||||||
options.pubsubTopics = [DefaultPubsubTopic];
|
|
||||||
}
|
|
||||||
|
|
||||||
const libp2pOptions = options?.libp2p ?? {};
|
const libp2pOptions = options?.libp2p ?? {};
|
||||||
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
||||||
if (options?.defaultBootstrap) {
|
if (options?.defaultBootstrap) {
|
||||||
|
@ -70,8 +65,8 @@ export async function createLightNode(
|
||||||
|
|
||||||
return new WakuNode(
|
return new WakuNode(
|
||||||
options ?? {},
|
options ?? {},
|
||||||
options.pubsubTopics,
|
|
||||||
libp2p,
|
libp2p,
|
||||||
|
options.shardInfo,
|
||||||
store,
|
store,
|
||||||
lightPush,
|
lightPush,
|
||||||
filter
|
filter
|
||||||
|
@ -87,10 +82,6 @@ export async function createRelayNode(
|
||||||
): Promise<RelayNode> {
|
): Promise<RelayNode> {
|
||||||
options = options ?? {};
|
options = options ?? {};
|
||||||
|
|
||||||
if (!options.pubsubTopics) {
|
|
||||||
options.pubsubTopics = [DefaultPubsubTopic];
|
|
||||||
}
|
|
||||||
|
|
||||||
const libp2pOptions = options?.libp2p ?? {};
|
const libp2pOptions = options?.libp2p ?? {};
|
||||||
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
||||||
if (options?.defaultBootstrap) {
|
if (options?.defaultBootstrap) {
|
||||||
|
@ -108,8 +99,8 @@ export async function createRelayNode(
|
||||||
|
|
||||||
return new WakuNode(
|
return new WakuNode(
|
||||||
options,
|
options,
|
||||||
options.pubsubTopics,
|
|
||||||
libp2p,
|
libp2p,
|
||||||
|
options.shardInfo,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
|
@ -135,10 +126,6 @@ export async function createFullNode(
|
||||||
): Promise<FullNode> {
|
): Promise<FullNode> {
|
||||||
options = options ?? {};
|
options = options ?? {};
|
||||||
|
|
||||||
if (!options.pubsubTopics) {
|
|
||||||
options.pubsubTopics = [DefaultPubsubTopic];
|
|
||||||
}
|
|
||||||
|
|
||||||
const libp2pOptions = options?.libp2p ?? {};
|
const libp2pOptions = options?.libp2p ?? {};
|
||||||
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
||||||
if (options?.defaultBootstrap) {
|
if (options?.defaultBootstrap) {
|
||||||
|
@ -159,8 +146,8 @@ export async function createFullNode(
|
||||||
|
|
||||||
return new WakuNode(
|
return new WakuNode(
|
||||||
options ?? {},
|
options ?? {},
|
||||||
options.pubsubTopics,
|
|
||||||
libp2p,
|
libp2p,
|
||||||
|
options.shardInfo,
|
||||||
store,
|
store,
|
||||||
lightPush,
|
lightPush,
|
||||||
filter,
|
filter,
|
||||||
|
|
|
@ -208,8 +208,16 @@ export function argsToArray(args: Args): Array<string> {
|
||||||
return "-" + capital.toLowerCase();
|
return "-" + capital.toLowerCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
const arg = `--${kebabKey}=${value}`;
|
if (Array.isArray(value)) {
|
||||||
array.push(arg);
|
// If the value is an array, create separate arguments for each element
|
||||||
|
value.forEach((val) => {
|
||||||
|
array.push(`--${kebabKey}=${val}`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Handle non-array values as before
|
||||||
|
const arg = `--${kebabKey}=${value}`;
|
||||||
|
array.push(arg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
|
|
|
@ -14,7 +14,7 @@ export interface Args {
|
||||||
peerExchange?: boolean;
|
peerExchange?: boolean;
|
||||||
discv5Discovery?: boolean;
|
discv5Discovery?: boolean;
|
||||||
storeMessageDbUrl?: string;
|
storeMessageDbUrl?: string;
|
||||||
topic?: Array<string>;
|
pubsubTopic?: Array<string>;
|
||||||
rpcPrivate?: boolean;
|
rpcPrivate?: boolean;
|
||||||
websocketSupport?: boolean;
|
websocketSupport?: boolean;
|
||||||
tcpPort?: number;
|
tcpPort?: number;
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import {
|
import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core";
|
||||||
createDecoder,
|
import type {
|
||||||
createEncoder,
|
IFilterSubscription,
|
||||||
DefaultPubsubTopic,
|
LightNode,
|
||||||
waitForRemotePeer
|
ShardInfo,
|
||||||
} from "@waku/core";
|
SingleShardInfo
|
||||||
import type { IFilterSubscription, LightNode } from "@waku/interfaces";
|
} from "@waku/interfaces";
|
||||||
import { Protocols } from "@waku/interfaces";
|
import { Protocols } from "@waku/interfaces";
|
||||||
|
import {
|
||||||
|
pubsubTopicToSingleShardInfo,
|
||||||
|
singleShardInfoToPubsubTopic
|
||||||
|
} from "@waku/utils";
|
||||||
import { utf8ToBytes } from "@waku/utils/bytes";
|
import { utf8ToBytes } from "@waku/utils/bytes";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
|
@ -16,12 +20,7 @@ import {
|
||||||
tearDownNodes
|
tearDownNodes
|
||||||
} from "../../src/index.js";
|
} from "../../src/index.js";
|
||||||
|
|
||||||
import {
|
import { runNodes } from "./utils.js";
|
||||||
runNodes,
|
|
||||||
TestContentTopic,
|
|
||||||
TestDecoder,
|
|
||||||
TestEncoder
|
|
||||||
} from "./utils.js";
|
|
||||||
|
|
||||||
describe("Waku Filter V2: Multiple PubsubTopics", function () {
|
describe("Waku Filter V2: Multiple PubsubTopics", 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
|
||||||
|
@ -31,21 +30,41 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () {
|
||||||
let nwaku2: NimGoNode;
|
let nwaku2: NimGoNode;
|
||||||
let subscription: IFilterSubscription;
|
let subscription: IFilterSubscription;
|
||||||
let messageCollector: MessageCollector;
|
let messageCollector: MessageCollector;
|
||||||
const customPubsubTopic = "/waku/2/custom-dapp/proto";
|
|
||||||
const customContentTopic = "/test/2/waku-filter";
|
const customPubsubTopic1 = singleShardInfoToPubsubTopic({
|
||||||
const newEncoder = createEncoder({
|
cluster: 3,
|
||||||
pubsubTopic: customPubsubTopic,
|
index: 1
|
||||||
contentTopic: customContentTopic
|
|
||||||
});
|
});
|
||||||
const newDecoder = createDecoder(customContentTopic, customPubsubTopic);
|
const customPubsubTopic2 = singleShardInfoToPubsubTopic({
|
||||||
|
cluster: 3,
|
||||||
|
index: 2
|
||||||
|
});
|
||||||
|
const shardInfo: ShardInfo = { cluster: 3, indexList: [1, 2] };
|
||||||
|
const singleShardInfo1: SingleShardInfo = { cluster: 3, index: 1 };
|
||||||
|
const singleShardInfo2: SingleShardInfo = { cluster: 3, index: 2 };
|
||||||
|
const customContentTopic1 = "/test/2/waku-filter";
|
||||||
|
const customContentTopic2 = "/test/3/waku-filter";
|
||||||
|
const customEncoder1 = createEncoder({
|
||||||
|
pubsubTopicShardInfo: singleShardInfo1,
|
||||||
|
contentTopic: customContentTopic1
|
||||||
|
});
|
||||||
|
const customDecoder1 = createDecoder(customContentTopic1, singleShardInfo1);
|
||||||
|
const customEncoder2 = createEncoder({
|
||||||
|
pubsubTopicShardInfo: singleShardInfo2,
|
||||||
|
contentTopic: customContentTopic2
|
||||||
|
});
|
||||||
|
const customDecoder2 = createDecoder(customContentTopic2, singleShardInfo2);
|
||||||
|
|
||||||
this.beforeEach(async function () {
|
this.beforeEach(async function () {
|
||||||
this.timeout(15000);
|
this.timeout(15000);
|
||||||
[nwaku, waku] = await runNodes(this, [
|
[nwaku, waku] = await runNodes(
|
||||||
customPubsubTopic,
|
this,
|
||||||
DefaultPubsubTopic
|
[customPubsubTopic1, customPubsubTopic2],
|
||||||
]);
|
shardInfo
|
||||||
subscription = await waku.filter.createSubscription(customPubsubTopic);
|
);
|
||||||
|
subscription = await waku.filter.createSubscription(
|
||||||
|
pubsubTopicToSingleShardInfo(customPubsubTopic1)
|
||||||
|
);
|
||||||
messageCollector = new MessageCollector();
|
messageCollector = new MessageCollector();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -55,94 +74,95 @@ describe("Waku Filter V2: Multiple PubsubTopics", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Subscribe and receive messages on custom pubsubtopic", async function () {
|
it("Subscribe and receive messages on custom pubsubtopic", async function () {
|
||||||
await subscription.subscribe([newDecoder], messageCollector.callback);
|
await subscription.subscribe([customDecoder1], messageCollector.callback);
|
||||||
await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M1") });
|
await waku.lightPush.send(customEncoder1, { payload: utf8ToBytes("M1") });
|
||||||
expect(await messageCollector.waitForMessages(1)).to.eq(true);
|
expect(await messageCollector.waitForMessages(1)).to.eq(true);
|
||||||
messageCollector.verifyReceivedMessage(0, {
|
messageCollector.verifyReceivedMessage(0, {
|
||||||
expectedContentTopic: customContentTopic,
|
expectedContentTopic: customContentTopic1,
|
||||||
expectedPubsubTopic: customPubsubTopic,
|
expectedPubsubTopic: customPubsubTopic1,
|
||||||
expectedMessageText: "M1"
|
expectedMessageText: "M1"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Subscribe and receive messages on 2 different pubsubtopics", async function () {
|
it("Subscribe and receive messages on 2 different pubsubtopics", async function () {
|
||||||
await subscription.subscribe([newDecoder], 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 =
|
const subscription2 = await waku.filter.createSubscription(
|
||||||
await waku.filter.createSubscription(DefaultPubsubTopic);
|
pubsubTopicToSingleShardInfo(customPubsubTopic2)
|
||||||
|
);
|
||||||
|
|
||||||
const messageCollector2 = new MessageCollector();
|
const messageCollector2 = new MessageCollector();
|
||||||
|
|
||||||
await subscription2.subscribe([TestDecoder], messageCollector2.callback);
|
await subscription2.subscribe([customDecoder2], messageCollector2.callback);
|
||||||
|
|
||||||
await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M1") });
|
await waku.lightPush.send(customEncoder1, { payload: utf8ToBytes("M1") });
|
||||||
await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M2") });
|
await waku.lightPush.send(customEncoder2, { payload: utf8ToBytes("M2") });
|
||||||
|
|
||||||
expect(await messageCollector.waitForMessages(1)).to.eq(true);
|
expect(await messageCollector.waitForMessages(1)).to.eq(true);
|
||||||
expect(await messageCollector2.waitForMessages(1)).to.eq(true);
|
expect(await messageCollector2.waitForMessages(1)).to.eq(true);
|
||||||
|
|
||||||
messageCollector.verifyReceivedMessage(0, {
|
messageCollector.verifyReceivedMessage(0, {
|
||||||
expectedContentTopic: customContentTopic,
|
expectedContentTopic: customContentTopic1,
|
||||||
expectedPubsubTopic: customPubsubTopic,
|
expectedPubsubTopic: customPubsubTopic1,
|
||||||
expectedMessageText: "M1"
|
expectedMessageText: "M1"
|
||||||
});
|
});
|
||||||
|
|
||||||
messageCollector2.verifyReceivedMessage(0, {
|
messageCollector2.verifyReceivedMessage(0, {
|
||||||
expectedContentTopic: TestContentTopic,
|
expectedContentTopic: customContentTopic2,
|
||||||
expectedPubsubTopic: DefaultPubsubTopic,
|
expectedPubsubTopic: customPubsubTopic2,
|
||||||
expectedMessageText: "M2"
|
expectedMessageText: "M2"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Subscribe and receive messages from 2 nwaku nodes each with different pubsubtopics", async function () {
|
it("Subscribe and receive messages from 2 nwaku nodes each with different pubsubtopics", async function () {
|
||||||
await subscription.subscribe([newDecoder], messageCollector.callback);
|
await subscription.subscribe([customDecoder1], messageCollector.callback);
|
||||||
|
|
||||||
// Set up and start a new nwaku node with Default Pubsubtopic
|
// Set up and start a new nwaku node with customPubsubTopic1
|
||||||
nwaku2 = new NimGoNode(makeLogFileName(this) + "2");
|
nwaku2 = new NimGoNode(makeLogFileName(this) + "2");
|
||||||
await nwaku2.start({
|
await nwaku2.start({
|
||||||
filter: true,
|
filter: true,
|
||||||
lightpush: true,
|
lightpush: true,
|
||||||
relay: true,
|
relay: true,
|
||||||
topic: [DefaultPubsubTopic]
|
pubsubTopic: [customPubsubTopic2]
|
||||||
});
|
});
|
||||||
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]);
|
||||||
|
|
||||||
// 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(
|
||||||
DefaultPubsubTopic,
|
pubsubTopicToSingleShardInfo(customPubsubTopic2),
|
||||||
await nwaku2.getPeerId()
|
await nwaku2.getPeerId()
|
||||||
);
|
);
|
||||||
await nwaku2.ensureSubscriptions([DefaultPubsubTopic]);
|
await nwaku2.ensureSubscriptions([customPubsubTopic2]);
|
||||||
|
|
||||||
const messageCollector2 = new MessageCollector();
|
const messageCollector2 = new MessageCollector();
|
||||||
|
|
||||||
await subscription2.subscribe([TestDecoder], messageCollector2.callback);
|
await subscription2.subscribe([customDecoder2], messageCollector2.callback);
|
||||||
|
|
||||||
// Making sure that messages are send and reveiced for both subscriptions
|
// Making sure that messages are send and reveiced for both subscriptions
|
||||||
// While loop is done because of https://github.com/waku-org/js-waku/issues/1606
|
// While loop is done because of https://github.com/waku-org/js-waku/issues/1606
|
||||||
while (
|
while (
|
||||||
!(await messageCollector.waitForMessages(1, {
|
!(await messageCollector.waitForMessages(1, {
|
||||||
pubsubTopic: customPubsubTopic
|
pubsubTopic: customPubsubTopic1
|
||||||
})) ||
|
})) ||
|
||||||
!(await messageCollector2.waitForMessages(1, {
|
!(await messageCollector2.waitForMessages(1, {
|
||||||
pubsubTopic: DefaultPubsubTopic
|
pubsubTopic: customPubsubTopic2
|
||||||
}))
|
}))
|
||||||
) {
|
) {
|
||||||
await waku.lightPush.send(newEncoder, { payload: utf8ToBytes("M1") });
|
await waku.lightPush.send(customEncoder1, { payload: utf8ToBytes("M1") });
|
||||||
await waku.lightPush.send(TestEncoder, { payload: utf8ToBytes("M2") });
|
await waku.lightPush.send(customEncoder2, { payload: utf8ToBytes("M2") });
|
||||||
}
|
}
|
||||||
|
|
||||||
messageCollector.verifyReceivedMessage(0, {
|
messageCollector.verifyReceivedMessage(0, {
|
||||||
expectedContentTopic: customContentTopic,
|
expectedContentTopic: customContentTopic1,
|
||||||
expectedPubsubTopic: customPubsubTopic,
|
expectedPubsubTopic: customPubsubTopic1,
|
||||||
expectedMessageText: "M1"
|
expectedMessageText: "M1"
|
||||||
});
|
});
|
||||||
|
|
||||||
messageCollector2.verifyReceivedMessage(0, {
|
messageCollector2.verifyReceivedMessage(0, {
|
||||||
expectedContentTopic: TestContentTopic,
|
expectedContentTopic: customContentTopic2,
|
||||||
expectedPubsubTopic: DefaultPubsubTopic,
|
expectedPubsubTopic: customPubsubTopic2,
|
||||||
expectedMessageText: "M2"
|
expectedMessageText: "M2"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -150,7 +170,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 `customPubsubTopic` but we're passing it a Decoder with the `DefaultPubsubTopic`
|
||||||
try {
|
try {
|
||||||
await subscription.subscribe([TestDecoder], messageCollector.callback);
|
await subscription.subscribe([customDecoder2], messageCollector.callback);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
expect((error as Error).message).to.include(
|
expect((error as Error).message).to.include(
|
||||||
"Pubsub topic not configured"
|
"Pubsub topic not configured"
|
||||||
|
|
|
@ -383,7 +383,7 @@ describe("Waku Filter V2: Subscribe", function () {
|
||||||
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(
|
||||||
DefaultPubsubTopic,
|
undefined,
|
||||||
await nwaku2.getPeerId()
|
await nwaku2.getPeerId()
|
||||||
);
|
);
|
||||||
await nwaku2.ensureSubscriptions([DefaultPubsubTopic]);
|
await nwaku2.ensureSubscriptions([DefaultPubsubTopic]);
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
import { createDecoder, createEncoder, waitForRemotePeer } from "@waku/core";
|
import {
|
||||||
import { IFilterSubscription, LightNode, Protocols } from "@waku/interfaces";
|
createDecoder,
|
||||||
|
createEncoder,
|
||||||
|
DefaultPubsubTopic,
|
||||||
|
waitForRemotePeer
|
||||||
|
} from "@waku/core";
|
||||||
|
import {
|
||||||
|
IFilterSubscription,
|
||||||
|
LightNode,
|
||||||
|
Protocols,
|
||||||
|
ShardInfo
|
||||||
|
} from "@waku/interfaces";
|
||||||
import { createLightNode } from "@waku/sdk";
|
import { createLightNode } from "@waku/sdk";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger } from "@waku/utils";
|
||||||
import { utf8ToBytes } from "@waku/utils/bytes";
|
import { utf8ToBytes } from "@waku/utils/bytes";
|
||||||
|
@ -38,7 +48,9 @@ export async function validatePingError(
|
||||||
|
|
||||||
export async function runNodes(
|
export async function runNodes(
|
||||||
context: Context,
|
context: Context,
|
||||||
pubsubTopics: string[]
|
//TODO: change this to use `ShardInfo` instead of `string[]`
|
||||||
|
pubsubTopics: string[],
|
||||||
|
shardInfo?: ShardInfo
|
||||||
): Promise<[NimGoNode, LightNode]> {
|
): Promise<[NimGoNode, LightNode]> {
|
||||||
const nwaku = new NimGoNode(makeLogFileName(context));
|
const nwaku = new NimGoNode(makeLogFileName(context));
|
||||||
|
|
||||||
|
@ -47,18 +59,24 @@ export async function runNodes(
|
||||||
filter: true,
|
filter: true,
|
||||||
lightpush: true,
|
lightpush: true,
|
||||||
relay: true,
|
relay: true,
|
||||||
topic: pubsubTopics
|
pubsubTopic: pubsubTopics
|
||||||
},
|
},
|
||||||
{ retries: 3 }
|
{ retries: 3 }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const waku_options = {
|
||||||
|
staticNoiseKey: NOISE_KEY_1,
|
||||||
|
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
|
||||||
|
...((pubsubTopics.length !== 1 ||
|
||||||
|
pubsubTopics[0] !== DefaultPubsubTopic) && {
|
||||||
|
shardInfo: shardInfo
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
log.info("Starting js waku node with :", JSON.stringify(waku_options));
|
||||||
let waku: LightNode | undefined;
|
let waku: LightNode | undefined;
|
||||||
try {
|
try {
|
||||||
waku = await createLightNode({
|
waku = await createLightNode(waku_options);
|
||||||
pubsubTopics: pubsubTopics,
|
|
||||||
staticNoiseKey: NOISE_KEY_1,
|
|
||||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
|
||||||
});
|
|
||||||
await waku.start();
|
await waku.start();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error("jswaku node failed to start:", error);
|
log.error("jswaku node failed to start:", error);
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import type { PeerId } from "@libp2p/interface/peer-id";
|
import type { PeerId } from "@libp2p/interface/peer-id";
|
||||||
|
import { createEncoder, waitForRemotePeer } from "@waku/core";
|
||||||
import {
|
import {
|
||||||
createEncoder,
|
LightNode,
|
||||||
DefaultPubsubTopic,
|
Protocols,
|
||||||
waitForRemotePeer
|
SendResult,
|
||||||
} from "@waku/core";
|
ShardInfo,
|
||||||
import { LightNode, Protocols, SendResult } from "@waku/interfaces";
|
SingleShardInfo
|
||||||
|
} from "@waku/interfaces";
|
||||||
|
import { singleShardInfoToPubsubTopic } from "@waku/utils";
|
||||||
import { utf8ToBytes } from "@waku/utils/bytes";
|
import { utf8ToBytes } from "@waku/utils/bytes";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
|
@ -15,12 +18,7 @@ import {
|
||||||
tearDownNodes
|
tearDownNodes
|
||||||
} from "../../src/index.js";
|
} from "../../src/index.js";
|
||||||
|
|
||||||
import {
|
import { messageText, runNodes } from "./utils.js";
|
||||||
messageText,
|
|
||||||
runNodes,
|
|
||||||
TestContentTopic,
|
|
||||||
TestEncoder
|
|
||||||
} from "./utils.js";
|
|
||||||
|
|
||||||
describe("Waku Light Push : Multiple PubsubTopics", function () {
|
describe("Waku Light Push : Multiple PubsubTopics", function () {
|
||||||
this.timeout(30000);
|
this.timeout(30000);
|
||||||
|
@ -28,20 +26,37 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
|
||||||
let nwaku: NimGoNode;
|
let nwaku: NimGoNode;
|
||||||
let nwaku2: NimGoNode;
|
let nwaku2: NimGoNode;
|
||||||
let messageCollector: MessageCollector;
|
let messageCollector: MessageCollector;
|
||||||
const customPubsubTopic = "/waku/2/custom-dapp/proto";
|
const customPubsubTopic1 = singleShardInfoToPubsubTopic({
|
||||||
const customContentTopic = "/test/2/waku-light-push/utf8";
|
cluster: 3,
|
||||||
const customEncoder = createEncoder({
|
index: 1
|
||||||
contentTopic: customContentTopic,
|
|
||||||
pubsubTopic: customPubsubTopic
|
|
||||||
});
|
});
|
||||||
|
const customPubsubTopic2 = singleShardInfoToPubsubTopic({
|
||||||
|
cluster: 3,
|
||||||
|
index: 2
|
||||||
|
});
|
||||||
|
const shardInfo: ShardInfo = { cluster: 3, indexList: [1, 2] };
|
||||||
|
const singleShardInfo1: SingleShardInfo = { cluster: 3, index: 1 };
|
||||||
|
const singleShardInfo2: SingleShardInfo = { cluster: 3, index: 2 };
|
||||||
|
const customContentTopic1 = "/test/2/waku-light-push/utf8";
|
||||||
|
const customContentTopic2 = "/test/3/waku-light-push/utf8";
|
||||||
|
const customEncoder1 = createEncoder({
|
||||||
|
pubsubTopicShardInfo: singleShardInfo1,
|
||||||
|
contentTopic: customContentTopic1
|
||||||
|
});
|
||||||
|
const customEncoder2 = createEncoder({
|
||||||
|
pubsubTopicShardInfo: singleShardInfo2,
|
||||||
|
contentTopic: customContentTopic2
|
||||||
|
});
|
||||||
|
|
||||||
let nimPeerId: PeerId;
|
let nimPeerId: PeerId;
|
||||||
|
|
||||||
this.beforeEach(async function () {
|
this.beforeEach(async function () {
|
||||||
this.timeout(15000);
|
this.timeout(15000);
|
||||||
[nwaku, waku] = await runNodes(this, [
|
[nwaku, waku] = await runNodes(
|
||||||
customPubsubTopic,
|
this,
|
||||||
DefaultPubsubTopic
|
[customPubsubTopic1, customPubsubTopic2],
|
||||||
]);
|
shardInfo
|
||||||
|
);
|
||||||
messageCollector = new MessageCollector(nwaku);
|
messageCollector = new MessageCollector(nwaku);
|
||||||
nimPeerId = await nwaku.getPeerId();
|
nimPeerId = await nwaku.getPeerId();
|
||||||
});
|
});
|
||||||
|
@ -52,7 +67,7 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Push message on custom pubsubTopic", async function () {
|
it("Push message on custom pubsubTopic", async function () {
|
||||||
const pushResponse = await waku.lightPush.send(customEncoder, {
|
const pushResponse = await waku.lightPush.send(customEncoder1, {
|
||||||
payload: utf8ToBytes(messageText)
|
payload: utf8ToBytes(messageText)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -60,20 +75,20 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await messageCollector.waitForMessages(1, {
|
await messageCollector.waitForMessages(1, {
|
||||||
pubsubTopic: customPubsubTopic
|
pubsubTopic: customPubsubTopic1
|
||||||
})
|
})
|
||||||
).to.eq(true);
|
).to.eq(true);
|
||||||
messageCollector.verifyReceivedMessage(0, {
|
messageCollector.verifyReceivedMessage(0, {
|
||||||
expectedMessageText: messageText,
|
expectedMessageText: messageText,
|
||||||
expectedContentTopic: customContentTopic
|
expectedContentTopic: customContentTopic1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Subscribe and receive messages on 2 different pubsubtopics", async function () {
|
it("Subscribe and receive messages on 2 different pubsubtopics", async function () {
|
||||||
const pushResponse1 = await waku.lightPush.send(customEncoder, {
|
const pushResponse1 = await waku.lightPush.send(customEncoder1, {
|
||||||
payload: utf8ToBytes("M1")
|
payload: utf8ToBytes("M1")
|
||||||
});
|
});
|
||||||
const pushResponse2 = await waku.lightPush.send(TestEncoder, {
|
const pushResponse2 = await waku.lightPush.send(customEncoder2, {
|
||||||
payload: utf8ToBytes("M2")
|
payload: utf8ToBytes("M2")
|
||||||
});
|
});
|
||||||
expect(pushResponse1.recipients[0].toString()).to.eq(nimPeerId.toString());
|
expect(pushResponse1.recipients[0].toString()).to.eq(nimPeerId.toString());
|
||||||
|
@ -83,25 +98,25 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await messageCollector.waitForMessages(1, {
|
await messageCollector.waitForMessages(1, {
|
||||||
pubsubTopic: customPubsubTopic
|
pubsubTopic: customPubsubTopic1
|
||||||
})
|
})
|
||||||
).to.eq(true);
|
).to.eq(true);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await messageCollector2.waitForMessages(1, {
|
await messageCollector2.waitForMessages(1, {
|
||||||
pubsubTopic: DefaultPubsubTopic
|
pubsubTopic: customPubsubTopic2
|
||||||
})
|
})
|
||||||
).to.eq(true);
|
).to.eq(true);
|
||||||
|
|
||||||
messageCollector.verifyReceivedMessage(0, {
|
messageCollector.verifyReceivedMessage(0, {
|
||||||
expectedMessageText: "M1",
|
expectedMessageText: "M1",
|
||||||
expectedContentTopic: customContentTopic,
|
expectedContentTopic: customContentTopic1,
|
||||||
expectedPubsubTopic: customPubsubTopic
|
expectedPubsubTopic: customPubsubTopic1
|
||||||
});
|
});
|
||||||
messageCollector2.verifyReceivedMessage(0, {
|
messageCollector2.verifyReceivedMessage(0, {
|
||||||
expectedMessageText: "M2",
|
expectedMessageText: "M2",
|
||||||
expectedContentTopic: TestContentTopic,
|
expectedContentTopic: customContentTopic2,
|
||||||
expectedPubsubTopic: DefaultPubsubTopic
|
expectedPubsubTopic: customPubsubTopic2
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -112,9 +127,9 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
|
||||||
filter: true,
|
filter: true,
|
||||||
lightpush: true,
|
lightpush: true,
|
||||||
relay: true,
|
relay: true,
|
||||||
topic: [DefaultPubsubTopic]
|
pubsubTopic: [customPubsubTopic2]
|
||||||
});
|
});
|
||||||
await nwaku2.ensureSubscriptions([DefaultPubsubTopic]);
|
await nwaku2.ensureSubscriptions([customPubsubTopic2]);
|
||||||
await waku.dial(await nwaku2.getMultiaddrWithId());
|
await waku.dial(await nwaku2.getMultiaddrWithId());
|
||||||
await waitForRemotePeer(waku, [Protocols.LightPush]);
|
await waitForRemotePeer(waku, [Protocols.LightPush]);
|
||||||
|
|
||||||
|
@ -126,31 +141,31 @@ describe("Waku Light Push : Multiple PubsubTopics", function () {
|
||||||
// While loop is done because of https://github.com/waku-org/js-waku/issues/1606
|
// While loop is done because of https://github.com/waku-org/js-waku/issues/1606
|
||||||
while (
|
while (
|
||||||
!(await messageCollector.waitForMessages(1, {
|
!(await messageCollector.waitForMessages(1, {
|
||||||
pubsubTopic: customPubsubTopic
|
pubsubTopic: customPubsubTopic1
|
||||||
})) ||
|
})) ||
|
||||||
!(await messageCollector2.waitForMessages(1, {
|
!(await messageCollector2.waitForMessages(1, {
|
||||||
pubsubTopic: DefaultPubsubTopic
|
pubsubTopic: customPubsubTopic2
|
||||||
})) ||
|
})) ||
|
||||||
pushResponse1!.recipients[0].toString() ===
|
pushResponse1!.recipients[0].toString() ===
|
||||||
pushResponse2!.recipients[0].toString()
|
pushResponse2!.recipients[0].toString()
|
||||||
) {
|
) {
|
||||||
pushResponse1 = await waku.lightPush.send(customEncoder, {
|
pushResponse1 = await waku.lightPush.send(customEncoder1, {
|
||||||
payload: utf8ToBytes("M1")
|
payload: utf8ToBytes("M1")
|
||||||
});
|
});
|
||||||
pushResponse2 = await waku.lightPush.send(TestEncoder, {
|
pushResponse2 = await waku.lightPush.send(customEncoder2, {
|
||||||
payload: utf8ToBytes("M2")
|
payload: utf8ToBytes("M2")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
messageCollector.verifyReceivedMessage(0, {
|
messageCollector.verifyReceivedMessage(0, {
|
||||||
expectedMessageText: "M1",
|
expectedMessageText: "M1",
|
||||||
expectedContentTopic: customContentTopic,
|
expectedContentTopic: customContentTopic1,
|
||||||
expectedPubsubTopic: customPubsubTopic
|
expectedPubsubTopic: customPubsubTopic1
|
||||||
});
|
});
|
||||||
messageCollector2.verifyReceivedMessage(0, {
|
messageCollector2.verifyReceivedMessage(0, {
|
||||||
expectedMessageText: "M2",
|
expectedMessageText: "M2",
|
||||||
expectedContentTopic: TestContentTopic,
|
expectedContentTopic: customContentTopic2,
|
||||||
expectedPubsubTopic: DefaultPubsubTopic
|
expectedPubsubTopic: customPubsubTopic2
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import { createEncoder, waitForRemotePeer } from "@waku/core";
|
import {
|
||||||
import { LightNode, Protocols } from "@waku/interfaces";
|
createEncoder,
|
||||||
|
DefaultPubsubTopic,
|
||||||
|
waitForRemotePeer
|
||||||
|
} from "@waku/core";
|
||||||
|
import { LightNode, Protocols, ShardInfo } from "@waku/interfaces";
|
||||||
import { createLightNode, utf8ToBytes } from "@waku/sdk";
|
import { createLightNode, utf8ToBytes } from "@waku/sdk";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger } from "@waku/utils";
|
||||||
|
|
||||||
|
@ -14,18 +18,22 @@ export const messagePayload = { payload: utf8ToBytes(messageText) };
|
||||||
|
|
||||||
export async function runNodes(
|
export async function runNodes(
|
||||||
context: Mocha.Context,
|
context: Mocha.Context,
|
||||||
pubsubTopics: string[]
|
pubsubTopics: string[],
|
||||||
|
shardInfo?: ShardInfo
|
||||||
): Promise<[NimGoNode, LightNode]> {
|
): Promise<[NimGoNode, LightNode]> {
|
||||||
const nwaku = new NimGoNode(makeLogFileName(context));
|
const nwaku = new NimGoNode(makeLogFileName(context));
|
||||||
await nwaku.start(
|
await nwaku.start(
|
||||||
{ lightpush: true, relay: true, topic: pubsubTopics },
|
{ lightpush: true, relay: true, pubsubTopic: pubsubTopics },
|
||||||
{ retries: 3 }
|
{ retries: 3 }
|
||||||
);
|
);
|
||||||
|
|
||||||
let waku: LightNode | undefined;
|
let waku: LightNode | undefined;
|
||||||
try {
|
try {
|
||||||
waku = await createLightNode({
|
waku = await createLightNode({
|
||||||
pubsubTopics: pubsubTopics,
|
...((pubsubTopics.length !== 1 ||
|
||||||
|
pubsubTopics[0] !== DefaultPubsubTopic) && {
|
||||||
|
shardInfo: shardInfo
|
||||||
|
}),
|
||||||
staticNoiseKey: NOISE_KEY_1
|
staticNoiseKey: NOISE_KEY_1
|
||||||
});
|
});
|
||||||
await waku.start();
|
await waku.start();
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import {
|
import {
|
||||||
|
createDecoder,
|
||||||
|
createEncoder,
|
||||||
DecodedMessage,
|
DecodedMessage,
|
||||||
DefaultPubsubTopic,
|
|
||||||
waitForRemotePeer
|
waitForRemotePeer
|
||||||
} from "@waku/core";
|
} from "@waku/core";
|
||||||
import { RelayNode } from "@waku/interfaces";
|
import { RelayNode, ShardInfo, SingleShardInfo } from "@waku/interfaces";
|
||||||
import { Protocols } from "@waku/interfaces";
|
import { Protocols } from "@waku/interfaces";
|
||||||
import { createRelayNode } from "@waku/sdk";
|
import { createRelayNode } from "@waku/sdk";
|
||||||
|
import { singleShardInfoToPubsubTopic } 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";
|
||||||
|
|
||||||
|
@ -16,16 +18,7 @@ import {
|
||||||
NOISE_KEY_3,
|
NOISE_KEY_3,
|
||||||
tearDownNodes
|
tearDownNodes
|
||||||
} from "../../src/index.js";
|
} from "../../src/index.js";
|
||||||
|
import { TestDecoder } from "../filter/utils.js";
|
||||||
import {
|
|
||||||
CustomContentTopic,
|
|
||||||
CustomDecoder,
|
|
||||||
CustomEncoder,
|
|
||||||
CustomPubsubTopic,
|
|
||||||
TestContentTopic,
|
|
||||||
TestDecoder,
|
|
||||||
TestEncoder
|
|
||||||
} from "./utils.js";
|
|
||||||
|
|
||||||
describe("Waku Relay, multiple pubsub topics", function () {
|
describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
this.timeout(15000);
|
this.timeout(15000);
|
||||||
|
@ -33,6 +26,38 @@ describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
let waku2: RelayNode;
|
let waku2: RelayNode;
|
||||||
let waku3: RelayNode;
|
let waku3: RelayNode;
|
||||||
|
|
||||||
|
const customPubsubTopic1 = singleShardInfoToPubsubTopic({
|
||||||
|
cluster: 3,
|
||||||
|
index: 1
|
||||||
|
});
|
||||||
|
const customPubsubTopic2 = singleShardInfoToPubsubTopic({
|
||||||
|
cluster: 3,
|
||||||
|
index: 2
|
||||||
|
});
|
||||||
|
const shardInfo1: ShardInfo = { cluster: 3, indexList: [1] };
|
||||||
|
const singleShardInfo1: SingleShardInfo = {
|
||||||
|
cluster: 3,
|
||||||
|
index: 1
|
||||||
|
};
|
||||||
|
const customContentTopic1 = "/test/2/waku-relay/utf8";
|
||||||
|
const customContentTopic2 = "/test/3/waku-relay/utf8";
|
||||||
|
const shardInfo2: ShardInfo = { cluster: 3, indexList: [2] };
|
||||||
|
const singleShardInfo2: SingleShardInfo = {
|
||||||
|
cluster: 3,
|
||||||
|
index: 2
|
||||||
|
};
|
||||||
|
const customEncoder1 = createEncoder({
|
||||||
|
pubsubTopicShardInfo: singleShardInfo1,
|
||||||
|
contentTopic: customContentTopic1
|
||||||
|
});
|
||||||
|
const customDecoder1 = createDecoder(customContentTopic1, singleShardInfo1);
|
||||||
|
const customEncoder2 = createEncoder({
|
||||||
|
pubsubTopicShardInfo: singleShardInfo2,
|
||||||
|
contentTopic: customContentTopic2
|
||||||
|
});
|
||||||
|
const customDecoder2 = createDecoder(customContentTopic2, singleShardInfo2);
|
||||||
|
const shardInfoBothShards: ShardInfo = { cluster: 3, indexList: [1, 2] };
|
||||||
|
|
||||||
afterEach(async function () {
|
afterEach(async function () {
|
||||||
this.timeout(15000);
|
this.timeout(15000);
|
||||||
await tearDownNodes([], [waku1, waku2, waku3]);
|
await tearDownNodes([], [waku1, waku2, waku3]);
|
||||||
|
@ -40,14 +65,16 @@ describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
pubsub: CustomPubsubTopic,
|
pubsub: customPubsubTopic1,
|
||||||
encoder: CustomEncoder,
|
shardInfo: shardInfo1,
|
||||||
decoder: CustomDecoder
|
encoder: customEncoder1,
|
||||||
|
decoder: customDecoder1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pubsub: DefaultPubsubTopic,
|
pubsub: customPubsubTopic2,
|
||||||
encoder: TestEncoder,
|
shardInfo: shardInfo2,
|
||||||
decoder: TestDecoder
|
encoder: customEncoder2,
|
||||||
|
decoder: customDecoder2
|
||||||
}
|
}
|
||||||
].forEach((testItem) => {
|
].forEach((testItem) => {
|
||||||
it(`3 nodes on ${testItem.pubsub} topic`, async function () {
|
it(`3 nodes on ${testItem.pubsub} topic`, async function () {
|
||||||
|
@ -57,16 +84,16 @@ describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
|
|
||||||
[waku1, waku2, waku3] = await Promise.all([
|
[waku1, waku2, waku3] = await Promise.all([
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [testItem.pubsub],
|
shardInfo: testItem.shardInfo,
|
||||||
staticNoiseKey: NOISE_KEY_1
|
staticNoiseKey: NOISE_KEY_1
|
||||||
}).then((waku) => waku.start().then(() => waku)),
|
}).then((waku) => waku.start().then(() => waku)),
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [testItem.pubsub],
|
shardInfo: testItem.shardInfo,
|
||||||
staticNoiseKey: NOISE_KEY_2,
|
staticNoiseKey: NOISE_KEY_2,
|
||||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
||||||
}).then((waku) => waku.start().then(() => waku)),
|
}).then((waku) => waku.start().then(() => waku)),
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [testItem.pubsub],
|
shardInfo: testItem.shardInfo,
|
||||||
staticNoiseKey: NOISE_KEY_3
|
staticNoiseKey: NOISE_KEY_3
|
||||||
}).then((waku) => waku.start().then(() => waku))
|
}).then((waku) => waku.start().then(() => waku))
|
||||||
]);
|
]);
|
||||||
|
@ -155,16 +182,16 @@ describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
// Waku1 and waku2 are using multiple pubsub topis
|
// Waku1 and waku2 are using multiple pubsub topis
|
||||||
[waku1, waku2, waku3] = await Promise.all([
|
[waku1, waku2, waku3] = await Promise.all([
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [DefaultPubsubTopic, CustomPubsubTopic],
|
shardInfo: shardInfoBothShards,
|
||||||
staticNoiseKey: NOISE_KEY_1
|
staticNoiseKey: NOISE_KEY_1
|
||||||
}).then((waku) => waku.start().then(() => waku)),
|
}).then((waku) => waku.start().then(() => waku)),
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [DefaultPubsubTopic, CustomPubsubTopic],
|
shardInfo: shardInfoBothShards,
|
||||||
staticNoiseKey: NOISE_KEY_2,
|
staticNoiseKey: NOISE_KEY_2,
|
||||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
||||||
}).then((waku) => waku.start().then(() => waku)),
|
}).then((waku) => waku.start().then(() => waku)),
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [DefaultPubsubTopic],
|
shardInfo: shardInfo1,
|
||||||
staticNoiseKey: NOISE_KEY_3
|
staticNoiseKey: NOISE_KEY_3
|
||||||
}).then((waku) => waku.start().then(() => waku))
|
}).then((waku) => waku.start().then(() => waku))
|
||||||
]);
|
]);
|
||||||
|
@ -187,45 +214,45 @@ describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await waku1.relay.subscribe(
|
await waku1.relay.subscribe(
|
||||||
[TestDecoder, CustomDecoder],
|
[customDecoder1, customDecoder2],
|
||||||
msgCollector1.callback
|
msgCollector1.callback
|
||||||
);
|
);
|
||||||
await waku2.relay.subscribe(
|
await waku2.relay.subscribe(
|
||||||
[TestDecoder, CustomDecoder],
|
[customDecoder1, customDecoder2],
|
||||||
msgCollector2.callback
|
msgCollector2.callback
|
||||||
);
|
);
|
||||||
await waku3.relay.subscribe([TestDecoder], msgCollector3.callback);
|
await waku3.relay.subscribe([customDecoder1], msgCollector3.callback);
|
||||||
|
|
||||||
// The nodes are setup in such a way that all messages send should be relayed to the other nodes in the network
|
// The nodes are setup in such a way that all messages send should be relayed to the other nodes in the network
|
||||||
// However onlt waku1 and waku2 are receiving messages on the CustomPubsubTopic
|
// However onlt waku1 and waku2 are receiving messages on the CustomPubSubTopic
|
||||||
await waku1.relay.send(TestEncoder, { payload: utf8ToBytes("M1") });
|
await waku1.relay.send(customEncoder1, { payload: utf8ToBytes("M1") });
|
||||||
await waku1.relay.send(CustomEncoder, { payload: utf8ToBytes("M2") });
|
await waku1.relay.send(customEncoder2, { payload: utf8ToBytes("M2") });
|
||||||
await waku2.relay.send(TestEncoder, { payload: utf8ToBytes("M3") });
|
await waku2.relay.send(customEncoder1, { payload: utf8ToBytes("M3") });
|
||||||
await waku2.relay.send(CustomEncoder, { payload: utf8ToBytes("M4") });
|
await waku2.relay.send(customEncoder2, { payload: utf8ToBytes("M4") });
|
||||||
await waku3.relay.send(TestEncoder, { payload: utf8ToBytes("M5") });
|
await waku3.relay.send(customEncoder1, { payload: utf8ToBytes("M5") });
|
||||||
await waku3.relay.send(CustomEncoder, { payload: utf8ToBytes("M6") });
|
await waku3.relay.send(customEncoder2, { payload: utf8ToBytes("M6") });
|
||||||
|
|
||||||
expect(await msgCollector1.waitForMessages(3, { exact: true })).to.eq(true);
|
expect(await msgCollector1.waitForMessages(3, { exact: true })).to.eq(true);
|
||||||
expect(await msgCollector2.waitForMessages(3, { exact: true })).to.eq(true);
|
expect(await msgCollector2.waitForMessages(3, { exact: true })).to.eq(true);
|
||||||
expect(await msgCollector3.waitForMessages(2, { exact: true })).to.eq(true);
|
expect(await msgCollector3.waitForMessages(2, { exact: true })).to.eq(true);
|
||||||
expect(msgCollector1.hasMessage(TestContentTopic, "M3")).to.eq(true);
|
expect(msgCollector1.hasMessage(customContentTopic1, "M3")).to.eq(true);
|
||||||
expect(msgCollector1.hasMessage(CustomContentTopic, "M4")).to.eq(true);
|
expect(msgCollector1.hasMessage(customContentTopic2, "M4")).to.eq(true);
|
||||||
expect(msgCollector1.hasMessage(TestContentTopic, "M5")).to.eq(true);
|
expect(msgCollector1.hasMessage(customContentTopic1, "M5")).to.eq(true);
|
||||||
expect(msgCollector2.hasMessage(TestContentTopic, "M1")).to.eq(true);
|
expect(msgCollector2.hasMessage(customContentTopic1, "M1")).to.eq(true);
|
||||||
expect(msgCollector2.hasMessage(CustomContentTopic, "M2")).to.eq(true);
|
expect(msgCollector2.hasMessage(customContentTopic2, "M2")).to.eq(true);
|
||||||
expect(msgCollector2.hasMessage(TestContentTopic, "M5")).to.eq(true);
|
expect(msgCollector2.hasMessage(customContentTopic1, "M5")).to.eq(true);
|
||||||
expect(msgCollector3.hasMessage(TestContentTopic, "M1")).to.eq(true);
|
expect(msgCollector3.hasMessage(customContentTopic1, "M1")).to.eq(true);
|
||||||
expect(msgCollector3.hasMessage(TestContentTopic, "M3")).to.eq(true);
|
expect(msgCollector3.hasMessage(customContentTopic1, "M3")).to.eq(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("n1 and n2 uses a custom pubsub, n3 uses the default pubsub", async function () {
|
it("n1 and n2 uses a custom pubsub, n3 uses the default pubsub", async function () {
|
||||||
[waku1, waku2, waku3] = await Promise.all([
|
[waku1, waku2, waku3] = await Promise.all([
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [CustomPubsubTopic],
|
shardInfo: shardInfo1,
|
||||||
staticNoiseKey: NOISE_KEY_1
|
staticNoiseKey: NOISE_KEY_1
|
||||||
}).then((waku) => waku.start().then(() => waku)),
|
}).then((waku) => waku.start().then(() => waku)),
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [CustomPubsubTopic],
|
shardInfo: shardInfo1,
|
||||||
staticNoiseKey: NOISE_KEY_2,
|
staticNoiseKey: NOISE_KEY_2,
|
||||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
||||||
}).then((waku) => waku.start().then(() => waku)),
|
}).then((waku) => waku.start().then(() => waku)),
|
||||||
|
@ -254,7 +281,7 @@ describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
|
|
||||||
const waku2ReceivedMsgPromise: Promise<DecodedMessage> = new Promise(
|
const waku2ReceivedMsgPromise: Promise<DecodedMessage> = new Promise(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
void waku2.relay.subscribe([CustomDecoder], resolve);
|
void waku2.relay.subscribe([customDecoder1], resolve);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -267,7 +294,7 @@ describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
await waku1.relay.send(CustomEncoder, {
|
await waku1.relay.send(customEncoder1, {
|
||||||
payload: utf8ToBytes(messageText)
|
payload: utf8ToBytes(messageText)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -275,6 +302,6 @@ describe("Waku Relay, multiple pubsub topics", function () {
|
||||||
await waku3NoMsgPromise;
|
await waku3NoMsgPromise;
|
||||||
|
|
||||||
expect(bytesToUtf8(waku2ReceivedMsg.payload!)).to.eq(messageText);
|
expect(bytesToUtf8(waku2ReceivedMsg.payload!)).to.eq(messageText);
|
||||||
expect(waku2ReceivedMsg.pubsubTopic).to.eq(CustomPubsubTopic);
|
expect(waku2ReceivedMsg.pubsubTopic).to.eq(customPubsubTopic1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { createEncoder, DefaultPubsubTopic } from "@waku/core";
|
import { createEncoder } from "@waku/core";
|
||||||
import { IRateLimitProof, RelayNode, SendError } from "@waku/interfaces";
|
import { IRateLimitProof, RelayNode, SendError } from "@waku/interfaces";
|
||||||
import { createRelayNode } from "@waku/sdk";
|
import { createRelayNode } from "@waku/sdk";
|
||||||
import { utf8ToBytes } from "@waku/utils/bytes";
|
import { utf8ToBytes } from "@waku/utils/bytes";
|
||||||
|
@ -34,11 +34,9 @@ describe("Waku Relay, Publish", function () {
|
||||||
log.info("Starting JS Waku instances");
|
log.info("Starting JS Waku instances");
|
||||||
[waku1, waku2] = await Promise.all([
|
[waku1, waku2] = await Promise.all([
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [DefaultPubsubTopic],
|
|
||||||
staticNoiseKey: NOISE_KEY_1
|
staticNoiseKey: NOISE_KEY_1
|
||||||
}).then((waku) => waku.start().then(() => waku)),
|
}).then((waku) => waku.start().then(() => waku)),
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [DefaultPubsubTopic],
|
|
||||||
staticNoiseKey: NOISE_KEY_2,
|
staticNoiseKey: NOISE_KEY_2,
|
||||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
||||||
}).then((waku) => waku.start().then(() => waku))
|
}).then((waku) => waku.start().then(() => waku))
|
||||||
|
@ -130,7 +128,7 @@ describe("Waku Relay, Publish", function () {
|
||||||
|
|
||||||
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({
|
||||||
pubsubTopic: "wrong",
|
pubsubTopicShardInfo: { cluster: 3, index: 1 },
|
||||||
contentTopic: TestContentTopic
|
contentTopic: TestContentTopic
|
||||||
});
|
});
|
||||||
const pushResponse = await waku1.relay.send(wrong_encoder, {
|
const pushResponse = await waku1.relay.send(wrong_encoder, {
|
||||||
|
|
|
@ -33,11 +33,9 @@ describe("Waku Relay, Subscribe", function () {
|
||||||
log.info("Starting JS Waku instances");
|
log.info("Starting JS Waku instances");
|
||||||
[waku1, waku2] = await Promise.all([
|
[waku1, waku2] = await Promise.all([
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [DefaultPubsubTopic],
|
|
||||||
staticNoiseKey: NOISE_KEY_1
|
staticNoiseKey: NOISE_KEY_1
|
||||||
}).then((waku) => waku.start().then(() => waku)),
|
}).then((waku) => waku.start().then(() => waku)),
|
||||||
createRelayNode({
|
createRelayNode({
|
||||||
pubsubTopics: [DefaultPubsubTopic],
|
|
||||||
staticNoiseKey: NOISE_KEY_2,
|
staticNoiseKey: NOISE_KEY_2,
|
||||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }
|
||||||
}).then((waku) => waku.start().then(() => waku))
|
}).then((waku) => waku.start().then(() => waku))
|
||||||
|
|
|
@ -6,17 +6,6 @@ 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 TestEncoder = createEncoder({ contentTopic: TestContentTopic });
|
||||||
export const TestDecoder = createDecoder(TestContentTopic);
|
export const TestDecoder = createDecoder(TestContentTopic);
|
||||||
export const CustomContentTopic = "/test/2/waku-relay/utf8";
|
|
||||||
export const CustomPubsubTopic = "/some/pubsub/topic";
|
|
||||||
export const CustomEncoder = createEncoder({
|
|
||||||
contentTopic: CustomContentTopic,
|
|
||||||
pubsubTopic: CustomPubsubTopic
|
|
||||||
});
|
|
||||||
export const CustomDecoder = createDecoder(
|
|
||||||
CustomContentTopic,
|
|
||||||
CustomPubsubTopic
|
|
||||||
);
|
|
||||||
|
|
||||||
export const log = new Logger("test:relay");
|
export const log = new Logger("test:relay");
|
||||||
|
|
||||||
export async function waitForAllRemotePeers(
|
export async function waitForAllRemotePeers(
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { bootstrap } from "@libp2p/bootstrap";
|
import { bootstrap } from "@libp2p/bootstrap";
|
||||||
import type { PeerId } from "@libp2p/interface/peer-id";
|
import type { PeerId } from "@libp2p/interface/peer-id";
|
||||||
import { wakuPeerExchangeDiscovery } from "@waku/peer-exchange";
|
import { wakuPeerExchangeDiscovery } from "@waku/peer-exchange";
|
||||||
import { createLightNode, LightNode, Tags } from "@waku/sdk";
|
import { createLightNode, LightNode, ShardInfo, Tags } from "@waku/sdk";
|
||||||
|
import { singleShardInfoToPubsubTopic } from "@waku/utils";
|
||||||
import chai, { expect } from "chai";
|
import chai, { expect } from "chai";
|
||||||
import chaiAsPromised from "chai-as-promised";
|
import chaiAsPromised from "chai-as-promised";
|
||||||
import Sinon, { SinonSpy } from "sinon";
|
import Sinon, { SinonSpy } from "sinon";
|
||||||
|
@ -38,10 +39,13 @@ describe("Static Sharding: Peer Management", function () {
|
||||||
it("all px service nodes subscribed to the shard topic should be dialed", async function () {
|
it("all px service nodes subscribed to the shard topic should be dialed", async function () {
|
||||||
this.timeout(100_000);
|
this.timeout(100_000);
|
||||||
|
|
||||||
const pubsubTopics = ["/waku/2/rs/18/2"];
|
const pubsubTopics = [
|
||||||
|
singleShardInfoToPubsubTopic({ cluster: 18, index: 2 })
|
||||||
|
];
|
||||||
|
const shardInfo: ShardInfo = { cluster: 18, indexList: [2] };
|
||||||
|
|
||||||
await nwaku1.start({
|
await nwaku1.start({
|
||||||
topic: pubsubTopics,
|
pubsubTopic: pubsubTopics,
|
||||||
discv5Discovery: true,
|
discv5Discovery: true,
|
||||||
peerExchange: true,
|
peerExchange: true,
|
||||||
relay: true
|
relay: true
|
||||||
|
@ -50,7 +54,7 @@ describe("Static Sharding: Peer Management", function () {
|
||||||
const enr1 = (await nwaku1.info()).enrUri;
|
const enr1 = (await nwaku1.info()).enrUri;
|
||||||
|
|
||||||
await nwaku2.start({
|
await nwaku2.start({
|
||||||
topic: pubsubTopics,
|
pubsubTopic: pubsubTopics,
|
||||||
discv5Discovery: true,
|
discv5Discovery: true,
|
||||||
peerExchange: true,
|
peerExchange: true,
|
||||||
discv5BootstrapNode: enr1,
|
discv5BootstrapNode: enr1,
|
||||||
|
@ -60,7 +64,7 @@ describe("Static Sharding: Peer Management", function () {
|
||||||
const enr2 = (await nwaku2.info()).enrUri;
|
const enr2 = (await nwaku2.info()).enrUri;
|
||||||
|
|
||||||
await nwaku3.start({
|
await nwaku3.start({
|
||||||
topic: pubsubTopics,
|
pubsubTopic: pubsubTopics,
|
||||||
discv5Discovery: true,
|
discv5Discovery: true,
|
||||||
peerExchange: true,
|
peerExchange: true,
|
||||||
discv5BootstrapNode: enr2,
|
discv5BootstrapNode: enr2,
|
||||||
|
@ -69,7 +73,7 @@ describe("Static Sharding: Peer Management", function () {
|
||||||
const nwaku3Ma = await nwaku3.getMultiaddrWithId();
|
const nwaku3Ma = await nwaku3.getMultiaddrWithId();
|
||||||
|
|
||||||
waku = await createLightNode({
|
waku = await createLightNode({
|
||||||
pubsubTopics,
|
shardInfo: shardInfo,
|
||||||
libp2p: {
|
libp2p: {
|
||||||
peerDiscovery: [
|
peerDiscovery: [
|
||||||
bootstrap({ list: [nwaku3Ma.toString()] }),
|
bootstrap({ list: [nwaku3Ma.toString()] }),
|
||||||
|
@ -107,12 +111,17 @@ describe("Static Sharding: Peer Management", function () {
|
||||||
|
|
||||||
it("px service nodes not subscribed to the shard should not be dialed", async function () {
|
it("px service nodes not subscribed to the shard should not be dialed", async function () {
|
||||||
this.timeout(100_000);
|
this.timeout(100_000);
|
||||||
const pubsubTopicsToDial = ["/waku/2/rs/18/2"];
|
const pubsubTopicsToDial = [
|
||||||
const pubsubTopicsToIgnore = ["/waku/2/rs/18/3"];
|
singleShardInfoToPubsubTopic({ cluster: 18, index: 2 })
|
||||||
|
];
|
||||||
|
const shardInfoToDial: ShardInfo = { cluster: 18, indexList: [2] };
|
||||||
|
const pubsubTopicsToIgnore = [
|
||||||
|
singleShardInfoToPubsubTopic({ cluster: 18, index: 1 })
|
||||||
|
];
|
||||||
|
|
||||||
// this service node is not subscribed to the shard
|
// this service node is not subscribed to the shard
|
||||||
await nwaku1.start({
|
await nwaku1.start({
|
||||||
topic: pubsubTopicsToIgnore,
|
pubsubTopic: pubsubTopicsToIgnore,
|
||||||
relay: true,
|
relay: true,
|
||||||
discv5Discovery: true,
|
discv5Discovery: true,
|
||||||
peerExchange: true
|
peerExchange: true
|
||||||
|
@ -121,7 +130,7 @@ describe("Static Sharding: Peer Management", function () {
|
||||||
const enr1 = (await nwaku1.info()).enrUri;
|
const enr1 = (await nwaku1.info()).enrUri;
|
||||||
|
|
||||||
await nwaku2.start({
|
await nwaku2.start({
|
||||||
topic: pubsubTopicsToDial,
|
pubsubTopic: pubsubTopicsToDial,
|
||||||
relay: true,
|
relay: true,
|
||||||
discv5Discovery: true,
|
discv5Discovery: true,
|
||||||
peerExchange: true,
|
peerExchange: true,
|
||||||
|
@ -139,7 +148,7 @@ describe("Static Sharding: Peer Management", function () {
|
||||||
const nwaku3Ma = await nwaku3.getMultiaddrWithId();
|
const nwaku3Ma = await nwaku3.getMultiaddrWithId();
|
||||||
|
|
||||||
waku = await createLightNode({
|
waku = await createLightNode({
|
||||||
pubsubTopics: pubsubTopicsToDial,
|
shardInfo: shardInfoToDial,
|
||||||
libp2p: {
|
libp2p: {
|
||||||
peerDiscovery: [
|
peerDiscovery: [
|
||||||
bootstrap({ list: [nwaku3Ma.toString()] }),
|
bootstrap({ list: [nwaku3Ma.toString()] }),
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
import { LightNode } from "@waku/interfaces";
|
import { LightNode, ShardInfo, SingleShardInfo } from "@waku/interfaces";
|
||||||
import { createEncoder, createLightNode, utf8ToBytes } from "@waku/sdk";
|
import { createEncoder, createLightNode, utf8ToBytes } from "@waku/sdk";
|
||||||
|
import { singleShardInfoToPubsubTopic } from "@waku/utils";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { tearDownNodes } from "../../src/index.js";
|
import { tearDownNodes } from "../../src/index.js";
|
||||||
import { makeLogFileName } from "../../src/log_file.js";
|
import { makeLogFileName } from "../../src/log_file.js";
|
||||||
import { NimGoNode } from "../../src/node/node.js";
|
import { NimGoNode } from "../../src/node/node.js";
|
||||||
|
|
||||||
const PubsubTopic1 = "/waku/2/rs/0/2";
|
const PubsubTopic1 = singleShardInfoToPubsubTopic({
|
||||||
const PubsubTopic2 = "/waku/2/rs/0/3";
|
cluster: 0,
|
||||||
|
index: 2
|
||||||
|
});
|
||||||
|
const PubsubTopic2 = singleShardInfoToPubsubTopic({
|
||||||
|
cluster: 0,
|
||||||
|
index: 3
|
||||||
|
});
|
||||||
|
const shardInfoFirstShard: ShardInfo = { cluster: 0, indexList: [2] };
|
||||||
|
const shardInfoBothShards: ShardInfo = { cluster: 0, indexList: [2, 3] };
|
||||||
|
const singleShardInfo1: SingleShardInfo = { cluster: 0, index: 2 };
|
||||||
|
const singleShardInfo2: SingleShardInfo = { cluster: 0, index: 3 };
|
||||||
const ContentTopic = "/waku/2/content/test.js";
|
const ContentTopic = "/waku/2/content/test.js";
|
||||||
|
|
||||||
describe("Static Sharding: Running Nodes", () => {
|
describe("Static Sharding: Running Nodes", () => {
|
||||||
|
@ -29,17 +39,17 @@ describe("Static Sharding: Running Nodes", () => {
|
||||||
it("configure the node with multiple pubsub topics", async function () {
|
it("configure the node with multiple pubsub topics", async function () {
|
||||||
this.timeout(15_000);
|
this.timeout(15_000);
|
||||||
waku = await createLightNode({
|
waku = await createLightNode({
|
||||||
pubsubTopics: [PubsubTopic1, PubsubTopic2]
|
shardInfo: shardInfoBothShards
|
||||||
});
|
});
|
||||||
|
|
||||||
const encoder1 = createEncoder({
|
const encoder1 = createEncoder({
|
||||||
contentTopic: ContentTopic,
|
contentTopic: ContentTopic,
|
||||||
pubsubTopic: PubsubTopic1
|
pubsubTopicShardInfo: singleShardInfo1
|
||||||
});
|
});
|
||||||
|
|
||||||
const encoder2 = createEncoder({
|
const encoder2 = createEncoder({
|
||||||
contentTopic: ContentTopic,
|
contentTopic: ContentTopic,
|
||||||
pubsubTopic: PubsubTopic2
|
pubsubTopicShardInfo: singleShardInfo2
|
||||||
});
|
});
|
||||||
|
|
||||||
const request1 = await waku.lightPush.send(encoder1, {
|
const request1 = await waku.lightPush.send(encoder1, {
|
||||||
|
@ -57,13 +67,13 @@ describe("Static Sharding: Running Nodes", () => {
|
||||||
it("using a protocol with unconfigured pubsub topic should fail", async function () {
|
it("using a protocol with unconfigured pubsub topic should fail", async function () {
|
||||||
this.timeout(15_000);
|
this.timeout(15_000);
|
||||||
waku = await createLightNode({
|
waku = await createLightNode({
|
||||||
pubsubTopics: [PubsubTopic1]
|
shardInfo: shardInfoFirstShard
|
||||||
});
|
});
|
||||||
|
|
||||||
// use a pubsub topic that is not configured
|
// use a pubsub topic that is not configured
|
||||||
const encoder = createEncoder({
|
const encoder = createEncoder({
|
||||||
contentTopic: ContentTopic,
|
contentTopic: ContentTopic,
|
||||||
pubsubTopic: PubsubTopic2
|
pubsubTopicShardInfo: singleShardInfo2
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { expect } from "chai";
|
||||||
import { makeLogFileName, NimGoNode, tearDownNodes } from "../../src/index.js";
|
import { makeLogFileName, NimGoNode, tearDownNodes } from "../../src/index.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
customPubsubTopic,
|
customShardedPubsubTopic1,
|
||||||
sendMessages,
|
sendMessages,
|
||||||
startAndConnectLightNode,
|
startAndConnectLightNode,
|
||||||
TestContentTopic,
|
TestContentTopic,
|
||||||
|
@ -179,7 +179,7 @@ describe("Waku Store, cursor", function () {
|
||||||
messages.push(msg as DecodedMessage);
|
messages.push(msg as DecodedMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
messages[5].pubsubTopic = customPubsubTopic;
|
messages[5].pubsubTopic = customShardedPubsubTopic1;
|
||||||
const cursor = await createCursor(messages[5]);
|
const cursor = await createCursor(messages[5]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -193,7 +193,7 @@ describe("Waku Store, cursor", function () {
|
||||||
if (
|
if (
|
||||||
!(err instanceof Error) ||
|
!(err instanceof Error) ||
|
||||||
!err.message.includes(
|
!err.message.includes(
|
||||||
`Cursor pubsub topic (${customPubsubTopic}) does not match decoder pubsub topic (${DefaultPubsubTopic})`
|
`Cursor pubsub topic (${customShardedPubsubTopic1}) does not match decoder pubsub topic (${DefaultPubsubTopic})`
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
throw err;
|
throw err;
|
||||||
|
|
|
@ -5,8 +5,8 @@ import { expect } from "chai";
|
||||||
import { makeLogFileName, NimGoNode, tearDownNodes } from "../../src/index.js";
|
import { makeLogFileName, NimGoNode, tearDownNodes } from "../../src/index.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
customPubsubTopic,
|
customDecoder1,
|
||||||
customTestDecoder,
|
customShardedPubsubTopic1,
|
||||||
processQueriedMessages,
|
processQueriedMessages,
|
||||||
startAndConnectLightNode,
|
startAndConnectLightNode,
|
||||||
TestDecoder
|
TestDecoder
|
||||||
|
@ -33,7 +33,7 @@ describe("Waku Store, error handling", function () {
|
||||||
it("Query Generator, Wrong PubsubTopic", async function () {
|
it("Query Generator, Wrong PubsubTopic", async function () {
|
||||||
try {
|
try {
|
||||||
for await (const msgPromises of waku.store.queryGenerator([
|
for await (const msgPromises of waku.store.queryGenerator([
|
||||||
customTestDecoder
|
customDecoder1
|
||||||
])) {
|
])) {
|
||||||
msgPromises;
|
msgPromises;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ describe("Waku Store, error handling", function () {
|
||||||
if (
|
if (
|
||||||
!(err instanceof Error) ||
|
!(err instanceof Error) ||
|
||||||
!err.message.includes(
|
!err.message.includes(
|
||||||
`Pubsub topic ${customPubsubTopic} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}`
|
`Pubsub topic ${customShardedPubsubTopic1} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}`
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -54,7 +54,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,
|
||||||
customTestDecoder
|
customDecoder1
|
||||||
])) {
|
])) {
|
||||||
msgPromises;
|
msgPromises;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ describe("Waku Store, error handling", function () {
|
||||||
it("Query with Ordered Callback, Wrong PubsubTopic", async function () {
|
it("Query with Ordered Callback, Wrong PubsubTopic", async function () {
|
||||||
try {
|
try {
|
||||||
await waku.store.queryWithOrderedCallback(
|
await waku.store.queryWithOrderedCallback(
|
||||||
[customTestDecoder],
|
[customDecoder1],
|
||||||
async () => {}
|
async () => {}
|
||||||
);
|
);
|
||||||
throw new Error("QueryGenerator was successful but was expected to fail");
|
throw new Error("QueryGenerator was successful but was expected to fail");
|
||||||
|
@ -107,7 +107,7 @@ describe("Waku Store, error handling", function () {
|
||||||
if (
|
if (
|
||||||
!(err instanceof Error) ||
|
!(err instanceof Error) ||
|
||||||
!err.message.includes(
|
!err.message.includes(
|
||||||
`Pubsub topic ${customPubsubTopic} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}`
|
`Pubsub topic ${customShardedPubsubTopic1} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}`
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -118,7 +118,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, customTestDecoder],
|
[TestDecoder, customDecoder1],
|
||||||
async () => {}
|
async () => {}
|
||||||
);
|
);
|
||||||
throw new Error("QueryGenerator was successful but was expected to fail");
|
throw new Error("QueryGenerator was successful but was expected to fail");
|
||||||
|
@ -159,7 +159,7 @@ describe("Waku Store, error handling", function () {
|
||||||
it("Query with Promise Callback, Wrong PubsubTopic", async function () {
|
it("Query with Promise Callback, Wrong PubsubTopic", async function () {
|
||||||
try {
|
try {
|
||||||
await waku.store.queryWithPromiseCallback(
|
await waku.store.queryWithPromiseCallback(
|
||||||
[customTestDecoder],
|
[customDecoder1],
|
||||||
async () => {}
|
async () => {}
|
||||||
);
|
);
|
||||||
throw new Error("QueryGenerator was successful but was expected to fail");
|
throw new Error("QueryGenerator was successful but was expected to fail");
|
||||||
|
@ -167,7 +167,7 @@ describe("Waku Store, error handling", function () {
|
||||||
if (
|
if (
|
||||||
!(err instanceof Error) ||
|
!(err instanceof Error) ||
|
||||||
!err.message.includes(
|
!err.message.includes(
|
||||||
`Pubsub topic ${customPubsubTopic} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}`
|
`Pubsub topic ${customShardedPubsubTopic1} has not been configured on this instance. Configured topics are: ${DefaultPubsubTopic}`
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -178,7 +178,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, customTestDecoder],
|
[TestDecoder, customDecoder1],
|
||||||
async () => {}
|
async () => {}
|
||||||
);
|
);
|
||||||
throw new Error("QueryGenerator was successful but was expected to fail");
|
throw new Error("QueryGenerator was successful but was expected to fail");
|
||||||
|
|
|
@ -33,7 +33,7 @@ import {
|
||||||
} from "../../src/index.js";
|
} from "../../src/index.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
customContentTopic,
|
customContentTopic1,
|
||||||
log,
|
log,
|
||||||
messageText,
|
messageText,
|
||||||
processQueriedMessages,
|
processQueriedMessages,
|
||||||
|
@ -45,7 +45,7 @@ import {
|
||||||
totalMsgs
|
totalMsgs
|
||||||
} from "./utils.js";
|
} from "./utils.js";
|
||||||
|
|
||||||
const secondDecoder = createDecoder(customContentTopic, DefaultPubsubTopic);
|
const secondDecoder = createDecoder(customContentTopic1);
|
||||||
|
|
||||||
describe("Waku Store, general", function () {
|
describe("Waku Store, general", function () {
|
||||||
this.timeout(15000);
|
this.timeout(15000);
|
||||||
|
@ -124,7 +124,7 @@ describe("Waku Store, general", function () {
|
||||||
await nwaku.sendMessage(
|
await nwaku.sendMessage(
|
||||||
NimGoNode.toMessageRpcQuery({
|
NimGoNode.toMessageRpcQuery({
|
||||||
payload: utf8ToBytes("M2"),
|
payload: utf8ToBytes("M2"),
|
||||||
contentTopic: customContentTopic
|
contentTopic: customContentTopic1
|
||||||
}),
|
}),
|
||||||
DefaultPubsubTopic
|
DefaultPubsubTopic
|
||||||
);
|
);
|
||||||
|
@ -137,7 +137,7 @@ describe("Waku Store, general", function () {
|
||||||
DefaultPubsubTopic
|
DefaultPubsubTopic
|
||||||
);
|
);
|
||||||
expect(messageCollector.hasMessage(TestContentTopic, "M1")).to.eq(true);
|
expect(messageCollector.hasMessage(TestContentTopic, "M1")).to.eq(true);
|
||||||
expect(messageCollector.hasMessage(customContentTopic, "M2")).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 () {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { DefaultPubsubTopic, waitForRemotePeer } from "@waku/core";
|
import { waitForRemotePeer } from "@waku/core";
|
||||||
import type { IMessage, LightNode } from "@waku/interfaces";
|
import type { IMessage, LightNode } from "@waku/interfaces";
|
||||||
import { createLightNode, Protocols } from "@waku/sdk";
|
import { createLightNode, Protocols } from "@waku/sdk";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
@ -11,14 +11,17 @@ import {
|
||||||
} from "../../src/index.js";
|
} from "../../src/index.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
customContentTopic,
|
customContentTopic1,
|
||||||
customPubsubTopic,
|
customContentTopic2,
|
||||||
customTestDecoder,
|
customDecoder1,
|
||||||
|
customDecoder2,
|
||||||
|
customShardedPubsubTopic1,
|
||||||
|
customShardedPubsubTopic2,
|
||||||
processQueriedMessages,
|
processQueriedMessages,
|
||||||
sendMessages,
|
sendMessages,
|
||||||
|
shardInfo1,
|
||||||
|
shardInfoBothShards,
|
||||||
startAndConnectLightNode,
|
startAndConnectLightNode,
|
||||||
TestContentTopic,
|
|
||||||
TestDecoder,
|
|
||||||
totalMsgs
|
totalMsgs
|
||||||
} from "./utils.js";
|
} from "./utils.js";
|
||||||
|
|
||||||
|
@ -33,10 +36,13 @@ describe("Waku Store, custom pubsub topic", function () {
|
||||||
nwaku = new NimGoNode(makeLogFileName(this));
|
nwaku = new NimGoNode(makeLogFileName(this));
|
||||||
await nwaku.start({
|
await nwaku.start({
|
||||||
store: true,
|
store: true,
|
||||||
topic: [customPubsubTopic, DefaultPubsubTopic],
|
pubsubTopic: [customShardedPubsubTopic1, customShardedPubsubTopic2],
|
||||||
relay: true
|
relay: true
|
||||||
});
|
});
|
||||||
await nwaku.ensureSubscriptions([customPubsubTopic, DefaultPubsubTopic]);
|
await nwaku.ensureSubscriptions([
|
||||||
|
customShardedPubsubTopic1,
|
||||||
|
customShardedPubsubTopic2
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(async function () {
|
afterEach(async function () {
|
||||||
|
@ -45,12 +51,17 @@ describe("Waku Store, custom pubsub topic", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Generator, custom pubsub topic", async function () {
|
it("Generator, custom pubsub topic", async function () {
|
||||||
await sendMessages(nwaku, totalMsgs, customContentTopic, customPubsubTopic);
|
await sendMessages(
|
||||||
waku = await startAndConnectLightNode(nwaku, [customPubsubTopic]);
|
nwaku,
|
||||||
|
totalMsgs,
|
||||||
|
customContentTopic1,
|
||||||
|
customShardedPubsubTopic1
|
||||||
|
);
|
||||||
|
waku = await startAndConnectLightNode(nwaku, [], shardInfo1);
|
||||||
const messages = await processQueriedMessages(
|
const messages = await processQueriedMessages(
|
||||||
waku,
|
waku,
|
||||||
[customTestDecoder],
|
[customDecoder1],
|
||||||
customPubsubTopic
|
customShardedPubsubTopic1
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(messages?.length).eq(totalMsgs);
|
expect(messages?.length).eq(totalMsgs);
|
||||||
|
@ -64,18 +75,25 @@ describe("Waku Store, custom pubsub topic", function () {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
const totalMsgs = 10;
|
const totalMsgs = 10;
|
||||||
await sendMessages(nwaku, totalMsgs, customContentTopic, customPubsubTopic);
|
await sendMessages(
|
||||||
await sendMessages(nwaku, totalMsgs, TestContentTopic, DefaultPubsubTopic);
|
nwaku,
|
||||||
|
totalMsgs,
|
||||||
|
customContentTopic1,
|
||||||
|
customShardedPubsubTopic1
|
||||||
|
);
|
||||||
|
await sendMessages(
|
||||||
|
nwaku,
|
||||||
|
totalMsgs,
|
||||||
|
customContentTopic2,
|
||||||
|
customShardedPubsubTopic2
|
||||||
|
);
|
||||||
|
|
||||||
waku = await startAndConnectLightNode(nwaku, [
|
waku = await startAndConnectLightNode(nwaku, [], shardInfoBothShards);
|
||||||
customPubsubTopic,
|
|
||||||
DefaultPubsubTopic
|
|
||||||
]);
|
|
||||||
|
|
||||||
const customMessages = await processQueriedMessages(
|
const customMessages = await processQueriedMessages(
|
||||||
waku,
|
waku,
|
||||||
[customTestDecoder],
|
[customDecoder1],
|
||||||
customPubsubTopic
|
customShardedPubsubTopic1
|
||||||
);
|
);
|
||||||
expect(customMessages?.length).eq(totalMsgs);
|
expect(customMessages?.length).eq(totalMsgs);
|
||||||
const result1 = customMessages?.findIndex((msg) => {
|
const result1 = customMessages?.findIndex((msg) => {
|
||||||
|
@ -85,8 +103,8 @@ describe("Waku Store, custom pubsub topic", function () {
|
||||||
|
|
||||||
const testMessages = await processQueriedMessages(
|
const testMessages = await processQueriedMessages(
|
||||||
waku,
|
waku,
|
||||||
[TestDecoder],
|
[customDecoder2],
|
||||||
DefaultPubsubTopic
|
customShardedPubsubTopic2
|
||||||
);
|
);
|
||||||
expect(testMessages?.length).eq(totalMsgs);
|
expect(testMessages?.length).eq(totalMsgs);
|
||||||
const result2 = testMessages?.findIndex((msg) => {
|
const result2 = testMessages?.findIndex((msg) => {
|
||||||
|
@ -102,18 +120,28 @@ describe("Waku Store, custom pubsub topic", function () {
|
||||||
nwaku2 = new NimGoNode(makeLogFileName(this) + "2");
|
nwaku2 = new NimGoNode(makeLogFileName(this) + "2");
|
||||||
await nwaku2.start({
|
await nwaku2.start({
|
||||||
store: true,
|
store: true,
|
||||||
topic: [DefaultPubsubTopic],
|
pubsubTopic: [customShardedPubsubTopic2],
|
||||||
relay: true
|
relay: true
|
||||||
});
|
});
|
||||||
await nwaku2.ensureSubscriptions([DefaultPubsubTopic]);
|
await nwaku2.ensureSubscriptions([customShardedPubsubTopic2]);
|
||||||
|
|
||||||
const totalMsgs = 10;
|
const totalMsgs = 10;
|
||||||
await sendMessages(nwaku, totalMsgs, customContentTopic, customPubsubTopic);
|
await sendMessages(
|
||||||
await sendMessages(nwaku2, totalMsgs, TestContentTopic, DefaultPubsubTopic);
|
nwaku,
|
||||||
|
totalMsgs,
|
||||||
|
customContentTopic1,
|
||||||
|
customShardedPubsubTopic1
|
||||||
|
);
|
||||||
|
await sendMessages(
|
||||||
|
nwaku2,
|
||||||
|
totalMsgs,
|
||||||
|
customContentTopic2,
|
||||||
|
customShardedPubsubTopic2
|
||||||
|
);
|
||||||
|
|
||||||
waku = await createLightNode({
|
waku = await createLightNode({
|
||||||
staticNoiseKey: NOISE_KEY_1,
|
staticNoiseKey: NOISE_KEY_1,
|
||||||
pubsubTopics: [customPubsubTopic, DefaultPubsubTopic]
|
shardInfo: shardInfoBothShards
|
||||||
});
|
});
|
||||||
await waku.start();
|
await waku.start();
|
||||||
|
|
||||||
|
@ -130,13 +158,13 @@ describe("Waku Store, custom pubsub topic", function () {
|
||||||
) {
|
) {
|
||||||
customMessages = await processQueriedMessages(
|
customMessages = await processQueriedMessages(
|
||||||
waku,
|
waku,
|
||||||
[customTestDecoder],
|
[customDecoder1],
|
||||||
customPubsubTopic
|
customShardedPubsubTopic1
|
||||||
);
|
);
|
||||||
testMessages = await processQueriedMessages(
|
testMessages = await processQueriedMessages(
|
||||||
waku,
|
waku,
|
||||||
[TestDecoder],
|
[customDecoder2],
|
||||||
DefaultPubsubTopic
|
customShardedPubsubTopic2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,9 +6,9 @@ import {
|
||||||
DefaultPubsubTopic,
|
DefaultPubsubTopic,
|
||||||
waitForRemotePeer
|
waitForRemotePeer
|
||||||
} from "@waku/core";
|
} from "@waku/core";
|
||||||
import { LightNode, Protocols } from "@waku/interfaces";
|
import { LightNode, Protocols, ShardInfo } from "@waku/interfaces";
|
||||||
import { createLightNode } from "@waku/sdk";
|
import { createLightNode } from "@waku/sdk";
|
||||||
import { Logger } from "@waku/utils";
|
import { Logger, singleShardInfoToPubsubTopic } from "@waku/utils";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { delay, NimGoNode, NOISE_KEY_1 } from "../../src";
|
import { delay, NimGoNode, NOISE_KEY_1 } from "../../src";
|
||||||
|
@ -18,12 +18,26 @@ export const log = new Logger("test:store");
|
||||||
export const TestContentTopic = "/test/1/waku-store/utf8";
|
export const TestContentTopic = "/test/1/waku-store/utf8";
|
||||||
export const TestEncoder = createEncoder({ contentTopic: TestContentTopic });
|
export const TestEncoder = createEncoder({ contentTopic: TestContentTopic });
|
||||||
export const TestDecoder = createDecoder(TestContentTopic);
|
export const TestDecoder = createDecoder(TestContentTopic);
|
||||||
export const customContentTopic = "/test/2/waku-store/utf8";
|
export const customShardedPubsubTopic1 = singleShardInfoToPubsubTopic({
|
||||||
export const customPubsubTopic = "/waku/2/custom-dapp/proto";
|
cluster: 3,
|
||||||
export const customTestDecoder = createDecoder(
|
index: 1
|
||||||
customContentTopic,
|
});
|
||||||
customPubsubTopic
|
export const customShardedPubsubTopic2 = singleShardInfoToPubsubTopic({
|
||||||
);
|
cluster: 3,
|
||||||
|
index: 2
|
||||||
|
});
|
||||||
|
export const shardInfo1: ShardInfo = { cluster: 3, indexList: [1] };
|
||||||
|
export const customContentTopic1 = "/test/2/waku-store/utf8";
|
||||||
|
export const customContentTopic2 = "/test/3/waku-store/utf8";
|
||||||
|
export const customDecoder1 = createDecoder(customContentTopic1, {
|
||||||
|
cluster: 3,
|
||||||
|
index: 1
|
||||||
|
});
|
||||||
|
export const customDecoder2 = createDecoder(customContentTopic2, {
|
||||||
|
cluster: 3,
|
||||||
|
index: 2
|
||||||
|
});
|
||||||
|
export const shardInfoBothShards: ShardInfo = { cluster: 3, indexList: [1, 2] };
|
||||||
export const totalMsgs = 20;
|
export const totalMsgs = 20;
|
||||||
export const messageText = "Store Push works!";
|
export const messageText = "Store Push works!";
|
||||||
|
|
||||||
|
@ -66,10 +80,14 @@ export async function processQueriedMessages(
|
||||||
|
|
||||||
export async function startAndConnectLightNode(
|
export async function startAndConnectLightNode(
|
||||||
instance: NimGoNode,
|
instance: NimGoNode,
|
||||||
pubsubTopics: string[] = [DefaultPubsubTopic]
|
pubsubTopics: string[] = [DefaultPubsubTopic],
|
||||||
|
shardInfo?: ShardInfo
|
||||||
): Promise<LightNode> {
|
): Promise<LightNode> {
|
||||||
const waku = await createLightNode({
|
const waku = await createLightNode({
|
||||||
pubsubTopics: pubsubTopics,
|
...((pubsubTopics.length !== 1 ||
|
||||||
|
pubsubTopics[0] !== DefaultPubsubTopic) && {
|
||||||
|
shardInfo: shardInfo
|
||||||
|
}),
|
||||||
staticNoiseKey: NOISE_KEY_1
|
staticNoiseKey: NOISE_KEY_1
|
||||||
});
|
});
|
||||||
await waku.start();
|
await waku.start();
|
||||||
|
|
|
@ -1,16 +1,41 @@
|
||||||
import { sha256 } from "@noble/hashes/sha256";
|
import { sha256 } from "@noble/hashes/sha256";
|
||||||
import type { PubsubTopic, ShardInfo } from "@waku/interfaces";
|
import type { PubsubTopic, ShardInfo, SingleShardInfo } from "@waku/interfaces";
|
||||||
|
|
||||||
import { concat, utf8ToBytes } from "../bytes/index.js";
|
import { concat, utf8ToBytes } from "../bytes/index.js";
|
||||||
|
|
||||||
|
export const singleShardInfoToPubsubTopic = (
|
||||||
|
shardInfo: SingleShardInfo
|
||||||
|
): PubsubTopic => {
|
||||||
|
if (shardInfo.cluster === undefined || shardInfo.index === undefined)
|
||||||
|
throw new Error("Invalid shard");
|
||||||
|
|
||||||
|
return `/waku/2/rs/${shardInfo.cluster}/${shardInfo.index}`;
|
||||||
|
};
|
||||||
|
|
||||||
export const shardInfoToPubsubTopics = (
|
export const shardInfoToPubsubTopics = (
|
||||||
shardInfo: ShardInfo
|
shardInfo: ShardInfo
|
||||||
): PubsubTopic[] => {
|
): PubsubTopic[] => {
|
||||||
|
if (shardInfo.cluster === undefined || shardInfo.indexList === undefined)
|
||||||
|
throw new Error("Invalid shard");
|
||||||
|
|
||||||
return shardInfo.indexList.map(
|
return shardInfo.indexList.map(
|
||||||
(index) => `/waku/2/rs/${shardInfo.cluster}/${index}`
|
(index) => `/waku/2/rs/${shardInfo.cluster}/${index}`
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const pubsubTopicToSingleShardInfo = (
|
||||||
|
pubsubTopics: PubsubTopic
|
||||||
|
): SingleShardInfo => {
|
||||||
|
const parts = pubsubTopics.split("/");
|
||||||
|
if (parts.length != 6) throw new Error("Invalid pubsub topic");
|
||||||
|
|
||||||
|
const cluster = parseInt(parts[4]);
|
||||||
|
const index = parseInt(parts[5]);
|
||||||
|
if (isNaN(cluster) || isNaN(index)) throw new Error("Invalid pubsub topic");
|
||||||
|
|
||||||
|
return { cluster, index };
|
||||||
|
};
|
||||||
|
|
||||||
export function ensurePubsubTopicIsConfigured(
|
export function ensurePubsubTopicIsConfigured(
|
||||||
pubsubTopic: PubsubTopic,
|
pubsubTopic: PubsubTopic,
|
||||||
configuredTopics: PubsubTopic[]
|
configuredTopics: PubsubTopic[]
|
||||||
|
|
Loading…
Reference in New Issue