This commit is contained in:
Danish Arora 2024-10-10 19:28:40 +05:30
parent 75fcca4cd9
commit e788f68742
No known key found for this signature in database
GPG Key ID: 1C6EF37CDAE1426E
4 changed files with 110 additions and 14 deletions

View File

@ -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<string>;
lightpush?: Array<string>;
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<T extends IDecodedMessage> = (

View File

@ -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<LightNode> {
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<string, string | string[] | undefined>,
// 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}`)
// );
// }
// }

View File

@ -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(

View File

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