From e788f687422a69ed31243bec3646f0c1959c033e Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Thu, 10 Oct 2024 19:28:40 +0530 Subject: [PATCH] temp --- packages/interfaces/src/protocols.ts | 13 ++++++ packages/sdk/src/create/create.ts | 55 ++++++++++++++++++++--- packages/sdk/src/create/libp2p.ts | 12 +++++ packages/sdk/src/protocols/store/index.ts | 44 ++++++++++++++---- 4 files changed, 110 insertions(+), 14 deletions(-) diff --git a/packages/interfaces/src/protocols.ts b/packages/interfaces/src/protocols.ts index ddd864659e..d9c21184ab 100644 --- a/packages/interfaces/src/protocols.ts +++ b/packages/interfaces/src/protocols.ts @@ -1,6 +1,7 @@ import type { Libp2p } from "@libp2p/interface"; import type { PeerId } from "@libp2p/interface"; import type { Peer, PeerStore } from "@libp2p/interface"; +import { Multiaddr } from "@multiformats/multiaddr"; import type { CreateLibp2pOptions } from "./libp2p.js"; import type { IDecodedMessage } from "./message.js"; @@ -31,6 +32,12 @@ export type IBaseProtocolSDK = { export type NetworkConfig = StaticSharding | AutoSharding; +export type NodesToUseForProtocols = { + filter?: Array; + lightpush?: Array; + store?: string; +}; + //TODO: merge this with ProtocolCreateOptions or establish distinction: https://github.com/waku-org/js-waku/issues/2048 /** * Options for using LightPush and Filter @@ -119,6 +126,12 @@ export type ProtocolCreateOptions = { * List of peers to use to bootstrap the node. Ignored if defaultBootstrap is set to true. */ bootstrapPeers?: string[]; + /** + * Optional list of nodes' multiaddresses (websocket-supported) to use for the protocol. + * If specified, only the nodes in the list will be used for the respective protocol. + * If not specified, nodes will be chosen automatically. + */ + nodesToUse?: NodesToUseForProtocols; }; export type Callback = ( diff --git a/packages/sdk/src/create/create.ts b/packages/sdk/src/create/create.ts index 155fee3403..7a0ff9a16f 100644 --- a/packages/sdk/src/create/create.ts +++ b/packages/sdk/src/create/create.ts @@ -1,3 +1,4 @@ +import { multiaddr } from "@multiformats/multiaddr"; import { type LightNode } from "@waku/interfaces"; import { CreateWakuNodeOptions, WakuNode } from "../waku/index.js"; @@ -5,18 +6,62 @@ import { CreateWakuNodeOptions, WakuNode } from "../waku/index.js"; import { createLibp2pAndUpdateOptions } from "./libp2p.js"; /** - * Create a Waku node that uses Waku Light Push, Filter and Store to send and - * receive messages, enabling low resource consumption. - * Uses Waku Filter V2 by default. + * Creates a Waku Light Node that uses Push, Filter, and Store protocols. + * This enables low resource consumption and uses Waku Filter V2 by default. */ export async function createLightNode( options: CreateWakuNodeOptions = {} ): Promise { - const { libp2p, pubsubTopics } = await createLibp2pAndUpdateOptions(options); + const { nodesToUse, bootstrapPeers } = options; + // validateMultiaddrs(nodesToUse, bootstrapPeers); - return new WakuNode(pubsubTopics, options, libp2p, { + const validatedOptions = { + ...options, + nodesToUse: nodesToUse ? nodesToUse : undefined, + bootstrapPeers: bootstrapPeers ? bootstrapPeers : undefined + }; + + const { libp2p, pubsubTopics } = + await createLibp2pAndUpdateOptions(validatedOptions); + + return new WakuNode(pubsubTopics, validatedOptions, libp2p, { store: true, lightpush: true, filter: true }) as LightNode; } + +/** + * Validates multiaddrs for nodesToUse and bootstrapPeers. + * Throws an error if any multiaddr is invalid. + */ +// function validateMultiaddrs( +// nodesToUse?: Record, +// bootstrapPeers?: string[] +// ): void { +// const validateMultiaddr = (addr: string, errorContext: string): void => { +// try { +// multiaddr(addr).getPeerId(); +// } catch (error) { +// throw new Error(`Invalid multiaddr: ${errorContext}`); +// } +// }; + +// if (nodesToUse) { +// for (const [protocol, nodes] of Object.entries(nodesToUse)) { +// if (Array.isArray(nodes)) { +// nodes.forEach((node) => +// validateMultiaddr(node, `${protocol} - ${node}`) +// ); +// } else if (nodes) { +// validateMultiaddr(nodes, `${protocol} - ${nodes}`); +// } +// } +// } + +// if (bootstrapPeers) { +// bootstrapPeers.forEach((peer) => +// validateMultiaddr(peer, `bootstrapPeers - ${peer}`) +// ); +// } +// } diff --git a/packages/sdk/src/create/libp2p.ts b/packages/sdk/src/create/libp2p.ts index 81ff9e7cfe..54049c3bd0 100644 --- a/packages/sdk/src/create/libp2p.ts +++ b/packages/sdk/src/create/libp2p.ts @@ -100,6 +100,18 @@ export async function createLibp2pAndUpdateOptions( peerDiscovery.push(bootstrap({ list: options.bootstrapPeers })); } + if (options?.nodesToUse) { + for (const nodes of Object.values(options.nodesToUse)) { + if (Array.isArray(nodes)) { + nodes.forEach((node) => { + peerDiscovery.push(bootstrap({ list: [node] })); + }); + } else if (nodes) { + peerDiscovery.push(bootstrap({ list: [nodes] })); + } + } + } + libp2pOptions.peerDiscovery = peerDiscovery; const libp2p = await defaultLibp2p( diff --git a/packages/sdk/src/protocols/store/index.ts b/packages/sdk/src/protocols/store/index.ts index 01ef45d58c..8befe1473d 100644 --- a/packages/sdk/src/protocols/store/index.ts +++ b/packages/sdk/src/protocols/store/index.ts @@ -1,9 +1,11 @@ +import type { Peer } from "@libp2p/interface"; import { ConnectionManager, StoreCore } from "@waku/core"; import { IDecodedMessage, IDecoder, IStore, Libp2p, + NodesToUseForProtocols, QueryRequestParams, StoreCursor } from "@waku/interfaces"; @@ -23,7 +25,11 @@ const log = new Logger("waku:store:sdk"); export class Store extends BaseProtocolSDK implements IStore { public readonly protocol: StoreCore; - public constructor(connectionManager: ConnectionManager, libp2p: Libp2p) { + public constructor( + connectionManager: ConnectionManager, + private libp2p: Libp2p, + private readonly nodeToUse?: NodesToUseForProtocols["store"] + ) { super( new StoreCore(connectionManager.configuredPubsubTopics, libp2p), connectionManager, @@ -58,12 +64,31 @@ export class Store extends BaseProtocolSDK implements IStore { ...options }; - const peer = ( - await this.protocol.getPeers({ - numPeers: this.numPeersToUse, - maxBootstrapPeers: 1 - }) - )[0]; + let peer: Peer | undefined; + + if (this.nodeToUse) { + const peerIdStr = this.nodeToUse.getPeerId(); + if (!peerIdStr) { + throw new Error("Provided multiaddr is invalid: No peer ID found"); + } + + const peerId = this.libp2p + .getPeers() + .find((p) => p.toString() === peerIdStr); + if (!peerId) { + throw new Error("Provided multiaddr is invalid: Peer is not connected"); + } + + peer = await this.libp2p.peerStore.get(peerId); + } else { + peer = ( + await this.protocol.getPeers({ + numPeers: this.numPeersToUse, + maxBootstrapPeers: 1 + }) + )[0]; + } + if (!peer) { log.error("No peers available to query"); throw new Error("No peers available to query"); @@ -237,9 +262,10 @@ export class Store extends BaseProtocolSDK implements IStore { * @returns A function that takes a Libp2p instance and returns a StoreSDK instance. */ export function wakuStore( - connectionManager: ConnectionManager + connectionManager: ConnectionManager, + nodeToUse?: NodesToUseForProtocols["store"] ): (libp2p: Libp2p) => IStore { return (libp2p: Libp2p) => { - return new Store(connectionManager, libp2p); + return new Store(connectionManager, libp2p, nodeToUse); }; }