mirror of https://github.com/waku-org/js-waku.git
feat: createLightNode and createPrivacyNode helpers
This commit is contained in:
parent
f56f6e2e83
commit
9fc16143fa
|
@ -12,12 +12,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
|
||||
- Simple connection management that selects the most recent connection for store, light push and filter requests.
|
||||
- `createLightNode` to create a Waku node for resource restricted environment with Light Push, Filter and Relay.
|
||||
- `createPrivacyNode` to create a Waku node for privacy preserving usage with Relay only.
|
||||
|
||||
### Changed
|
||||
|
||||
- **breaking**: `DecryptionParams` may be passed when using `queryHistory` instead of just keys.
|
||||
- Examples have been moved to https://github.com/waku-org/js-waku-examples.
|
||||
- `Waku` is now defined as an interface with `WakuNode` an implementation of it.
|
||||
- `createWaku` is deprecated in favour of `createLightNode` and `createPrivacyNode`.
|
||||
- `waitForRemotePeer` can throw, default behaviour has changed.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"@libp2p/interface-peer-id": "^1.0.2",
|
||||
"@libp2p/interface-peer-info": "^1.0.1",
|
||||
"@libp2p/interface-peer-store": "^1.0.0",
|
||||
"@libp2p/interface-pubsub": "^2.0.1",
|
||||
"@libp2p/interfaces": "^3.0.2",
|
||||
"@libp2p/mplex": "^5.1.1",
|
||||
"@libp2p/peer-id": "^1.1.10",
|
||||
|
|
|
@ -98,6 +98,7 @@
|
|||
"@libp2p/interface-peer-id": "^1.0.2",
|
||||
"@libp2p/interface-peer-info": "^1.0.1",
|
||||
"@libp2p/interface-peer-store": "^1.0.0",
|
||||
"@libp2p/interface-pubsub": "^2.0.1",
|
||||
"@libp2p/interfaces": "^3.0.2",
|
||||
"@libp2p/mplex": "^5.1.1",
|
||||
"@libp2p/peer-id": "^1.1.10",
|
||||
|
|
|
@ -6,7 +6,7 @@ import { all as filterAll } from "@libp2p/websockets/filters";
|
|||
import { createLibp2p, Libp2pOptions } from "libp2p";
|
||||
import type { Libp2p } from "libp2p";
|
||||
|
||||
import type { Waku } from "./interfaces";
|
||||
import type { Waku, WakuLight, WakuPrivacy } from "./interfaces";
|
||||
import { PeerDiscoveryStaticPeers } from "./peer_discovery_static_list";
|
||||
import { getPredefinedBootstrapNodes } from "./predefined_bootstrap_nodes";
|
||||
import { WakuNode, WakuOptions } from "./waku";
|
||||
|
@ -50,6 +50,60 @@ export interface CreateOptions {
|
|||
defaultBootstrap?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Waku node that uses Waku Light Push, Filter and Store to send and
|
||||
* receive messages, enabling low resource consumption.
|
||||
* **Note: This is NOT compatible with nwaku**
|
||||
* Ref: https://github.com/status-im/nwaku/issues/1085
|
||||
*/
|
||||
export async function createLightNode(
|
||||
options?: CreateOptions & WakuOptions
|
||||
): Promise<WakuLight> {
|
||||
const libp2pOptions = options?.libp2p ?? {};
|
||||
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
||||
if (options?.defaultBootstrap) {
|
||||
peerDiscovery.push(defaultPeerDiscovery());
|
||||
Object.assign(libp2pOptions, { peerDiscovery });
|
||||
}
|
||||
|
||||
const libp2p = await defaultLibp2p(undefined, libp2pOptions);
|
||||
|
||||
const wakuStore = new WakuStore(libp2p, options);
|
||||
const wakuLightPush = new WakuLightPush(libp2p, options);
|
||||
const wakuFilter = new WakuFilter(libp2p, options);
|
||||
|
||||
return new WakuNode(
|
||||
options ?? {},
|
||||
libp2p,
|
||||
wakuStore,
|
||||
wakuLightPush,
|
||||
wakuFilter
|
||||
) as WakuLight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Waku node that uses Waku Relay to send and receive messages,
|
||||
* enabling some privacy preserving properties.
|
||||
*/
|
||||
export async function createPrivacyNode(
|
||||
options?: CreateOptions & WakuOptions
|
||||
): Promise<WakuPrivacy> {
|
||||
const libp2pOptions = options?.libp2p ?? {};
|
||||
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
||||
if (options?.defaultBootstrap) {
|
||||
peerDiscovery.push(defaultPeerDiscovery());
|
||||
Object.assign(libp2pOptions, { peerDiscovery });
|
||||
}
|
||||
|
||||
const libp2p = await defaultLibp2p(new WakuRelay(options), libp2pOptions);
|
||||
|
||||
return new WakuNode(options ?? {}, libp2p) as WakuPrivacy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use { @link createLightNode } (only compatible with nwaku v0.12),
|
||||
* { @link createPrivacyNode } or { @link Waku.constructor } instead;
|
||||
*/
|
||||
export async function createWaku(
|
||||
options?: CreateOptions & WakuOptions
|
||||
): Promise<Waku> {
|
||||
|
@ -80,7 +134,7 @@ export function defaultPeerDiscovery(): PeerDiscovery {
|
|||
}
|
||||
|
||||
export async function defaultLibp2p(
|
||||
wakuRelay: WakuRelay,
|
||||
wakuRelay?: WakuRelay,
|
||||
options?: Partial<Libp2pOptions>
|
||||
): Promise<Libp2p> {
|
||||
const libp2pOpts = Object.assign(
|
||||
|
@ -89,7 +143,7 @@ export async function defaultLibp2p(
|
|||
streamMuxers: [new Mplex()],
|
||||
connectionEncryption: [new Noise()],
|
||||
},
|
||||
{ pubsub: wakuRelay },
|
||||
wakuRelay ? { pubsub: wakuRelay } : {},
|
||||
options ?? {}
|
||||
);
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ import type { WakuStore } from "./waku_store";
|
|||
|
||||
export interface Waku {
|
||||
libp2p: Libp2p;
|
||||
relay: WakuRelay;
|
||||
store: WakuStore;
|
||||
filter: WakuFilter;
|
||||
lightPush: WakuLightPush;
|
||||
relay?: WakuRelay;
|
||||
store?: WakuStore;
|
||||
filter?: WakuFilter;
|
||||
lightPush?: WakuLightPush;
|
||||
|
||||
dial(peer: PeerId | Multiaddr, protocols?: Protocols[]): Promise<Stream>;
|
||||
|
||||
|
@ -37,3 +37,17 @@ export interface Waku {
|
|||
|
||||
deleteDecryptionKey(key: Uint8Array | string): void;
|
||||
}
|
||||
|
||||
export interface WakuLight extends Waku {
|
||||
relay: undefined;
|
||||
store: WakuStore;
|
||||
filter: WakuFilter;
|
||||
lightPush: WakuLightPush;
|
||||
}
|
||||
|
||||
export interface WakuPrivacy extends Waku {
|
||||
relay: WakuRelay;
|
||||
store: undefined;
|
||||
filter: undefined;
|
||||
lightPush: undefined;
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@ import { expect } from "chai";
|
|||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../test_utils";
|
||||
import { delay } from "../test_utils/delay";
|
||||
|
||||
import { createWaku } from "./create_waku";
|
||||
import type { Waku } from "./interfaces";
|
||||
import { createLightNode, createPrivacyNode } from "./create_waku";
|
||||
import type { WakuLight, WakuPrivacy } from "./interfaces";
|
||||
import { waitForRemotePeer } from "./wait_for_remote_peer";
|
||||
import { Protocols } from "./waku";
|
||||
|
||||
describe("Wait for remote peer", function () {
|
||||
let waku: Waku;
|
||||
let waku1: WakuPrivacy;
|
||||
let waku2: WakuLight;
|
||||
let nwaku: Nwaku | undefined;
|
||||
|
||||
afterEach(async function () {
|
||||
|
@ -17,7 +18,8 @@ describe("Wait for remote peer", function () {
|
|||
nwaku.stop();
|
||||
nwaku = undefined;
|
||||
}
|
||||
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
|
||||
waku1?.stop().catch((e) => console.log("Waku failed to stop", e));
|
||||
waku2?.stop().catch((e) => console.log("Waku failed to stop", e));
|
||||
});
|
||||
|
||||
it("Relay - dialed first", async function () {
|
||||
|
@ -31,14 +33,14 @@ describe("Wait for remote peer", function () {
|
|||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku = await createWaku({
|
||||
waku1 = await createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
await waku.dial(multiAddrWithId);
|
||||
await waku1.start();
|
||||
await waku1.dial(multiAddrWithId);
|
||||
await delay(1000);
|
||||
await waitForRemotePeer(waku, [Protocols.Relay]);
|
||||
const peers = waku.relay.getMeshPeers();
|
||||
await waitForRemotePeer(waku1, [Protocols.Relay]);
|
||||
const peers = waku1.relay.getMeshPeers();
|
||||
const nimPeerId = multiAddrWithId.getPeerId();
|
||||
|
||||
expect(nimPeerId).to.not.be.undefined;
|
||||
|
@ -56,17 +58,17 @@ describe("Wait for remote peer", function () {
|
|||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku = await createWaku({
|
||||
waku1 = await createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
await waku1.start();
|
||||
|
||||
const waitPromise = waitForRemotePeer(waku, [Protocols.Relay]);
|
||||
const waitPromise = waitForRemotePeer(waku1, [Protocols.Relay]);
|
||||
await delay(1000);
|
||||
await waku.dial(multiAddrWithId);
|
||||
await waku1.dial(multiAddrWithId);
|
||||
await waitPromise;
|
||||
|
||||
const peers = waku.relay.getMeshPeers();
|
||||
const peers = waku1.relay.getMeshPeers();
|
||||
const nimPeerId = multiAddrWithId.getPeerId();
|
||||
|
||||
expect(nimPeerId).to.not.be.undefined;
|
||||
|
@ -75,12 +77,12 @@ describe("Wait for remote peer", function () {
|
|||
|
||||
it("Relay - times out", function (done) {
|
||||
this.timeout(5000);
|
||||
createWaku({
|
||||
createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
})
|
||||
.then((waku) => waku.start().then(() => waku))
|
||||
.then((waku) => {
|
||||
waitForRemotePeer(waku, [Protocols.Relay], 200).then(
|
||||
.then((waku1) => waku1.start().then(() => waku1))
|
||||
.then((waku1) => {
|
||||
waitForRemotePeer(waku1, [Protocols.Relay], 200).then(
|
||||
() => {
|
||||
throw "Promise expected to reject on time out";
|
||||
},
|
||||
|
@ -104,15 +106,15 @@ describe("Wait for remote peer", function () {
|
|||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku = await createWaku({
|
||||
waku2 = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
await waku.dial(multiAddrWithId);
|
||||
await waku2.start();
|
||||
await waku2.dial(multiAddrWithId);
|
||||
await delay(1000);
|
||||
await waitForRemotePeer(waku, [Protocols.Store]);
|
||||
await waitForRemotePeer(waku2, [Protocols.Store]);
|
||||
|
||||
const peers = (await waku.store.peers()).map((peer) => peer.id.toString());
|
||||
const peers = (await waku2.store.peers()).map((peer) => peer.id.toString());
|
||||
const nimPeerId = multiAddrWithId.getPeerId();
|
||||
|
||||
expect(nimPeerId).to.not.be.undefined;
|
||||
|
@ -131,16 +133,16 @@ describe("Wait for remote peer", function () {
|
|||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku = await createWaku({
|
||||
waku2 = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
const waitPromise = waitForRemotePeer(waku, [Protocols.Store], 2000);
|
||||
await waku2.start();
|
||||
const waitPromise = waitForRemotePeer(waku2, [Protocols.Store], 2000);
|
||||
await delay(1000);
|
||||
await waku.dial(multiAddrWithId);
|
||||
await waku2.dial(multiAddrWithId);
|
||||
await waitPromise;
|
||||
|
||||
const peers = (await waku.store.peers()).map((peer) => peer.id.toString());
|
||||
const peers = (await waku2.store.peers()).map((peer) => peer.id.toString());
|
||||
|
||||
const nimPeerId = multiAddrWithId.getPeerId();
|
||||
|
||||
|
@ -159,14 +161,14 @@ describe("Wait for remote peer", function () {
|
|||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku = await createWaku({
|
||||
waku2 = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
await waku.dial(multiAddrWithId);
|
||||
await waitForRemotePeer(waku, [Protocols.LightPush]);
|
||||
await waku2.start();
|
||||
await waku2.dial(multiAddrWithId);
|
||||
await waitForRemotePeer(waku2, [Protocols.LightPush]);
|
||||
|
||||
const peers = (await waku.lightPush.peers()).map((peer) =>
|
||||
const peers = (await waku2.lightPush.peers()).map((peer) =>
|
||||
peer.id.toString()
|
||||
);
|
||||
|
||||
|
@ -187,14 +189,79 @@ describe("Wait for remote peer", function () {
|
|||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku = await createWaku({
|
||||
waku2 = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
await waku.dial(multiAddrWithId);
|
||||
await waitForRemotePeer(waku, [Protocols.Filter]);
|
||||
await waku2.start();
|
||||
await waku2.dial(multiAddrWithId);
|
||||
await waitForRemotePeer(waku2, [Protocols.Filter]);
|
||||
|
||||
const peers = (await waku.filter.peers()).map((peer) => peer.id.toString());
|
||||
const peers = (await waku2.filter.peers()).map((peer) =>
|
||||
peer.id.toString()
|
||||
);
|
||||
|
||||
const nimPeerId = multiAddrWithId.getPeerId();
|
||||
|
||||
expect(nimPeerId).to.not.be.undefined;
|
||||
expect(peers.includes(nimPeerId as string)).to.be.true;
|
||||
});
|
||||
|
||||
it("Light Node - default protocols", async function () {
|
||||
this.timeout(20_000);
|
||||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
await nwaku.start({
|
||||
filter: true,
|
||||
lightpush: true,
|
||||
relay: false,
|
||||
store: true,
|
||||
persistMessages: true,
|
||||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku2 = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku2.start();
|
||||
await waku2.dial(multiAddrWithId);
|
||||
await waitForRemotePeer(waku2);
|
||||
|
||||
const filterPeers = (await waku2.filter.peers()).map((peer) =>
|
||||
peer.id.toString()
|
||||
);
|
||||
const storePeers = (await waku2.store.peers()).map((peer) =>
|
||||
peer.id.toString()
|
||||
);
|
||||
const lightPushPeers = (await waku2.lightPush.peers()).map((peer) =>
|
||||
peer.id.toString()
|
||||
);
|
||||
|
||||
const nimPeerId = multiAddrWithId.getPeerId();
|
||||
|
||||
expect(nimPeerId).to.not.be.undefined;
|
||||
expect(filterPeers.includes(nimPeerId as string)).to.be.true;
|
||||
expect(storePeers.includes(nimPeerId as string)).to.be.true;
|
||||
expect(lightPushPeers.includes(nimPeerId as string)).to.be.true;
|
||||
});
|
||||
|
||||
it("Privacy Node - default protocol", async function () {
|
||||
this.timeout(20_000);
|
||||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
await nwaku.start({
|
||||
filter: false,
|
||||
lightpush: false,
|
||||
relay: true,
|
||||
store: false,
|
||||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku1 = await createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku1.start();
|
||||
await waku1.dial(multiAddrWithId);
|
||||
await waitForRemotePeer(waku1);
|
||||
|
||||
const peers = await waku1.relay.getMeshPeers();
|
||||
|
||||
const nimPeerId = multiAddrWithId.getPeerId();
|
||||
|
||||
|
|
|
@ -36,33 +36,41 @@ interface WakuGossipSubProtocol extends GossipSub {
|
|||
*
|
||||
* @returns A promise that **resolves** if all desired protocols are fulfilled by
|
||||
* remote nodes, **rejects** if the timeoutMs is reached.
|
||||
*
|
||||
* @default Remote peer must have Waku Relay enabled and no time out is applied.
|
||||
* @throws If passing a protocol that is not mounted
|
||||
* @default Wait for remote peers with protocols enabled locally and no time out is applied.
|
||||
*/
|
||||
export async function waitForRemotePeer(
|
||||
waku: Waku,
|
||||
protocols?: Protocols[],
|
||||
timeoutMs?: number
|
||||
): Promise<void> {
|
||||
protocols = protocols ?? [Protocols.Relay];
|
||||
protocols = protocols ?? getEnabledProtocols(waku);
|
||||
|
||||
if (!waku.isStarted()) return Promise.reject("Waku node is not started");
|
||||
|
||||
const promises = [];
|
||||
|
||||
if (protocols.includes(Protocols.Relay)) {
|
||||
if (!waku.relay)
|
||||
throw new Error("Cannot wait for Relay peer: protocol not mounted");
|
||||
promises.push(waitForGossipSubPeerInMesh(waku.relay));
|
||||
}
|
||||
|
||||
if (protocols.includes(Protocols.Store)) {
|
||||
if (!waku.store)
|
||||
throw new Error("Cannot wait for Store peer: protocol not mounted");
|
||||
promises.push(waitForConnectedPeer(waku.store, Object.values(StoreCodecs)));
|
||||
}
|
||||
|
||||
if (protocols.includes(Protocols.LightPush)) {
|
||||
if (!waku.lightPush)
|
||||
throw new Error("Cannot wait for LightPush peer: protocol not mounted");
|
||||
promises.push(waitForConnectedPeer(waku.lightPush, [LightPushCodec]));
|
||||
}
|
||||
|
||||
if (protocols.includes(Protocols.Filter)) {
|
||||
if (!waku.filter)
|
||||
throw new Error("Cannot wait for Filter peer: protocol not mounted");
|
||||
promises.push(waitForConnectedPeer(waku.filter, [FilterCodec]));
|
||||
}
|
||||
|
||||
|
@ -131,3 +139,25 @@ async function rejectOnTimeout<T>(
|
|||
): Promise<void> {
|
||||
await Promise.race([promise, awaitTimeout(timeoutMs, rejectReason)]);
|
||||
}
|
||||
|
||||
function getEnabledProtocols(waku: Waku): Protocols[] {
|
||||
const protocols = [];
|
||||
|
||||
if (waku.relay) {
|
||||
protocols.push(Protocols.Relay);
|
||||
}
|
||||
|
||||
if (waku.filter) {
|
||||
protocols.push(Protocols.Filter);
|
||||
}
|
||||
|
||||
if (waku.store) {
|
||||
protocols.push(Protocols.Store);
|
||||
}
|
||||
|
||||
if (waku.lightPush) {
|
||||
protocols.push(Protocols.LightPush);
|
||||
}
|
||||
|
||||
return protocols;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ import {
|
|||
Nwaku,
|
||||
} from "../test_utils/";
|
||||
|
||||
import { createWaku } from "./create_waku";
|
||||
import { createLightNode, createPrivacyNode } from "./create_waku";
|
||||
import { generateSymmetricKey } from "./crypto";
|
||||
import type { Waku } from "./interfaces";
|
||||
import type { Waku, WakuLight, WakuPrivacy } from "./interfaces";
|
||||
import { PeerDiscoveryStaticPeers } from "./peer_discovery_static_list";
|
||||
import { waitForRemotePeer } from "./wait_for_remote_peer";
|
||||
import { Protocols } from "./waku";
|
||||
|
@ -31,15 +31,20 @@ describe("Waku Dial [node only]", function () {
|
|||
it("connects to nwaku", async function () {
|
||||
this.timeout(20_000);
|
||||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
await nwaku.start();
|
||||
await nwaku.start({
|
||||
filter: true,
|
||||
store: true,
|
||||
lightpush: true,
|
||||
persistMessages: true,
|
||||
});
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
await waku.dial(multiAddrWithId);
|
||||
await waitForRemotePeer(waku, [Protocols.Relay]);
|
||||
await waitForRemotePeer(waku);
|
||||
|
||||
const nimPeerId = await nwaku.getPeerId();
|
||||
expect(await waku.libp2p.peerStore.has(nimPeerId)).to.be.true;
|
||||
|
@ -47,7 +52,7 @@ describe("Waku Dial [node only]", function () {
|
|||
});
|
||||
|
||||
describe("Bootstrap", function () {
|
||||
let waku: Waku;
|
||||
let waku: WakuLight;
|
||||
let nwaku: Nwaku;
|
||||
|
||||
afterEach(async function () {
|
||||
|
@ -61,7 +66,7 @@ describe("Waku Dial [node only]", function () {
|
|||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
await nwaku.start();
|
||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
libp2p: {
|
||||
peerDiscovery: [new PeerDiscoveryStaticPeers([multiAddrWithId])],
|
||||
|
@ -87,7 +92,7 @@ describe("Waku Dial [node only]", function () {
|
|||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
await nwaku.start();
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
libp2p: {
|
||||
peerDiscovery: [
|
||||
|
@ -119,15 +124,15 @@ describe("Decryption Keys", () => {
|
|||
}
|
||||
});
|
||||
|
||||
let waku1: Waku;
|
||||
let waku2: Waku;
|
||||
let waku1: WakuPrivacy;
|
||||
let waku2: WakuPrivacy;
|
||||
beforeEach(async function () {
|
||||
this.timeout(5000);
|
||||
[waku1, waku2] = await Promise.all([
|
||||
createWaku({ staticNoiseKey: NOISE_KEY_1 }).then((waku) =>
|
||||
createPrivacyNode({ staticNoiseKey: NOISE_KEY_1 }).then((waku) =>
|
||||
waku.start().then(() => waku)
|
||||
),
|
||||
createWaku({
|
||||
createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_2,
|
||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { Stream } from "@libp2p/interface-connection";
|
||||
import type { PeerId } from "@libp2p/interface-peer-id";
|
||||
import type { PubSub } from "@libp2p/interface-pubsub";
|
||||
import { peerIdFromString } from "@libp2p/peer-id";
|
||||
import type { Multiaddr } from "@multiformats/multiaddr";
|
||||
import { multiaddr } from "@multiformats/multiaddr";
|
||||
|
@ -12,6 +13,7 @@ import { LightPushCodec, WakuLightPush } from "./waku_light_push";
|
|||
import { DecryptionMethod, WakuMessage } from "./waku_message";
|
||||
import { WakuRelay } from "./waku_relay";
|
||||
import { RelayCodecs, RelayPingContentTopic } from "./waku_relay/constants";
|
||||
import * as relayConstants from "./waku_relay/constants";
|
||||
import { StoreCodecs, WakuStore } from "./waku_store";
|
||||
|
||||
export const DefaultPingKeepAliveValueSecs = 0;
|
||||
|
@ -46,10 +48,10 @@ export interface WakuOptions {
|
|||
|
||||
export class WakuNode implements Waku {
|
||||
public libp2p: Libp2p;
|
||||
public relay: WakuRelay;
|
||||
public store: WakuStore;
|
||||
public filter: WakuFilter;
|
||||
public lightPush: WakuLightPush;
|
||||
public relay?: WakuRelay;
|
||||
public store?: WakuStore;
|
||||
public filter?: WakuFilter;
|
||||
public lightPush?: WakuLightPush;
|
||||
|
||||
private pingKeepAliveTimers: {
|
||||
[peer: string]: ReturnType<typeof setInterval>;
|
||||
|
@ -61,22 +63,27 @@ export class WakuNode implements Waku {
|
|||
constructor(
|
||||
options: WakuOptions,
|
||||
libp2p: Libp2p,
|
||||
store: WakuStore,
|
||||
lightPush: WakuLightPush,
|
||||
filter: WakuFilter
|
||||
store?: WakuStore,
|
||||
lightPush?: WakuLightPush,
|
||||
filter?: WakuFilter
|
||||
) {
|
||||
this.libp2p = libp2p;
|
||||
this.relay = libp2p.pubsub as unknown as WakuRelay;
|
||||
this.store = store;
|
||||
this.filter = filter;
|
||||
this.lightPush = lightPush;
|
||||
|
||||
if (isWakuRelay(libp2p.pubsub)) {
|
||||
this.relay = libp2p.pubsub;
|
||||
}
|
||||
|
||||
this.pingKeepAliveTimers = {};
|
||||
this.relayKeepAliveTimers = {};
|
||||
|
||||
const pingKeepAlive =
|
||||
options.pingKeepAlive || DefaultPingKeepAliveValueSecs;
|
||||
const relayKeepAlive =
|
||||
options.relayKeepAlive || DefaultRelayKeepAliveValueSecs;
|
||||
const relayKeepAlive = this.relay
|
||||
? options.relayKeepAlive || DefaultRelayKeepAliveValueSecs
|
||||
: 0;
|
||||
|
||||
libp2p.connectionManager.addEventListener("peer:connect", (evt) => {
|
||||
this.startKeepAlive(evt.detail.remotePeer, pingKeepAlive, relayKeepAlive);
|
||||
|
@ -180,9 +187,9 @@ export class WakuNode implements Waku {
|
|||
key: Uint8Array | string,
|
||||
options?: { method?: DecryptionMethod; contentTopics?: string[] }
|
||||
): void {
|
||||
this.relay.addDecryptionKey(key, options);
|
||||
this.store.addDecryptionKey(key, options);
|
||||
this.filter.addDecryptionKey(key, options);
|
||||
if (this.relay) this.relay.addDecryptionKey(key, options);
|
||||
if (this.store) this.store.addDecryptionKey(key, options);
|
||||
if (this.filter) this.filter.addDecryptionKey(key, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -192,9 +199,9 @@ export class WakuNode implements Waku {
|
|||
* Strings must be in hex format.
|
||||
*/
|
||||
deleteDecryptionKey(key: Uint8Array | string): void {
|
||||
this.relay.deleteDecryptionKey(key);
|
||||
this.store.deleteDecryptionKey(key);
|
||||
this.filter.deleteDecryptionKey(key);
|
||||
if (this.relay) this.relay.deleteDecryptionKey(key);
|
||||
if (this.store) this.store.deleteDecryptionKey(key);
|
||||
if (this.filter) this.filter.deleteDecryptionKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,11 +237,12 @@ export class WakuNode implements Waku {
|
|||
}, pingPeriodSecs * 1000);
|
||||
}
|
||||
|
||||
if (relayPeriodSecs !== 0) {
|
||||
const relay = this.relay;
|
||||
if (relay && relayPeriodSecs !== 0) {
|
||||
this.relayKeepAliveTimers[peerIdStr] = setInterval(() => {
|
||||
log("Sending Waku Relay ping message");
|
||||
WakuMessage.fromBytes(new Uint8Array(), RelayPingContentTopic).then(
|
||||
(wakuMsg) => this.relay.send(wakuMsg)
|
||||
(wakuMsg) => relay.send(wakuMsg)
|
||||
);
|
||||
}, relayPeriodSecs * 1000);
|
||||
}
|
||||
|
@ -266,3 +274,16 @@ export class WakuNode implements Waku {
|
|||
this.relayKeepAliveTimers = {};
|
||||
}
|
||||
}
|
||||
|
||||
function isWakuRelay(pubsub: PubSub): pubsub is WakuRelay {
|
||||
if (pubsub) {
|
||||
try {
|
||||
return pubsub.multicodecs.includes(
|
||||
relayConstants.RelayCodecs[relayConstants.RelayCodecs.length - 1]
|
||||
);
|
||||
// Exception is expected if `libp2p` was not instantiated with pubsub
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ import debug from "debug";
|
|||
|
||||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { createWaku } from "../create_waku";
|
||||
import type { Waku } from "../interfaces";
|
||||
import { createLightNode } from "../create_waku";
|
||||
import type { WakuLight } from "../interfaces";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { Protocols } from "../waku";
|
||||
import { WakuMessage } from "../waku_message";
|
||||
|
@ -14,7 +14,7 @@ const log = debug("waku:test");
|
|||
const TestContentTopic = "/test/1/waku-filter";
|
||||
|
||||
describe("Waku Filter", () => {
|
||||
let waku: Waku;
|
||||
let waku: WakuLight;
|
||||
let nwaku: Nwaku;
|
||||
|
||||
afterEach(async function () {
|
||||
|
@ -26,7 +26,7 @@ describe("Waku Filter", () => {
|
|||
this.timeout(15000);
|
||||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
await nwaku.start({ filter: true, lightpush: true });
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
|
||||
});
|
||||
|
@ -47,7 +47,7 @@ describe("Waku Filter", () => {
|
|||
expect(msg.payloadAsUtf8).to.eq(messageText);
|
||||
};
|
||||
await waku.filter.subscribe(callback, [TestContentTopic]);
|
||||
// As the filter protocol does not cater for a ack of subscription
|
||||
// As the filter protocol does not cater for an ack of subscription
|
||||
// we cannot know whether the subscription happened. Something we want to
|
||||
// correct in future versions of the protocol.
|
||||
await delay(200);
|
||||
|
|
|
@ -3,8 +3,8 @@ import debug from "debug";
|
|||
|
||||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { createWaku } from "../create_waku";
|
||||
import type { Waku } from "../interfaces";
|
||||
import { createLightNode } from "../create_waku";
|
||||
import type { WakuLight } from "../interfaces";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { Protocols } from "../waku";
|
||||
import { WakuMessage } from "../waku_message";
|
||||
|
@ -14,7 +14,7 @@ const log = debug("waku:test:lightpush");
|
|||
const TestContentTopic = "/test/1/waku-light-push/utf8";
|
||||
|
||||
describe("Waku Light Push [node only]", () => {
|
||||
let waku: Waku;
|
||||
let waku: WakuLight;
|
||||
let nwaku: Nwaku;
|
||||
|
||||
afterEach(async function () {
|
||||
|
@ -28,7 +28,7 @@ describe("Waku Light Push [node only]", () => {
|
|||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
await nwaku.start({ lightpush: true });
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
|
@ -64,7 +64,7 @@ describe("Waku Light Push [node only]", () => {
|
|||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
await nwaku.start({ lightpush: true, topics: customPubSubTopic });
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
pubSubTopic: customPubSubTopic,
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
|
|
|
@ -8,13 +8,13 @@ import {
|
|||
WakuRelayMessage,
|
||||
} from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { createWaku } from "../create_waku";
|
||||
import { createPrivacyNode } from "../create_waku";
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "../crypto";
|
||||
import type { Waku } from "../interfaces";
|
||||
import type { WakuPrivacy } from "../interfaces";
|
||||
import { bytesToHex, bytesToUtf8, hexToBytes, utf8ToBytes } from "../utils";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { Protocols } from "../waku";
|
||||
|
@ -27,12 +27,12 @@ const TestContentTopic = "/test/1/waku-message/utf8";
|
|||
|
||||
describe("Waku Message [node only]", function () {
|
||||
describe("Interop: nwaku", function () {
|
||||
let waku: Waku;
|
||||
let waku: WakuPrivacy;
|
||||
let nwaku: Nwaku;
|
||||
|
||||
beforeEach(async function () {
|
||||
this.timeout(30_000);
|
||||
waku = await createWaku({
|
||||
waku = await createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
|
|
|
@ -11,13 +11,13 @@ import {
|
|||
} from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { DefaultPubSubTopic } from "../constants";
|
||||
import { createWaku } from "../create_waku";
|
||||
import { createPrivacyNode } from "../create_waku";
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "../crypto";
|
||||
import type { Waku } from "../interfaces";
|
||||
import type { WakuPrivacy } from "../interfaces";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { Protocols } from "../waku";
|
||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||
|
@ -36,17 +36,17 @@ describe("Waku Relay [node only]", () => {
|
|||
}
|
||||
});
|
||||
|
||||
let waku1: Waku;
|
||||
let waku2: Waku;
|
||||
let waku1: WakuPrivacy;
|
||||
let waku2: WakuPrivacy;
|
||||
beforeEach(async function () {
|
||||
this.timeout(10000);
|
||||
|
||||
log("Starting JS Waku instances");
|
||||
[waku1, waku2] = await Promise.all([
|
||||
createWaku({ staticNoiseKey: NOISE_KEY_1 }).then((waku) =>
|
||||
createPrivacyNode({ staticNoiseKey: NOISE_KEY_1 }).then((waku) =>
|
||||
waku.start().then(() => waku)
|
||||
),
|
||||
createWaku({
|
||||
createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_2,
|
||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
|
@ -259,9 +259,9 @@ describe("Waku Relay [node only]", () => {
|
|||
});
|
||||
|
||||
describe("Custom pubsub topic", () => {
|
||||
let waku1: Waku;
|
||||
let waku2: Waku;
|
||||
let waku3: Waku;
|
||||
let waku1: WakuPrivacy;
|
||||
let waku2: WakuPrivacy;
|
||||
let waku3: WakuPrivacy;
|
||||
afterEach(async function () {
|
||||
!!waku1 &&
|
||||
waku1.stop().catch((e) => console.log("Waku failed to stop", e));
|
||||
|
@ -279,16 +279,16 @@ describe("Waku Relay [node only]", () => {
|
|||
// 1 and 2 uses a custom pubsub
|
||||
// 3 uses the default pubsub
|
||||
[waku1, waku2, waku3] = await Promise.all([
|
||||
createWaku({
|
||||
createPrivacyNode({
|
||||
pubSubTopic: pubSubTopic,
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
createWaku({
|
||||
createPrivacyNode({
|
||||
pubSubTopic: pubSubTopic,
|
||||
staticNoiseKey: NOISE_KEY_2,
|
||||
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
createWaku({
|
||||
createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_3,
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
]);
|
||||
|
@ -338,12 +338,12 @@ describe("Waku Relay [node only]", () => {
|
|||
});
|
||||
|
||||
describe("Interop: nwaku", function () {
|
||||
let waku: Waku;
|
||||
let waku: WakuPrivacy;
|
||||
let nwaku: Nwaku;
|
||||
|
||||
beforeEach(async function () {
|
||||
this.timeout(30_000);
|
||||
waku = await createWaku({
|
||||
waku = await createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
|
@ -423,8 +423,8 @@ describe("Waku Relay [node only]", () => {
|
|||
});
|
||||
|
||||
describe.skip("Two nodes connected to nwaku", function () {
|
||||
let waku1: Waku;
|
||||
let waku2: Waku;
|
||||
let waku1: WakuPrivacy;
|
||||
let waku2: WakuPrivacy;
|
||||
let nwaku: Nwaku;
|
||||
|
||||
afterEach(async function () {
|
||||
|
@ -438,10 +438,10 @@ describe("Waku Relay [node only]", () => {
|
|||
it("Js publishes, other Js receives", async function () {
|
||||
this.timeout(60_000);
|
||||
[waku1, waku2] = await Promise.all([
|
||||
createWaku({
|
||||
createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
createWaku({
|
||||
createPrivacyNode({
|
||||
staticNoiseKey: NOISE_KEY_2,
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
]);
|
||||
|
|
|
@ -229,3 +229,5 @@ export class WakuRelay extends GossipSub {
|
|||
return super.getMeshPeers(topic ?? this.pubSubTopic);
|
||||
}
|
||||
}
|
||||
|
||||
WakuRelay.multicodec = constants.RelayCodecs[constants.RelayCodecs.length - 1];
|
||||
|
|
|
@ -7,13 +7,13 @@ import {
|
|||
NOISE_KEY_2,
|
||||
Nwaku,
|
||||
} from "../../test_utils";
|
||||
import { createWaku } from "../create_waku";
|
||||
import { createLightNode } from "../create_waku";
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "../crypto";
|
||||
import type { Waku } from "../interfaces";
|
||||
import type { WakuLight } from "../interfaces";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { Protocols } from "../waku";
|
||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||
|
@ -25,7 +25,7 @@ const log = debug("waku:test:store");
|
|||
const TestContentTopic = "/test/1/waku-store/utf8";
|
||||
|
||||
describe("Waku Store", () => {
|
||||
let waku: Waku;
|
||||
let waku: WakuLight;
|
||||
let nwaku: Nwaku;
|
||||
|
||||
afterEach(async function () {
|
||||
|
@ -49,7 +49,7 @@ describe("Waku Store", () => {
|
|||
).to.be.true;
|
||||
}
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
|
@ -82,7 +82,7 @@ describe("Waku Store", () => {
|
|||
).to.be.true;
|
||||
}
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
|
@ -122,7 +122,7 @@ describe("Waku Store", () => {
|
|||
).to.be.true;
|
||||
}
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
|
@ -159,7 +159,7 @@ describe("Waku Store", () => {
|
|||
).to.be.true;
|
||||
}
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
|
@ -202,7 +202,7 @@ describe("Waku Store", () => {
|
|||
).to.be.true;
|
||||
}
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
pubSubTopic: customPubSubTopic,
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
|
@ -269,10 +269,10 @@ describe("Waku Store", () => {
|
|||
log("Messages have been encrypted");
|
||||
|
||||
const [waku1, waku2, nimWakuMultiaddr] = await Promise.all([
|
||||
createWaku({
|
||||
createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
createWaku({
|
||||
createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_2,
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
nwaku.getMultiaddrWithId(),
|
||||
|
@ -371,10 +371,10 @@ describe("Waku Store", () => {
|
|||
log("Messages have been encrypted");
|
||||
|
||||
const [waku1, waku2, nimWakuMultiaddr] = await Promise.all([
|
||||
createWaku({
|
||||
createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
createWaku({
|
||||
createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_2,
|
||||
}).then((waku) => waku.start().then(() => waku)),
|
||||
nwaku.getMultiaddrWithId(),
|
||||
|
@ -458,7 +458,7 @@ describe("Waku Store", () => {
|
|||
).to.be.true;
|
||||
}
|
||||
|
||||
waku = await createWaku({
|
||||
waku = await createLightNode({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
});
|
||||
await waku.start();
|
||||
|
|
Loading…
Reference in New Issue