2023-02-27 10:14:16 +11:00
|
|
|
import { BaseProtocol } from "@waku/core/lib/base_protocol";
|
2023-03-03 13:49:32 +11:00
|
|
|
import { EnrDecoder } from "@waku/enr";
|
2022-12-07 11:35:30 +05:30
|
|
|
import type {
|
2022-12-06 12:36:29 +11:00
|
|
|
IPeerExchange,
|
2023-07-25 02:17:52 +02:00
|
|
|
Libp2pComponents,
|
2022-12-07 11:35:30 +05:30
|
|
|
PeerExchangeQueryParams,
|
2023-08-16 20:18:13 +05:30
|
|
|
PeerInfo
|
2022-12-07 11:35:30 +05:30
|
|
|
} from "@waku/interfaces";
|
2023-03-16 12:22:14 +11:00
|
|
|
import { isDefined } from "@waku/utils";
|
2023-10-20 16:36:47 +05:30
|
|
|
import { Logger } from "@waku/utils";
|
2022-12-07 11:35:30 +05:30
|
|
|
import all from "it-all";
|
|
|
|
import * as lp from "it-length-prefixed";
|
|
|
|
import { pipe } from "it-pipe";
|
2023-03-14 13:56:15 +05:30
|
|
|
import { Uint8ArrayList } from "uint8arraylist";
|
2022-12-07 11:35:30 +05:30
|
|
|
|
|
|
|
import { PeerExchangeRPC } from "./rpc.js";
|
|
|
|
|
|
|
|
export const PeerExchangeCodec = "/vac/waku/peer-exchange/2.0.0-alpha1";
|
|
|
|
|
2023-10-20 16:36:47 +05:30
|
|
|
const log = new Logger("peer-exchange");
|
2022-12-07 11:35:30 +05:30
|
|
|
|
2023-01-04 14:35:44 +05:30
|
|
|
/**
|
|
|
|
* Implementation of the Peer Exchange protocol (https://rfc.vac.dev/spec/34/)
|
|
|
|
*/
|
2023-02-27 10:14:16 +11:00
|
|
|
export class WakuPeerExchange extends BaseProtocol implements IPeerExchange {
|
2023-01-04 14:35:44 +05:30
|
|
|
/**
|
|
|
|
* @param components - libp2p components
|
|
|
|
*/
|
2023-07-25 02:17:52 +02:00
|
|
|
constructor(components: Libp2pComponents) {
|
|
|
|
super(PeerExchangeCodec, components);
|
2022-12-07 11:35:30 +05:30
|
|
|
}
|
|
|
|
|
2023-01-04 14:35:44 +05:30
|
|
|
/**
|
|
|
|
* Make a peer exchange query to a peer
|
|
|
|
*/
|
2023-03-16 12:22:14 +11:00
|
|
|
async query(
|
2023-08-16 20:18:13 +05:30
|
|
|
params: PeerExchangeQueryParams
|
2023-03-16 12:22:14 +11:00
|
|
|
): Promise<PeerInfo[] | undefined> {
|
2022-12-07 11:35:30 +05:30
|
|
|
const { numPeers } = params;
|
|
|
|
|
|
|
|
const rpcQuery = PeerExchangeRPC.createRequest({
|
2023-08-16 20:18:13 +05:30
|
|
|
numPeers: BigInt(numPeers)
|
2022-12-07 11:35:30 +05:30
|
|
|
});
|
|
|
|
|
2023-01-04 14:35:44 +05:30
|
|
|
const peer = await this.getPeer(params.peerId);
|
2022-12-07 11:35:30 +05:30
|
|
|
|
2023-09-04 10:27:25 +05:30
|
|
|
const stream = await this.getStream(peer);
|
2022-12-07 11:35:30 +05:30
|
|
|
|
2023-03-14 13:56:15 +05:30
|
|
|
const res = await pipe(
|
2022-12-07 11:35:30 +05:30
|
|
|
[rpcQuery.encode()],
|
2023-05-06 03:31:15 +00:00
|
|
|
lp.encode,
|
2022-12-07 11:35:30 +05:30
|
|
|
stream,
|
2023-05-06 03:31:15 +00:00
|
|
|
lp.decode,
|
2023-08-16 20:18:13 +05:30
|
|
|
async (source) => await all(source)
|
2022-12-07 11:35:30 +05:30
|
|
|
);
|
|
|
|
|
2023-03-14 13:56:15 +05:30
|
|
|
try {
|
|
|
|
const bytes = new Uint8ArrayList();
|
|
|
|
res.forEach((chunk) => {
|
|
|
|
bytes.append(chunk);
|
|
|
|
});
|
|
|
|
|
2023-03-16 12:22:14 +11:00
|
|
|
const { response } = PeerExchangeRPC.decode(bytes);
|
2023-03-14 13:56:15 +05:30
|
|
|
|
2023-03-16 12:22:14 +11:00
|
|
|
if (!response) {
|
2023-10-20 16:36:47 +05:30
|
|
|
log.error(
|
|
|
|
"PeerExchangeRPC message did not contains a `response` field"
|
|
|
|
);
|
2023-03-16 12:22:14 +11:00
|
|
|
return;
|
2022-12-07 11:35:30 +05:30
|
|
|
}
|
2023-03-14 13:56:15 +05:30
|
|
|
|
2023-03-16 12:22:14 +11:00
|
|
|
return Promise.all(
|
|
|
|
response.peerInfos
|
|
|
|
.map((peerInfo) => peerInfo.enr)
|
|
|
|
.filter(isDefined)
|
|
|
|
.map(async (enr) => {
|
|
|
|
return { ENR: await EnrDecoder.fromRLP(enr) };
|
2023-08-16 20:18:13 +05:30
|
|
|
})
|
2023-03-14 13:56:15 +05:30
|
|
|
);
|
|
|
|
} catch (err) {
|
2023-10-20 16:36:47 +05:30
|
|
|
log.error("Failed to decode push reply", err);
|
2023-03-16 12:22:14 +11:00
|
|
|
return;
|
2023-03-14 13:56:15 +05:30
|
|
|
}
|
2022-12-07 11:35:30 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-04 14:35:44 +05:30
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @returns A function that creates a new peer exchange protocol
|
|
|
|
*/
|
2023-02-02 08:02:06 +05:30
|
|
|
export function wakuPeerExchange(): (
|
2023-08-16 20:18:13 +05:30
|
|
|
components: Libp2pComponents
|
2023-02-02 08:02:06 +05:30
|
|
|
) => WakuPeerExchange {
|
2023-07-25 02:17:52 +02:00
|
|
|
return (components: Libp2pComponents) => new WakuPeerExchange(components);
|
2022-12-07 11:35:30 +05:30
|
|
|
}
|