From 95715d43b7bc3ba6ee2e2f1759675e02bacbe97f Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 11:57:36 +0530 Subject: [PATCH 01/16] disable libp2p autodial --- packages/core/src/lib/connection_manager.ts | 1 + packages/sdk/src/create.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/core/src/lib/connection_manager.ts b/packages/core/src/lib/connection_manager.ts index ed2de604bb..e01f97f9a6 100644 --- a/packages/core/src/lib/connection_manager.ts +++ b/packages/core/src/lib/connection_manager.ts @@ -166,6 +166,7 @@ export class ConnectionManager { async dropConnection(peerId: PeerId): Promise { try { + this.keepAliveManager.stop(peerId); await this.libp2p.hangUp(peerId); log(`Dropped connection with peer ${peerId.toString()}`); } catch (error) { diff --git a/packages/sdk/src/create.ts b/packages/sdk/src/create.ts index 8a10abf9a2..b9eb138bda 100644 --- a/packages/sdk/src/create.ts +++ b/packages/sdk/src/create.ts @@ -164,6 +164,9 @@ export async function defaultLibp2p( : {}; return createLibp2p({ + connectionManager: { + minConnections: 1, + }, transports: [webSockets({ filter: filterAll })], streamMuxers: [mplex()], connectionEncryption: [noise()], From 34e22ad6774f6682b958109eb5badaeed2bae2d2 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 14:18:14 +0530 Subject: [PATCH 02/16] improve logs for peer-exchange --- .../peer-exchange/src/waku_peer_exchange_discovery.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/peer-exchange/src/waku_peer_exchange_discovery.ts b/packages/peer-exchange/src/waku_peer_exchange_discovery.ts index 9dafba5ae7..05407cb838 100644 --- a/packages/peer-exchange/src/waku_peer_exchange_discovery.ts +++ b/packages/peer-exchange/src/waku_peer_exchange_discovery.ts @@ -134,6 +134,12 @@ export class PeerExchangeDiscovery maxRetries = DEFAULT_MAX_RETRIES, } = this.options; + log( + `Querying peer: ${peerIdStr} (attempt ${ + this.queryAttempts.get(peerIdStr) ?? 1 + })` + ); + await this.query(peerId); const currentAttempt = this.queryAttempts.get(peerIdStr) ?? 1; @@ -189,6 +195,8 @@ export class PeerExchangeDiscovery }, }); + log(`Discovered peer: ${peerId.toString()}`); + this.dispatchEvent( new CustomEvent("peer", { detail: { From 164508ce8db81d4b9819d35c0731f4ef9707d720 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 14:18:33 +0530 Subject: [PATCH 03/16] add a function to fetch discovered and connected peers by discovery --- packages/core/src/lib/connection_manager.ts | 52 ++++++++++++++++++- packages/interfaces/src/connection_manager.ts | 13 +++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/packages/core/src/lib/connection_manager.ts b/packages/core/src/lib/connection_manager.ts index e01f97f9a6..7aa8e1a3c4 100644 --- a/packages/core/src/lib/connection_manager.ts +++ b/packages/core/src/lib/connection_manager.ts @@ -1,6 +1,11 @@ import type { PeerId } from "@libp2p/interface-peer-id"; import type { PeerInfo } from "@libp2p/interface-peer-info"; -import type { ConnectionManagerOptions, IRelay } from "@waku/interfaces"; +import { Peer } from "@libp2p/interface-peer-store"; +import type { + ConnectionManagerOptions, + IRelay, + PeersByDiscovery, +} from "@waku/interfaces"; import { Libp2p, Tags } from "@waku/interfaces"; import debug from "debug"; @@ -44,6 +49,51 @@ export class ConnectionManager { return instance; } + // write a public function to get all the peers discovered (by bootstrap and peer exchange), and connected (by bootstrap and peer exchange) + public async getPeersByDiscovery(): Promise { + const peersDiscovered = await this.libp2p.peerStore.all(); + const peersConnected = this.libp2p + .getConnections() + .map((conn) => conn.remotePeer); + + const peersDiscoveredByBootstrap: Peer[] = []; + const peersDiscoveredByPeerExchange: Peer[] = []; + const peersConnectedByBootstrap: Peer[] = []; + const peersConnectedByPeerExchange: Peer[] = []; + + for (const peer of peersDiscovered) { + const tags = await this.getTagNamesForPeer(peer.id); + + if (tags.includes(Tags.BOOTSTRAP)) { + peersDiscoveredByBootstrap.push(peer); + } else if (tags.includes(Tags.PEER_EXCHANGE)) { + peersDiscoveredByPeerExchange.push(peer); + } + } + + for (const peerId of peersConnected) { + const peer = await this.libp2p.peerStore.get(peerId); + const tags = await this.getTagNamesForPeer(peerId); + + if (tags.includes(Tags.BOOTSTRAP)) { + peersConnectedByBootstrap.push(peer); + } else if (tags.includes(Tags.PEER_EXCHANGE)) { + peersConnectedByPeerExchange.push(peer); + } + } + + return { + DISCOVERED: { + [Tags.BOOTSTRAP]: peersDiscoveredByBootstrap, + [Tags.PEER_EXCHANGE]: peersDiscoveredByPeerExchange, + }, + CONNECTED: { + [Tags.BOOTSTRAP]: peersConnectedByBootstrap, + [Tags.PEER_EXCHANGE]: peersConnectedByPeerExchange, + }, + }; + } + private constructor( libp2p: Libp2p, keepAliveOptions: KeepAliveOptions, diff --git a/packages/interfaces/src/connection_manager.ts b/packages/interfaces/src/connection_manager.ts index 7424621cd4..f987bcc042 100644 --- a/packages/interfaces/src/connection_manager.ts +++ b/packages/interfaces/src/connection_manager.ts @@ -1,3 +1,5 @@ +import type { Peer } from "@libp2p/interface-peer-store"; + export enum Tags { BOOTSTRAP = "bootstrap", PEER_EXCHANGE = "peer-exchange", @@ -19,3 +21,14 @@ export interface ConnectionManagerOptions { */ maxParallelDials: number; } + +export interface PeersByDiscovery { + DISCOVERED: { + [Tags.BOOTSTRAP]: Peer[]; + [Tags.PEER_EXCHANGE]: Peer[]; + }; + CONNECTED: { + [Tags.BOOTSTRAP]: Peer[]; + [Tags.PEER_EXCHANGE]: Peer[]; + }; +} From 1e0708b235305f5654f960d9d0e1478699093475 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 15:22:06 +0530 Subject: [PATCH 04/16] connection-manager: introduce event emissions by discovery --- packages/core/src/lib/connection_manager.ts | 22 +++++++++++++++++-- packages/interfaces/src/connection_manager.ts | 7 ++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/core/src/lib/connection_manager.ts b/packages/core/src/lib/connection_manager.ts index 7aa8e1a3c4..b1b91e1291 100644 --- a/packages/core/src/lib/connection_manager.ts +++ b/packages/core/src/lib/connection_manager.ts @@ -1,9 +1,12 @@ +import { EventEmitter } from "events"; + import type { PeerId } from "@libp2p/interface-peer-id"; import type { PeerInfo } from "@libp2p/interface-peer-info"; import { Peer } from "@libp2p/interface-peer-store"; -import type { +import { ConnectionManagerOptions, IRelay, + PeerEvents, PeersByDiscovery, } from "@waku/interfaces"; import { Libp2p, Tags } from "@waku/interfaces"; @@ -17,7 +20,7 @@ export const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1; export const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3; export const DEFAULT_MAX_PARALLEL_DIALS = 3; -export class ConnectionManager { +export class ConnectionManager extends EventEmitter { private static instances = new Map(); private keepAliveManager: KeepAliveManager; private options: ConnectionManagerOptions; @@ -100,6 +103,7 @@ export class ConnectionManager { relay?: IRelay, options?: Partial ) { + super(); this.libp2p = libp2p; this.options = { maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER, @@ -290,6 +294,16 @@ export class ConnectionManager { void (async () => { const { id: peerId } = evt.detail; + const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes( + Tags.BOOTSTRAP + ); + + if (isBootstrap) { + this.emit(PeerEvents.PEER_DISCOVERY_BOOTSTRAP, peerId); + } else { + this.emit(PeerEvents.PEER_DISCOVERY_PEER_EXCHANGE, peerId); + } + try { await this.attemptDial(peerId); } catch (error) { @@ -317,7 +331,11 @@ export class ConnectionManager { bootstrapConnections.length > this.options.maxBootstrapPeersAllowed ) { await this.dropConnection(peerId); + } else { + this.emit(PeerEvents.PEER_CONNECT_BOOTSTRAP, peerId); } + } else { + this.emit(PeerEvents.PEER_CONNECT_PEER_EXCHANGE, peerId); } })(); }, diff --git a/packages/interfaces/src/connection_manager.ts b/packages/interfaces/src/connection_manager.ts index f987bcc042..9fbb1c455a 100644 --- a/packages/interfaces/src/connection_manager.ts +++ b/packages/interfaces/src/connection_manager.ts @@ -22,6 +22,13 @@ export interface ConnectionManagerOptions { maxParallelDials: number; } +export enum PeerEvents { + PEER_DISCOVERY_BOOTSTRAP = "peer:discovery:bootstrap", + PEER_DISCOVERY_PEER_EXCHANGE = "peer:discovery:peer-exchange", + PEER_CONNECT_BOOTSTRAP = "peer:connected:bootstrap", + PEER_CONNECT_PEER_EXCHANGE = "peer:connected:peer-exchange", +} + export interface PeersByDiscovery { DISCOVERED: { [Tags.BOOTSTRAP]: Peer[]; From dfa3618ed95b12ad6ea7dd1568a1241f347448e7 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 15:22:20 +0530 Subject: [PATCH 05/16] write a spec test for events --- .../tests/tests/connection_manager.spec.ts | 340 ++++++++++++------ 1 file changed, 230 insertions(+), 110 deletions(-) diff --git a/packages/tests/tests/connection_manager.spec.ts b/packages/tests/tests/connection_manager.spec.ts index b29c22efbb..5fbbd5aefe 100644 --- a/packages/tests/tests/connection_manager.spec.ts +++ b/packages/tests/tests/connection_manager.spec.ts @@ -1,6 +1,7 @@ import { CustomEvent } from "@libp2p/interfaces/events"; +import { createSecp256k1PeerId } from "@libp2p/peer-id-factory"; import { ConnectionManager, KeepAliveOptions } from "@waku/core"; -import { LightNode, Tags } from "@waku/interfaces"; +import { LightNode, PeerEvents, Tags } from "@waku/interfaces"; import { createLightNode } from "@waku/sdk"; import { expect } from "chai"; import sinon, { SinonSpy, SinonStub } from "sinon"; @@ -34,162 +35,281 @@ describe("ConnectionManager", function () { afterEach(async () => { await waku.stop(); - sinon.restore(); }); - describe("attemptDial method", function () { - let attemptDialSpy: SinonSpy; + describe("Events", () => { + it("should emit `peer:discovery:{bootstrap/peer-exchange}` event when a peer is discovered", async function () { + this.timeout(TEST_TIMEOUT); - beforeEach(function () { - attemptDialSpy = sinon.spy(connectionManager as any, "attemptDial"); - }); + const peerIdBootstrap = await createSecp256k1PeerId(); + + await waku.libp2p.peerStore.save(peerIdBootstrap, { + tags: { + [Tags.BOOTSTRAP]: { + value: 50, + ttl: 1200000, + }, + }, + }); + + const peerDiscoveryEventPromise = new Promise((resolve) => { + connectionManager!.addListener( + PeerEvents.PEER_DISCOVERY_BOOTSTRAP, + (peerId) => { + expect(peerId.toString()).to.equal(peerIdBootstrap.toString()); + resolve(); + } + ); + }); + + waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerId })); + + await peerDiscoveryEventPromise; - afterEach(function () { - attemptDialSpy.restore(); + const peerIdPx = await createSecp256k1PeerId(); + + await waku.libp2p.peerStore.save(peerIdPx, { + tags: { + [Tags.PEER_EXCHANGE]: { + value: 50, + ttl: 1200000, + }, + }, + }); + + const peerDiscoveryEventPromise2 = new Promise((resolve) => { + connectionManager!.addListener( + PeerEvents.PEER_DISCOVERY_PEER_EXCHANGE, + (peerId) => { + expect(peerId.toString()).to.equal(peerIdPx.toString()); + resolve(); + } + ); + }); + + waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerIdPx })); + + await peerDiscoveryEventPromise2; }); - it("should be called on all `peer:discovery` events", async function () { + it("should emit `peer:connected:{bootstrap/peer-exchange}` event when a peer is connected", async function () { this.timeout(TEST_TIMEOUT); - const totalPeerIds = 1; - for (let i = 1; i <= totalPeerIds; i++) { - waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { detail: `peer-id-${i}` }) + const peerIdBootstrap = await createSecp256k1PeerId(); + + await waku.libp2p.peerStore.save(peerIdBootstrap, { + tags: { + [Tags.BOOTSTRAP]: { + value: 50, + ttl: 1200000, + }, + }, + }); + + const peerConnectedEventPromise = new Promise((resolve) => { + connectionManager!.addListener( + PeerEvents.PEER_CONNECT_BOOTSTRAP, + (peerId) => { + expect(peerId.toString()).to.equal(peerIdBootstrap.toString()); + resolve(); + } ); - } + }); - expect(attemptDialSpy.callCount).to.equal( - totalPeerIds, - "attemptDial should be called once for each peer:discovery event" + waku.libp2p.dispatchEvent( + new CustomEvent("peer:connect", { detail: peerIdBootstrap }) ); - }); - }); - describe("dialPeer method", function () { - beforeEach(function () { - getConnectionsStub = sinon.stub( - (connectionManager as any).libp2p, - "getConnections" - ); - getTagNamesForPeerStub = sinon.stub( - connectionManager as any, - "getTagNamesForPeer" + await peerConnectedEventPromise; + + const peerIdPx = await createSecp256k1PeerId(); + + await waku.libp2p.peerStore.save(peerIdPx, { + tags: { + [Tags.PEER_EXCHANGE]: { + value: 50, + ttl: 1200000, + }, + }, + }); + + const peerConnectedEventPromise2 = new Promise((resolve) => { + connectionManager!.addListener( + PeerEvents.PEER_CONNECT_PEER_EXCHANGE, + (peerId) => { + expect(peerId.toString()).to.equal(peerIdPx.toString()); + resolve(); + } + ); + }); + + waku.libp2p.dispatchEvent( + new CustomEvent("peer:connect", { detail: peerIdPx }) ); - dialPeerStub = sinon.stub(connectionManager as any, "dialPeer"); + + await peerConnectedEventPromise2; }); + }); - afterEach(function () { - dialPeerStub.restore(); - getTagNamesForPeerStub.restore(); - getConnectionsStub.restore(); + describe("Testing Dials", () => { + afterEach(() => { + sinon.restore(); }); - describe("For bootstrap peers", function () { - it("should be called for bootstrap peers", async function () { - this.timeout(TEST_TIMEOUT); + describe("attemptDial method", function () { + let attemptDialSpy: SinonSpy; - // simulate that the peer is not connected - getConnectionsStub.returns([]); + beforeEach(function () { + attemptDialSpy = sinon.spy(connectionManager as any, "attemptDial"); + }); - // simulate that the peer is a bootstrap peer - getTagNamesForPeerStub.resolves([Tags.BOOTSTRAP]); + afterEach(function () { + attemptDialSpy.restore(); + }); - // emit a peer:discovery event - waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { detail: "bootstrap-peer" }) - ); + it("should be called on all `peer:discovery` events", async function () { + this.timeout(TEST_TIMEOUT); - // wait for the async function calls within attemptDial to finish - await delay(DELAY_MS); + const totalPeerIds = 1; + for (let i = 1; i <= totalPeerIds; i++) { + waku.libp2p.dispatchEvent( + new CustomEvent("peer:discovery", { detail: `peer-id-${i}` }) + ); + } - // check that dialPeer was called once - expect(dialPeerStub.callCount).to.equal( - 1, - "dialPeer should be called for bootstrap peers" + expect(attemptDialSpy.callCount).to.equal( + totalPeerIds, + "attemptDial should be called once for each peer:discovery event" ); }); + }); - it("should not be called more than DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED times for bootstrap peers", async function () { - this.timeout(TEST_TIMEOUT); + describe("dialPeer method", function () { + beforeEach(function () { + getConnectionsStub = sinon.stub( + (connectionManager as any).libp2p, + "getConnections" + ); + getTagNamesForPeerStub = sinon.stub( + connectionManager as any, + "getTagNamesForPeer" + ); + dialPeerStub = sinon.stub(connectionManager as any, "dialPeer"); + }); - // simulate that the peer is not connected - getConnectionsStub.returns([]); + afterEach(function () { + dialPeerStub.restore(); + getTagNamesForPeerStub.restore(); + getConnectionsStub.restore(); + }); - // simulate that the peer is a bootstrap peer - getTagNamesForPeerStub.resolves([Tags.BOOTSTRAP]); + describe("For bootstrap peers", function () { + it("should be called for bootstrap peers", async function () { + this.timeout(TEST_TIMEOUT); - // emit first peer:discovery event - waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { detail: "bootstrap-peer" }) - ); + // simulate that the peer is not connected + getConnectionsStub.returns([]); - // simulate that the peer is connected - getConnectionsStub.returns([{ tags: [{ name: Tags.BOOTSTRAP }] }]); + // simulate that the peer is a bootstrap peer + getTagNamesForPeerStub.resolves([Tags.BOOTSTRAP]); - // emit multiple peer:discovery events - const totalBootstrapPeers = 5; - for (let i = 1; i <= totalBootstrapPeers; i++) { - await delay(500); + // emit a peer:discovery event waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { - detail: `bootstrap-peer-id-${i}`, - }) + new CustomEvent("peer:discovery", { detail: "bootstrap-peer" }) ); - } - // check that dialPeer was called only once - expect(dialPeerStub.callCount).to.equal( - 1, - "dialPeer should not be called more than once for bootstrap peers" - ); - }); - }); + // wait for the async function calls within attemptDial to finish + await delay(DELAY_MS); - describe("For peer-exchange peers", function () { - it("should be called for peers with PEER_EXCHANGE tags", async function () { - this.timeout(TEST_TIMEOUT); + // check that dialPeer was called once + expect(dialPeerStub.callCount).to.equal( + 1, + "dialPeer should be called for bootstrap peers" + ); + }); - // simulate that the peer is not connected - getConnectionsStub.returns([]); + it("should not be called more than DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED times for bootstrap peers", async function () { + this.timeout(TEST_TIMEOUT); - // simulate that the peer has a PEER_EXCHANGE tag - getTagNamesForPeerStub.resolves([Tags.PEER_EXCHANGE]); + // simulate that the peer is not connected + getConnectionsStub.returns([]); - // emit a peer:discovery event - waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { detail: "px-peer" }) - ); + // simulate that the peer is a bootstrap peer + getTagNamesForPeerStub.resolves([Tags.BOOTSTRAP]); - // wait for the async function calls within attemptDial to finish - await delay(DELAY_MS); + // emit first peer:discovery event + waku.libp2p.dispatchEvent( + new CustomEvent("peer:discovery", { detail: "bootstrap-peer" }) + ); - // check that dialPeer was called once - expect(dialPeerStub.callCount).to.equal( - 1, - "dialPeer should be called for peers with PEER_EXCHANGE tags" - ); + // simulate that the peer is connected + getConnectionsStub.returns([{ tags: [{ name: Tags.BOOTSTRAP }] }]); + + // emit multiple peer:discovery events + const totalBootstrapPeers = 5; + for (let i = 1; i <= totalBootstrapPeers; i++) { + await delay(500); + waku.libp2p.dispatchEvent( + new CustomEvent("peer:discovery", { + detail: `bootstrap-peer-id-${i}`, + }) + ); + } + + // check that dialPeer was called only once + expect(dialPeerStub.callCount).to.equal( + 1, + "dialPeer should not be called more than once for bootstrap peers" + ); + }); }); - it("should be called for every peer with PEER_EXCHANGE tags", async function () { - this.timeout(TEST_TIMEOUT); + describe("For peer-exchange peers", function () { + it("should be called for peers with PEER_EXCHANGE tags", async function () { + this.timeout(TEST_TIMEOUT); - // simulate that the peer is not connected - getConnectionsStub.returns([]); + // simulate that the peer is not connected + getConnectionsStub.returns([]); - // simulate that the peer has a PEER_EXCHANGE tag - getTagNamesForPeerStub.resolves([Tags.PEER_EXCHANGE]); + // simulate that the peer has a PEER_EXCHANGE tag + getTagNamesForPeerStub.resolves([Tags.PEER_EXCHANGE]); - // emit multiple peer:discovery events - const totalPxPeers = 5; - for (let i = 0; i < totalPxPeers; i++) { + // emit a peer:discovery event waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { detail: `px-peer-id-${i}` }) + new CustomEvent("peer:discovery", { detail: "px-peer" }) ); - await delay(500); - } - // check that dialPeer was called for each peer with PEER_EXCHANGE tags - expect(dialPeerStub.callCount).to.equal(totalPxPeers); + // wait for the async function calls within attemptDial to finish + await delay(DELAY_MS); + + // check that dialPeer was called once + expect(dialPeerStub.callCount).to.equal( + 1, + "dialPeer should be called for peers with PEER_EXCHANGE tags" + ); + }); + + it("should be called for every peer with PEER_EXCHANGE tags", async function () { + this.timeout(TEST_TIMEOUT); + + // simulate that the peer is not connected + getConnectionsStub.returns([]); + + // simulate that the peer has a PEER_EXCHANGE tag + getTagNamesForPeerStub.resolves([Tags.PEER_EXCHANGE]); + + // emit multiple peer:discovery events + const totalPxPeers = 5; + for (let i = 0; i < totalPxPeers; i++) { + waku.libp2p.dispatchEvent( + new CustomEvent("peer:discovery", { detail: `px-peer-id-${i}` }) + ); + await delay(500); + } + + // check that dialPeer was called for each peer with PEER_EXCHANGE tags + expect(dialPeerStub.callCount).to.equal(totalPxPeers); + }); }); }); }); From da6b66107d6af4531313ac0ac1f28527bc81b2c5 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 15:23:04 +0530 Subject: [PATCH 06/16] minor code improvement for peer-exchange --- packages/peer-exchange/src/waku_peer_exchange_discovery.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/peer-exchange/src/waku_peer_exchange_discovery.ts b/packages/peer-exchange/src/waku_peer_exchange_discovery.ts index 05407cb838..1c14f6360f 100644 --- a/packages/peer-exchange/src/waku_peer_exchange_discovery.ts +++ b/packages/peer-exchange/src/waku_peer_exchange_discovery.ts @@ -7,7 +7,7 @@ import { peerDiscovery as symbol } from "@libp2p/interface-peer-discovery"; import type { PeerId } from "@libp2p/interface-peer-id"; import type { PeerInfo } from "@libp2p/interface-peer-info"; import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events"; -import type { Libp2pComponents } from "@waku/interfaces"; +import { Libp2pComponents, Tags } from "@waku/interfaces"; import debug from "debug"; import { PeerExchangeCodec, WakuPeerExchange } from "./waku_peer_exchange.js"; @@ -45,7 +45,7 @@ export interface Options { maxRetries?: number; } -export const DEFAULT_PEER_EXCHANGE_TAG_NAME = "peer-exchange"; +export const DEFAULT_PEER_EXCHANGE_TAG_NAME = Tags.PEER_EXCHANGE; const DEFAULT_PEER_EXCHANGE_TAG_VALUE = 50; const DEFAULT_PEER_EXCHANGE_TAG_TTL = 120000; From b815615aa8c905ec1a4025c59490002b88a805a0 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 15:30:05 +0530 Subject: [PATCH 07/16] rm: comment --- packages/core/src/lib/connection_manager.ts | 1 - .../tests/tests/peer_exchange.node.spec.ts | 26 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/core/src/lib/connection_manager.ts b/packages/core/src/lib/connection_manager.ts index b1b91e1291..6715dd1e38 100644 --- a/packages/core/src/lib/connection_manager.ts +++ b/packages/core/src/lib/connection_manager.ts @@ -52,7 +52,6 @@ export class ConnectionManager extends EventEmitter { return instance; } - // write a public function to get all the peers discovered (by bootstrap and peer exchange), and connected (by bootstrap and peer exchange) public async getPeersByDiscovery(): Promise { const peersDiscovered = await this.libp2p.peerStore.all(); const peersConnected = this.libp2p diff --git a/packages/tests/tests/peer_exchange.node.spec.ts b/packages/tests/tests/peer_exchange.node.spec.ts index 32913705a4..3c57f76b03 100644 --- a/packages/tests/tests/peer_exchange.node.spec.ts +++ b/packages/tests/tests/peer_exchange.node.spec.ts @@ -38,7 +38,7 @@ describe("Peer Exchange", () => { waku = await createLightNode({ libp2p: { peerDiscovery: [ - bootstrap({ list: getPredefinedBootstrapNodes(Fleet.Test, 3) }), + bootstrap({ list: getPredefinedBootstrapNodes(Fleet.Prod, 3) }), wakuPeerExchangeDiscovery(), ], }, @@ -46,18 +46,18 @@ describe("Peer Exchange", () => { await waku.start(); - const foundPxPeer = await new Promise((resolve) => { - const testNodes = getPredefinedBootstrapNodes(Fleet.Test, 3); - waku.libp2p.addEventListener("peer:discovery", (evt) => { - const peerId = evt.detail.id.toString(); - const isBootstrapNode = testNodes.find((n) => n.includes(peerId)); - if (!isBootstrapNode) { - resolve(true); - } - }); - }); - - expect(foundPxPeer).to.be.true; + await delay(50_000); + + // const foundPxPeer = await new Promise((resolve) => { + // const testNodes = getPredefinedBootstrapNodes(Fleet.Test, 3); + // waku.libp2p.addEventListener("peer:discovery", (evt) => { + // const peerId = evt.detail.id.toString(); + // const isBootstrapNode = testNodes.find((n) => n.includes(peerId)); + // if (!isBootstrapNode) { + // resolve(true); + // } + // }); + // }); }); }); From fb8ae26c0550292861de885a2f4e8319f815ae12 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 15:32:43 +0530 Subject: [PATCH 08/16] rename peer event result interface --- packages/core/src/lib/connection_manager.ts | 4 ++-- packages/interfaces/src/connection_manager.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/lib/connection_manager.ts b/packages/core/src/lib/connection_manager.ts index 6715dd1e38..2c72b093a0 100644 --- a/packages/core/src/lib/connection_manager.ts +++ b/packages/core/src/lib/connection_manager.ts @@ -7,7 +7,7 @@ import { ConnectionManagerOptions, IRelay, PeerEvents, - PeersByDiscovery, + PeersByDiscoveryResult, } from "@waku/interfaces"; import { Libp2p, Tags } from "@waku/interfaces"; import debug from "debug"; @@ -52,7 +52,7 @@ export class ConnectionManager extends EventEmitter { return instance; } - public async getPeersByDiscovery(): Promise { + public async getPeersByDiscovery(): Promise { const peersDiscovered = await this.libp2p.peerStore.all(); const peersConnected = this.libp2p .getConnections() diff --git a/packages/interfaces/src/connection_manager.ts b/packages/interfaces/src/connection_manager.ts index 9fbb1c455a..ee7bfc7bfc 100644 --- a/packages/interfaces/src/connection_manager.ts +++ b/packages/interfaces/src/connection_manager.ts @@ -29,7 +29,7 @@ export enum PeerEvents { PEER_CONNECT_PEER_EXCHANGE = "peer:connected:peer-exchange", } -export interface PeersByDiscovery { +export interface PeersByDiscoveryResult { DISCOVERED: { [Tags.BOOTSTRAP]: Peer[]; [Tags.PEER_EXCHANGE]: Peer[]; From 5c6074c16f0ff36b5039f665bcc66ec3d8161d1b Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 17:18:40 +0530 Subject: [PATCH 09/16] switch to using libp2p EventEmitter --- packages/core/src/lib/connection_manager.ts | 47 +++++++++++++++---- packages/interfaces/src/connection_manager.ts | 10 +++- .../tests/tests/connection_manager.spec.ts | 40 +++++++++------- 3 files changed, 69 insertions(+), 28 deletions(-) diff --git a/packages/core/src/lib/connection_manager.ts b/packages/core/src/lib/connection_manager.ts index 2c72b093a0..1543d5150c 100644 --- a/packages/core/src/lib/connection_manager.ts +++ b/packages/core/src/lib/connection_manager.ts @@ -1,12 +1,13 @@ -import { EventEmitter } from "events"; - import type { PeerId } from "@libp2p/interface-peer-id"; import type { PeerInfo } from "@libp2p/interface-peer-info"; -import { Peer } from "@libp2p/interface-peer-store"; +import type { Peer } from "@libp2p/interface-peer-store"; +import { CustomEvent } from "@libp2p/interfaces/events"; +import { EventEmitter } from "@libp2p/interfaces/events"; import { ConnectionManagerOptions, + EPeersByDiscoveryEvents, + IPeersByDiscoveryEvents, IRelay, - PeerEvents, PeersByDiscoveryResult, } from "@waku/interfaces"; import { Libp2p, Tags } from "@waku/interfaces"; @@ -20,7 +21,7 @@ export const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1; export const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3; export const DEFAULT_MAX_PARALLEL_DIALS = 3; -export class ConnectionManager extends EventEmitter { +export class ConnectionManager extends EventEmitter { private static instances = new Map(); private keepAliveManager: KeepAliveManager; private options: ConnectionManagerOptions; @@ -298,9 +299,23 @@ export class ConnectionManager extends EventEmitter { ); if (isBootstrap) { - this.emit(PeerEvents.PEER_DISCOVERY_BOOTSTRAP, peerId); + this.dispatchEvent( + new CustomEvent( + EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP, + { + detail: peerId, + } + ) + ); } else { - this.emit(PeerEvents.PEER_DISCOVERY_PEER_EXCHANGE, peerId); + this.dispatchEvent( + new CustomEvent( + EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE, + { + detail: peerId, + } + ) + ); } try { @@ -331,10 +346,24 @@ export class ConnectionManager extends EventEmitter { ) { await this.dropConnection(peerId); } else { - this.emit(PeerEvents.PEER_CONNECT_BOOTSTRAP, peerId); + this.dispatchEvent( + new CustomEvent( + EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP, + { + detail: peerId, + } + ) + ); } } else { - this.emit(PeerEvents.PEER_CONNECT_PEER_EXCHANGE, peerId); + this.dispatchEvent( + new CustomEvent( + EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE, + { + detail: peerId, + } + ) + ); } })(); }, diff --git a/packages/interfaces/src/connection_manager.ts b/packages/interfaces/src/connection_manager.ts index ee7bfc7bfc..8814aefba6 100644 --- a/packages/interfaces/src/connection_manager.ts +++ b/packages/interfaces/src/connection_manager.ts @@ -1,3 +1,4 @@ +import type { PeerId } from "@libp2p/interface-peer-id"; import type { Peer } from "@libp2p/interface-peer-store"; export enum Tags { @@ -22,13 +23,20 @@ export interface ConnectionManagerOptions { maxParallelDials: number; } -export enum PeerEvents { +export enum EPeersByDiscoveryEvents { PEER_DISCOVERY_BOOTSTRAP = "peer:discovery:bootstrap", PEER_DISCOVERY_PEER_EXCHANGE = "peer:discovery:peer-exchange", PEER_CONNECT_BOOTSTRAP = "peer:connected:bootstrap", PEER_CONNECT_PEER_EXCHANGE = "peer:connected:peer-exchange", } +export interface IPeersByDiscoveryEvents { + [EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP]: CustomEvent; + [EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE]: CustomEvent; + [EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP]: CustomEvent; + [EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE]: CustomEvent; +} + export interface PeersByDiscoveryResult { DISCOVERED: { [Tags.BOOTSTRAP]: Peer[]; diff --git a/packages/tests/tests/connection_manager.spec.ts b/packages/tests/tests/connection_manager.spec.ts index 5fbbd5aefe..b9c82e9a66 100644 --- a/packages/tests/tests/connection_manager.spec.ts +++ b/packages/tests/tests/connection_manager.spec.ts @@ -1,7 +1,7 @@ import { CustomEvent } from "@libp2p/interfaces/events"; import { createSecp256k1PeerId } from "@libp2p/peer-id-factory"; import { ConnectionManager, KeepAliveOptions } from "@waku/core"; -import { LightNode, PeerEvents, Tags } from "@waku/interfaces"; +import { EPeersByDiscoveryEvents, LightNode, Tags } from "@waku/interfaces"; import { createLightNode } from "@waku/sdk"; import { expect } from "chai"; import sinon, { SinonSpy, SinonStub } from "sinon"; @@ -37,7 +37,7 @@ describe("ConnectionManager", function () { await waku.stop(); }); - describe("Events", () => { + describe.only("Events", () => { it("should emit `peer:discovery:{bootstrap/peer-exchange}` event when a peer is discovered", async function () { this.timeout(TEST_TIMEOUT); @@ -53,10 +53,12 @@ describe("ConnectionManager", function () { }); const peerDiscoveryEventPromise = new Promise((resolve) => { - connectionManager!.addListener( - PeerEvents.PEER_DISCOVERY_BOOTSTRAP, - (peerId) => { - expect(peerId.toString()).to.equal(peerIdBootstrap.toString()); + connectionManager!.addEventListener( + EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP, + ({ detail: receivedPeerId }) => { + expect(receivedPeerId.toString()).to.equal( + peerIdBootstrap.toString() + ); resolve(); } ); @@ -78,10 +80,10 @@ describe("ConnectionManager", function () { }); const peerDiscoveryEventPromise2 = new Promise((resolve) => { - connectionManager!.addListener( - PeerEvents.PEER_DISCOVERY_PEER_EXCHANGE, - (peerId) => { - expect(peerId.toString()).to.equal(peerIdPx.toString()); + connectionManager!.addEventListener( + EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE, + ({ detail: receivedPeerId }) => { + expect(receivedPeerId.toString()).to.equal(peerIdPx.toString()); resolve(); } ); @@ -107,10 +109,12 @@ describe("ConnectionManager", function () { }); const peerConnectedEventPromise = new Promise((resolve) => { - connectionManager!.addListener( - PeerEvents.PEER_CONNECT_BOOTSTRAP, - (peerId) => { - expect(peerId.toString()).to.equal(peerIdBootstrap.toString()); + connectionManager!.addEventListener( + EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP, + ({ detail: receivedPeerId }) => { + expect(receivedPeerId.toString()).to.equal( + peerIdBootstrap.toString() + ); resolve(); } ); @@ -134,10 +138,10 @@ describe("ConnectionManager", function () { }); const peerConnectedEventPromise2 = new Promise((resolve) => { - connectionManager!.addListener( - PeerEvents.PEER_CONNECT_PEER_EXCHANGE, - (peerId) => { - expect(peerId.toString()).to.equal(peerIdPx.toString()); + connectionManager!.addEventListener( + EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE, + ({ detail: receivedPeerId }) => { + expect(receivedPeerId.toString()).to.equal(peerIdPx.toString()); resolve(); } ); From 82b9239f3076aefd34ef756a95279cb0d63d91f5 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 17:22:10 +0530 Subject: [PATCH 10/16] rename variables for readability --- packages/tests/tests/connection_manager.spec.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/tests/tests/connection_manager.spec.ts b/packages/tests/tests/connection_manager.spec.ts index b9c82e9a66..566a6d9d31 100644 --- a/packages/tests/tests/connection_manager.spec.ts +++ b/packages/tests/tests/connection_manager.spec.ts @@ -52,7 +52,7 @@ describe("ConnectionManager", function () { }, }); - const peerDiscoveryEventPromise = new Promise((resolve) => { + const peerDiscoveryBootstrap = new Promise((resolve) => { connectionManager!.addEventListener( EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP, ({ detail: receivedPeerId }) => { @@ -66,7 +66,7 @@ describe("ConnectionManager", function () { waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerId })); - await peerDiscoveryEventPromise; + await peerDiscoveryBootstrap; const peerIdPx = await createSecp256k1PeerId(); @@ -79,7 +79,7 @@ describe("ConnectionManager", function () { }, }); - const peerDiscoveryEventPromise2 = new Promise((resolve) => { + const peerDiscoveryPeerExchange = new Promise((resolve) => { connectionManager!.addEventListener( EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE, ({ detail: receivedPeerId }) => { @@ -91,7 +91,7 @@ describe("ConnectionManager", function () { waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerIdPx })); - await peerDiscoveryEventPromise2; + await peerDiscoveryPeerExchange; }); it("should emit `peer:connected:{bootstrap/peer-exchange}` event when a peer is connected", async function () { @@ -108,7 +108,7 @@ describe("ConnectionManager", function () { }, }); - const peerConnectedEventPromise = new Promise((resolve) => { + const peerConnectedBootstrap = new Promise((resolve) => { connectionManager!.addEventListener( EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP, ({ detail: receivedPeerId }) => { @@ -124,7 +124,7 @@ describe("ConnectionManager", function () { new CustomEvent("peer:connect", { detail: peerIdBootstrap }) ); - await peerConnectedEventPromise; + await peerConnectedBootstrap; const peerIdPx = await createSecp256k1PeerId(); @@ -137,7 +137,7 @@ describe("ConnectionManager", function () { }, }); - const peerConnectedEventPromise2 = new Promise((resolve) => { + const peerConnectedPeerExchange = new Promise((resolve) => { connectionManager!.addEventListener( EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE, ({ detail: receivedPeerId }) => { @@ -151,7 +151,7 @@ describe("ConnectionManager", function () { new CustomEvent("peer:connect", { detail: peerIdPx }) ); - await peerConnectedEventPromise2; + await peerConnectedPeerExchange; }); }); From 81539c2761e0e6b91f482ed9d6af81870fc2e673 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 17:24:00 +0530 Subject: [PATCH 11/16] reset peer-exchange spec file --- .../tests/tests/peer_exchange.node.spec.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/tests/tests/peer_exchange.node.spec.ts b/packages/tests/tests/peer_exchange.node.spec.ts index 3c57f76b03..32913705a4 100644 --- a/packages/tests/tests/peer_exchange.node.spec.ts +++ b/packages/tests/tests/peer_exchange.node.spec.ts @@ -38,7 +38,7 @@ describe("Peer Exchange", () => { waku = await createLightNode({ libp2p: { peerDiscovery: [ - bootstrap({ list: getPredefinedBootstrapNodes(Fleet.Prod, 3) }), + bootstrap({ list: getPredefinedBootstrapNodes(Fleet.Test, 3) }), wakuPeerExchangeDiscovery(), ], }, @@ -46,18 +46,18 @@ describe("Peer Exchange", () => { await waku.start(); - await delay(50_000); - - // const foundPxPeer = await new Promise((resolve) => { - // const testNodes = getPredefinedBootstrapNodes(Fleet.Test, 3); - // waku.libp2p.addEventListener("peer:discovery", (evt) => { - // const peerId = evt.detail.id.toString(); - // const isBootstrapNode = testNodes.find((n) => n.includes(peerId)); - // if (!isBootstrapNode) { - // resolve(true); - // } - // }); - // }); + const foundPxPeer = await new Promise((resolve) => { + const testNodes = getPredefinedBootstrapNodes(Fleet.Test, 3); + waku.libp2p.addEventListener("peer:discovery", (evt) => { + const peerId = evt.detail.id.toString(); + const isBootstrapNode = testNodes.find((n) => n.includes(peerId)); + if (!isBootstrapNode) { + resolve(true); + } + }); + }); + + expect(foundPxPeer).to.be.true; }); }); From fc07c9ae37c83eb08217cc9a78aeb3fd7955be1b Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 17:34:47 +0530 Subject: [PATCH 12/16] address review --- .../tests/tests/connection_manager.spec.ts | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/tests/tests/connection_manager.spec.ts b/packages/tests/tests/connection_manager.spec.ts index 566a6d9d31..65f39751b8 100644 --- a/packages/tests/tests/connection_manager.spec.ts +++ b/packages/tests/tests/connection_manager.spec.ts @@ -52,21 +52,18 @@ describe("ConnectionManager", function () { }, }); - const peerDiscoveryBootstrap = new Promise((resolve) => { + const peerDiscoveryBootstrap = new Promise((resolve) => { connectionManager!.addEventListener( EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP, ({ detail: receivedPeerId }) => { - expect(receivedPeerId.toString()).to.equal( - peerIdBootstrap.toString() - ); - resolve(); + resolve(receivedPeerId.toString() === peerIdBootstrap.toString()); } ); }); waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerId })); - await peerDiscoveryBootstrap; + expect(await peerDiscoveryBootstrap).to.eq(true); const peerIdPx = await createSecp256k1PeerId(); @@ -79,19 +76,18 @@ describe("ConnectionManager", function () { }, }); - const peerDiscoveryPeerExchange = new Promise((resolve) => { + const peerDiscoveryPeerExchange = new Promise((resolve) => { connectionManager!.addEventListener( EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE, ({ detail: receivedPeerId }) => { - expect(receivedPeerId.toString()).to.equal(peerIdPx.toString()); - resolve(); + resolve(receivedPeerId.toString() === peerIdPx.toString()); } ); }); waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerIdPx })); - await peerDiscoveryPeerExchange; + expect(await peerDiscoveryPeerExchange).to.eq(true); }); it("should emit `peer:connected:{bootstrap/peer-exchange}` event when a peer is connected", async function () { @@ -108,14 +104,11 @@ describe("ConnectionManager", function () { }, }); - const peerConnectedBootstrap = new Promise((resolve) => { + const peerConnectedBootstrap = new Promise((resolve) => { connectionManager!.addEventListener( EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP, ({ detail: receivedPeerId }) => { - expect(receivedPeerId.toString()).to.equal( - peerIdBootstrap.toString() - ); - resolve(); + resolve(receivedPeerId.toString() === peerIdBootstrap.toString()); } ); }); @@ -124,7 +117,7 @@ describe("ConnectionManager", function () { new CustomEvent("peer:connect", { detail: peerIdBootstrap }) ); - await peerConnectedBootstrap; + expect(await peerConnectedBootstrap).to.eq(true); const peerIdPx = await createSecp256k1PeerId(); @@ -137,12 +130,11 @@ describe("ConnectionManager", function () { }, }); - const peerConnectedPeerExchange = new Promise((resolve) => { + const peerConnectedPeerExchange = new Promise((resolve) => { connectionManager!.addEventListener( EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE, ({ detail: receivedPeerId }) => { - expect(receivedPeerId.toString()).to.equal(peerIdPx.toString()); - resolve(); + resolve(receivedPeerId.toString() === peerIdPx.toString()); } ); }); @@ -151,7 +143,7 @@ describe("ConnectionManager", function () { new CustomEvent("peer:connect", { detail: peerIdPx }) ); - await peerConnectedPeerExchange; + expect(await peerConnectedPeerExchange).to.eq(true); }); }); From dae61fa3f1fc6987d5b5144e129ad991147a8119 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 17:52:32 +0530 Subject: [PATCH 13/16] test: minor refactor --- packages/tests/tests/connection_manager.spec.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/tests/tests/connection_manager.spec.ts b/packages/tests/tests/connection_manager.spec.ts index 65f39751b8..df7abf4e26 100644 --- a/packages/tests/tests/connection_manager.spec.ts +++ b/packages/tests/tests/connection_manager.spec.ts @@ -19,9 +19,6 @@ describe("ConnectionManager", function () { let connectionManager: ConnectionManager | undefined; let waku: LightNode; let peerId: string; - let getConnectionsStub: SinonStub; - let getTagNamesForPeerStub: SinonStub; - let dialPeerStub: SinonStub; beforeEach(async function () { waku = await createLightNode(); @@ -37,7 +34,7 @@ describe("ConnectionManager", function () { await waku.stop(); }); - describe.only("Events", () => { + describe("Events", () => { it("should emit `peer:discovery:{bootstrap/peer-exchange}` event when a peer is discovered", async function () { this.timeout(TEST_TIMEOUT); @@ -148,6 +145,10 @@ describe("ConnectionManager", function () { }); describe("Testing Dials", () => { + let dialPeerStub: SinonStub; + let getConnectionsStub: SinonStub; + let getTagNamesForPeerStub: SinonStub; + afterEach(() => { sinon.restore(); }); @@ -173,6 +174,9 @@ describe("ConnectionManager", function () { ); } + // add delay to allow async function calls within attemptDial to finish + await delay(100); + expect(attemptDialSpy.callCount).to.equal( totalPeerIds, "attemptDial should be called once for each peer:discovery event" From 9d2821360a67374200c245c43f5993c909583736 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 18:54:36 +0530 Subject: [PATCH 14/16] fix: failing test --- packages/tests/tests/connection_manager.spec.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/tests/tests/connection_manager.spec.ts b/packages/tests/tests/connection_manager.spec.ts index df7abf4e26..68a60e5f61 100644 --- a/packages/tests/tests/connection_manager.spec.ts +++ b/packages/tests/tests/connection_manager.spec.ts @@ -213,9 +213,11 @@ describe("ConnectionManager", function () { // simulate that the peer is a bootstrap peer getTagNamesForPeerStub.resolves([Tags.BOOTSTRAP]); + const bootstrapPeer = await createSecp256k1PeerId(); + // emit a peer:discovery event waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { detail: "bootstrap-peer" }) + new CustomEvent("peer:discovery", { detail: bootstrapPeer }) ); // wait for the async function calls within attemptDial to finish @@ -241,6 +243,7 @@ describe("ConnectionManager", function () { waku.libp2p.dispatchEvent( new CustomEvent("peer:discovery", { detail: "bootstrap-peer" }) ); + await delay(500); // simulate that the peer is connected getConnectionsStub.returns([{ tags: [{ name: Tags.BOOTSTRAP }] }]); @@ -251,7 +254,7 @@ describe("ConnectionManager", function () { await delay(500); waku.libp2p.dispatchEvent( new CustomEvent("peer:discovery", { - detail: `bootstrap-peer-id-${i}`, + detail: await createSecp256k1PeerId(), }) ); } @@ -274,9 +277,11 @@ describe("ConnectionManager", function () { // simulate that the peer has a PEER_EXCHANGE tag getTagNamesForPeerStub.resolves([Tags.PEER_EXCHANGE]); + const pxPeer = await createSecp256k1PeerId(); + // emit a peer:discovery event waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { detail: "px-peer" }) + new CustomEvent("peer:discovery", { detail: pxPeer }) ); // wait for the async function calls within attemptDial to finish @@ -302,7 +307,9 @@ describe("ConnectionManager", function () { const totalPxPeers = 5; for (let i = 0; i < totalPxPeers; i++) { waku.libp2p.dispatchEvent( - new CustomEvent("peer:discovery", { detail: `px-peer-id-${i}` }) + new CustomEvent("peer:discovery", { + detail: await createSecp256k1PeerId(), + }) ); await delay(500); } From ba03bc3dbcc40f3be24bd1a58de503a2c629a416 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 18:56:30 +0530 Subject: [PATCH 15/16] increase peer IDs to test against for attemptDial --- packages/tests/tests/connection_manager.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/tests/tests/connection_manager.spec.ts b/packages/tests/tests/connection_manager.spec.ts index 68a60e5f61..4c8b1f2cce 100644 --- a/packages/tests/tests/connection_manager.spec.ts +++ b/packages/tests/tests/connection_manager.spec.ts @@ -15,7 +15,7 @@ const KEEP_ALIVE_OPTIONS: KeepAliveOptions = { const TEST_TIMEOUT = 10_000; const DELAY_MS = 1_000; -describe("ConnectionManager", function () { +describe.only("ConnectionManager", function () { let connectionManager: ConnectionManager | undefined; let waku: LightNode; let peerId: string; @@ -167,7 +167,7 @@ describe("ConnectionManager", function () { it("should be called on all `peer:discovery` events", async function () { this.timeout(TEST_TIMEOUT); - const totalPeerIds = 1; + const totalPeerIds = 5; for (let i = 1; i <= totalPeerIds; i++) { waku.libp2p.dispatchEvent( new CustomEvent("peer:discovery", { detail: `peer-id-${i}` }) From 9d777c93b35e83363bf8017b7a5ec6887463cba5 Mon Sep 17 00:00:00 2001 From: danisharora099 Date: Wed, 26 Jul 2023 22:44:29 +0530 Subject: [PATCH 16/16] improve structuring --- packages/core/src/lib/connection_manager.ts | 3 +- .../tests/tests/connection_manager.spec.ts | 177 +++++++++--------- 2 files changed, 94 insertions(+), 86 deletions(-) diff --git a/packages/core/src/lib/connection_manager.ts b/packages/core/src/lib/connection_manager.ts index 1543d5150c..9bf978ab7b 100644 --- a/packages/core/src/lib/connection_manager.ts +++ b/packages/core/src/lib/connection_manager.ts @@ -1,8 +1,7 @@ import type { PeerId } from "@libp2p/interface-peer-id"; import type { PeerInfo } from "@libp2p/interface-peer-info"; import type { Peer } from "@libp2p/interface-peer-store"; -import { CustomEvent } from "@libp2p/interfaces/events"; -import { EventEmitter } from "@libp2p/interfaces/events"; +import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events"; import { ConnectionManagerOptions, EPeersByDiscoveryEvents, diff --git a/packages/tests/tests/connection_manager.spec.ts b/packages/tests/tests/connection_manager.spec.ts index 4c8b1f2cce..d00a61aa60 100644 --- a/packages/tests/tests/connection_manager.spec.ts +++ b/packages/tests/tests/connection_manager.spec.ts @@ -15,7 +15,7 @@ const KEEP_ALIVE_OPTIONS: KeepAliveOptions = { const TEST_TIMEOUT = 10_000; const DELAY_MS = 1_000; -describe.only("ConnectionManager", function () { +describe("ConnectionManager", function () { let connectionManager: ConnectionManager | undefined; let waku: LightNode; let peerId: string; @@ -35,116 +35,125 @@ describe.only("ConnectionManager", function () { }); describe("Events", () => { - it("should emit `peer:discovery:{bootstrap/peer-exchange}` event when a peer is discovered", async function () { - this.timeout(TEST_TIMEOUT); + describe("peer:discovery", () => { + it("should emit `peer:discovery:bootstrap` event when a peer is discovered", async function () { + this.timeout(TEST_TIMEOUT); - const peerIdBootstrap = await createSecp256k1PeerId(); + const peerIdBootstrap = await createSecp256k1PeerId(); - await waku.libp2p.peerStore.save(peerIdBootstrap, { - tags: { - [Tags.BOOTSTRAP]: { - value: 50, - ttl: 1200000, + await waku.libp2p.peerStore.save(peerIdBootstrap, { + tags: { + [Tags.BOOTSTRAP]: { + value: 50, + ttl: 1200000, + }, }, - }, - }); + }); - const peerDiscoveryBootstrap = new Promise((resolve) => { - connectionManager!.addEventListener( - EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP, - ({ detail: receivedPeerId }) => { - resolve(receivedPeerId.toString() === peerIdBootstrap.toString()); - } - ); - }); + const peerDiscoveryBootstrap = new Promise((resolve) => { + connectionManager!.addEventListener( + EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP, + ({ detail: receivedPeerId }) => { + resolve(receivedPeerId.toString() === peerIdBootstrap.toString()); + } + ); + }); - waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerId })); + waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerId })); - expect(await peerDiscoveryBootstrap).to.eq(true); + expect(await peerDiscoveryBootstrap).to.eq(true); + }); - const peerIdPx = await createSecp256k1PeerId(); + it("should emit `peer:discovery:peer-exchange` event when a peer is discovered", async function () { + const peerIdPx = await createSecp256k1PeerId(); - await waku.libp2p.peerStore.save(peerIdPx, { - tags: { - [Tags.PEER_EXCHANGE]: { - value: 50, - ttl: 1200000, + await waku.libp2p.peerStore.save(peerIdPx, { + tags: { + [Tags.PEER_EXCHANGE]: { + value: 50, + ttl: 1200000, + }, }, - }, - }); + }); - const peerDiscoveryPeerExchange = new Promise((resolve) => { - connectionManager!.addEventListener( - EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE, - ({ detail: receivedPeerId }) => { - resolve(receivedPeerId.toString() === peerIdPx.toString()); - } - ); - }); + const peerDiscoveryPeerExchange = new Promise((resolve) => { + connectionManager!.addEventListener( + EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE, + ({ detail: receivedPeerId }) => { + resolve(receivedPeerId.toString() === peerIdPx.toString()); + } + ); + }); - waku.libp2p.dispatchEvent(new CustomEvent("peer", { detail: peerIdPx })); + waku.libp2p.dispatchEvent( + new CustomEvent("peer", { detail: peerIdPx }) + ); - expect(await peerDiscoveryPeerExchange).to.eq(true); + expect(await peerDiscoveryPeerExchange).to.eq(true); + }); }); - it("should emit `peer:connected:{bootstrap/peer-exchange}` event when a peer is connected", async function () { - this.timeout(TEST_TIMEOUT); + describe("peer:connect", () => { + it("should emit `peer:connected:bootstrap` event when a peer is connected", async function () { + this.timeout(TEST_TIMEOUT); - const peerIdBootstrap = await createSecp256k1PeerId(); + const peerIdBootstrap = await createSecp256k1PeerId(); - await waku.libp2p.peerStore.save(peerIdBootstrap, { - tags: { - [Tags.BOOTSTRAP]: { - value: 50, - ttl: 1200000, + await waku.libp2p.peerStore.save(peerIdBootstrap, { + tags: { + [Tags.BOOTSTRAP]: { + value: 50, + ttl: 1200000, + }, }, - }, - }); - - const peerConnectedBootstrap = new Promise((resolve) => { - connectionManager!.addEventListener( - EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP, - ({ detail: receivedPeerId }) => { - resolve(receivedPeerId.toString() === peerIdBootstrap.toString()); - } - ); - }); - - waku.libp2p.dispatchEvent( - new CustomEvent("peer:connect", { detail: peerIdBootstrap }) - ); + }); - expect(await peerConnectedBootstrap).to.eq(true); + const peerConnectedBootstrap = new Promise((resolve) => { + connectionManager!.addEventListener( + EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP, + ({ detail: receivedPeerId }) => { + resolve(receivedPeerId.toString() === peerIdBootstrap.toString()); + } + ); + }); - const peerIdPx = await createSecp256k1PeerId(); + waku.libp2p.dispatchEvent( + new CustomEvent("peer:connect", { detail: peerIdBootstrap }) + ); - await waku.libp2p.peerStore.save(peerIdPx, { - tags: { - [Tags.PEER_EXCHANGE]: { - value: 50, - ttl: 1200000, - }, - }, + expect(await peerConnectedBootstrap).to.eq(true); }); + it("should emit `peer:connected:peer-exchange` event when a peer is connected", async function () { + const peerIdPx = await createSecp256k1PeerId(); + + await waku.libp2p.peerStore.save(peerIdPx, { + tags: { + [Tags.PEER_EXCHANGE]: { + value: 50, + ttl: 1200000, + }, + }, + }); - const peerConnectedPeerExchange = new Promise((resolve) => { - connectionManager!.addEventListener( - EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE, - ({ detail: receivedPeerId }) => { - resolve(receivedPeerId.toString() === peerIdPx.toString()); - } - ); - }); + const peerConnectedPeerExchange = new Promise((resolve) => { + connectionManager!.addEventListener( + EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE, + ({ detail: receivedPeerId }) => { + resolve(receivedPeerId.toString() === peerIdPx.toString()); + } + ); + }); - waku.libp2p.dispatchEvent( - new CustomEvent("peer:connect", { detail: peerIdPx }) - ); + waku.libp2p.dispatchEvent( + new CustomEvent("peer:connect", { detail: peerIdPx }) + ); - expect(await peerConnectedPeerExchange).to.eq(true); + expect(await peerConnectedPeerExchange).to.eq(true); + }); }); }); - describe("Testing Dials", () => { + describe("Dials", () => { let dialPeerStub: SinonStub; let getConnectionsStub: SinonStub; let getTagNamesForPeerStub: SinonStub;