diff --git a/.cspell.json b/.cspell.json index 2506252475..5f5de115bf 100644 --- a/.cspell.json +++ b/.cspell.json @@ -11,7 +11,6 @@ "backoffs", "bitauth", "bitjson", - "extip", "bufbuild", "chainsafe", "cimg", @@ -25,6 +24,7 @@ "discv", "Dlazy", "dnsaddr", + "Dockerode", "Dout", "Dscore", "ecies", @@ -37,6 +37,7 @@ "ethersproject", "execa", "exponentiate", + "extip", "fanout", "floodsub", "fontsource", @@ -47,6 +48,7 @@ "ihave", "ihaves", "ineed", + "IPAM", "ipfs", "iwant", "jdev", @@ -93,6 +95,7 @@ "sscanf", "staticnode", "statusim", + "statusteam", "submodule", "submodules", "supercrypto", @@ -114,8 +117,7 @@ "webfonts", "websockets", "wifi", - "xsalsa20", - "statusteam" + "xsalsa20" ], "flagWords": [], "ignorePaths": [ diff --git a/packages/tests/src/index.ts b/packages/tests/src/index.ts index c3745a51f1..90a3281b8c 100644 --- a/packages/tests/src/index.ts +++ b/packages/tests/src/index.ts @@ -9,5 +9,4 @@ export * from "./async_fs.js"; export * from "./constants.js"; export * from "./delay.js"; export * from "./log_file.js"; -export * from "./nwaku.js"; -export * from "./random_array.js"; +export * from "./node/nwaku.js"; diff --git a/packages/tests/src/node/dockerode.ts b/packages/tests/src/node/dockerode.ts new file mode 100644 index 0000000000..83c6af9f60 --- /dev/null +++ b/packages/tests/src/node/dockerode.ts @@ -0,0 +1,215 @@ +import fs from "fs"; + +import debug from "debug"; +import Docker from "dockerode"; + +import { Args } from "./interfaces.js"; + +const log = debug("waku:docker"); + +const NETWORK_NAME = "waku"; +const SUBNET = "172.18.0.0/16"; +const IP_RANGE = "172.18.0.0/24"; +const GATEWAY = "172.18.0.1"; + +export default class Dockerode { + public docker: Docker; + private readonly IMAGE_NAME: string; + public containerId?: string; + + private static network: Docker.Network; + private static lastUsedIp = "172.18.0.1"; + private containerIp: string; + + private constructor(imageName: string, containerIp: string) { + this.docker = new Docker(); + this.IMAGE_NAME = imageName; + this.containerIp = containerIp; + } + + public static async createInstance(imageName: string): Promise { + if (!Dockerode.network) { + Dockerode.network = await Dockerode.createNetwork(NETWORK_NAME); + } + + const instance = new Dockerode(imageName, Dockerode.getNextIp()); + return instance; + } + + private static async createNetwork( + networkName: string = NETWORK_NAME + ): Promise { + const docker = new Docker(); + const networks = await docker.listNetworks(); + const existingNetwork = networks.find( + (network) => network.Name === networkName + ); + + let network: Docker.Network; + + if (existingNetwork) { + network = docker.getNetwork(existingNetwork.Id); + } else { + network = await docker.createNetwork({ + Name: networkName, + Driver: "bridge", + IPAM: { + Driver: "default", + Config: [ + { + Subnet: SUBNET, + IPRange: IP_RANGE, + Gateway: GATEWAY, + }, + ], + }, + }); + } + + return network; + } + + private static getNextIp(): string { + const ipFragments = Dockerode.lastUsedIp.split("."); + let lastFragment = Number(ipFragments[3]); + lastFragment++; + if (lastFragment > 254) { + throw new Error("IP Address Range Exhausted"); + } + ipFragments[3] = lastFragment.toString(); + Dockerode.lastUsedIp = ipFragments.join("."); + return Dockerode.lastUsedIp; + } + + get container(): Docker.Container | undefined { + if (!this.containerId) { + return undefined; + } + return this.docker.getContainer(this.containerId); + } + + async startContainer( + ports: number[], + args: Args, + logPath: string, + wakuServiceNodeParams?: string + ): Promise { + const [rpcPort, tcpPort, websocketPort, discv5UdpPort] = ports; + + await this.confirmImageExistsOrPull(); + + const argsArray = argsToArray(args); + if (wakuServiceNodeParams) { + argsArray.push(wakuServiceNodeParams); + } + + const argsArrayWithIP = [...argsArray, `--nat=extip:${this.containerIp}`]; + log(`Args: ${argsArray.join(" ")}`); + + const container = await this.docker.createContainer({ + Image: this.IMAGE_NAME, + HostConfig: { + AutoRemove: true, + PortBindings: { + [`${rpcPort}/tcp`]: [{ HostPort: rpcPort.toString() }], + [`${tcpPort}/tcp`]: [{ HostPort: tcpPort.toString() }], + [`${websocketPort}/tcp`]: [{ HostPort: websocketPort.toString() }], + ...(args?.peerExchange && { + [`${discv5UdpPort}/udp`]: [{ HostPort: discv5UdpPort.toString() }], + }), + }, + }, + ExposedPorts: { + [`${rpcPort}/tcp`]: {}, + [`${tcpPort}/tcp`]: {}, + [`${websocketPort}/tcp`]: {}, + ...(args?.peerExchange && { + [`${discv5UdpPort}/udp`]: {}, + }), + }, + Cmd: argsArrayWithIP, + }); + await container.start(); + + await Dockerode.network.connect({ + Container: container.id, + EndpointConfig: { + IPAMConfig: { + IPv4Address: this.containerIp, + }, + }, + }); + const logStream = fs.createWriteStream(logPath); + + container.logs( + { follow: true, stdout: true, stderr: true }, + (err, stream) => { + if (err) { + throw err; + } + if (stream) { + stream.pipe(logStream); + } + } + ); + + this.containerId = container.id; + log(`${this.containerId} started at ${new Date().toLocaleTimeString()}`); + return container; + } + + async stop(): Promise { + if (!this.container) throw "containerId not set"; + + log( + `Shutting down container ID ${ + this.containerId + } at ${new Date().toLocaleTimeString()}` + ); + + await this.container.stop(); + await this.container.remove(); + + this.containerId = undefined; + } + + private async confirmImageExistsOrPull(): Promise { + log(`Confirming that image ${this.IMAGE_NAME} exists`); + + const doesImageExist = this.docker.getImage(this.IMAGE_NAME); + if (!doesImageExist) { + await new Promise((resolve, reject) => { + this.docker.pull(this.IMAGE_NAME, {}, (err, stream) => { + if (err) { + reject(err); + } + this.docker.modem.followProgress(stream, (err, result) => { + if (err) { + reject(err); + } + if (result) { + resolve(); + } + }); + }); + }); + } + log(`Image ${this.IMAGE_NAME} successfully found`); + } +} + +export function argsToArray(args: Args): Array { + const array = []; + + for (const [key, value] of Object.entries(args)) { + // Change the key from camelCase to kebab-case + const kebabKey = key.replace(/([A-Z])/g, (_, capital) => { + return "-" + capital.toLowerCase(); + }); + + const arg = `--${kebabKey}=${value}`; + array.push(arg); + } + + return array; +} diff --git a/packages/tests/src/node/interfaces.ts b/packages/tests/src/node/interfaces.ts new file mode 100644 index 0000000000..5a530d6e12 --- /dev/null +++ b/packages/tests/src/node/interfaces.ts @@ -0,0 +1,53 @@ +export interface Args { + staticnode?: string; + nat?: "none"; + listenAddress?: string; + relay?: boolean; + rpc?: boolean; + rpcAdmin?: boolean; + nodekey?: string; + portsShift?: number; + logLevel?: LogLevel; + lightpush?: boolean; + filter?: boolean; + store?: boolean; + peerExchange?: boolean; + discv5Discovery?: boolean; + storeMessageDbUrl?: string; + topics?: string; + rpcPrivate?: boolean; + websocketSupport?: boolean; + tcpPort?: number; + rpcPort?: number; + websocketPort?: number; + discv5BootstrapNode?: string; + discv5UdpPort?: number; +} + +export enum LogLevel { + Error = "ERROR", + Info = "INFO", + Warn = "WARN", + Debug = "DEBUG", + Trace = "TRACE", + Notice = "NOTICE", + Fatal = "FATAL", +} + +export interface KeyPair { + privateKey: string; + publicKey: string; +} + +export interface MessageRpcQuery { + payload: string; // Hex encoded data string without `0x` prefix. + contentTopic?: string; + timestamp?: bigint; // Unix epoch time in nanoseconds as a 64-bits integer value. +} + +export interface MessageRpcResponse { + payload: string; + contentTopic?: string; + version?: number; + timestamp?: bigint; // Unix epoch time in nanoseconds as a 64-bits integer value. +} diff --git a/packages/tests/src/nwaku.ts b/packages/tests/src/node/nwaku.ts similarity index 61% rename from packages/tests/src/nwaku.ts rename to packages/tests/src/node/nwaku.ts index 61139641e6..d329ed488d 100644 --- a/packages/tests/src/nwaku.ts +++ b/packages/tests/src/node/nwaku.ts @@ -1,5 +1,3 @@ -import fs from "fs"; - import type { PeerId } from "@libp2p/interface-peer-id"; import { peerIdFromString } from "@libp2p/peer-id"; import { Multiaddr, multiaddr } from "@multiformats/multiaddr"; @@ -7,14 +5,22 @@ import { DefaultPubSubTopic } from "@waku/core"; import { isDefined } from "@waku/utils"; import { bytesToHex, hexToBytes } from "@waku/utils/bytes"; import debug from "debug"; -import Docker from "dockerode"; import portfinder from "portfinder"; -import { existsAsync, mkdirAsync, openAsync } from "./async_fs.js"; -import { delay } from "./delay.js"; -import waitForLine from "./log_file.js"; +import { existsAsync, mkdirAsync, openAsync } from "../async_fs.js"; +import { delay } from "../delay.js"; +import waitForLine from "../log_file.js"; -const log = debug("waku:nwaku"); +import Dockerode from "./dockerode.js"; +import { + Args, + KeyPair, + LogLevel, + MessageRpcQuery, + MessageRpcResponse, +} from "./interfaces.js"; + +const log = debug("waku:node"); const WAKU_SERVICE_NODE_PARAMS = process.env.WAKU_SERVICE_NODE_PARAMS ?? undefined; @@ -35,63 +41,8 @@ BigInt.prototype.toJSON = function toJSON() { return Number(this); }; -export interface Args { - staticnode?: string; - nat?: "none"; - listenAddress?: string; - relay?: boolean; - rpc?: boolean; - rpcAdmin?: boolean; - nodekey?: string; - portsShift?: number; - logLevel?: LogLevel; - lightpush?: boolean; - filter?: boolean; - store?: boolean; - peerExchange?: boolean; - discv5Discovery?: boolean; - storeMessageDbUrl?: string; - topics?: string; - rpcPrivate?: boolean; - websocketSupport?: boolean; - tcpPort?: number; - rpcPort?: number; - websocketPort?: number; - discv5BootstrapNode?: string; - discv5UdpPort?: number; -} - -export enum LogLevel { - Error = "ERROR", - Info = "INFO", - Warn = "WARN", - Debug = "DEBUG", - Trace = "TRACE", - Notice = "NOTICE", - Fatal = "FATAL", -} - -export interface KeyPair { - privateKey: string; - publicKey: string; -} - -export interface MessageRpcQuery { - payload: string; // Hex encoded data string without `0x` prefix. - contentTopic?: string; - timestamp?: bigint; // Unix epoch time in nanoseconds as a 64-bits integer value. -} - -export interface MessageRpcResponse { - payload: string; - contentTopic?: string; - version?: number; - timestamp?: bigint; // Unix epoch time in nanoseconds as a 64-bits integer value. -} - -export class Nwaku { - private docker: Docker; - private containerId?: string; +export class NimGoNode { + private docker?: Dockerode; private peerId?: PeerId; private multiaddrWithId?: Multiaddr; private websocketPort?: number; @@ -124,11 +75,15 @@ export class Nwaku { } constructor(logName: string) { - this.docker = new Docker(); - this.logPath = `${LOG_DIR}/nwaku_${logName}.log`; + this.logPath = `${LOG_DIR}/wakunode_${logName}.log`; + } + + type(): "go-waku" | "nwaku" { + return isGoWaku ? "go-waku" : "nwaku"; } async start(args: Args = {}): Promise { + this.docker = await Dockerode.createInstance(DOCKER_IMAGE_NAME); try { await existsAsync(LOG_DIR); } catch (e) { @@ -144,7 +99,7 @@ export class Nwaku { const mergedArgs = defaultArgs(); - // nwaku takes some time to bind port so to decrease chances of conflict + // waku nodes takes some time to bind port so to decrease chances of conflict // we also randomize the first port that portfinder will try const startPort = Math.floor(Math.random() * (65535 - 1025) + 1025); @@ -172,101 +127,37 @@ export class Nwaku { websocketPort, ...(args?.peerExchange && { discv5UdpPort }), }, + { rpcAddress: "0.0.0.0" }, args ); process.env.WAKUNODE2_STORE_MESSAGE_DB_URL = ""; - const argsArray = argsToArray(mergedArgs); - - const natExtIp = "--nat=extip:127.0.0.1"; - const rpcAddress = "--rpc-address=0.0.0.0"; - argsArray.push(natExtIp, rpcAddress); - - if (WAKU_SERVICE_NODE_PARAMS) { - argsArray.push(WAKU_SERVICE_NODE_PARAMS); + if (this.docker.container) { + await this.docker.stop(); } - log(`nwaku args: ${argsArray.join(" ")}`); - if (this.containerId) { - this.stop(); - } + await this.docker.startContainer( + ports, + mergedArgs, + this.logPath, + WAKU_SERVICE_NODE_PARAMS + ); try { - await this.confirmImageExistsOrPull(); - const container = await this.docker.createContainer({ - Image: DOCKER_IMAGE_NAME, - HostConfig: { - PortBindings: { - [`${rpcPort}/tcp`]: [{ HostPort: rpcPort.toString() }], - [`${tcpPort}/tcp`]: [{ HostPort: tcpPort.toString() }], - [`${websocketPort}/tcp`]: [{ HostPort: websocketPort.toString() }], - ...(args?.peerExchange && { - [`${discv5UdpPort}/udp`]: [ - { HostPort: discv5UdpPort.toString() }, - ], - }), - }, - }, - ExposedPorts: { - [`${rpcPort}/tcp`]: {}, - [`${tcpPort}/tcp`]: {}, - [`${websocketPort}/tcp`]: {}, - ...(args?.peerExchange && { - [`${discv5UdpPort}/udp`]: {}, - }), - }, - Cmd: argsArray, - }); - await container.start(); - - const logStream = fs.createWriteStream(this.logPath); - - container.logs( - { follow: true, stdout: true, stderr: true }, - (err, stream) => { - if (err) { - throw err; - } - if (stream) { - stream.pipe(logStream); - } - } - ); - - this.containerId = container.id; - - log( - `nwaku ${ - this.containerId - } started at ${new Date().toLocaleTimeString()}` - ); - - log(`Waiting to see '${NODE_READY_LOG_LINE}' in nwaku logs`); + log(`Waiting to see '${NODE_READY_LOG_LINE}' in ${this.type} logs`); await this.waitForLog(NODE_READY_LOG_LINE, 15000); if (process.env.CI) await delay(100); - log("nwaku node has been started"); + log(`${this.type} node has been started`); } catch (error) { - log(`Error starting nwaku: ${error}`); - if (this.containerId) await this.stop(); + log(`Error starting ${this.type}: ${error}`); + if (this.docker.container) await this.docker.stop(); throw error; } } public async stop(): Promise { - if (!this.containerId) throw "nwaku containerId not set"; - - const container = this.docker.getContainer(this.containerId); - - log( - `Shutting down nwaku container ID ${ - this.containerId - } at ${new Date().toLocaleTimeString()}` - ); - - await container.remove({ force: true }); - - this.containerId = undefined; + this.docker?.stop(); } async waitForLog(msg: string, timeout: number): Promise { @@ -275,7 +166,7 @@ export class Nwaku { /** Calls nwaku JSON-RPC API `get_waku_v2_admin_v1_peers` to check * for known peers - * @throws if nwaku isn't started. + * @throws if WakuNode isn't started. */ async peers(): Promise { this.checkProcess(); @@ -436,9 +327,9 @@ export class Nwaku { const multiaddrWithId = res.listenAddresses .map((ma) => multiaddr(ma)) .find((ma) => ma.protoNames().includes("ws")); - if (!multiaddrWithId) throw "Nwaku did not return a ws multiaddr"; + if (!multiaddrWithId) throw `${this.type} did not return a ws multiaddr`; const peerIdStr = multiaddrWithId.getPeerId(); - if (!peerIdStr) throw "Nwaku multiaddr does not contain peerId"; + if (!peerIdStr) throw `${this.type} multiaddr does not contain peerId`; this.peerId = peerIdFromString(peerIdStr); return this.peerId; @@ -469,50 +360,10 @@ export class Nwaku { } private checkProcess(): void { - if (!this.containerId || !this.docker.getContainer(this.containerId)) { - throw "Nwaku container hasn't started"; + if (!this.docker?.container) { + throw `${this.type} container hasn't started`; } } - - async confirmImageExistsOrPull(): Promise { - log(`Confirming that image ${DOCKER_IMAGE_NAME} exists`); - - const doesImageExist = this.docker.getImage(DOCKER_IMAGE_NAME); - if (!doesImageExist) { - await new Promise((resolve, reject) => { - this.docker.pull(DOCKER_IMAGE_NAME, {}, (err, stream) => { - if (err) { - reject(err); - } - this.docker.modem.followProgress(stream, (err, result) => { - if (err) { - reject(err); - } - if (result) { - resolve(); - } - }); - }); - }); - } - log(`Image ${DOCKER_IMAGE_NAME} successfully found`); - } -} - -export function argsToArray(args: Args): Array { - const array = []; - - for (const [key, value] of Object.entries(args)) { - // Change the key from camelCase to kebab-case - const kebabKey = key.replace(/([A-Z])/g, (_, capital) => { - return "-" + capital.toLowerCase(); - }); - - const arg = `--${kebabKey}=${value}`; - array.push(arg); - } - - return array; } export function defaultArgs(): Args { diff --git a/packages/tests/tests/enr.node.spec.ts b/packages/tests/tests/enr.node.spec.ts index d64c8a9071..0921ad5625 100644 --- a/packages/tests/tests/enr.node.spec.ts +++ b/packages/tests/tests/enr.node.spec.ts @@ -5,11 +5,12 @@ import type { RelayNode } from "@waku/interfaces"; import { Protocols } from "@waku/interfaces"; import { expect } from "chai"; -import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../src/index.js"; +import { makeLogFileName, NOISE_KEY_1 } from "../src/index.js"; +import { NimGoNode } from "../src/node/nwaku.js"; -describe("ENR Interop: nwaku", function () { +describe("ENR Interop: NimGoNode", function () { let waku: RelayNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; afterEach(async function () { !!nwaku && @@ -19,7 +20,7 @@ describe("ENR Interop: nwaku", function () { it("Relay", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ relay: true, store: false, @@ -51,7 +52,7 @@ describe("ENR Interop: nwaku", function () { it("Relay + Store", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ relay: true, store: true, @@ -83,7 +84,7 @@ describe("ENR Interop: nwaku", function () { it("All", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ relay: true, store: true, diff --git a/packages/tests/tests/ephemeral.node.spec.ts b/packages/tests/tests/ephemeral.node.spec.ts index 2849dceb11..46742ff708 100644 --- a/packages/tests/tests/ephemeral.node.spec.ts +++ b/packages/tests/tests/ephemeral.node.spec.ts @@ -27,8 +27,8 @@ import { makeLogFileName, NOISE_KEY_1, NOISE_KEY_2, - Nwaku, } from "../src/index.js"; +import { NimGoNode } from "../src/node/nwaku.js"; const log = debug("waku:test:ephemeral"); @@ -40,7 +40,7 @@ const TestDecoder = createDecoder(TestContentTopic); describe("Waku Message Ephemeral field", () => { let waku: LightNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; afterEach(async function () { !!nwaku && @@ -50,7 +50,7 @@ describe("Waku Message Ephemeral field", () => { beforeEach(async function () { this.timeout(15_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ filter: true, lightpush: true, diff --git a/packages/tests/tests/filter.node.spec.ts b/packages/tests/tests/filter.node.spec.ts index 9938989821..a605092698 100644 --- a/packages/tests/tests/filter.node.spec.ts +++ b/packages/tests/tests/filter.node.spec.ts @@ -12,7 +12,8 @@ import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; import debug from "debug"; -import { delay, makeLogFileName, NOISE_KEY_1, Nwaku } from "../src/index.js"; +import { delay, makeLogFileName, NOISE_KEY_1 } from "../src/index.js"; +import { NimGoNode } from "../src/node/nwaku.js"; const log = debug("waku:test"); @@ -22,7 +23,7 @@ const TestDecoder = createDecoder(TestContentTopic); describe("Waku Filter", () => { let waku: LightNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; afterEach(async function () { !!nwaku && @@ -32,7 +33,7 @@ describe("Waku Filter", () => { beforeEach(async function () { this.timeout(15000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ filter: true, lightpush: true, relay: true }); waku = await createLightNode({ staticNoiseKey: NOISE_KEY_1, diff --git a/packages/tests/tests/light_push.node.spec.ts b/packages/tests/tests/light_push.node.spec.ts index 50be34386e..67c19ca135 100644 --- a/packages/tests/tests/light_push.node.spec.ts +++ b/packages/tests/tests/light_push.node.spec.ts @@ -9,12 +9,12 @@ import debug from "debug"; import { base64ToUtf8, delay, - generateRandomUint8Array, makeLogFileName, - MessageRpcResponse, + NimGoNode, NOISE_KEY_1, - Nwaku, } from "../src/index.js"; +import { MessageRpcResponse } from "../src/node/interfaces.js"; +import { generateRandomUint8Array } from "../src/random_array.js"; const log = debug("waku:test:lightpush"); @@ -25,14 +25,14 @@ const TestEncoder = createEncoder({ describe("Waku Light Push [node only]", () => { let waku: LightNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; const runNodes = async ( context: Mocha.Context, pubSubTopic?: string ): Promise => { const nwakuOptional = pubSubTopic ? { topics: pubSubTopic } : {}; - nwaku = new Nwaku(makeLogFileName(context)); + nwaku = new NimGoNode(makeLogFileName(context)); await nwaku.start({ lightpush: true, relay: true, diff --git a/packages/tests/tests/nwaku.node.spec.ts b/packages/tests/tests/nwaku.node.spec.ts index 7a551987e3..ea012a1b7d 100644 --- a/packages/tests/tests/nwaku.node.spec.ts +++ b/packages/tests/tests/nwaku.node.spec.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; -import { argsToArray, defaultArgs } from "../src/index.js"; +import { defaultArgs } from "../src/index.js"; +import { argsToArray } from "../src/node/dockerode.js"; describe("nwaku", () => { it("Correctly serialized arguments", function () { diff --git a/packages/tests/tests/peer_exchange.node.spec.ts b/packages/tests/tests/peer_exchange.node.spec.ts index 1bbf335465..3ab7783e00 100644 --- a/packages/tests/tests/peer_exchange.node.spec.ts +++ b/packages/tests/tests/peer_exchange.node.spec.ts @@ -14,8 +14,9 @@ import { } from "@waku/peer-exchange"; import { expect } from "chai"; +import { delay } from "../src/delay.js"; import { makeLogFileName } from "../src/log_file.js"; -import { Nwaku } from "../src/nwaku.js"; +import { NimGoNode } from "../src/node/nwaku.js"; describe("Peer Exchange", () => { let waku: LightNode; @@ -62,12 +63,12 @@ describe("Peer Exchange", () => { describe("Locally run nodes", () => { let waku: LightNode; - let nwaku1: Nwaku; - let nwaku2: Nwaku; + let nwaku1: NimGoNode; + let nwaku2: NimGoNode; beforeEach(async function () { - nwaku1 = new Nwaku(makeLogFileName(this) + "1"); - nwaku2 = new Nwaku(makeLogFileName(this) + "2"); + nwaku1 = new NimGoNode(makeLogFileName(this) + "1"); + nwaku2 = new NimGoNode(makeLogFileName(this) + "2"); }); afterEach(async function () { @@ -77,9 +78,10 @@ describe("Peer Exchange", () => { }); it("nwaku interop", async function () { - this.timeout(15_000); + this.timeout(55_000); await nwaku1.start({ + relay: true, discv5Discovery: true, peerExchange: true, }); @@ -87,6 +89,7 @@ describe("Peer Exchange", () => { const enr = (await nwaku1.info()).enrUri; await nwaku2.start({ + relay: true, discv5Discovery: true, peerExchange: true, discv5BootstrapNode: enr, @@ -107,8 +110,6 @@ describe("Peer Exchange", () => { }); }); - await nwaku2.waitForLog("Discovered px peers via discv5", 10); - // the forced type casting is done in ref to https://github.com/libp2p/js-libp2p-interfaces/issues/338#issuecomment-1431643645 const { connectionManager, registrar, peerStore } = waku.libp2p as unknown as Libp2pComponents; @@ -122,9 +123,13 @@ describe("Peer Exchange", () => { const numPeersToRequest = 1; - const peerInfos = (await peerExchange.query({ - numPeers: numPeersToRequest, - })) as PeerInfo[]; + let peerInfos: PeerInfo[] = []; + while (peerInfos.length <= 0) { + peerInfos = (await peerExchange.query({ + numPeers: numPeersToRequest, + })) as PeerInfo[]; + await delay(3000); + } expect(peerInfos.length).to.be.greaterThan(0); expect(peerInfos.length).to.be.lessThanOrEqual(numPeersToRequest); @@ -142,20 +147,21 @@ describe("Peer Exchange", () => { }); describe("compliance test", async function () { - this.timeout(25_000); + this.timeout(55_000); let waku: LightNode; - let nwaku1: Nwaku; - let nwaku2: Nwaku; + let nwaku1: NimGoNode; + let nwaku2: NimGoNode; beforeEach(async function () { - nwaku1 = new Nwaku(makeLogFileName(this) + "1"); - nwaku2 = new Nwaku(makeLogFileName(this) + "2"); + nwaku1 = new NimGoNode(makeLogFileName(this) + "1"); + nwaku2 = new NimGoNode(makeLogFileName(this) + "2"); }); tests({ async setup() { await nwaku1.start({ + relay: true, discv5Discovery: true, peerExchange: true, }); @@ -163,6 +169,7 @@ describe("Peer Exchange", () => { const enr = (await nwaku1.info()).enrUri; await nwaku2.start({ + relay: true, discv5Discovery: true, peerExchange: true, discv5BootstrapNode: enr, @@ -194,8 +201,8 @@ describe("Peer Exchange", () => { return new PeerExchangeDiscovery(components); }, teardown: async () => { - !!nwaku1 && nwaku1.stop(); - !!nwaku2 && nwaku2.stop(); + !!nwaku1 && (await nwaku1.stop()); + !!nwaku2 && (await nwaku2.stop()); !!waku && (await waku.stop()); }, }); diff --git a/packages/tests/tests/relay.node.spec.ts b/packages/tests/tests/relay.node.spec.ts index ad87bf17b5..9d86b6e43f 100644 --- a/packages/tests/tests/relay.node.spec.ts +++ b/packages/tests/tests/relay.node.spec.ts @@ -25,16 +25,15 @@ import { expect } from "chai"; import debug from "debug"; import { - base64ToUtf8, delay, - generateRandomUint8Array, makeLogFileName, - MessageRpcResponse, NOISE_KEY_1, NOISE_KEY_2, NOISE_KEY_3, - Nwaku, } from "../src/index.js"; +import { MessageRpcResponse } from "../src/node/interfaces.js"; +import { base64ToUtf8, NimGoNode } from "../src/node/nwaku.js"; +import { generateRandomUint8Array } from "../src/random_array.js"; const log = debug("waku:test"); @@ -400,9 +399,9 @@ describe("Waku Relay [node only]", () => { }); }); - describe("Interop: nwaku", function () { + describe("Interop: NimGoNode", function () { let waku: RelayNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; beforeEach(async function () { this.timeout(30_000); @@ -411,7 +410,7 @@ describe("Waku Relay [node only]", () => { }); await waku.start(); - nwaku = new Nwaku(this.test?.ctx?.currentTest?.title + ""); + nwaku = new NimGoNode(this.test?.ctx?.currentTest?.title + ""); await nwaku.start({ relay: true }); await waku.dial(await nwaku.getMultiaddrWithId()); @@ -471,7 +470,7 @@ describe("Waku Relay [node only]", () => { ); await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ contentTopic: TestContentTopic, payload: utf8ToBytes(messageText), }) @@ -487,7 +486,7 @@ describe("Waku Relay [node only]", () => { describe.skip("Two nodes connected to nwaku", function () { let waku1: RelayNode; let waku2: RelayNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; afterEach(async function () { !!nwaku && @@ -510,7 +509,7 @@ describe("Waku Relay [node only]", () => { }).then((waku) => waku.start().then(() => waku)), ]); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start(); const nwakuMultiaddr = await nwaku.getMultiaddrWithId(); diff --git a/packages/tests/tests/store.node.spec.ts b/packages/tests/tests/store.node.spec.ts index da3ab15002..a30ee676ce 100644 --- a/packages/tests/tests/store.node.spec.ts +++ b/packages/tests/tests/store.node.spec.ts @@ -29,8 +29,8 @@ import { makeLogFileName, NOISE_KEY_1, NOISE_KEY_2, - Nwaku, } from "../src/index.js"; +import { NimGoNode } from "../src/node/nwaku.js"; const log = debug("waku:test:store"); @@ -40,11 +40,11 @@ const TestDecoder = createDecoder(TestContentTopic); describe("Waku Store", () => { let waku: LightNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; beforeEach(async function () { this.timeout(15_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ store: true, lightpush: true, relay: true }); }); @@ -61,7 +61,7 @@ describe("Waku Store", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: new Uint8Array([i]), contentTopic: TestContentTopic, }) @@ -131,7 +131,7 @@ describe("Waku Store", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: utf8ToBytes(`Message ${i}`), contentTopic: TestContentTopic, }) @@ -188,7 +188,7 @@ describe("Waku Store", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: new Uint8Array([i]), contentTopic: TestContentTopic, }) @@ -229,7 +229,7 @@ describe("Waku Store", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: new Uint8Array([i]), contentTopic: TestContentTopic, }) @@ -268,7 +268,7 @@ describe("Waku Store", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: new Uint8Array([i]), contentTopic: TestContentTopic, }) @@ -307,7 +307,7 @@ describe("Waku Store", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: new Uint8Array([i]), contentTopic: TestContentTopic, }) @@ -472,7 +472,7 @@ describe("Waku Store", () => { for (let i = 0; i < 2; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: new Uint8Array([i]), contentTopic: TestContentTopic, timestamp: messageTimestamps[i], @@ -534,7 +534,7 @@ describe("Waku Store", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: new Uint8Array([i]), contentTopic: TestContentTopic, }) @@ -568,11 +568,11 @@ describe("Waku Store", () => { describe("Waku Store, custom pubsub topic", () => { const customPubSubTopic = "/waku/2/custom-dapp/proto"; let waku: LightNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; beforeEach(async function () { this.timeout(15_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ store: true, topics: customPubSubTopic, @@ -593,7 +593,7 @@ describe("Waku Store, custom pubsub topic", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toMessageRpcQuery({ + NimGoNode.toMessageRpcQuery({ payload: new Uint8Array([i]), contentTopic: TestContentTopic, }), diff --git a/packages/tests/tests/utils.spec.ts b/packages/tests/tests/utils.spec.ts index 6b26b1c18f..5426ba81f5 100644 --- a/packages/tests/tests/utils.spec.ts +++ b/packages/tests/tests/utils.spec.ts @@ -11,7 +11,8 @@ import { toAsyncIterator } from "@waku/utils"; import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; -import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../src/index.js"; +import { makeLogFileName, NOISE_KEY_1 } from "../src/index.js"; +import { NimGoNode } from "../src/node/nwaku.js"; const TestContentTopic = "/test/1/waku-filter"; const TestEncoder = createEncoder({ contentTopic: TestContentTopic }); @@ -19,11 +20,11 @@ const TestDecoder = createDecoder(TestContentTopic); describe("Util: toAsyncIterator", () => { let waku: LightNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; beforeEach(async function () { this.timeout(15000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ filter: true, lightpush: true, relay: true }); waku = await createLightNode({ staticNoiseKey: NOISE_KEY_1, diff --git a/packages/tests/tests/wait_for_remote_peer.node.spec.ts b/packages/tests/tests/wait_for_remote_peer.node.spec.ts index 05a8b8318d..0b44bc16aa 100644 --- a/packages/tests/tests/wait_for_remote_peer.node.spec.ts +++ b/packages/tests/tests/wait_for_remote_peer.node.spec.ts @@ -4,12 +4,13 @@ import type { LightNode, RelayNode } from "@waku/interfaces"; import { Protocols } from "@waku/interfaces"; import { expect } from "chai"; -import { delay, makeLogFileName, NOISE_KEY_1, Nwaku } from "../src/index.js"; +import { delay, makeLogFileName, NOISE_KEY_1 } from "../src/index.js"; +import { NimGoNode } from "../src/node/nwaku.js"; describe("Wait for remote peer", function () { let waku1: RelayNode; let waku2: LightNode; - let nwaku: Nwaku | undefined; + let nwaku: NimGoNode | undefined; afterEach(async function () { if (nwaku) { @@ -22,7 +23,7 @@ describe("Wait for remote peer", function () { it("Relay - dialed first", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ relay: true, store: false, @@ -47,7 +48,7 @@ describe("Wait for remote peer", function () { it("Relay - dialed after", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ relay: true, store: false, @@ -94,7 +95,7 @@ describe("Wait for remote peer", function () { it("Store - dialed first", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ store: true, relay: false, @@ -120,7 +121,7 @@ describe("Wait for remote peer", function () { it("Store - dialed after - with timeout", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ store: true, relay: false, @@ -148,7 +149,7 @@ describe("Wait for remote peer", function () { it("LightPush", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ lightpush: true, filter: false, @@ -176,7 +177,7 @@ describe("Wait for remote peer", function () { it("Filter", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ filter: true, lightpush: false, @@ -204,7 +205,7 @@ describe("Wait for remote peer", function () { it("Light Node - default protocols", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ filter: true, lightpush: true, @@ -244,7 +245,7 @@ describe("Wait for remote peer", function () { it("Privacy Node - default protocol", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ filter: false, lightpush: false, diff --git a/packages/tests/tests/waku.node.spec.ts b/packages/tests/tests/waku.node.spec.ts index 9f43e49f2c..2535298260 100644 --- a/packages/tests/tests/waku.node.spec.ts +++ b/packages/tests/tests/waku.node.spec.ts @@ -16,19 +16,15 @@ import { import { bytesToUtf8, utf8ToBytes } from "@waku/utils/bytes"; import { expect } from "chai"; -import { - makeLogFileName, - NOISE_KEY_1, - NOISE_KEY_2, - Nwaku, -} from "../src/index.js"; +import { makeLogFileName, NOISE_KEY_1, NOISE_KEY_2 } from "../src/index.js"; +import { NimGoNode } from "../src/node/nwaku.js"; const TestContentTopic = "/test/1/waku/utf8"; describe("Waku Dial [node only]", function () { - describe("Interop: nwaku", function () { + describe("Interop: NimGoNode", function () { let waku: Waku; - let nwaku: Nwaku; + let nwaku: NimGoNode; afterEach(async function () { !!nwaku && @@ -38,7 +34,7 @@ describe("Waku Dial [node only]", function () { it("connects to nwaku", async function () { this.timeout(20_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start({ filter: true, store: true, @@ -64,7 +60,7 @@ describe("Waku Dial [node only]", function () { describe("Bootstrap", function () { let waku: LightNode; - let nwaku: Nwaku; + let nwaku: NimGoNode; afterEach(async function () { !!nwaku && nwaku.stop(); @@ -74,7 +70,7 @@ describe("Waku Dial [node only]", function () { it("Passing an array", async function () { this.timeout(10_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start(); const multiAddrWithId = await nwaku.getMultiaddrWithId(); waku = await createLightNode({ @@ -97,7 +93,7 @@ describe("Waku Dial [node only]", function () { it("Using a function", async function () { this.timeout(10_000); - nwaku = new Nwaku(makeLogFileName(this)); + nwaku = new NimGoNode(makeLogFileName(this)); await nwaku.start(); const nwakuMa = await nwaku.getMultiaddrWithId();