From 098c17a6807efa6c25e87f666e2410bd47910ec2 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Sun, 16 Apr 2023 16:36:22 +0200 Subject: [PATCH 01/10] feat: add event bus Adds an event emitter as a libp2p component that will echo every emitted event on the main libp2p object. Fixes #1574 --- src/components.ts | 18 ++++++++++++++++++ src/libp2p.ts | 14 ++++++++++++++ src/transport-manager.ts | 4 ++++ 3 files changed, 36 insertions(+) diff --git a/src/components.ts b/src/components.ts index 156e4abdde..4a8f5243ac 100644 --- a/src/components.ts +++ b/src/components.ts @@ -14,9 +14,12 @@ import type { PubSub } from '@libp2p/interface-pubsub' import type { DualDHT } from '@libp2p/interface-dht' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { ConnectionGater } from '@libp2p/interface-connection-gater' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' +import type { EventEmitter } from '@libp2p/interfaces/events' export interface Components { peerId: PeerId + events: EventEmitter addressManager: AddressManager peerStore: PeerStore upgrader: Upgrader @@ -35,6 +38,7 @@ export interface Components { export interface ComponentsInit { peerId?: PeerId + events?: EventEmitter addressManager?: AddressManager peerStore?: PeerStore upgrader?: Upgrader @@ -53,6 +57,7 @@ export interface ComponentsInit { export class DefaultComponents implements Components, Startable { private _peerId?: PeerId + private _events?: EventEmitter private _addressManager?: AddressManager private _peerStore?: PeerStore private _upgrader?: Upgrader @@ -71,6 +76,7 @@ export class DefaultComponents implements Components, Startable { constructor (init: ComponentsInit = {}) { this._peerId = init.peerId + this._events = init.events this._addressManager = init.addressManager this._peerStore = init.peerStore this._upgrader = init.upgrader @@ -163,6 +169,18 @@ export class DefaultComponents implements Components, Startable { this._peerId = peerId } + get events (): EventEmitter { + if (this._events == null) { + throw new CodeError('events not set', 'ERR_SERVICE_MISSING') + } + + return this._events + } + + set events (events: EventEmitter) { + this._events = events + } + get addressManager (): AddressManager { if (this._addressManager == null) { throw new CodeError('addressManager not set', 'ERR_SERVICE_MISSING') diff --git a/src/libp2p.ts b/src/libp2p.ts index 5cd345bd21..6f7607e79f 100644 --- a/src/libp2p.ts +++ b/src/libp2p.ts @@ -86,10 +86,24 @@ export class Libp2pNode extends EventEmitter implements Libp2p { constructor (init: Libp2pInit) { super() + // event bus - components can listen to this emitter to be notified of system events + // and also cause them to be emitted + const events = new EventEmitter() + const originalDispatch = events.dispatchEvent.bind(events) + events.dispatchEvent = (evt: any) => { + const internalResult = originalDispatch(evt) + const externalResult = this.dispatchEvent( + new CustomEvent(evt.type, { detail: evt.detail }) + ) + + return internalResult || externalResult + } + this.started = false this.peerId = init.peerId const components = this.components = new DefaultComponents({ peerId: init.peerId, + events, datastore: init.datastore ?? new MemoryDatastore(), connectionGater: { denyDialPeer: async () => await Promise.resolve(false), diff --git a/src/transport-manager.ts b/src/transport-manager.ts index 7ed1609e23..276b42213c 100644 --- a/src/transport-manager.ts +++ b/src/transport-manager.ts @@ -11,6 +11,7 @@ import type { Startable } from '@libp2p/interfaces/startable' import { trackedMap } from '@libp2p/tracked-map' import type { Metrics } from '@libp2p/interface-metrics' import type { AddressManager } from '@libp2p/interface-address-manager' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:transports') @@ -22,6 +23,7 @@ export interface DefaultTransportManagerComponents { metrics?: Metrics addressManager: AddressManager upgrader: Upgrader + events: EventEmitter } export class DefaultTransportManager extends EventEmitter implements TransportManager, Startable { @@ -237,6 +239,8 @@ export class DefaultTransportManager extends EventEmitter Date: Mon, 17 Apr 2023 09:13:57 +0200 Subject: [PATCH 02/10] chore: pull events from interfaces --- src/index.ts | 18 ------------------ src/libp2p.ts | 3 ++- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/index.ts b/src/index.ts index 60be8248a6..eefb49aede 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,7 +32,6 @@ import type { PeerRouting } from '@libp2p/interface-peer-routing' import type { ContentRouting } from '@libp2p/interface-content-routing' import type { PubSub } from '@libp2p/interface-pubsub' import type { Metrics } from '@libp2p/interface-metrics' -import type { PeerInfo } from '@libp2p/interface-peer-info' import type { PingServiceInit } from './ping/index.js' import type { FetchServiceInit } from './fetch/index.js' import type { AutonatServiceInit } from './autonat/index.js' @@ -158,23 +157,6 @@ export interface Libp2pInit { connectionProtector?: (components: Components) => ConnectionProtector } -/** - * Once you have a libp2p instance, you can listen to several events it emits, so that you can be notified of relevant network events. - */ -export interface Libp2pEvents { - /** - * @example - * - * ```js - * libp2p.addEventListener('peer:discovery', (event) => { - * const peerInfo = event.detail - * // ... - * }) - * ``` - */ - 'peer:discovery': CustomEvent -} - export type { Libp2p } export type Libp2pOptions = RecursivePartial & { start?: boolean } diff --git a/src/libp2p.ts b/src/libp2p.ts index 6f7607e79f..22a959e5b4 100644 --- a/src/libp2p.ts +++ b/src/libp2p.ts @@ -32,7 +32,7 @@ import type { PubSub } from '@libp2p/interface-pubsub' import type { Registrar, StreamHandler, StreamHandlerOptions, Topology } from '@libp2p/interface-registrar' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { PeerInfo } from '@libp2p/interface-peer-info' -import type { Libp2p, Libp2pEvents, Libp2pInit, Libp2pOptions } from './index.js' +import type { Libp2p, Libp2pInit, Libp2pOptions } from './index.js' import { validateConfig } from './config.js' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import type { PeerStore } from '@libp2p/interface-peer-store' @@ -50,6 +50,7 @@ import type { Datastore } from 'interface-datastore' import type { KeyChain } from '@libp2p/interface-keychain' import mergeOptions from 'merge-options' import type { CircuitRelayService } from './circuit-relay/index.js' +import { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p') From 462fb0ab45f58dcba59fe6d6b9b0b0bfbd7f4078 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 20 Apr 2023 16:41:52 +0100 Subject: [PATCH 03/10] chore: update code to use event bus --- src/address-manager/index.ts | 18 +++--- src/circuit-relay/server/advert-service.ts | 4 +- src/circuit-relay/server/index.ts | 4 +- src/circuit-relay/transport/index.ts | 8 ++- src/circuit-relay/transport/listener.ts | 12 ++-- .../transport/reservation-store.ts | 10 +++- src/connection-manager/auto-dial.ts | 11 ++++ src/connection-manager/connection-pruner.ts | 18 +++++- src/connection-manager/index.ts | 55 +++++++------------ src/content-routing/index.ts | 2 +- src/identify/index.ts | 7 ++- src/libp2p.ts | 20 +++---- src/peer-record-updater.ts | 17 +++--- src/registrar.ts | 29 +++++----- src/transport-manager.ts | 22 ++++---- src/upgrader.ts | 20 ++++--- test/addresses/address-manager.spec.ts | 53 ++++++++++-------- test/circuit-relay/hop.spec.ts | 16 ++++-- test/circuit-relay/stop.spec.ts | 4 +- test/connection-manager/auto-dial.spec.ts | 4 +- test/connection-manager/direct.spec.ts | 6 +- test/connection-manager/index.node.ts | 38 ++++++------- test/connection-manager/index.spec.ts | 50 ++++++++++------- test/core/consume-peer-record.spec.ts | 5 +- test/fetch/index.spec.ts | 13 +++-- test/identify/index.spec.ts | 21 +++---- test/identify/push.spec.ts | 21 +++---- test/identify/service.spec.ts | 4 +- test/nat-manager/nat-manager.node.ts | 6 +- test/ping/index.spec.ts | 13 +++-- test/registrar/registrar.spec.ts | 51 ++++++++++------- test/upgrading/upgrader.spec.ts | 49 +++++++++-------- 32 files changed, 342 insertions(+), 269 deletions(-) diff --git a/src/address-manager/index.ts b/src/address-manager/index.ts index 35834b3b0c..7344ddbcf8 100644 --- a/src/address-manager/index.ts +++ b/src/address-manager/index.ts @@ -1,10 +1,12 @@ -import type { AddressManagerEvents } from '@libp2p/interface-address-manager' -import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events' import type { Multiaddr } from '@multiformats/multiaddr' import { multiaddr } from '@multiformats/multiaddr' import { peerIdFromString } from '@libp2p/peer-id' import type { PeerId } from '@libp2p/interface-peer-id' import type { TransportManager } from '@libp2p/interface-transport' +import type { PeerStore } from '@libp2p/interface-peer-store' +import { logger } from '@libp2p/logger' + +const log = logger('libp2p:address-manager') export interface AddressManagerInit { /** @@ -32,6 +34,7 @@ export interface AddressManagerInit { export interface DefaultAddressManagerComponents { peerId: PeerId transportManager: TransportManager + peerStore: PeerStore } /** @@ -67,7 +70,7 @@ function stripPeerId (ma: Multiaddr, peerId: PeerId): Multiaddr { return ma } -export class DefaultAddressManager extends EventEmitter { +export class DefaultAddressManager { private readonly components: DefaultAddressManagerComponents // this is an array to allow for duplicates, e.g. multiples of `/ip4/0.0.0.0/tcp/0` private readonly listen: string[] @@ -81,9 +84,7 @@ export class DefaultAddressManager extends EventEmitter { * The listen addresses will be used by the libp2p transports to listen for new connections, * while the announce addresses will be used for the peer addresses' to other peers in the network. */ - constructor (components: DefaultAddressManagerComponents, init: AddressManagerInit) { - super() - + constructor (components: DefaultAddressManagerComponents, init: AddressManagerInit = {}) { const { listen = [], announce = [] } = init this.components = components @@ -145,9 +146,10 @@ export class DefaultAddressManager extends EventEmitter { confident: true }) - // only trigger the change:addresses event if our confidence in an address has changed + // only trigger the 'self:peer:update' event if our confidence in an address has changed if (!startingConfidence) { - this.dispatchEvent(new CustomEvent('change:addresses')) + this.components.peerStore.addressBook.set(this.components.peerId, this.getAddresses()) + .catch(err => { log.error('error updating addresses', err) }) } } diff --git a/src/circuit-relay/server/advert-service.ts b/src/circuit-relay/server/advert-service.ts index e9a942870a..259de01fb9 100644 --- a/src/circuit-relay/server/advert-service.ts +++ b/src/circuit-relay/server/advert-service.ts @@ -7,7 +7,7 @@ import { } from '../constants.js' import type { Startable } from '@libp2p/interfaces/startable' import type { ContentRouting } from '@libp2p/interface-content-routing' -import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import pRetry from 'p-retry' const log = logger('libp2p:circuit-relay:advert-service') @@ -90,7 +90,7 @@ export class AdvertService extends EventEmitter implements const cid = await namespaceToCid(RELAY_RENDEZVOUS_NS) await this.contentRouting.provide(cid) - this.dispatchEvent(new CustomEvent('advert:success')) + this.safeDispatchEvent('advert:success', { detail: undefined }) } catch (err: any) { this.safeDispatchEvent('advert:error', { detail: err }) diff --git a/src/circuit-relay/server/index.ts b/src/circuit-relay/server/index.ts index 2f82575f75..83482696ae 100644 --- a/src/circuit-relay/server/index.ts +++ b/src/circuit-relay/server/index.ts @@ -24,7 +24,7 @@ import { ReservationVoucherRecord } from './reservation-voucher.js' import type { AddressManager } from '@libp2p/interface-address-manager' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { CircuitRelayService, RelayReservation } from '../index.js' -import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import { setMaxListeners } from 'events' import type { PeerMap } from '@libp2p/peer-collections' @@ -128,7 +128,7 @@ class CircuitRelayServer extends EventEmitter implements Star if (init.advertise != null && init.advertise !== false) { this.advertService = new AdvertService(components, init.advertise === true ? undefined : init.advertise) this.advertService.addEventListener('advert:success', () => { - this.dispatchEvent(new CustomEvent('relay:advert:success')) + this.safeDispatchEvent('relay:advert:success', {}) }) this.advertService.addEventListener('advert:error', (evt) => { this.safeDispatchEvent('relay:advert:error', { detail: evt.detail }) diff --git a/src/circuit-relay/transport/index.ts b/src/circuit-relay/transport/index.ts index d95233ee36..2bbf3e3246 100644 --- a/src/circuit-relay/transport/index.ts +++ b/src/circuit-relay/transport/index.ts @@ -23,6 +23,8 @@ import { CIRCUIT_PROTO_CODE, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC } from '../ import { RelayStoreInit, ReservationStore } from './reservation-store.js' import { RelayDiscovery, RelayDiscoveryComponents } from './discovery.js' import { CodeError } from '@libp2p/interfaces/errors' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:circuit-relay:transport') @@ -49,6 +51,7 @@ export interface CircuitRelayTransportComponents extends RelayDiscoveryComponent addressManager: AddressManager contentRouting: ContentRouting connectionGater: ConnectionGater + events: EventEmitter } interface ConnectOptions { @@ -81,6 +84,7 @@ class CircuitRelayTransport implements Transport { private readonly upgrader: Upgrader private readonly addressManager: AddressManager private readonly connectionGater: ConnectionGater + private readonly events: EventEmitter private readonly reservationStore: ReservationStore private started: boolean @@ -92,6 +96,7 @@ class CircuitRelayTransport implements Transport { this.upgrader = components.upgrader this.addressManager = components.addressManager this.connectionGater = components.connectionGater + this.events = components.events if (init.discoverRelays != null && init.discoverRelays > 0) { this.discovery = new RelayDiscovery(components) @@ -249,7 +254,8 @@ class CircuitRelayTransport implements Transport { createListener (options: CreateListenerOptions): Listener { return createListener({ connectionManager: this.connectionManager, - relayStore: this.reservationStore + relayStore: this.reservationStore, + events: this.events }) } diff --git a/src/circuit-relay/transport/listener.ts b/src/circuit-relay/transport/listener.ts index 2e5196a3c1..2e36a1468d 100644 --- a/src/circuit-relay/transport/listener.ts +++ b/src/circuit-relay/transport/listener.ts @@ -1,4 +1,4 @@ -import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { Listener, ListenerEvents } from '@libp2p/interface-transport' import type { Multiaddr } from '@multiformats/multiaddr' @@ -7,24 +7,28 @@ import type { ReservationStore } from './reservation-store.js' import type { PeerId } from '@libp2p/interface-peer-id' import { PeerMap } from '@libp2p/peer-collections' import { logger } from '@libp2p/logger' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:circuit-relay:transport:listener') export interface CircuitRelayTransportListenerComponents { connectionManager: ConnectionManager relayStore: ReservationStore + events: EventEmitter } class CircuitRelayTransportListener extends EventEmitter implements Listener { private readonly connectionManager: ConnectionManager private readonly relayStore: ReservationStore private readonly listeningAddrs: PeerMap + private readonly events: EventEmitter constructor (components: CircuitRelayTransportListenerComponents) { super() this.connectionManager = components.connectionManager this.relayStore = components.relayStore + this.events = components.events this.listeningAddrs = new PeerMap() // remove listening addrs when a relay is removed @@ -33,7 +37,7 @@ class CircuitRelayTransportListener extends EventEmitter impleme }) // remove listening addrs when a peer disconnects - this.connectionManager.addEventListener('peer:disconnect', (evt) => { + this.events.addEventListener('connection:close', (evt) => { this.#removeRelayPeer(evt.detail.remotePeer) }) } @@ -57,7 +61,7 @@ class CircuitRelayTransportListener extends EventEmitter impleme } this.listeningAddrs.set(relayConn.remotePeer, addr) - this.dispatchEvent(new CustomEvent('listening')) + this.safeDispatchEvent('listening', {}) } /** @@ -89,7 +93,7 @@ class CircuitRelayTransportListener extends EventEmitter impleme if (had) { // Announce listen addresses change - this.dispatchEvent(new CustomEvent('close')) + this.safeDispatchEvent('close', {}) } } } diff --git a/src/circuit-relay/transport/reservation-store.ts b/src/circuit-relay/transport/reservation-store.ts index 047c3ec613..1e815b675d 100644 --- a/src/circuit-relay/transport/reservation-store.ts +++ b/src/circuit-relay/transport/reservation-store.ts @@ -11,9 +11,10 @@ import { HopMessage, Status } from '../pb/index.js' import { getExpirationMilliseconds } from '../utils.js' import type { TransportManager } from '@libp2p/interface-transport' import type { Startable } from '@libp2p/interfaces/startable' -import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import type { PeerStore } from '@libp2p/interface-peer-store' import { multiaddr } from '@multiformats/multiaddr' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:circuit-relay:transport:reservation-store') @@ -31,6 +32,7 @@ export interface RelayStoreComponents { connectionManager: ConnectionManager transportManager: TransportManager peerStore: PeerStore + events: EventEmitter } export interface RelayStoreInit { @@ -68,6 +70,7 @@ export class ReservationStore extends EventEmitter imple private readonly connectionManager: ConnectionManager private readonly transportManager: TransportManager private readonly peerStore: PeerStore + private readonly events: EventEmitter private readonly reserveQueue: PQueue private readonly reservations: PeerMap private readonly maxDiscoveredRelays: number @@ -80,6 +83,7 @@ export class ReservationStore extends EventEmitter imple this.connectionManager = components.connectionManager this.transportManager = components.transportManager this.peerStore = components.peerStore + this.events = components.events this.reservations = new PeerMap() this.maxDiscoveredRelays = init?.discoverRelays ?? 0 this.started = false @@ -92,7 +96,7 @@ export class ReservationStore extends EventEmitter imple // When a peer disconnects, if we had a reservation on that peer // remove the reservation and multiaddr and maybe trigger search // for new relays - this.connectionManager.addEventListener('peer:disconnect', (evt) => { + this.events.addEventListener('connection:close', (evt) => { this.removeRelay(evt.detail.remotePeer) }) } @@ -250,7 +254,7 @@ export class ReservationStore extends EventEmitter imple this.safeDispatchEvent('relay:removed', { detail: peerId }) if (this.reservations.size < this.maxDiscoveredRelays) { - this.dispatchEvent(new CustomEvent('relay:not-enough-relays')) + this.safeDispatchEvent('relay:not-enough-relays', {}) } } } diff --git a/src/connection-manager/auto-dial.ts b/src/connection-manager/auto-dial.ts index cbbf98ffdf..b25f85fafa 100644 --- a/src/connection-manager/auto-dial.ts +++ b/src/connection-manager/auto-dial.ts @@ -5,6 +5,8 @@ import { PeerMap } from '@libp2p/peer-collections' import PQueue from 'p-queue' import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_INTERVAL, AUTO_DIAL_PRIORITY, MIN_CONNECTIONS } from './constants.js' import type { Startable } from '@libp2p/interfaces/startable' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:connection-manager:auto-dial') @@ -18,6 +20,7 @@ interface AutoDialInit { interface AutoDialComponents { connectionManager: ConnectionManager peerStore: PeerStore + events: EventEmitter } const defaultOptions = { @@ -55,6 +58,14 @@ export class AutoDial implements Startable { this.queue.addListener('error', (err) => { log.error('error during auto-dial', err) }) + + // check the min connection limit whenever a peer disconnects + components.events.addEventListener('connection:close', () => { + this.autoDial() + .catch(err => { + log.error(err) + }) + }) } isStarted (): boolean { diff --git a/src/connection-manager/connection-pruner.ts b/src/connection-manager/connection-pruner.ts index f556e9d176..814c3dedd8 100644 --- a/src/connection-manager/connection-pruner.ts +++ b/src/connection-manager/connection-pruner.ts @@ -4,7 +4,8 @@ import type { PeerStore } from '@libp2p/interface-peer-store' import { PeerMap } from '@libp2p/peer-collections' import type { Multiaddr } from '@multiformats/multiaddr' import { MAX_CONNECTIONS } from './constants.js' -import { CustomEvent } from '@libp2p/interfaces/events' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:connection-manager:connection-pruner') @@ -16,6 +17,7 @@ interface ConnectionPrunerInit { interface ConnectionPrunerComponents { connectionManager: ConnectionManager peerStore: PeerStore + events: EventEmitter } const defaultOptions = { @@ -31,12 +33,22 @@ export class ConnectionPruner { private readonly connectionManager: ConnectionManager private readonly peerStore: PeerStore private readonly allow: Multiaddr[] + private readonly events: EventEmitter constructor (components: ConnectionPrunerComponents, init: ConnectionPrunerInit = {}) { this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections this.allow = init.allow ?? defaultOptions.allow this.connectionManager = components.connectionManager this.peerStore = components.peerStore + this.events = components.events + + // check the max connection limit whenever a peer connects + components.events.addEventListener('connection:open', () => { + this.maybePruneConnections() + .catch(err => { + log.error(err) + }) + }) } /** @@ -48,7 +60,7 @@ export class ConnectionPruner { const numConnections = connections.length const toPrune = Math.max(numConnections - this.maxConnections, 0) - log.trace('checking max connections limit %d/%d', numConnections, this.maxConnections) + log('checking max connections limit %d/%d', numConnections, this.maxConnections) if (numConnections <= this.maxConnections) { return } @@ -132,6 +144,6 @@ export class ConnectionPruner { ) // despatch prune event - this.connectionManager.dispatchEvent(new CustomEvent('peer:prune', { detail: toClose.map(conn => conn.remotePeer) })) + this.events.safeDispatchEvent('connection:prune', { detail: toClose }) } } diff --git a/src/connection-manager/index.ts b/src/connection-manager/index.ts index f69290ce3b..5fe6f4619b 100644 --- a/src/connection-manager/index.ts +++ b/src/connection-manager/index.ts @@ -1,19 +1,18 @@ import { logger } from '@libp2p/logger' import { CodeError } from '@libp2p/interfaces/errors' import type { AbortOptions } from '@libp2p/interfaces' -import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events' +import type { EventEmitter } from '@libp2p/interfaces/events' import type { Startable } from '@libp2p/interfaces/startable' import { codes } from '../errors.js' import type { PeerId } from '@libp2p/interface-peer-id' -import { setMaxListeners } from 'events' import type { Connection, MultiaddrConnection } from '@libp2p/interface-connection' -import type { ConnectionManager, ConnectionManagerEvents } from '@libp2p/interface-connection-manager' +import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { AddressSorter, PeerStore } from '@libp2p/interface-peer-store' import { Multiaddr, Resolver, multiaddr } from '@multiformats/multiaddr' import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags' import { RateLimiterMemory } from 'rate-limiter-flexible' import type { Metrics } from '@libp2p/interface-metrics' -import type { TransportManager, Upgrader } from '@libp2p/interface-transport' +import type { TransportManager } from '@libp2p/interface-transport' import { getPeerAddress } from '../get-peer.js' import { AutoDial } from './auto-dial.js' import { DialQueue } from './dial-queue.js' @@ -24,6 +23,7 @@ import { publicAddressesFirst } from '@libp2p/utils/address-sort' import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_PRIORITY, DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, MAX_CONNECTIONS, MAX_INCOMING_PENDING_CONNECTIONS, MAX_PARALLEL_DIALS, MAX_PEER_ADDRS_TO_DIAL, MIN_CONNECTIONS } from './constants.js' import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers' import type { PendingDial } from '../libp2p.js' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:connection-manager') @@ -143,10 +143,10 @@ const defaultOptions = { export interface DefaultConnectionManagerComponents { peerId: PeerId metrics?: Metrics - upgrader: Upgrader peerStore: PeerStore transportManager: TransportManager connectionGater: ConnectionGater + events: EventEmitter } export interface OpenConnectionOptions extends AbortOptions { @@ -156,7 +156,7 @@ export interface OpenConnectionOptions extends AbortOptions { /** * Responsible for managing known connections. */ -export class DefaultConnectionManager extends EventEmitter implements ConnectionManager, Startable { +export class DefaultConnectionManager implements ConnectionManager, Startable { private started: boolean private readonly connections: PeerMap private readonly allow: Multiaddr[] @@ -172,10 +172,9 @@ export class DefaultConnectionManager extends EventEmitter constructor (components: DefaultConnectionManagerComponents, init: ConnectionManagerInit = {}) { - super() - this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections const minConnections = init.minConnections ?? defaultOptions.minConnections @@ -189,17 +188,14 @@ export class DefaultConnectionManager extends EventEmitter multiaddr(ma)) @@ -217,35 +213,23 @@ export class DefaultConnectionManager extends EventEmitter { - this.autoDial.autoDial() - .catch(err => { - log.error(err) - }) - }) // controls what happens when we have too many connections this.connectionPruner = new ConnectionPruner({ connectionManager: this, - peerStore: components.peerStore + peerStore: components.peerStore, + events: components.events }, { maxConnections: this.maxConnections, allow: this.allow }) - // check the max connection limit whenever a peer connects - this.addEventListener('peer:connect', () => { - this.connectionPruner.maybePruneConnections() - .catch(err => { - log.error(err) - }) - }) this.dialQueue = new DialQueue({ peerId: components.peerId, @@ -262,9 +246,6 @@ export class DefaultConnectionManager extends EventEmitter('peer:connect', { detail: connection })) + if (isNewPeer) { + this.events.safeDispatchEvent('peer:connect', { detail: connection.remotePeer }) + } } /** @@ -472,7 +457,7 @@ export class DefaultConnectionManager extends EventEmitter('peer:disconnect', { detail: connection })) + this.events.safeDispatchEvent('peer:disconnect', { detail: connection.remotePeer }) } } diff --git a/src/content-routing/index.ts b/src/content-routing/index.ts index a3cfe7fc9c..5d5603d344 100644 --- a/src/content-routing/index.ts +++ b/src/content-routing/index.ts @@ -54,7 +54,7 @@ export class CompoundContentRouting implements ContentRouting, Startable { */ async * findProviders (key: CID, options: AbortOptions = {}): AsyncIterable { if (this.routers.length === 0) { - throw new CodeError('No content this.routers available', codes.ERR_NO_ROUTERS_AVAILABLE) + throw new CodeError('No content routers available', codes.ERR_NO_ROUTERS_AVAILABLE) } yield * pipe( diff --git a/src/identify/index.ts b/src/identify/index.ts index 610dc71fdc..0391afb3df 100644 --- a/src/identify/index.ts +++ b/src/identify/index.ts @@ -29,6 +29,8 @@ import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { PeerId } from '@libp2p/interface-peer-id' import type { PeerStore } from '@libp2p/interface-peer-store' import type { AddressManager } from '@libp2p/interface-address-manager' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:identify') @@ -74,6 +76,7 @@ export interface IdentifyServiceComponents { connectionManager: ConnectionManager registrar: Registrar addressManager: AddressManager + events: EventEmitter } export class IdentifyService implements Startable { @@ -103,9 +106,9 @@ export class IdentifyService implements Startable { } // When a new connection happens, trigger identify - this.components.connectionManager.addEventListener('peer:connect', (evt) => { + this.components.events.addEventListener('connection:open', (evt) => { const connection = evt.detail - this.identify(connection).catch(log.error) + this.identify(connection).catch(err => { log.error('error during identify trigged by connection:open', err) }) }) // When self multiaddrs change, trigger identify-push diff --git a/src/libp2p.ts b/src/libp2p.ts index 22a959e5b4..56c7c89786 100644 --- a/src/libp2p.ts +++ b/src/libp2p.ts @@ -50,7 +50,8 @@ import type { Datastore } from 'interface-datastore' import type { KeyChain } from '@libp2p/interface-keychain' import mergeOptions from 'merge-options' import type { CircuitRelayService } from './circuit-relay/index.js' -import { Libp2pEvents } from '@libp2p/interface-libp2p' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' +import { setMaxListeners } from 'events' const log = logger('libp2p') @@ -100,6 +101,11 @@ export class Libp2pNode extends EventEmitter implements Libp2p { return internalResult || externalResult } + try { + // This emitter gets listened to a lot + setMaxListeners?.(Infinity, events) + } catch {} + this.started = false this.peerId = init.peerId const components = this.components = new DefaultComponents({ @@ -138,7 +144,7 @@ export class Libp2pNode extends EventEmitter implements Libp2p { this.peerStore.addEventListener('peer', evt => { const { detail: peerData } = evt - this.dispatchEvent(new CustomEvent('peer:discovery', { detail: peerData })) + this.safeDispatchEvent('peer:discovery', { detail: peerData }) }) // Set up connection protector if configured @@ -159,14 +165,6 @@ export class Libp2pNode extends EventEmitter implements Libp2p { // Create the Connection Manager this.connectionManager = this.components.connectionManager = new DefaultConnectionManager(this.components, init.connectionManager) - // forward connection manager events - this.components.connectionManager.addEventListener('peer:disconnect', (event) => { - this.dispatchEvent(new CustomEvent('peer:disconnect', { detail: event.detail })) - }) - this.components.connectionManager.addEventListener('peer:connect', (event) => { - this.dispatchEvent(new CustomEvent('peer:connect', { detail: event.detail })) - }) - // Create the Registrar this.registrar = this.components.registrar = new DefaultRegistrar(this.components) @@ -529,7 +527,7 @@ export class Libp2pNode extends EventEmitter implements Libp2p { void this.components.peerStore.protoBook.set(peer.id, peer.protocols).catch(err => { log.error(err) }) } - this.dispatchEvent(new CustomEvent('peer:discovery', { detail: peer })) + this.safeDispatchEvent('peer:discovery', { detail: peer }) } } diff --git a/src/peer-record-updater.ts b/src/peer-record-updater.ts index 64f2f2f7bb..893d220f3a 100644 --- a/src/peer-record-updater.ts +++ b/src/peer-record-updater.ts @@ -2,18 +2,19 @@ import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' import type { Startable } from '@libp2p/interfaces/startable' import { logger } from '@libp2p/logger' import { protocols } from '@multiformats/multiaddr' -import type { TransportManager } from '@libp2p/interface-transport' import type { AddressManager } from '@libp2p/interface-address-manager' import type { PeerId } from '@libp2p/interface-peer-id' import type { PeerStore } from '@libp2p/interface-peer-store' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:peer-record-updater') export interface PeerRecordUpdaterComponents { peerId: PeerId peerStore: PeerStore - transportManager: TransportManager addressManager: AddressManager + events: EventEmitter } export class PeerRecordUpdater implements Startable { @@ -32,16 +33,16 @@ export class PeerRecordUpdater implements Startable { async start (): Promise { this.started = true - this.components.transportManager.addEventListener('listener:listening', this.update) - this.components.transportManager.addEventListener('listener:close', this.update) - this.components.addressManager.addEventListener('change:addresses', this.update) + this.components.events.addEventListener('transport:listening', this.update) + this.components.events.addEventListener('transport:close', this.update) + this.components.events.addEventListener('self:peer:update', this.update) } async stop (): Promise { this.started = false - this.components.transportManager.removeEventListener('listener:listening', this.update) - this.components.transportManager.removeEventListener('listener:close', this.update) - this.components.addressManager.removeEventListener('change:addresses', this.update) + this.components.events.removeEventListener('transport:listening', this.update) + this.components.events.removeEventListener('transport:close', this.update) + this.components.events.removeEventListener('self:peer:update', this.update) } /** diff --git a/src/registrar.ts b/src/registrar.ts index ea0ee5cae7..43c6d78afe 100644 --- a/src/registrar.ts +++ b/src/registrar.ts @@ -4,10 +4,12 @@ import { codes } from './errors.js' import { isTopology, StreamHandlerOptions, StreamHandlerRecord } from '@libp2p/interface-registrar' import merge from 'merge-options' import type { Registrar, StreamHandler, Topology } from '@libp2p/interface-registrar' -import type { PeerProtocolsChangeData, PeerStore } from '@libp2p/interface-peer-store' +import type { PeerStore, PeerUpdate } from '@libp2p/interface-peer-store' import type { Connection } from '@libp2p/interface-connection' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { PeerId } from '@libp2p/interface-peer-id' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:registrar') @@ -18,6 +20,7 @@ export interface RegistrarComponents { peerId: PeerId connectionManager: ConnectionManager peerStore: PeerStore + events: EventEmitter } /** @@ -34,14 +37,12 @@ export class DefaultRegistrar implements Registrar { this.components = components this._onDisconnect = this._onDisconnect.bind(this) - this._onProtocolChange = this._onProtocolChange.bind(this) + this._onPeerUpdate = this._onPeerUpdate.bind(this) this._onConnect = this._onConnect.bind(this) - this.components.connectionManager.addEventListener('peer:disconnect', this._onDisconnect) - this.components.connectionManager.addEventListener('peer:connect', this._onConnect) - - // happens after identify - this.components.peerStore.addEventListener('change:protocols', this._onProtocolChange) + this.components.events.addEventListener('connection:close', this._onDisconnect) + this.components.events.addEventListener('connection:open', this._onConnect) + this.components.events.addEventListener('peer:update', this._onPeerUpdate) } getProtocols (): string[] { @@ -208,10 +209,10 @@ export class DefaultRegistrar implements Registrar { /** * Check if a new peer support the multicodecs for this topology */ - _onProtocolChange (evt: CustomEvent): void { - const { peerId, protocols, oldProtocols } = evt.detail - const removed = oldProtocols.filter(protocol => !protocols.includes(protocol)) - const added = protocols.filter(protocol => !oldProtocols.includes(protocol)) + _onPeerUpdate (evt: CustomEvent): void { + const { peer, previous } = evt.detail + const removed = (previous?.protocols ?? []).filter(protocol => !peer.protocols.includes(protocol)) + const added = peer.protocols.filter(protocol => !(previous?.protocols ?? []).includes(protocol)) for (const protocol of removed) { const topologies = this.topologies.get(protocol) @@ -222,7 +223,7 @@ export class DefaultRegistrar implements Registrar { } for (const topology of topologies.values()) { - topology.onDisconnect(peerId) + topology.onDisconnect(peer.id) } } @@ -235,12 +236,12 @@ export class DefaultRegistrar implements Registrar { } for (const topology of topologies.values()) { - const connection = this.components.connectionManager.getConnections(peerId)[0] + const connection = this.components.connectionManager.getConnections(peer.id)[0] if (connection == null) { continue } - topology.onConnect(peerId, connection) + topology.onConnect(peer.id, connection) } } } diff --git a/src/transport-manager.ts b/src/transport-manager.ts index 276b42213c..df37b54f3b 100644 --- a/src/transport-manager.ts +++ b/src/transport-manager.ts @@ -2,16 +2,18 @@ import { logger } from '@libp2p/logger' import { codes } from './errors.js' import { CodeError } from '@libp2p/interfaces/errors' import { FaultTolerance } from '@libp2p/interface-transport' -import type { Listener, Transport, TransportManager, TransportManagerEvents, Upgrader } from '@libp2p/interface-transport' +import type { Listener, Transport, TransportManager, Upgrader } from '@libp2p/interface-transport' import type { Multiaddr } from '@multiformats/multiaddr' import type { Connection } from '@libp2p/interface-connection' import type { AbortOptions } from '@libp2p/interfaces' -import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events' +import type { EventEmitter } from '@libp2p/interfaces/events' import type { Startable } from '@libp2p/interfaces/startable' import { trackedMap } from '@libp2p/tracked-map' import type { Metrics } from '@libp2p/interface-metrics' import type { AddressManager } from '@libp2p/interface-address-manager' import type { Libp2pEvents } from '@libp2p/interface-libp2p' +import type { PeerStore } from '@libp2p/interface-peer-store' +import type { PeerId } from '@libp2p/interface-peer-id' const log = logger('libp2p:transports') @@ -24,9 +26,11 @@ export interface DefaultTransportManagerComponents { addressManager: AddressManager upgrader: Upgrader events: EventEmitter + peerId: PeerId + peerStore: PeerStore } -export class DefaultTransportManager extends EventEmitter implements TransportManager, Startable { +export class DefaultTransportManager implements TransportManager, Startable { private readonly components: DefaultTransportManagerComponents private readonly transports: Map private readonly listeners: Map @@ -34,8 +38,6 @@ export class DefaultTransportManager extends EventEmitter() @@ -199,14 +201,14 @@ export class DefaultTransportManager extends EventEmitter { - this.dispatchEvent(new CustomEvent('listener:listening', { + this.components.events.safeDispatchEvent('transport:listening', { detail: listener - })) + }) }) listener.addEventListener('close', () => { - this.dispatchEvent(new CustomEvent('listener:close', { + this.components.events.safeDispatchEvent('transport:close', { detail: listener - })) + }) }) // We need to attempt to listen on everything @@ -240,7 +242,7 @@ export class DefaultTransportManager extends EventEmitter } -export class DefaultUpgrader extends EventEmitter implements Upgrader { +export class DefaultUpgrader implements Upgrader { private readonly components: DefaultUpgraderComponents private readonly connectionEncryption: Map private readonly muxers: Map private readonly inboundUpgradeTimeout: number + private readonly events: EventEmitter constructor (components: DefaultUpgraderComponents, init: UpgraderInit) { - super() - this.components = components this.connectionEncryption = new Map() @@ -128,6 +129,7 @@ export class DefaultUpgrader extends EventEmitter implements Upg }) this.inboundUpgradeTimeout = init.inboundUpgradeTimeout ?? INBOUND_UPGRADE_TIMEOUT + this.events = components.events } /** @@ -510,9 +512,9 @@ export class DefaultUpgrader extends EventEmitter implements Upg } catch (err: any) { log.error(err) } finally { - this.dispatchEvent(new CustomEvent('connectionEnd', { + this.events.safeDispatchEvent('connection:close', { detail: connection - })) + }) } })().catch(err => { log.error(err) @@ -550,9 +552,9 @@ export class DefaultUpgrader extends EventEmitter implements Upg } }) - this.dispatchEvent(new CustomEvent('connection', { + this.events.safeDispatchEvent('connection:open', { detail: connection - })) + }) return connection } diff --git a/test/addresses/address-manager.spec.ts b/test/addresses/address-manager.spec.ts index 41274f2da9..592994e71d 100644 --- a/test/addresses/address-manager.spec.ts +++ b/test/addresses/address-manager.spec.ts @@ -6,25 +6,30 @@ import { AddressFilter, DefaultAddressManager } from '../../src/address-manager/ import { createNode } from '../utils/creators/peer.js' import { createFromJSON } from '@libp2p/peer-id-factory' import Peers from '../fixtures/peers.js' -import { stubInterface } from 'sinon-ts' +import { StubbedInstance, stubInterface } from 'sinon-ts' import type { TransportManager } from '@libp2p/interface-transport' import type { PeerId } from '@libp2p/interface-peer-id' import type { Libp2p } from '../../src/index.js' +import type { AddressBook, PeerStore } from '@libp2p/interface-peer-store' const listenAddresses = ['/ip4/127.0.0.1/tcp/15006/ws', '/ip4/127.0.0.1/tcp/15008/ws'] const announceAddreses = ['/dns4/peer.io'] describe('Address Manager', () => { let peerId: PeerId + let peerStore: StubbedInstance before(async () => { peerId = await createFromJSON(Peers[0]) + peerStore = stubInterface() + peerStore.addressBook = stubInterface() }) it('should not need any addresses', () => { const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() + transportManager: stubInterface(), + peerStore }, { announceFilter: stubInterface() }) @@ -36,7 +41,8 @@ describe('Address Manager', () => { it('should return listen multiaddrs on get', () => { const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() + transportManager: stubInterface(), + peerStore }, { announceFilter: stubInterface(), listen: listenAddresses @@ -54,7 +60,8 @@ describe('Address Manager', () => { it('should return announce multiaddrs on get', () => { const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() + transportManager: stubInterface(), + peerStore }, { announceFilter: stubInterface(), listen: listenAddresses, @@ -72,7 +79,8 @@ describe('Address Manager', () => { it('should add observed addresses', () => { const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() + transportManager: stubInterface(), + peerStore }, { announceFilter: stubInterface() }) @@ -88,7 +96,8 @@ describe('Address Manager', () => { const ma = multiaddr('/ip4/0.0.0.0/tcp/0') const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() + transportManager: stubInterface(), + peerStore }, { announceFilter: stubInterface(), listen: [ @@ -107,7 +116,8 @@ describe('Address Manager', () => { const ma = multiaddr('/ip4/123.123.123.123/tcp/39201') const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() + transportManager: stubInterface(), + peerStore }, { announceFilter: stubInterface() }) @@ -122,18 +132,14 @@ describe('Address Manager', () => { expect(am.getObservedAddrs().map(ma => ma.toString())).to.include(ma.toString()) }) - it('should only emit one change:addresses event', () => { + it('should only set addresses once', () => { const ma = '/ip4/123.123.123.123/tcp/39201' const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() - }, { - announceFilter: stubInterface() - }) - let eventCount = 0 - - am.addEventListener('change:addresses', () => { - eventCount++ + transportManager: stubInterface({ + getAddrs: [] + }), + peerStore }) am.confirmObservedAddr(multiaddr(ma)) @@ -141,16 +147,15 @@ describe('Address Manager', () => { am.confirmObservedAddr(multiaddr(ma)) am.confirmObservedAddr(multiaddr(`${ma.toString()}/p2p/${peerId.toString()}`)) - expect(eventCount).to.equal(1) + expect(peerStore.addressBook.set).to.have.property('callCount', 1) }) it('should strip our peer address from added observed addresses', () => { const ma = multiaddr('/ip4/123.123.123.123/tcp/39201') const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() - }, { - announceFilter: stubInterface() + transportManager: stubInterface(), + peerStore }) expect(am.getObservedAddrs()).to.be.empty() @@ -166,9 +171,8 @@ describe('Address Manager', () => { const ma = multiaddr('/ip4/123.123.123.123/tcp/39201') const am = new DefaultAddressManager({ peerId, - transportManager: stubInterface() - }, { - announceFilter: stubInterface() + transportManager: stubInterface(), + peerStore }) expect(am.getObservedAddrs()).to.be.empty() @@ -185,7 +189,8 @@ describe('Address Manager', () => { const transportManager = stubInterface() const am = new DefaultAddressManager({ peerId, - transportManager + transportManager, + peerStore }, { listen: [ma], announce: [] diff --git a/test/circuit-relay/hop.spec.ts b/test/circuit-relay/hop.spec.ts index c82d92e1b6..cc55be138a 100644 --- a/test/circuit-relay/hop.spec.ts +++ b/test/circuit-relay/hop.spec.ts @@ -24,6 +24,7 @@ import type { CircuitRelayServerInit } from '../../src/circuit-relay/server/inde import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { ConnectionGater } from '@libp2p/interface-connection-gater' import Sinon from 'sinon' +import { EventEmitter } from '@libp2p/interfaces/events' interface Node { peerId: PeerId @@ -67,18 +68,20 @@ describe('circuit-relay hop protocol', function () { registrar }) - const upgrader = mockUpgrader({ - registrar - }) - upgrader.addEventListener('connection', (evt) => { + const events = new EventEmitter() + events.addEventListener('connection:open', (evt) => { const conn = evt.detail connections.set(conn.remotePeer, conn) }) - upgrader.addEventListener('connectionEnd', (evt) => { + events.addEventListener('connection:close', (evt) => { const conn = evt.detail connections.delete(conn.remotePeer) }) + const upgrader = mockUpgrader({ + registrar + }) + const connectionGater = mockConnectionGater() const service = circuitRelayServer(circuitRelayInit)({ @@ -104,7 +107,8 @@ describe('circuit-relay hop protocol', function () { registrar, transportManager: stubInterface(), upgrader, - connectionGater + connectionGater, + events }) if (isStartable(transport)) { diff --git a/test/circuit-relay/stop.spec.ts b/test/circuit-relay/stop.spec.ts index cd48c5f0b7..2c8cf63f89 100644 --- a/test/circuit-relay/stop.spec.ts +++ b/test/circuit-relay/stop.spec.ts @@ -18,6 +18,7 @@ import { Status, StopMessage } from '../../src/circuit-relay/pb/index.js' import type { PeerId } from '@libp2p/interface-peer-id' import { duplexPair } from 'it-pair/duplex' import type { ConnectionGater } from '@libp2p/interface-connection-gater' +import { EventEmitter } from '@libp2p/interfaces/events' describe('circuit-relay stop protocol', function () { let transport: Transport @@ -35,7 +36,8 @@ describe('circuit-relay stop protocol', function () { registrar: stubInterface(), transportManager: stubInterface(), upgrader: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() } transport = circuitRelayTransport({})(components) diff --git a/test/connection-manager/auto-dial.spec.ts b/test/connection-manager/auto-dial.spec.ts index d46e83dbdc..cb6281a1f2 100644 --- a/test/connection-manager/auto-dial.spec.ts +++ b/test/connection-manager/auto-dial.spec.ts @@ -9,6 +9,7 @@ import { stubInterface } from 'sinon-ts' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { PeerStore, Peer } from '@libp2p/interface-peer-store' import { multiaddr } from '@multiformats/multiaddr' +import { EventEmitter } from '@libp2p/interfaces/events' describe('auto-dial', () => { it('should not dial peers without multiaddrs', async () => { @@ -42,7 +43,8 @@ describe('auto-dial', () => { const autoDialler = new AutoDial({ peerStore, - connectionManager + connectionManager, + events: new EventEmitter() }, { minConnections: 10 }) diff --git a/test/connection-manager/direct.spec.ts b/test/connection-manager/direct.spec.ts index b813a66975..22aa4dad2b 100644 --- a/test/connection-manager/direct.spec.ts +++ b/test/connection-manager/direct.spec.ts @@ -30,6 +30,7 @@ import type { PeerId } from '@libp2p/interface-peer-id' import { pEvent } from 'p-event' import { DefaultComponents } from '../../src/components.js' import { stubInterface } from 'sinon-ts' +import { EventEmitter } from '@libp2p/interfaces/events' const unsupportedAddr = multiaddr('/ip4/127.0.0.1/tcp/9999') @@ -45,7 +46,8 @@ describe('dialing (direct, WebSockets)', () => { datastore: new MemoryDatastore(), upgrader: mockUpgrader(), connectionGater: mockConnectionGater(), - transportManager: stubInterface() + transportManager: stubInterface(), + events: new EventEmitter() }) localComponents.peerStore = new PersistentPeerStore(localComponents, { addressFilter: localComponents.connectionGater.filterMultiaddrForPeer @@ -377,7 +379,7 @@ describe('libp2p.dialer (direct, WebSockets)', () => { const identifySpy = sinon.spy(libp2p.identifyService, 'identify') const protobookSetSpy = sinon.spy(libp2p.components.peerStore.protoBook, 'set') - const connectionPromise = pEvent(libp2p.connectionManager, 'peer:connect') + const connectionPromise = pEvent(libp2p, 'connection:open') await libp2p.start() diff --git a/test/connection-manager/index.node.ts b/test/connection-manager/index.node.ts index 2b69702e66..3efe122bfb 100644 --- a/test/connection-manager/index.node.ts +++ b/test/connection-manager/index.node.ts @@ -2,24 +2,24 @@ import { expect } from 'aegir/chai' import { createNode, createPeerId } from '../utils/creators/peer.js' -import { mockConnection, mockDuplex, mockMultiaddrConnection, mockUpgrader } from '@libp2p/interface-mocks' +import { mockConnection, mockDuplex, mockMultiaddrConnection } from '@libp2p/interface-mocks' import { createBaseOptions } from '../utils/base-options.browser.js' import type { Libp2p } from '../../src/index.js' import type { PeerId } from '@libp2p/interface-peer-id' import { DefaultConnectionManager } from '../../src/connection-manager/index.js' -import { CustomEvent } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import * as STATUS from '@libp2p/interface-connection/status' import { stubInterface } from 'sinon-ts' import type { KeyBook, PeerStore } from '@libp2p/interface-peer-store' import sinon from 'sinon' import pWaitFor from 'p-wait-for' -import type { Connection } from '@libp2p/interface-connection' import delay from 'delay' import type { Libp2pNode } from '../../src/libp2p.js' import { codes } from '../../src/errors.js' import { start } from '@libp2p/interfaces/startable' import type { TransportManager } from '@libp2p/interface-transport' import type { ConnectionGater } from '@libp2p/interface-connection-gater' +import { DefaultComponents } from '../../src/components.js' describe('Connection Manager', () => { let libp2p: Libp2p @@ -48,17 +48,16 @@ describe('Connection Manager', () => { }) it('should filter connections on disconnect, removing the closed one', async () => { - const upgrader = mockUpgrader() const peerStore = stubInterface() peerStore.keyBook = stubInterface() - - const connectionManager = new DefaultConnectionManager({ + const components = new DefaultComponents({ peerId: peerIds[0], - upgrader, peerStore, transportManager: stubInterface(), - connectionGater: stubInterface() - }, { + connectionGater: stubInterface(), + events: new EventEmitter() + }) + const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, minConnections: 50, inboundUpgradeTimeout: 1000 @@ -72,13 +71,13 @@ describe('Connection Manager', () => { expect(connectionManager.getConnections(peerIds[1])).to.have.lengthOf(0) // Add connection to the connectionManager - upgrader.dispatchEvent(new CustomEvent('connection', { detail: conn1 })) - upgrader.dispatchEvent(new CustomEvent('connection', { detail: conn2 })) + components.events.safeDispatchEvent('connection:open', { detail: conn1 }) + components.events.safeDispatchEvent('connection:open', { detail: conn2 }) expect(connectionManager.getConnections(peerIds[1])).to.have.lengthOf(2) await conn2.close() - upgrader.dispatchEvent(new CustomEvent('connectionEnd', { detail: conn2 })) + components.events.safeDispatchEvent('connection:close', { detail: conn2 }) expect(connectionManager.getConnections(peerIds[1])).to.have.lengthOf(1) @@ -88,17 +87,16 @@ describe('Connection Manager', () => { }) it('should close connections on stop', async () => { - const upgrader = mockUpgrader() const peerStore = stubInterface() peerStore.keyBook = stubInterface() - - const connectionManager = new DefaultConnectionManager({ + const components = new DefaultComponents({ peerId: peerIds[0], - upgrader, peerStore, transportManager: stubInterface(), - connectionGater: stubInterface() - }, { + connectionGater: stubInterface(), + events: new EventEmitter() + }) + const connectionManager = new DefaultConnectionManager(components, { maxConnections: 1000, minConnections: 50, inboundUpgradeTimeout: 1000 @@ -110,8 +108,8 @@ describe('Connection Manager', () => { const conn2 = mockConnection(mockMultiaddrConnection(mockDuplex(), peerIds[1])) // Add connection to the connectionManager - upgrader.dispatchEvent(new CustomEvent('connection', { detail: conn1 })) - upgrader.dispatchEvent(new CustomEvent('connection', { detail: conn2 })) + components.events.safeDispatchEvent('connection:open', { detail: conn1 }) + components.events.safeDispatchEvent('connection:open', { detail: conn2 }) expect(connectionManager.getConnections(peerIds[1])).to.have.lengthOf(2) diff --git a/test/connection-manager/index.spec.ts b/test/connection-manager/index.spec.ts index f32c99d640..99ec4ef0e9 100644 --- a/test/connection-manager/index.spec.ts +++ b/test/connection-manager/index.spec.ts @@ -8,13 +8,13 @@ import type { Libp2pNode } from '../../src/libp2p.js' import { DefaultConnectionManager } from '../../src/connection-manager/index.js' import { mockConnection, mockDuplex, mockMultiaddrConnection, mockMetrics } from '@libp2p/interface-mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { CustomEvent } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags' import pWaitFor from 'p-wait-for' import { multiaddr } from '@multiformats/multiaddr' import { stubInterface } from 'sinon-ts' import type { Connection } from '@libp2p/interface-connection' -import type { TransportManager, Upgrader } from '@libp2p/interface-transport' +import type { TransportManager } from '@libp2p/interface-transport' import type { PeerStore } from '@libp2p/interface-peer-store' import type { ConnectionGater } from '@libp2p/interface-connection-gater' import { pEvent } from 'p-event' @@ -83,6 +83,9 @@ describe('Connection Manager', () => { const connectionManagerMaybePruneConnectionsSpy = sinon.spy(connectionManager.connectionPruner, 'maybePruneConnections') const spies = new Map>>() + // wait for prune event + const eventPromise = pEvent(libp2p, 'connection:prune') + // Add 1 connection too many for (let i = 0; i < max + 1; i++) { const connection = mockConnection(mockMultiaddrConnection(mockDuplex(), await createEd25519PeerId())) @@ -94,11 +97,10 @@ describe('Connection Manager', () => { value }) - await connectionManager._onConnect(new CustomEvent('connection', { detail: connection })) + libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) } - // wait for prune event - await pEvent(connectionManager, 'peer:prune') + await eventPromise // get the lowest value const lowest = Array.from(spies.keys()).sort((a, b) => { @@ -135,6 +137,7 @@ describe('Connection Manager', () => { const connectionManager = libp2p.connectionManager as DefaultConnectionManager const connectionManagerMaybePruneConnectionsSpy = sinon.spy(connectionManager.connectionPruner, 'maybePruneConnections') const spies = new Map>>() + const eventPromise = pEvent(libp2p, 'connection:prune') const createConnection = async (value: number, open: number = Date.now(), peerTag: string = 'test-tag'): Promise => { // #TODO: Mock the connection timeline to simulate an older connection @@ -147,7 +150,7 @@ describe('Connection Manager', () => { value }) - await connectionManager._onConnect(new CustomEvent('connection', { detail: connection })) + libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) } // Create one short of enough connections to initiate pruning @@ -163,7 +166,7 @@ describe('Connection Manager', () => { await createConnection(value, Date.now(), 'shortest') // wait for prune event - await pEvent(connectionManager, 'peer:prune') + await eventPromise // get the lowest tagged value, but this would be also the longest lived connection const longestLivedWithLowestTagSpy = spies.get('longest') @@ -198,6 +201,7 @@ describe('Connection Manager', () => { const connectionManager = libp2p.connectionManager as DefaultConnectionManager const connectionManagerMaybePruneConnectionsSpy = sinon.spy(connectionManager.connectionPruner, 'maybePruneConnections') const spies = new Map>>() + const eventPromise = pEvent(libp2p, 'connection:prune') // Max out connections for (let i = 0; i < max; i++) { @@ -208,7 +212,7 @@ describe('Connection Manager', () => { await libp2p.peerStore.tagPeer(connection.remotePeer, 'test-tag', { value }) - await connectionManager._onConnect(new CustomEvent('connection', { detail: connection })) + libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) } // an outbound connection is opened from an address in the allow list @@ -230,7 +234,10 @@ describe('Connection Manager', () => { value }) - await connectionManager._onConnect(new CustomEvent('connection', { detail: connection })) + libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) + + // wait for prune event + await eventPromise // get the lowest value const lowest = Array.from(spies.keys()).sort((a, b) => { @@ -267,17 +274,18 @@ describe('Connection Manager', () => { const connectionManager = libp2p.connectionManager as DefaultConnectionManager const connectionManagerMaybePruneConnectionsSpy = sinon.spy(connectionManager.connectionPruner, 'maybePruneConnections') + const eventPromise = pEvent(libp2p, 'connection:prune') // Add 1 too many connections const spy = sinon.spy() for (let i = 0; i < max + 1; i++) { const connection = mockConnection(mockMultiaddrConnection(mockDuplex(), await createEd25519PeerId())) sinon.stub(connection, 'close').callsFake(async () => spy()) // eslint-disable-line - await connectionManager._onConnect(new CustomEvent('connection', { detail: connection })) + libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) } // wait for prune event - await pEvent(connectionManager, 'peer:prune') + await eventPromise expect(connectionManagerMaybePruneConnectionsSpy.callCount).to.equal(6) @@ -328,10 +336,10 @@ describe('Connection Manager', () => { const remoteAddr = multiaddr('/ip4/83.13.55.32/tcp/59283') const connectionManager = new DefaultConnectionManager({ peerId: libp2p.peerId, - upgrader: stubInterface(), peerStore: stubInterface(), transportManager: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() }, { ...defaultOptions, deny: [ @@ -355,10 +363,10 @@ describe('Connection Manager', () => { it('should deny connections when maxConnections is exceeded', async () => { const connectionManager = new DefaultConnectionManager({ peerId: libp2p.peerId, - upgrader: stubInterface(), peerStore: stubInterface(), transportManager: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() }, { ...defaultOptions, maxConnections: 1 @@ -386,10 +394,10 @@ describe('Connection Manager', () => { it('should deny connections from peers that connect too frequently', async () => { const connectionManager = new DefaultConnectionManager({ peerId: libp2p.peerId, - upgrader: stubInterface(), peerStore: stubInterface(), transportManager: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() }, { ...defaultOptions, inboundConnectionThreshold: 1 @@ -422,10 +430,10 @@ describe('Connection Manager', () => { const connectionManager = new DefaultConnectionManager({ peerId: libp2p.peerId, - upgrader: stubInterface(), peerStore: stubInterface(), transportManager: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() }, { ...defaultOptions, maxConnections: 1, @@ -457,10 +465,10 @@ describe('Connection Manager', () => { it('should limit the number of inbound pending connections', async () => { const connectionManager = new DefaultConnectionManager({ peerId: await createEd25519PeerId(), - upgrader: stubInterface(), peerStore: stubInterface(), transportManager: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() }, { ...defaultOptions, maxIncomingPendingConnections: 1 diff --git a/test/core/consume-peer-record.spec.ts b/test/core/consume-peer-record.spec.ts index 7f5e304a4e..c49856b000 100644 --- a/test/core/consume-peer-record.spec.ts +++ b/test/core/consume-peer-record.spec.ts @@ -28,12 +28,11 @@ describe('Consume peer record', () => { await libp2p.stop() }) - it('should consume peer record when observed addrs are confirmed', async () => { + it('should update addresses when observed addrs are confirmed', async () => { let done: () => void - libp2p.components.peerStore.addressBook.consumePeerRecord = async () => { + libp2p.components.peerStore.addressBook.set = async () => { done() - return true } const p = new Promise(resolve => { diff --git a/test/fetch/index.spec.ts b/test/fetch/index.spec.ts index ca6a3160b7..674c3e9642 100644 --- a/test/fetch/index.spec.ts +++ b/test/fetch/index.spec.ts @@ -8,7 +8,7 @@ import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-m import { createFromJSON } from '@libp2p/peer-id-factory' import { DefaultConnectionManager } from '../../src/connection-manager/index.js' import { start, stop } from '@libp2p/interfaces/startable' -import { CustomEvent } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import { TimeoutController } from 'timeout-abort-controller' import delay from 'delay' import { pipe } from 'it-pipe' @@ -35,7 +35,8 @@ async function createComponents (index: number): Promise { upgrader: mockUpgrader(), datastore: new MemoryDatastore(), transportManager: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { @@ -87,8 +88,8 @@ describe('fetch', () => { // simulate connection between nodes const [localToRemote, remoteToLocal] = connectionPair(localComponents, remoteComponents) - localComponents.upgrader.dispatchEvent(new CustomEvent('connection', { detail: localToRemote })) - remoteComponents.upgrader.dispatchEvent(new CustomEvent('connection', { detail: remoteToLocal })) + localComponents.events.safeDispatchEvent('connection:open', { detail: localToRemote }) + remoteComponents.events.safeDispatchEvent('connection:open', { detail: remoteToLocal }) // Run fetch const result = await localFetch.fetch(remoteComponents.peerId, key) @@ -106,8 +107,8 @@ describe('fetch', () => { // simulate connection between nodes const [localToRemote, remoteToLocal] = connectionPair(localComponents, remoteComponents) - localComponents.upgrader.dispatchEvent(new CustomEvent('connection', { detail: localToRemote })) - remoteComponents.upgrader.dispatchEvent(new CustomEvent('connection', { detail: remoteToLocal })) + localComponents.events.safeDispatchEvent('connection:open', { detail: localToRemote }) + remoteComponents.events.safeDispatchEvent('connection:open', { detail: remoteToLocal }) // replace existing handler with a really slow one await remoteComponents.registrar.unhandle(remoteFetch.protocol) diff --git a/test/identify/index.spec.ts b/test/identify/index.spec.ts index ee1b259d23..2f4d0f200a 100644 --- a/test/identify/index.spec.ts +++ b/test/identify/index.spec.ts @@ -26,7 +26,7 @@ import { DefaultTransportManager } from '../../src/transport-manager.js' import delay from 'delay' import { start, stop } from '@libp2p/interfaces/startable' import { TimeoutController } from 'timeout-abort-controller' -import { CustomEvent } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import pDefer from 'p-defer' import { DefaultComponents } from '../../src/components.js' import { stubInterface } from 'sinon-ts' @@ -57,7 +57,8 @@ async function createComponents (index: number): Promise { registrar: mockRegistrar(), upgrader: mockUpgrader(), transportManager: stubInterface(), - connectionGater: mockConnectionGater() + connectionGater: mockConnectionGater(), + events: new EventEmitter() }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { @@ -315,12 +316,12 @@ describe('identify', () => { }) // ensure connections are registered by connection manager - localComponents.upgrader.dispatchEvent(new CustomEvent('connection', { + localComponents.events.safeDispatchEvent('connection:open', { detail: localToRemote - })) - remoteComponents.upgrader.dispatchEvent(new CustomEvent('connection', { + }) + remoteComponents.events.safeDispatchEvent('connection:open', { detail: remoteToLocal - })) + }) await deferred.promise await stop(remoteIdentify) @@ -370,12 +371,12 @@ describe('identify', () => { }) // ensure connections are registered by connection manager - localComponents.upgrader.dispatchEvent(new CustomEvent('connection', { + localComponents.events.safeDispatchEvent('connection:open', { detail: localToRemote - })) - remoteComponents.upgrader.dispatchEvent(new CustomEvent('connection', { + }) + remoteComponents.events.safeDispatchEvent('connection:open', { detail: remoteToLocal - })) + }) await deferred.promise await stop(remoteIdentify) diff --git a/test/identify/push.spec.ts b/test/identify/push.spec.ts index 7ba94da197..96eaf7972e 100644 --- a/test/identify/push.spec.ts +++ b/test/identify/push.spec.ts @@ -19,7 +19,7 @@ import { } from '../../src/identify/consts.js' import { DefaultConnectionManager } from '../../src/connection-manager/index.js' import { DefaultTransportManager } from '../../src/transport-manager.js' -import { CustomEvent } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import delay from 'delay' import { pEvent } from 'p-event' import { start, stop } from '@libp2p/interfaces/startable' @@ -52,7 +52,8 @@ async function createComponents (index: number): Promise { registrar: mockRegistrar(), upgrader: mockUpgrader(), transportManager: stubInterface(), - connectionGater: mockConnectionGater() + connectionGater: mockConnectionGater(), + events: new EventEmitter() }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { @@ -109,12 +110,12 @@ describe('identify (push)', () => { const [localToRemote, remoteToLocal] = connectionPair(localComponents, remoteComponents) // ensure connections are registered by connection manager - localComponents.upgrader.dispatchEvent(new CustomEvent('connection', { + localComponents.events.safeDispatchEvent('connection:open', { detail: localToRemote - })) - remoteComponents.upgrader.dispatchEvent(new CustomEvent('connection', { + }) + remoteComponents.events.safeDispatchEvent('connection:open', { detail: remoteToLocal - })) + }) // identify both ways await localIdentify.identify(localToRemote) @@ -240,12 +241,12 @@ describe('identify (push)', () => { const [localToRemote, remoteToLocal] = connectionPair(localComponents, remoteComponents) // ensure connections are registered by connection manager - localComponents.upgrader.dispatchEvent(new CustomEvent('connection', { + localComponents.events.safeDispatchEvent('connection:open', { detail: localToRemote - })) - remoteComponents.upgrader.dispatchEvent(new CustomEvent('connection', { + }) + remoteComponents.events.safeDispatchEvent('connection:open', { detail: remoteToLocal - })) + }) // identify both ways await localIdentify.identify(localToRemote) diff --git a/test/identify/service.spec.ts b/test/identify/service.spec.ts index ac9f9b474a..77d1882b77 100644 --- a/test/identify/service.spec.ts +++ b/test/identify/service.spec.ts @@ -113,7 +113,7 @@ describe('libp2p.dialer.identifyService', () => { const identityServiceIdentifySpy = sinon.spy(libp2p.identifyService, 'identify') const identityServicePushSpy = sinon.spy(libp2p.identifyService, 'push') - const connectionPromise = pEvent(libp2p.connectionManager, 'peer:connect') + const connectionPromise = pEvent(libp2p, 'connection:open') const connection = await libp2p.dial(remoteAddr) expect(connection).to.exist() @@ -213,7 +213,7 @@ describe('libp2p.dialer.identifyService', () => { const identityServiceIdentifySpy = sinon.spy(libp2p.identifyService, 'identify') const identityServicePushSpy = sinon.spy(libp2p.identifyService, 'push') - const connectionPromise = pEvent(libp2p.connectionManager, 'peer:connect') + const connectionPromise = pEvent(libp2p, 'connection:open') const connection = await libp2p.dial(remoteAddr) expect(connection).to.exist() diff --git a/test/nat-manager/nat-manager.node.ts b/test/nat-manager/nat-manager.node.ts index 6da477b8ed..3cdae123b5 100644 --- a/test/nat-manager/nat-manager.node.ts +++ b/test/nat-manager/nat-manager.node.ts @@ -16,6 +16,7 @@ import { StubbedInstance, stubInterface } from 'sinon-ts' import { start, stop } from '@libp2p/interfaces/startable' import { multiaddr } from '@multiformats/multiaddr' import { DefaultComponents } from '../../src/components.js' +import { EventEmitter } from '@libp2p/interfaces/events' const DEFAULT_ADDRESSES = [ '/ip4/127.0.0.1/tcp/0', @@ -29,7 +30,8 @@ describe('Nat Manager (TCP)', () => { async function createNatManager (addrs = DEFAULT_ADDRESSES, natManagerOptions = {}): Promise<{ natManager: NatManager, components: DefaultComponents }> { const components: any = { peerId: await createFromJSON(Peers[0]), - upgrader: mockUpgrader() + upgrader: mockUpgrader(), + events: new EventEmitter() } components.addressManager = new DefaultAddressManager(components, { listen: addrs }) components.transportManager = new DefaultTransportManager(components, { @@ -72,7 +74,7 @@ describe('Nat Manager (TCP)', () => { let addressChangedEventFired = false - components.addressManager.addEventListener('change:addresses', () => { + components.events.addEventListener('self:peer:update', () => { addressChangedEventFired = true }) diff --git a/test/ping/index.spec.ts b/test/ping/index.spec.ts index 962a8ebf04..ebd8e1567e 100644 --- a/test/ping/index.spec.ts +++ b/test/ping/index.spec.ts @@ -8,7 +8,7 @@ import { mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-m import { createFromJSON } from '@libp2p/peer-id-factory' import { DefaultConnectionManager } from '../../src/connection-manager/index.js' import { start, stop } from '@libp2p/interfaces/startable' -import { CustomEvent } from '@libp2p/interfaces/events' +import { EventEmitter } from '@libp2p/interfaces/events' import { TimeoutController } from 'timeout-abort-controller' import delay from 'delay' import { pipe } from 'it-pipe' @@ -35,7 +35,8 @@ async function createComponents (index: number): Promise { upgrader: mockUpgrader(), datastore: new MemoryDatastore(), transportManager: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { @@ -79,8 +80,8 @@ describe('ping', () => { // simulate connection between nodes const [localToRemote, remoteToLocal] = connectionPair(localComponents, remoteComponents) - localComponents.upgrader.dispatchEvent(new CustomEvent('connection', { detail: localToRemote })) - remoteComponents.upgrader.dispatchEvent(new CustomEvent('connection', { detail: remoteToLocal })) + localComponents.events.safeDispatchEvent('connection:open', { detail: localToRemote }) + remoteComponents.events.safeDispatchEvent('connection:open', { detail: remoteToLocal }) // Run ping await expect(localPing.ping(remoteComponents.peerId)).to.eventually.be.gte(0) @@ -95,8 +96,8 @@ describe('ping', () => { // simulate connection between nodes const [localToRemote, remoteToLocal] = connectionPair(localComponents, remoteComponents) - localComponents.upgrader.dispatchEvent(new CustomEvent('connection', { detail: localToRemote })) - remoteComponents.upgrader.dispatchEvent(new CustomEvent('connection', { detail: remoteToLocal })) + localComponents.events.safeDispatchEvent('connection:open', { detail: localToRemote }) + remoteComponents.events.safeDispatchEvent('connection:open', { detail: remoteToLocal }) // replace existing handler with a really slow one await remoteComponents.registrar.unhandle(remotePing.protocol) diff --git a/test/registrar/registrar.spec.ts b/test/registrar/registrar.spec.ts index 14635fa39f..b661781619 100644 --- a/test/registrar/registrar.spec.ts +++ b/test/registrar/registrar.spec.ts @@ -13,13 +13,11 @@ import type { Registrar } from '@libp2p/interface-registrar' import type { PeerId } from '@libp2p/interface-peer-id' import { createLibp2pNode, Libp2pNode } from '../../src/libp2p.js' import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { CustomEvent } from '@libp2p/interfaces/events' -import type { Connection } from '@libp2p/interface-connection' +import { EventEmitter } from '@libp2p/interfaces/events' import { DefaultConnectionManager } from '../../src/connection-manager/index.js' import { plaintext } from '../../src/insecure/index.js' import { webSockets } from '@libp2p/websockets' import { mplex } from '@libp2p/mplex' -import type { PeerProtocolsChangeData } from '@libp2p/interface-peer-store' import { DefaultComponents } from '../../src/components.js' import { stubInterface } from 'sinon-ts' import type { TransportManager } from '@libp2p/interface-transport' @@ -43,7 +41,8 @@ describe('registrar', () => { datastore: new MemoryDatastore(), upgrader: mockUpgrader(), transportManager: stubInterface(), - connectionGater: stubInterface() + connectionGater: stubInterface(), + events: new EventEmitter() }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { @@ -147,15 +146,15 @@ describe('registrar', () => { await libp2p.peerStore.protoBook.set(remotePeerId, [protocol]) // remote peer connects - libp2p.components.upgrader.dispatchEvent(new CustomEvent('connection', { + libp2p.components.events.safeDispatchEvent('connection:open', { detail: conn - })) + }) await onConnectDefer.promise // remote peer disconnects await conn.close() - libp2p.components.upgrader.dispatchEvent(new CustomEvent('connectionEnd', { + libp2p.components.events.safeDispatchEvent('connection:close', { detail: conn - })) + }) await onDisconnectDefer.promise }) @@ -185,29 +184,41 @@ describe('registrar', () => { await libp2p.peerStore.protoBook.set(remotePeerId, []) // remote peer connects - libp2p.components.upgrader.dispatchEvent(new CustomEvent('connection', { + libp2p.components.events.safeDispatchEvent('connection:open', { detail: conn - })) + }) // identify completes - libp2p.components.peerStore.dispatchEvent(new CustomEvent('change:protocols', { + libp2p.components.events.safeDispatchEvent('peer:update', { detail: { - peerId: conn.remotePeer, - protocols: [protocol], - oldProtocols: [] + peer: { + id: conn.remotePeer, + protocols: [protocol], + addresses: [], + metadata: new Map() + } } - })) + }) await onConnectDefer.promise // Peer no longer supports the protocol our topology is registered for - libp2p.components.peerStore.dispatchEvent(new CustomEvent('change:protocols', { + libp2p.components.events.safeDispatchEvent('peer:update', { detail: { - peerId: conn.remotePeer, - protocols: [], - oldProtocols: [protocol] + peer: { + id: conn.remotePeer, + protocols: [], + addresses: [], + metadata: new Map() + }, + previous: { + id: conn.remotePeer, + protocols: [protocol], + addresses: [], + metadata: new Map() + } } - })) + }) await onDisconnectDefer.promise }) diff --git a/test/upgrading/upgrader.spec.ts b/test/upgrading/upgrader.spec.ts index 7ba379e117..65ff6abbc8 100644 --- a/test/upgrading/upgrader.spec.ts +++ b/test/upgrading/upgrader.spec.ts @@ -20,7 +20,7 @@ import { createFromJSON } from '@libp2p/peer-id-factory' import { plaintext } from '../../src/insecure/index.js' import type { ConnectionEncrypter, SecuredConnection } from '@libp2p/interface-connection-encrypter' import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface-stream-muxer' -import type { ConnectionProtector, Stream } from '@libp2p/interface-connection' +import type { Connection, ConnectionProtector, Stream } from '@libp2p/interface-connection' import pDefer from 'p-defer' import { createLibp2pNode, Libp2pNode } from '../../src/libp2p.js' import { pEvent } from 'p-event' @@ -32,6 +32,7 @@ import { PersistentPeerStore } from '@libp2p/peer-store' import { MemoryDatastore } from 'datastore-core' import { DefaultComponents } from '../../src/components.js' import { StubbedInstance, stubInterface } from 'sinon-ts' +import { EventEmitter } from '@libp2p/interfaces/events' const addrs = [ multiaddr('/ip4/127.0.0.1/tcp/0'), @@ -69,7 +70,8 @@ describe('Upgrader', () => { connectionGater: mockConnectionGater(), registrar: mockRegistrar(), datastore: new MemoryDatastore(), - connectionProtector: localConnectionProtector + connectionProtector: localConnectionProtector, + events: new EventEmitter() }) localComponents.peerStore = new PersistentPeerStore(localComponents) localComponents.connectionManager = mockConnectionManager(localComponents) @@ -93,7 +95,8 @@ describe('Upgrader', () => { connectionGater: mockConnectionGater(), registrar: mockRegistrar(), datastore: new MemoryDatastore(), - connectionProtector: remoteConnectionProtector + connectionProtector: remoteConnectionProtector, + events: new EventEmitter() }) remoteComponents.peerStore = new PersistentPeerStore(remoteComponents) remoteComponents.connectionManager = mockConnectionManager(remoteComponents) @@ -359,16 +362,16 @@ describe('Upgrader', () => { const remoteConnectionEventReceived = pDefer() const remoteConnectionEndEventReceived = pDefer() - localUpgrader.addEventListener('connection', () => { + localComponents.events.addEventListener('connection:open', () => { localConnectionEventReceived.resolve() }) - localUpgrader.addEventListener('connectionEnd', () => { + localComponents.events.addEventListener('connection:close', () => { localConnectionEndEventReceived.resolve() }) - remoteUpgrader.addEventListener('connection', () => { + remoteComponents.events.addEventListener('connection:open', () => { remoteConnectionEventReceived.resolve() }) - remoteUpgrader.addEventListener('connectionEnd', () => { + remoteComponents.events.addEventListener('connection:close', () => { remoteConnectionEndEventReceived.resolve() }) @@ -660,30 +663,32 @@ describe('libp2p.upgrader', () => { const { inbound, outbound } = mockMultiaddrConnPair({ addrs, remotePeer }) - // Spy on emit for easy verification - const connectionManagerDispatchEventSpy = sinon.spy(libp2p.connectionManager, 'dispatchEvent') - // Upgrade and check the connect event - const connectionPromise = pEvent(libp2p.connectionManager, 'peer:connect') + const connectionPromise = pEvent(libp2p, 'connection:open') const connections = await Promise.all([ libp2p.components.upgrader.upgradeOutbound(outbound), remoteLibp2p.components.upgrader.upgradeInbound(inbound) ]) - await connectionPromise - expect(connectionManagerDispatchEventSpy.callCount).to.equal(1) + const connectEvent = await connectionPromise as CustomEvent + + if (connectEvent.type !== 'connection:open') { + throw new Error(`Incorrect event type, expected: 'connection:open' actual: ${connectEvent.type}`) + } + + expect(remotePeer.equals(connectEvent.detail.remotePeer)).to.equal(true) - let [event] = connectionManagerDispatchEventSpy.getCall(0).args - expect(event).to.have.property('type', 'peer:connect') - // @ts-expect-error detail is only on CustomEvent type - expect(remotePeer.equals(event.detail.remotePeer)).to.equal(true) + const disconnectionPromise = pEvent(libp2p, 'peer:disconnect') // Close and check the disconnect event await Promise.all(connections.map(async conn => { await conn.close() })) - expect(connectionManagerDispatchEventSpy.callCount).to.equal(2) - ;([event] = connectionManagerDispatchEventSpy.getCall(1).args) - expect(event).to.have.property('type', 'peer:disconnect') - // @ts-expect-error detail is only on CustomEvent type - expect(remotePeer.equals(event.detail.remotePeer)).to.equal(true) + + const disconnectEvent = await disconnectionPromise as CustomEvent + + if (disconnectEvent.type !== 'peer:disconnect') { + throw new Error(`Incorrect event type, expected: 'peer:disconnect' actual: ${disconnectEvent.type}`) + } + + expect(remotePeer.equals(disconnectEvent.detail)).to.equal(true) }) it('should limit the number of incoming streams that can be opened using a protocol', async () => { From 0834c42ea4976076acf515abc1b2bfd429bcb965 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 24 Apr 2023 15:32:50 +0100 Subject: [PATCH 04/10] chore: update peerstore implementation --- examples/auto-relay/README.md | 6 +- examples/auto-relay/listener.js | 8 +- examples/chat/src/listener.js | 2 +- examples/connection-encryption/1.js | 4 +- examples/discovery-mechanisms/1.js | 2 +- examples/discovery-mechanisms/README.md | 2 +- examples/echo/src/listener.js | 2 +- examples/libp2p-in-the-browser/index.js | 4 +- examples/libp2p-in-the-browser/package.json | 2 +- examples/peer-and-content-routing/1.js | 8 +- examples/peer-and-content-routing/2.js | 8 +- examples/peer-and-content-routing/README.md | 8 +- examples/pnet/index.js | 4 +- examples/protocol-and-stream-muxing/1.js | 4 +- examples/protocol-and-stream-muxing/2.js | 4 +- examples/protocol-and-stream-muxing/3.js | 4 +- examples/protocol-and-stream-muxing/README.md | 8 +- examples/pubsub/1.js | 4 +- examples/pubsub/README.md | 4 +- examples/pubsub/message-filtering/1.js | 8 +- examples/pubsub/message-filtering/README.md | 8 +- examples/transports/2.js | 4 +- examples/transports/3.js | 12 +- examples/transports/README.md | 16 +- examples/webrtc-direct/dialer.js | 4 +- examples/webrtc-direct/package.json | 2 +- package.json | 18 +- src/address-manager/index.ts | 4 +- src/circuit-relay/server/index.ts | 6 +- src/circuit-relay/transport/discovery.ts | 4 +- src/circuit-relay/transport/index.ts | 4 +- .../transport/reservation-store.ts | 10 +- src/connection-manager/auto-dial.ts | 8 +- src/connection-manager/connection-pruner.ts | 20 +- src/connection-manager/dial-queue.ts | 14 +- src/connection-manager/index.ts | 16 +- src/content-routing/utils.ts | 4 +- src/identify/index.ts | 227 +++++++----------- src/index.ts | 4 +- src/libp2p.ts | 60 ++--- src/peer-record-updater.ts | 66 ----- src/registrar.ts | 29 ++- src/transport-manager.ts | 26 +- src/upgrader.ts | 8 +- test/addresses/address-manager.spec.ts | 10 +- test/autonat/index.spec.ts | 3 +- test/circuit-relay/hop.spec.ts | 29 ++- test/circuit-relay/relay.node.ts | 42 ++-- test/circuit-relay/utils.ts | 8 +- test/configuration/protocol-prefix.node.ts | 8 +- test/connection-manager/auto-dial.spec.ts | 15 +- test/connection-manager/direct.node.ts | 49 +++- test/connection-manager/direct.spec.ts | 45 +++- test/connection-manager/index.node.ts | 78 ++++-- test/connection-manager/index.spec.ts | 38 ++- test/connection-manager/resolver.spec.ts | 12 +- test/content-routing/content-routing.node.ts | 4 +- test/content-routing/dht/operation.node.ts | 22 +- test/core/consume-peer-record.spec.ts | 3 +- test/core/get-public-key.spec.ts | 4 +- test/fetch/index.spec.ts | 5 +- test/identify/index.spec.ts | 91 ++----- test/identify/push.spec.ts | 123 ++-------- test/identify/service.spec.ts | 32 ++- test/nat-manager/nat-manager.node.ts | 18 +- test/peer-discovery/index.node.ts | 14 +- test/peer-routing/peer-routing.node.ts | 32 +-- test/ping/index.spec.ts | 5 +- test/ping/ping.node.ts | 12 +- test/registrar/registrar.spec.ts | 15 +- test/transports/transport-manager.node.ts | 36 +-- test/transports/transport-manager.spec.ts | 5 +- test/utils/creators/peer.ts | 4 +- 73 files changed, 719 insertions(+), 713 deletions(-) delete mode 100644 src/peer-record-updater.ts diff --git a/examples/auto-relay/README.md b/examples/auto-relay/README.md index da3100d5e8..51d541459c 100644 --- a/examples/auto-relay/README.md +++ b/examples/auto-relay/README.md @@ -98,11 +98,9 @@ const conn = await node.dial(relayAddr) console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`) // Wait for connection and relay to be bind for the example purpose -node.peerStore.addEventListener('change:multiaddrs', (evt) => { +node.addEventListener('self:peer:update', (evt) => { // Updated self multiaddrs? - if (evt.detail.peerId.equals(node.peerId)) { - console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`) - } + console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`) }) ``` diff --git a/examples/auto-relay/listener.js b/examples/auto-relay/listener.js index c52d045610..24ee8da64c 100644 --- a/examples/auto-relay/listener.js +++ b/examples/auto-relay/listener.js @@ -33,13 +33,9 @@ async function main () { console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`) // Wait for connection and relay to be bind for the example purpose - node.peerStore.addEventListener('change:multiaddrs', (evt) => { - const { peerId } = evt.detail - + node.addEventListener('self:peer:update', (evt) => { // Updated self multiaddrs? - if (peerId.equals(node.peerId)) { - console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`) - } + console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`) }) } diff --git a/examples/chat/src/listener.js b/examples/chat/src/listener.js index 5ce4c9535c..f97b534d57 100644 --- a/examples/chat/src/listener.js +++ b/examples/chat/src/listener.js @@ -16,7 +16,7 @@ async function run () { }) // Log a message when a remote peer connects to us - nodeListener.connectionManager.addEventListener('peer:connect', (evt) => { + nodeListener.addEventListener('peer:connect', (evt) => { const connection = evt.detail console.log('connected to: ', connection.remotePeer.toString()) }) diff --git a/examples/connection-encryption/1.js b/examples/connection-encryption/1.js index b662d88a4c..2aae533f5b 100644 --- a/examples/connection-encryption/1.js +++ b/examples/connection-encryption/1.js @@ -25,7 +25,9 @@ const createNode = async () => { createNode() ]) - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) node2.handle('/a-protocol', ({ stream }) => { pipe( diff --git a/examples/discovery-mechanisms/1.js b/examples/discovery-mechanisms/1.js index d58fef4156..65b39d4e34 100644 --- a/examples/discovery-mechanisms/1.js +++ b/examples/discovery-mechanisms/1.js @@ -22,7 +22,7 @@ import bootstrappers from './bootstrappers.js' ] }) - node.connectionManager.addEventListener('peer:connect', (evt) => { + node.addEventListener('peer:connect', (evt) => { const connection = evt.detail console.log('Connection established to:', connection.remotePeer.toString()) // Emitted when a peer has been found }) diff --git a/examples/discovery-mechanisms/README.md b/examples/discovery-mechanisms/README.md index eead89fca3..17650373d5 100644 --- a/examples/discovery-mechanisms/README.md +++ b/examples/discovery-mechanisms/README.md @@ -76,7 +76,7 @@ const node = await createLibp2p({ ] }) -node.connectionManager.addEventListener('peer:connect', (evt) => { +node.addEventListener('peer:connect', (evt) => { console.log('Connection established to:', evt.detail.remotePeer.toString()) // Emitted when a new connection has been created }) diff --git a/examples/echo/src/listener.js b/examples/echo/src/listener.js index 5477ff9ac4..559ea1c9b4 100644 --- a/examples/echo/src/listener.js +++ b/examples/echo/src/listener.js @@ -21,7 +21,7 @@ async function run() { }) // Log a message when we receive a connection - listenerNode.connectionManager.addEventListener('peer:connect', (evt) => { + listenerNode.addEventListener('peer:connect', (evt) => { const connection = evt.detail console.log('received dial to me from:', connection.remotePeer.toString()) }) diff --git a/examples/libp2p-in-the-browser/index.js b/examples/libp2p-in-the-browser/index.js index 82551fd20f..d26dc2bea8 100644 --- a/examples/libp2p-in-the-browser/index.js +++ b/examples/libp2p-in-the-browser/index.js @@ -62,13 +62,13 @@ document.addEventListener('DOMContentLoaded', async () => { }) // Listen for new connections to peers - libp2p.connectionManager.addEventListener('peer:connect', (evt) => { + libp2p.addEventListener('peer:connect', (evt) => { const connection = evt.detail log(`Connected to ${connection.remotePeer.toString()}`) }) // Listen for peers disconnecting - libp2p.connectionManager.addEventListener('peer:disconnect', (evt) => { + libp2p.addEventListener('peer:disconnect', (evt) => { const connection = evt.detail log(`Disconnected from ${connection.remotePeer.toString()}`) }) diff --git a/examples/libp2p-in-the-browser/package.json b/examples/libp2p-in-the-browser/package.json index 0bd6c1905e..1d222ddbf8 100644 --- a/examples/libp2p-in-the-browser/package.json +++ b/examples/libp2p-in-the-browser/package.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@chainsafe/libp2p-noise": "^11.0.0", - "@libp2p/bootstrap": "^6.0.0", + "@libp2p/bootstrap": "^7.0.0", "@libp2p/mplex": "^7.1.6", "@libp2p/webrtc-star": "^6.0.0", "@libp2p/websockets": "^5.0.0", diff --git a/examples/peer-and-content-routing/1.js b/examples/peer-and-content-routing/1.js index 22f477d344..5717ebe71c 100644 --- a/examples/peer-and-content-routing/1.js +++ b/examples/peer-and-content-routing/1.js @@ -28,8 +28,12 @@ const createNode = async () => { createNode() ]) - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) - await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) + await node2.peerStore(node3.peerId, { + multiaddrs: node3.getMultiaddrs() + }) await Promise.all([ node1.dial(node2.peerId), diff --git a/examples/peer-and-content-routing/2.js b/examples/peer-and-content-routing/2.js index a4ff651dbb..9b494fcfbd 100644 --- a/examples/peer-and-content-routing/2.js +++ b/examples/peer-and-content-routing/2.js @@ -30,8 +30,12 @@ const createNode = async () => { createNode() ]) - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) - await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) + await node2.peerStore.patch(node3.peerId, { + multiaddrs: node3.getMultiaddrs() + }) await Promise.all([ node1.dial(node2.peerId), diff --git a/examples/peer-and-content-routing/README.md b/examples/peer-and-content-routing/README.md index 7d3351d885..23c7b3fe20 100644 --- a/examples/peer-and-content-routing/README.md +++ b/examples/peer-and-content-routing/README.md @@ -43,8 +43,12 @@ const [node1, node2, node3] = await Promise.all([ createNode() ]) -await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) -await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs()) +await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() +}) +await node2.peerStore.patch(node3.peerId, { + mulitaddrs: node3.getMultiaddrs() +}) await Promise.all([ node1.dial(node2.peerId), diff --git a/examples/pnet/index.js b/examples/pnet/index.js index 06b9dfe99f..cdc04825b3 100644 --- a/examples/pnet/index.js +++ b/examples/pnet/index.js @@ -24,7 +24,9 @@ generateKey(otherSwarmKey) console.log('nodes started...') // Add node 2 data to node1's PeerStore - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) await node1.dial(node2.peerId) node2.handle('/private', ({ stream }) => { diff --git a/examples/protocol-and-stream-muxing/1.js b/examples/protocol-and-stream-muxing/1.js index d43a0e1869..be22a717c3 100644 --- a/examples/protocol-and-stream-muxing/1.js +++ b/examples/protocol-and-stream-muxing/1.js @@ -26,7 +26,9 @@ const createNode = async () => { ]) // Add node's 2 data to the PeerStore - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) // exact matching node2.handle('/your-protocol', ({ stream }) => { diff --git a/examples/protocol-and-stream-muxing/2.js b/examples/protocol-and-stream-muxing/2.js index a9c93b0fb4..3f2d1f2f7e 100644 --- a/examples/protocol-and-stream-muxing/2.js +++ b/examples/protocol-and-stream-muxing/2.js @@ -26,7 +26,9 @@ const createNode = async () => { ]) // Add node's 2 data to the PeerStore - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) node2.handle(['/a', '/b'], ({ protocol, stream }) => { pipe( diff --git a/examples/protocol-and-stream-muxing/3.js b/examples/protocol-and-stream-muxing/3.js index 438ff7a406..abd3ad1cc9 100644 --- a/examples/protocol-and-stream-muxing/3.js +++ b/examples/protocol-and-stream-muxing/3.js @@ -28,7 +28,9 @@ const createNode = async () => { ]) // Add node's 2 data to the PeerStore - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) node1.handle('/node-1', ({ stream }) => { pipe( diff --git a/examples/protocol-and-stream-muxing/README.md b/examples/protocol-and-stream-muxing/README.md index 0060690c5b..ae05c63405 100644 --- a/examples/protocol-and-stream-muxing/README.md +++ b/examples/protocol-and-stream-muxing/README.md @@ -24,7 +24,9 @@ const [node1, node2] = await Promise.all([ ]) // Add node's 2 data to the PeerStore -await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) +await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() +}) // Here we are telling libp2p that if someone dials this node to talk with the `/your-protocol` // multicodec, the protocol identifier, please call this handler and give it the stream @@ -199,7 +201,9 @@ const [node1, node2] = await Promise.all([ Since, we want to connect these nodes `node1` & `node2`, we add our `node2` multiaddr in key-value pair in `node1` peer store. ```js -await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) +await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() +}) ``` You may notice that we are only adding `node2` to `node1` peer store. This is because we want to dial up a bidirectional connection between these two nodes. diff --git a/examples/pubsub/1.js b/examples/pubsub/1.js index 9cb49fcb0b..a7b8589b46 100644 --- a/examples/pubsub/1.js +++ b/examples/pubsub/1.js @@ -31,7 +31,9 @@ const createNode = async () => { ]) // Add node's 2 data to the PeerStore - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) await node1.dial(node2.peerId) node1.pubsub.subscribe(topic) diff --git a/examples/pubsub/README.md b/examples/pubsub/README.md index e3ea9bb86d..d5e7ea1da5 100644 --- a/examples/pubsub/README.md +++ b/examples/pubsub/README.md @@ -57,7 +57,9 @@ const [node1, node2] = await Promise.all([ ]) // Add node's 2 data to the PeerStore -await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) +await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() +}) await node1.dial(node2.peerId) node1.pubsub.addEventListener("message", (evt) => { diff --git a/examples/pubsub/message-filtering/1.js b/examples/pubsub/message-filtering/1.js index c0e1540847..45a4125c30 100644 --- a/examples/pubsub/message-filtering/1.js +++ b/examples/pubsub/message-filtering/1.js @@ -32,10 +32,14 @@ const createNode = async () => { ]) // node1 conect to node2 and node2 conect to node3 - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) await node1.dial(node2.peerId) - await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs()) + await node2.peerStore.patch(node3.peerId, { + multiaddrs: node3.getMultiaddrs() + }) await node2.dial(node3.peerId) //subscribe diff --git a/examples/pubsub/message-filtering/README.md b/examples/pubsub/message-filtering/README.md index 4fa61e273a..88008cd54d 100644 --- a/examples/pubsub/message-filtering/README.md +++ b/examples/pubsub/message-filtering/README.md @@ -38,10 +38,14 @@ const [node1, node2, node3] = await Promise.all([ createNode(), ]) -await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) +await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() +}) await node1.dial(node2.peerId) -await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs()) +await node2.peerStore.patch(node3.peerId, { + multiaddrs: node3.getMultiaddrs() +}) await node2.dial(node3.peerId) ``` diff --git a/examples/transports/2.js b/examples/transports/2.js index a23931d18d..4a0ceea20a 100644 --- a/examples/transports/2.js +++ b/examples/transports/2.js @@ -51,7 +51,9 @@ function printAddrs (node, number) { console.log(uint8ArrayToString(result)) }) - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) const stream = await node1.dialProtocol(node2.peerId, '/print') await pipe( diff --git a/examples/transports/3.js b/examples/transports/3.js index 400a5e5621..197f190963 100644 --- a/examples/transports/3.js +++ b/examples/transports/3.js @@ -57,9 +57,15 @@ function print ({ stream }) { node2.handle('/print', print) node3.handle('/print', print) - await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) - await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs()) - await node3.peerStore.addressBook.set(node1.peerId, node1.getMultiaddrs()) + await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() + }) + await node2.peerStore.patch(node3.peerId, { + multiaddrs: node3.getMultiaddrs() + }) + await node3.peerStore.patch(node1.peerId, { + multiaddrs: node1.getMultiaddrs() + }) // node 1 (TCP) dials to node 2 (TCP+WebSockets) const stream = await node1.dialProtocol(node2.peerId, '/print') diff --git a/examples/transports/README.md b/examples/transports/README.md index 4ee963e950..fb8ca0239a 100644 --- a/examples/transports/README.md +++ b/examples/transports/README.md @@ -138,7 +138,9 @@ node2.handle('/print', async ({ stream }) => { console.log(result.map(buf => uint8ArrayToString(buf.subarray())).join("")) }) -await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) +await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() +}) const stream = await node1.dialProtocol(node2.peerId, '/print') await pipe( @@ -218,9 +220,15 @@ node1.handle('/print', print) node2.handle('/print', print) node3.handle('/print', print) -await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs()) -await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs()) -await node3.peerStore.addressBook.set(node1.peerId, node1.getMultiaddrs()) +await node1.peerStore.patch(node2.peerId, { + multiaddrs: node2.getMultiaddrs() +}) +await node2.peerStore.patch(node3.peerId, { + multiaddrs: node3.getMultiaddrs() +}) +await node3.peerStore.patch(node1.peerId, { + multiaddrs: node1.getMultiaddrs() +}) // node 1 (TCP) dials to node 2 (TCP+WebSockets) const stream = await node1.dialProtocol(node2.peerId, '/print') diff --git a/examples/webrtc-direct/dialer.js b/examples/webrtc-direct/dialer.js index 9c50a23b45..07d75ff922 100644 --- a/examples/webrtc-direct/dialer.js +++ b/examples/webrtc-direct/dialer.js @@ -39,12 +39,12 @@ document.addEventListener('DOMContentLoaded', async () => { }) // Listen for new connections to peers - libp2p.connectionManager.addEventListener('peer:connect', (evt) => { + libp2p.addEventListener('peer:connect', (evt) => { log(`Connected to ${evt.detail.remotePeer.toString()}`) }) // Listen for peers disconnecting - libp2p.connectionManager.addEventListener('peer:disconnect', (evt) => { + libp2p.addEventListener('peer:disconnect', (evt) => { log(`Disconnected from ${evt.detail.remotePeer.toString()}`) }) diff --git a/examples/webrtc-direct/package.json b/examples/webrtc-direct/package.json index 2d5bd0e0b4..a02feb1a29 100644 --- a/examples/webrtc-direct/package.json +++ b/examples/webrtc-direct/package.json @@ -11,7 +11,7 @@ "dependencies": { "@libp2p/webrtc-direct": "^5.0.0", "@chainsafe/libp2p-noise": "^11.0.0", - "@libp2p/bootstrap": "^5.0.0", + "@libp2p/bootstrap": "^7.0.0", "@libp2p/mplex": "^7.1.6", "libp2p": "file:../../", "wrtc": "^0.4.7" diff --git a/package.json b/package.json index 99e8a568fb..fe430b63c3 100644 --- a/package.json +++ b/package.json @@ -101,26 +101,26 @@ "dependencies": { "@achingbrain/nat-port-mapper": "^1.0.3", "@libp2p/crypto": "^1.0.4", - "@libp2p/interface-address-manager": "^2.0.0", + "@libp2p/interface-address-manager": "^3.0.0", "@libp2p/interface-connection": "^5.0.0", "@libp2p/interface-connection-encrypter": "^4.0.0", "@libp2p/interface-connection-gater": "^3.0.0", - "@libp2p/interface-connection-manager": "^2.1.1", + "@libp2p/interface-connection-manager": "^3.0.0", "@libp2p/interface-content-routing": "^2.0.0", "@libp2p/interface-dht": "^2.0.0", "@libp2p/interface-keychain": "^2.0.4", - "@libp2p/interface-libp2p": "^1.0.0", + "@libp2p/interface-libp2p": "^2.0.0", "@libp2p/interface-metrics": "^4.0.0", "@libp2p/interface-peer-discovery": "^1.0.1", "@libp2p/interface-peer-id": "^2.0.1", "@libp2p/interface-peer-info": "^1.0.3", "@libp2p/interface-peer-routing": "^1.0.1", - "@libp2p/interface-peer-store": "^1.2.2", + "@libp2p/interface-peer-store": "^2.0.0", "@libp2p/interface-pubsub": "^4.0.0", "@libp2p/interface-record": "^2.0.6", "@libp2p/interface-registrar": "^2.0.3", "@libp2p/interface-stream-muxer": "^4.0.0", - "@libp2p/interface-transport": "^3.0.0", + "@libp2p/interface-transport": "^4.0.0", "@libp2p/interfaces": "^3.2.0", "@libp2p/keychain": "^2.0.0", "@libp2p/logger": "^2.0.1", @@ -129,7 +129,7 @@ "@libp2p/peer-id": "^2.0.0", "@libp2p/peer-id-factory": "^2.0.0", "@libp2p/peer-record": "^5.0.0", - "@libp2p/peer-store": "^7.0.0", + "@libp2p/peer-store": "^8.0.0", "@libp2p/topology": "^4.0.1", "@libp2p/tracked-map": "^3.0.0", "@libp2p/utils": "^3.0.10", @@ -170,17 +170,17 @@ "xsalsa20": "^1.1.0" }, "devDependencies": { - "@chainsafe/libp2p-gossipsub": "^6.2.0", + "@chainsafe/libp2p-gossipsub": "^7.0.0", "@chainsafe/libp2p-noise": "^11.0.0", "@chainsafe/libp2p-yamux": "^4.0.0", - "@libp2p/bootstrap": "^6.0.0", + "@libp2p/bootstrap": "^7.0.0", "@libp2p/daemon-client": "^6.0.0", "@libp2p/daemon-server": "^5.0.0", "@libp2p/floodsub": "^7.0.1", "@libp2p/interface-compliance-tests": "^3.0.6", "@libp2p/interface-connection-compliance-tests": "^2.0.8", "@libp2p/interface-connection-encrypter-compliance-tests": "^5.0.0", - "@libp2p/interface-mocks": "^10.0.0", + "@libp2p/interface-mocks": "^11.0.0", "@libp2p/interop": "^8.0.0", "@libp2p/kad-dht": "^8.0.11", "@libp2p/mdns": "^7.0.0", diff --git a/src/address-manager/index.ts b/src/address-manager/index.ts index 7344ddbcf8..0dc0203ff2 100644 --- a/src/address-manager/index.ts +++ b/src/address-manager/index.ts @@ -148,7 +148,9 @@ export class DefaultAddressManager { // only trigger the 'self:peer:update' event if our confidence in an address has changed if (!startingConfidence) { - this.components.peerStore.addressBook.set(this.components.peerId, this.getAddresses()) + this.components.peerStore.patch(this.components.peerId, { + multiaddrs: this.getAddresses() + }) .catch(err => { log.error('error updating addresses', err) }) } } diff --git a/src/circuit-relay/server/index.ts b/src/circuit-relay/server/index.ts index 83482696ae..d86ec3aca8 100644 --- a/src/circuit-relay/server/index.ts +++ b/src/circuit-relay/server/index.ts @@ -260,7 +260,11 @@ class CircuitRelayServer extends EventEmitter implements Star // result.expire is non-null if `ReservationStore.reserve` returns with status == OK if (result.expire != null) { const ttl = (result.expire * 1000) - Date.now() - await this.peerStore.tagPeer(connection.remotePeer, RELAY_SOURCE_TAG, { value: 1, ttl }) + await this.peerStore.merge(connection.remotePeer, { + tags: { + [RELAY_SOURCE_TAG]: { value: 1, ttl } + } + }) } hopstr.write({ diff --git a/src/circuit-relay/transport/discovery.ts b/src/circuit-relay/transport/discovery.ts index 545ced3cae..22438a02b5 100644 --- a/src/circuit-relay/transport/discovery.ts +++ b/src/circuit-relay/transport/discovery.ts @@ -113,7 +113,9 @@ export class RelayDiscovery extends EventEmitter implement found++ log('found relay peer %p in content routing', peerId) - await this.peerStore.addressBook.add(peerId, provider.multiaddrs) + await this.peerStore.merge(peerId, { + multiaddrs: provider.multiaddrs + }) this.safeDispatchEvent('relay:discover', { detail: peerId }) } diff --git a/src/circuit-relay/transport/index.ts b/src/circuit-relay/transport/index.ts index 2bbf3e3246..b8fa45c5b5 100644 --- a/src/circuit-relay/transport/index.ts +++ b/src/circuit-relay/transport/index.ts @@ -183,7 +183,9 @@ class CircuitRelayTransport implements Transport { let relayConnection = relayConnections[0] if (relayConnection == null) { - await this.peerStore.addressBook.add(relayPeer, [relayAddr]) + await this.peerStore.merge(relayPeer, { + multiaddrs: [relayAddr] + }) relayConnection = await this.connectionManager.openConnection(relayPeer, options) disconnectOnFailure = true } diff --git a/src/circuit-relay/transport/reservation-store.ts b/src/circuit-relay/transport/reservation-store.ts index 1e815b675d..2b670c17d5 100644 --- a/src/circuit-relay/transport/reservation-store.ts +++ b/src/circuit-relay/transport/reservation-store.ts @@ -188,9 +188,13 @@ export class ReservationStore extends EventEmitter imple }) // ensure we don't close the connection to the relay - await this.peerStore.tagPeer(peerId, RELAY_TAG, { - value: 1, - ttl: expiration + await this.peerStore.merge(peerId, { + tags: { + [RELAY_TAG]: { + value: 1, + ttl: expiration + } + } }) await this.transportManager.listen( diff --git a/src/connection-manager/auto-dial.ts b/src/connection-manager/auto-dial.ts index b25f85fafa..581dd4e589 100644 --- a/src/connection-manager/auto-dial.ts +++ b/src/connection-manager/auto-dial.ts @@ -97,6 +97,10 @@ export class AutoDial implements Startable { } async autoDial (): Promise { + if (!this.started) { + return + } + const numConnections = this.connectionManager.getConnections().length // Already has enough connections @@ -131,10 +135,8 @@ export class AutoDial implements Startable { continue } - const tags = await this.peerStore.getTags(peer.id) - // sum all tag values - peerValues.set(peer.id, (tags ?? []).reduce((acc, curr) => { + peerValues.set(peer.id, [...peer.tags.values()].reduce((acc, curr) => { return acc + curr.value }, 0)) } diff --git a/src/connection-manager/connection-pruner.ts b/src/connection-manager/connection-pruner.ts index 814c3dedd8..5837082fe1 100644 --- a/src/connection-manager/connection-pruner.ts +++ b/src/connection-manager/connection-pruner.ts @@ -76,12 +76,20 @@ export class ConnectionPruner { continue } - const tags = await this.peerStore.getTags(remotePeer) - - // sum all tag values - peerValues.set(remotePeer, tags.reduce((acc, curr) => { - return acc + curr.value - }, 0)) + peerValues.set(remotePeer, 0) + + try { + const peer = await this.peerStore.get(remotePeer) + + // sum all tag values + peerValues.set(remotePeer, [...peer.tags.values()].reduce((acc, curr) => { + return acc + curr.value + }, 0)) + } catch (err: any) { + if (err.code !== 'ERR_NOT_FOUND') { + log.error('error loading peer tags', err) + } + } } // sort by value, lowest to highest diff --git a/src/connection-manager/dial-queue.ts b/src/connection-manager/dial-queue.ts index 1eff2c1a68..0297414227 100644 --- a/src/connection-manager/dial-queue.ts +++ b/src/connection-manager/dial-queue.ts @@ -14,7 +14,7 @@ import type { Connection } from '@libp2p/interface-connection' import type { AbortOptions } from '@libp2p/interfaces' import type { PeerId } from '@libp2p/interface-peer-id' import { getPeerAddress } from '../get-peer.js' -import type { Address, AddressSorter, PeerStore } from '@libp2p/interface-peer-store' +import type { Address, PeerStore } from '@libp2p/interface-peer-store' import type { Metric, Metrics } from '@libp2p/interface-metrics' import type { TransportManager } from '@libp2p/interface-transport' import type { ConnectionGater } from '@libp2p/interface-connection-gater' @@ -23,6 +23,7 @@ import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers' import { combineSignals, resolveMultiaddrs } from './utils.js' import pDefer from 'p-defer' import type { ClearableSignal } from 'any-signal' +import type { AddressSorter } from '@libp2p/interface-libp2p' const log = logger('libp2p:connection-manager:dial-queue') @@ -280,8 +281,15 @@ export class DialQueue { // if just a peer id was passed, load available multiaddrs for this peer from the address book if (addrs.length === 0) { log('loading multiaddrs for %p', peerId) - addrs.push(...(await this.peerStore.addressBook.get(peerId))) - log('loaded multiaddrs for %p', peerId, addrs.map(({ multiaddr }) => multiaddr.toString())) + try { + const peer = await this.peerStore.get(peerId) + addrs.push(...peer.addresses) + log('loaded multiaddrs for %p', peerId, addrs.map(({ multiaddr }) => multiaddr.toString())) + } catch (err: any) { + if (err.code !== codes.ERR_NOT_FOUND) { + throw err + } + } } } diff --git a/src/connection-manager/index.ts b/src/connection-manager/index.ts index 5fe6f4619b..aa7d7e9521 100644 --- a/src/connection-manager/index.ts +++ b/src/connection-manager/index.ts @@ -7,7 +7,7 @@ import { codes } from '../errors.js' import type { PeerId } from '@libp2p/interface-peer-id' import type { Connection, MultiaddrConnection } from '@libp2p/interface-connection' import type { ConnectionManager } from '@libp2p/interface-connection-manager' -import type { AddressSorter, PeerStore } from '@libp2p/interface-peer-store' +import type { PeerStore } from '@libp2p/interface-peer-store' import { Multiaddr, Resolver, multiaddr } from '@multiformats/multiaddr' import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags' import { RateLimiterMemory } from 'rate-limiter-flexible' @@ -23,7 +23,7 @@ import { publicAddressesFirst } from '@libp2p/utils/address-sort' import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_PRIORITY, DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, MAX_CONNECTIONS, MAX_INCOMING_PENDING_CONNECTIONS, MAX_PARALLEL_DIALS, MAX_PEER_ADDRS_TO_DIAL, MIN_CONNECTIONS } from './constants.js' import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers' import type { PendingDial } from '../libp2p.js' -import type { Libp2pEvents } from '@libp2p/interface-libp2p' +import type { AddressSorter, Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:connection-manager') @@ -348,10 +348,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable { const keepAlivePeers: PeerId[] = [] for (const peer of await this.peerStore.all()) { - const tags = await this.peerStore.getTags(peer.id) - const hasKeepAlive = tags.filter(tag => tag.name === KEEP_ALIVE).length > 0 - - if (hasKeepAlive) { + if (peer.tags.has(KEEP_ALIVE)) { keepAlivePeers.push(peer.id) } } @@ -429,8 +426,11 @@ export class DefaultConnectionManager implements ConnectionManager, Startable { this.connections.set(peerId, [connection]) } - if (peerId.publicKey != null) { - await this.peerStore.keyBook.set(peerId, peerId.publicKey) + // only need to store RSA public keys, all other types are embedded in the peer id + if (peerId.publicKey != null && peerId.type === 'RSA') { + await this.peerStore.patch(peerId, { + publicKey: peerId.publicKey + }) } if (isNewPeer) { diff --git a/src/content-routing/utils.ts b/src/content-routing/utils.ts index 47c01922df..47725262b0 100644 --- a/src/content-routing/utils.ts +++ b/src/content-routing/utils.ts @@ -11,7 +11,9 @@ import type { PeerStore } from '@libp2p/interface-peer-store' export async function * storeAddresses (source: Source, peerStore: PeerStore): AsyncIterable { yield * map(source, async (peer) => { // ensure we have the addresses for a given peer - await peerStore.addressBook.add(peer.id, peer.multiaddrs) + await peerStore.merge(peer.id, { + multiaddrs: peer.multiaddrs + }) return peer }) diff --git a/src/identify/index.ts b/src/identify/index.ts index 0391afb3df..2ec3fbd85a 100644 --- a/src/identify/index.ts +++ b/src/identify/index.ts @@ -27,10 +27,12 @@ import { abortableDuplex } from 'abortable-iterator' import { setMaxListeners } from 'events' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { PeerId } from '@libp2p/interface-peer-id' -import type { PeerStore } from '@libp2p/interface-peer-store' +import type { Peer, PeerStore } from '@libp2p/interface-peer-store' import type { AddressManager } from '@libp2p/interface-address-manager' import type { EventEmitter } from '@libp2p/interfaces/events' import type { Libp2pEvents } from '@libp2p/interface-libp2p' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' +import { pbStream } from 'it-pb-stream' const log = logger('libp2p:identify') @@ -111,22 +113,9 @@ export class IdentifyService implements Startable { this.identify(connection).catch(err => { log.error('error during identify trigged by connection:open', err) }) }) - // When self multiaddrs change, trigger identify-push - this.components.peerStore.addEventListener('change:multiaddrs', (evt) => { - const { peerId } = evt.detail - - if (this.components.peerId.equals(peerId)) { - void this.pushToPeerStore().catch(err => { log.error(err) }) - } - }) - - // When self protocols change, trigger identify-push - this.components.peerStore.addEventListener('change:protocols', (evt) => { - const { peerId } = evt.detail - - if (this.components.peerId.equals(peerId)) { - void this.pushToPeerStore().catch(err => { log.error(err) }) - } + // When self peer record changes, trigger identify-push + this.components.events.addEventListener('self:peer:update', (evt) => { + void this.pushToPeerStore().catch(err => { log.error(err) }) }) } @@ -139,8 +128,12 @@ export class IdentifyService implements Startable { return } - await this.components.peerStore.metadataBook.setValue(this.components.peerId, 'AgentVersion', uint8ArrayFromString(this.host.agentVersion)) - await this.components.peerStore.metadataBook.setValue(this.components.peerId, 'ProtocolVersion', uint8ArrayFromString(this.host.protocolVersion)) + await this.components.peerStore.merge(this.components.peerId, { + metadata: { + AgentVersion: uint8ArrayFromString(this.host.agentVersion), + ProtocolVersion: uint8ArrayFromString(this.host.protocolVersion) + } + }) await this.components.registrar.handle(this.identifyProtocolStr, (data) => { void this._handleIdentify(data).catch(err => { @@ -173,9 +166,16 @@ export class IdentifyService implements Startable { * Send an Identify Push update to the list of connections */ async push (connections: Connection[]): Promise { - const signedPeerRecord = await this.components.peerStore.addressBook.getRawEnvelope(this.components.peerId) - const listenAddrs = this.components.addressManager.getAddresses().map((ma) => ma.bytes) - const protocols = await this.components.peerStore.protoBook.get(this.components.peerId) + const listenAddresses = this.components.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code)) + const peerRecord = new PeerRecord({ + peerId: this.components.peerId, + multiaddrs: listenAddresses + }) + const signedPeerRecord = await RecordEnvelope.seal(peerRecord, this.components.peerId) + const supportedProtocols = this.components.registrar.getProtocols() + const peer = await this.components.peerStore.get(this.components.peerId) + const agentVersion = uint8ArrayToString(peer.metadata.get('AgentVersion') ?? uint8ArrayFromString(this.host.agentVersion)) + const protocolVersion = uint8ArrayToString(peer.metadata.get('ProtocolVersion') ?? uint8ArrayFromString(this.host.protocolVersion)) const pushes = connections.map(async connection => { let stream: Stream | undefined @@ -196,9 +196,11 @@ export class IdentifyService implements Startable { await source.sink(pipe( [Identify.encode({ - listenAddrs, - signedPeerRecord, - protocols + listenAddrs: listenAddresses.map(ma => ma.bytes), + signedPeerRecord: signedPeerRecord.marshal(), + protocols: supportedProtocols, + agentVersion, + protocolVersion })], (source) => lp.encode(source) )) @@ -302,15 +304,10 @@ export class IdentifyService implements Startable { */ async identify (connection: Connection, options: AbortOptions = {}): Promise { const message = await this._identify(connection, options) - const { publicKey, - listenAddrs, protocols, - observedAddr, - signedPeerRecord, - agentVersion, - protocolVersion + observedAddr } = message if (publicKey == null) { @@ -330,57 +327,6 @@ export class IdentifyService implements Startable { // Get the observedAddr if there is one const cleanObservedAddr = IdentifyService.getCleanMultiaddr(observedAddr) - if (signedPeerRecord != null) { - log('received signed peer record from %p', id) - - try { - const envelope = await RecordEnvelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN) - - if (!envelope.peerId.equals(id)) { - throw new CodeError('identified peer does not match the expected peer', codes.ERR_INVALID_PEER) - } - - if (await this.components.peerStore.addressBook.consumePeerRecord(envelope)) { - await this.components.peerStore.protoBook.set(id, protocols) - - if (agentVersion != null) { - await this.components.peerStore.metadataBook.setValue(id, 'AgentVersion', uint8ArrayFromString(agentVersion)) - } - - if (protocolVersion != null) { - await this.components.peerStore.metadataBook.setValue(id, 'ProtocolVersion', uint8ArrayFromString(protocolVersion)) - } - - log('identify completed for peer %p with protocols %o', id, protocols) - - return - } - } catch (err: any) { - log('received invalid envelope, discard it and fallback to listenAddrs is available', err) - } - } else { - log('no signed peer record received from %p', id) - } - - log('falling back to legacy addresses from %p', id) - - // LEGACY: Update peers data in PeerStore - try { - await this.components.peerStore.addressBook.set(id, listenAddrs.map((addr) => multiaddr(addr))) - } catch (err: any) { - log.error('received invalid addrs', err) - } - - await this.components.peerStore.protoBook.set(id, protocols) - - if (agentVersion != null) { - await this.components.peerStore.metadataBook.setValue(id, 'AgentVersion', uint8ArrayFromString(agentVersion)) - } - - if (protocolVersion != null) { - await this.components.peerStore.metadataBook.setValue(id, 'ProtocolVersion', uint8ArrayFromString(protocolVersion)) - } - log('identify completed for peer %p and protocols %o', id, protocols) log('our observed address is %s', cleanObservedAddr) @@ -389,6 +335,8 @@ export class IdentifyService implements Startable { log('storing our observed address %s', cleanObservedAddr?.toString()) this.components.addressManager.addObservedAddr(cleanObservedAddr) } + + await this.#consumeIdentifyMessage(connection.remotePeer, message) } /** @@ -417,7 +365,6 @@ export class IdentifyService implements Startable { }) const envelope = await RecordEnvelope.seal(peerRecord, this.components.peerId) - await this.components.peerStore.addressBook.consumePeerRecord(envelope) signedPeerRecord = envelope.marshal().subarray() } @@ -449,88 +396,98 @@ export class IdentifyService implements Startable { */ async _handlePush (data: IncomingStreamData): Promise { const { connection, stream } = data - const timeoutController = new TimeoutController(this.init.timeout) try { - // fails on node < 15.4 - setMaxListeners?.(Infinity, timeoutController.signal) - } catch {} + if (this.components.peerId.equals(connection.remotePeer)) { + throw new Error('received push from ourselves?') + } - let message: Identify | undefined - try { // make stream abortable - const source = abortableDuplex(stream, timeoutController.signal) - - const data = await pipe( - [], - source, - (source) => lp.decode(source, { - maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE - }), - async (source) => await first(source) - ) + const source = abortableDuplex(stream, AbortSignal.timeout(this.init.timeout)) + const pb = pbStream(source, { + maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE + }) + const message = await pb.readPB(Identify) - if (data != null) { - message = Identify.decode(data) - } + await this.#consumeIdentifyMessage(connection.remotePeer, message) } catch (err: any) { log.error('received invalid message', err) return } finally { stream.close() - timeoutController.clear() } + log('handled push from %p', connection.remotePeer) + } + + async #consumeIdentifyMessage (remotePeer: PeerId, message: Identify): Promise { if (message == null) { - log.error('received invalid message') - return + throw new Error('Message was null or undefined') } - const id = connection.remotePeer + log('received identify from %p', remotePeer) - if (this.components.peerId.equals(id)) { - log('received push from ourselves?') + if (message.signedPeerRecord == null) { return } - log('received push from %p', id) + const envelope = await RecordEnvelope.openAndCertify(message.signedPeerRecord, PeerRecord.DOMAIN) + const peerRecord = PeerRecord.createFromProtobuf(envelope.payload) - if (message.signedPeerRecord != null) { - log('received signedPeerRecord in push') + // Verify peerId + if (!peerRecord.peerId.equals(envelope.peerId)) { + throw new Error('signing key does not match PeerId in the PeerRecord') + } - try { - const envelope = await RecordEnvelope.openAndCertify(message.signedPeerRecord, PeerRecord.DOMAIN) + // Make sure remote peer is the one sending the record + if (!remotePeer.equals(peerRecord.peerId)) { + throw new Error('signing key does not match remote PeerId') + } - if (await this.components.peerStore.addressBook.consumePeerRecord(envelope)) { - log('consumed signedPeerRecord sent in push') + let peer: Peer | undefined - await this.components.peerStore.protoBook.set(id, message.protocols) - return - } else { - log('failed to consume signedPeerRecord sent in push') - } - } catch (err: any) { - log('received invalid envelope, discard it and fallback to listenAddrs is available', err) + try { + peer = await this.components.peerStore.get(peerRecord.peerId) + } catch (err: any) { + if (err.code !== 'ERR_NOT_FOUND') { + throw err } - } else { - log('did not receive signedPeerRecord in push') } - // LEGACY: Update peers data in PeerStore - try { - await this.components.peerStore.addressBook.set(id, message.listenAddrs.map((addr) => multiaddr(addr))) - } catch (err: any) { - log.error('received invalid addrs', err) + log('received signedPeerRecord in push from %p', remotePeer) + let metadata = new Map() + + if (peer?.peerRecordEnvelope != null) { + const storedEnvelope = await RecordEnvelope.createFromProtobuf(peer.peerRecordEnvelope) + const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload) + + // ensure seq is greater than, or equal to, the last received + if (storedRecord.seqNumber >= peerRecord.seqNumber) { + log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber) + } + + metadata = peer.metadata } - // Update the protocols - try { - await this.components.peerStore.protoBook.set(id, message.protocols) - } catch (err: any) { - log.error('received invalid protocols', err) + if (message.agentVersion != null) { + metadata.set('AgentVersion', uint8ArrayFromString(message.agentVersion)) } - log('handled push from %p', id) + if (message.protocolVersion != null) { + metadata.set('ProtocolVersion', uint8ArrayFromString(message.protocolVersion)) + } + + await this.components.peerStore.patch(peerRecord.peerId, { + peerRecordEnvelope: message.signedPeerRecord, + protocols: message.protocols, + addresses: peerRecord.multiaddrs.map(multiaddr => ({ + isCertified: true, + multiaddr + })), + metadata + }) + + log('consumed signedPeerRecord sent in push from %p', remotePeer) } /** diff --git a/src/index.ts b/src/index.ts index eefb49aede..bba959a515 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,6 @@ import type { TransportManagerInit } from './transport-manager.js' import type { IdentifyServiceInit } from './identify/index.js' import type { DualDHT } from '@libp2p/interface-dht' import type { Datastore } from 'interface-datastore' -import type { PeerStoreInit } from '@libp2p/interface-peer-store' import type { PeerId } from '@libp2p/interface-peer-id' import type { PeerDiscovery } from '@libp2p/interface-peer-discovery' import type { ConnectionProtector } from '@libp2p/interface-connection' @@ -43,6 +42,7 @@ import type { AddressManagerInit } from './address-manager/index.js' import type { PeerRoutingInit } from './peer-routing.js' import type { ConnectionManagerInit } from './connection-manager/index.js' import type { CircuitRelayService } from './circuit-relay/index.js' +import type { PersistentPeerStoreInit } from '@libp2p/peer-store' /** * For Libp2p configurations and modules details read the [Configuration Document](./CONFIGURATION.md). @@ -83,7 +83,7 @@ export interface Libp2pInit { /** * libp2p PeerStore configuration */ - peerStore: PeerStoreInit + peerStore: PersistentPeerStoreInit /** * libp2p Peer routing service configuration diff --git a/src/libp2p.ts b/src/libp2p.ts index 56c7c89786..4fb5079688 100644 --- a/src/libp2p.ts +++ b/src/libp2p.ts @@ -17,7 +17,6 @@ import { IdentifyService } from './identify/index.js' import { FetchService } from './fetch/index.js' import { PingService } from './ping/index.js' import { NatManager } from './nat-manager.js' -import { PeerRecordUpdater } from './peer-record-updater.js' import { DHTPeerRouting } from './dht/dht-peer-routing.js' import { PersistentPeerStore } from '@libp2p/peer-store' import { DHTContentRouting } from './dht/dht-content-routing.js' @@ -40,7 +39,6 @@ import type { DualDHT } from '@libp2p/interface-dht' import { concat as uint8ArrayConcat } from 'uint8arrays/concat' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { CodeError } from '@libp2p/interfaces/errors' -import { unmarshalPublicKey } from '@libp2p/crypto/keys' import type { Metrics } from '@libp2p/interface-metrics' import { DummyDHT } from './dht/dummy-dht.js' import { DummyPubSub } from './pubsub/dummy-pubsub.js' @@ -141,10 +139,11 @@ export class Libp2pNode extends EventEmitter implements Libp2p { this.peerStore = this.components.peerStore - this.peerStore.addEventListener('peer', evt => { - const { detail: peerData } = evt - - this.safeDispatchEvent('peer:discovery', { detail: peerData }) + this.components.events.addEventListener('peer:update', evt => { + // if there was no peer previously in the peer store this is a new peer + if (evt.detail.previous == null) { + this.safeDispatchEvent('peer:discovery', { detail: evt.detail.peer }) + } }) // Set up connection protector if configured @@ -171,9 +170,6 @@ export class Libp2pNode extends EventEmitter implements Libp2p { // Addresses {listen, announce, noAnnounce} this.components.addressManager = new DefaultAddressManager(this.components, init.addresses) - // update our peer record when addresses change - this.configureComponent(new PeerRecordUpdater(this.components)) - // Create keychain const keychainOpts = DefaultKeyChain.generateOptions() this.keychain = this.configureComponent(new DefaultKeyChain(this.components, { @@ -428,12 +424,8 @@ export class Libp2pNode extends EventEmitter implements Libp2p { const peerInfo = await this.peerStore.get(peer) - if (peerInfo.pubKey != null) { - return peerInfo.pubKey - } - - if (this.dht == null) { - throw new CodeError('Public key was not in the peer store and the DHT is not enabled', codes.ERR_NO_ROUTERS_AVAILABLE) + if (peerInfo.id.publicKey != null) { + return peerInfo.id.publicKey } const peerKey = uint8ArrayConcat([ @@ -441,24 +433,22 @@ export class Libp2pNode extends EventEmitter implements Libp2p { peer.multihash.digest ]) - // search the dht - for await (const event of this.dht.get(peerKey, options)) { - if (event.name === 'VALUE') { - const key = unmarshalPublicKey(event.value) - - await this.peerStore.keyBook.set(peer, event.value) + // search any available content routing methods + const bytes = await this.contentRouting.get(peerKey, options) - return key.bytes - } - } + await this.peerStore.patch(peer, { + publicKey: bytes + }) - throw new CodeError(`Node not responding with its public key: ${peer.toString()}`, codes.ERR_INVALID_RECORD) + return bytes } async fetch (peer: PeerId | Multiaddr, key: string, options: AbortOptions = {}): Promise { if (isMultiaddr(peer)) { const peerId = peerIdFromString(peer.getPeerId() ?? '') - await this.components.peerStore.addressBook.add(peerId, [peer]) + await this.components.peerStore.merge(peerId, { + multiaddrs: [peer] + }) peer = peerId } @@ -468,7 +458,9 @@ export class Libp2pNode extends EventEmitter implements Libp2p { async ping (peer: PeerId | Multiaddr, options: AbortOptions = {}): Promise { if (isMultiaddr(peer)) { const peerId = peerIdFromString(peer.getPeerId() ?? '') - await this.components.peerStore.addressBook.add(peerId, [peer]) + await this.components.peerStore.merge(peerId, { + multiaddrs: [peer] + }) peer = peerId } @@ -519,15 +511,11 @@ export class Libp2pNode extends EventEmitter implements Libp2p { return } - if (peer.multiaddrs.length > 0) { - void this.components.peerStore.addressBook.add(peer.id, peer.multiaddrs).catch(err => { log.error(err) }) - } - - if (peer.protocols.length > 0) { - void this.components.peerStore.protoBook.set(peer.id, peer.protocols).catch(err => { log.error(err) }) - } - - this.safeDispatchEvent('peer:discovery', { detail: peer }) + void this.components.peerStore.merge(peer.id, { + multiaddrs: peer.multiaddrs, + protocols: peer.protocols + }) + .catch(err => { log.error(err) }) } } diff --git a/src/peer-record-updater.ts b/src/peer-record-updater.ts deleted file mode 100644 index 893d220f3a..0000000000 --- a/src/peer-record-updater.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' -import type { Startable } from '@libp2p/interfaces/startable' -import { logger } from '@libp2p/logger' -import { protocols } from '@multiformats/multiaddr' -import type { AddressManager } from '@libp2p/interface-address-manager' -import type { PeerId } from '@libp2p/interface-peer-id' -import type { PeerStore } from '@libp2p/interface-peer-store' -import type { EventEmitter } from '@libp2p/interfaces/events' -import type { Libp2pEvents } from '@libp2p/interface-libp2p' - -const log = logger('libp2p:peer-record-updater') - -export interface PeerRecordUpdaterComponents { - peerId: PeerId - peerStore: PeerStore - addressManager: AddressManager - events: EventEmitter -} - -export class PeerRecordUpdater implements Startable { - private readonly components: PeerRecordUpdaterComponents - private started: boolean - - constructor (components: PeerRecordUpdaterComponents) { - this.components = components - this.started = false - this.update = this.update.bind(this) - } - - isStarted (): boolean { - return this.started - } - - async start (): Promise { - this.started = true - this.components.events.addEventListener('transport:listening', this.update) - this.components.events.addEventListener('transport:close', this.update) - this.components.events.addEventListener('self:peer:update', this.update) - } - - async stop (): Promise { - this.started = false - this.components.events.removeEventListener('transport:listening', this.update) - this.components.events.removeEventListener('transport:close', this.update) - this.components.events.removeEventListener('self:peer:update', this.update) - } - - /** - * Create (or update if existing) self peer record and store it in the AddressBook. - */ - update (): void { - Promise.resolve() - .then(async () => { - const peerRecord = new PeerRecord({ - peerId: this.components.peerId, - multiaddrs: this.components.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code)) - }) - - const envelope = await RecordEnvelope.seal(peerRecord, this.components.peerId) - await this.components.peerStore.addressBook.consumePeerRecord(envelope) - }) - .catch(err => { - log.error('Could not update self peer record: %o', err) - }) - } -} diff --git a/src/registrar.ts b/src/registrar.ts index 43c6d78afe..b5d0acf949 100644 --- a/src/registrar.ts +++ b/src/registrar.ts @@ -4,12 +4,12 @@ import { codes } from './errors.js' import { isTopology, StreamHandlerOptions, StreamHandlerRecord } from '@libp2p/interface-registrar' import merge from 'merge-options' import type { Registrar, StreamHandler, Topology } from '@libp2p/interface-registrar' -import type { PeerStore, PeerUpdate } from '@libp2p/interface-peer-store' +import type { PeerStore } from '@libp2p/interface-peer-store' import type { Connection } from '@libp2p/interface-connection' import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { PeerId } from '@libp2p/interface-peer-id' import type { EventEmitter } from '@libp2p/interfaces/events' -import type { Libp2pEvents } from '@libp2p/interface-libp2p' +import type { Libp2pEvents, PeerUpdate } from '@libp2p/interface-libp2p' const log = logger('libp2p:registrar') @@ -47,7 +47,6 @@ export class DefaultRegistrar implements Registrar { getProtocols (): string[] { return Array.from(new Set([ - ...this.topologies.keys(), ...this.handlers.keys() ])).sort() } @@ -92,8 +91,10 @@ export class DefaultRegistrar implements Registrar { options }) - // Add new protocols to self protocols in the Protobook - await this.components.peerStore.protoBook.add(this.components.peerId, [protocol]) + // Add new protocol to self protocols in the peer store + await this.components.peerStore.merge(this.components.peerId, { + protocols: [protocol] + }) } /** @@ -107,8 +108,10 @@ export class DefaultRegistrar implements Registrar { this.handlers.delete(protocol) }) - // Remove protocols from self protocols in the Protobook - await this.components.peerStore.protoBook.remove(this.components.peerId, protocolList) + // Update self protocols in the peer store + await this.components.peerStore.patch(this.components.peerId, { + protocols: protocolList + }) } /** @@ -159,9 +162,9 @@ export class DefaultRegistrar implements Registrar { _onDisconnect (evt: CustomEvent): void { const connection = evt.detail - void this.components.peerStore.protoBook.get(connection.remotePeer) - .then(peerProtocols => { - for (const protocol of peerProtocols) { + void this.components.peerStore.get(connection.remotePeer) + .then(peer => { + for (const protocol of peer.protocols) { const topologies = this.topologies.get(protocol) if (topologies == null) { @@ -186,9 +189,9 @@ export class DefaultRegistrar implements Registrar { _onConnect (evt: CustomEvent): void { const connection = evt.detail - void this.components.peerStore.protoBook.get(connection.remotePeer) - .then(peerProtocols => { - for (const protocol of peerProtocols) { + void this.components.peerStore.get(connection.remotePeer) + .then(peer => { + for (const protocol of peer.protocols) { const topologies = this.topologies.get(protocol) if (topologies == null) { diff --git a/src/transport-manager.ts b/src/transport-manager.ts index df37b54f3b..c4ebd7a9c3 100644 --- a/src/transport-manager.ts +++ b/src/transport-manager.ts @@ -201,14 +201,30 @@ export class DefaultTransportManager implements TransportManager, Startable { // Track listen/close events listener.addEventListener('listening', () => { - this.components.events.safeDispatchEvent('transport:listening', { - detail: listener + this.components.peerStore.patch(this.components.peerId, { + multiaddrs: this.getAddrs() }) + .then(() => { + this.components.events.safeDispatchEvent('transport:listening', { + detail: listener + }) + }) + .catch(err => { + log.error('error while updating peer record after listener began listening', err) + }) }) listener.addEventListener('close', () => { - this.components.events.safeDispatchEvent('transport:close', { - detail: listener + this.components.peerStore.patch(this.components.peerId, { + multiaddrs: this.getAddrs() }) + .then(() => { + this.components.events.safeDispatchEvent('transport:close', { + detail: listener + }) + }) + .catch(err => { + log.error('error while updating peer record after listener stopped listening', err) + }) }) // We need to attempt to listen on everything @@ -241,8 +257,6 @@ export class DefaultTransportManager implements TransportManager, Startable { } log(`libp2p in dial mode only: ${message}`) } - - await this.components.peerStore.addressBook.set(this.components.peerId, this.getAddrs()) } /** diff --git a/src/upgrader.ts b/src/upgrader.ts index e68a800633..711887316f 100644 --- a/src/upgrader.ts +++ b/src/upgrader.ts @@ -403,7 +403,9 @@ export class DefaultUpgrader implements Upgrader { // If a protocol stream has been successfully negotiated and is to be passed to the application, // the peerstore should ensure that the peer is registered with that protocol - this.components.peerStore.protoBook.add(remotePeer, [protocol]).catch(err => { log.error(err) }) + await this.components.peerStore.merge(remotePeer, { + protocols: [protocol] + }) connection.addStream(muxedStream) this.components.metrics?.trackProtocolStream(muxedStream, connection) @@ -460,7 +462,9 @@ export class DefaultUpgrader implements Upgrader { // If a protocol stream has been successfully negotiated and is to be passed to the application, // the peerstore should ensure that the peer is registered with that protocol - this.components.peerStore.protoBook.add(remotePeer, [protocol]).catch(err => { log.error(err) }) + await this.components.peerStore.merge(remotePeer, { + protocols: [protocol] + }) // after the handshake the returned stream can have early data so override // the souce/sink diff --git a/test/addresses/address-manager.spec.ts b/test/addresses/address-manager.spec.ts index 592994e71d..278275fda6 100644 --- a/test/addresses/address-manager.spec.ts +++ b/test/addresses/address-manager.spec.ts @@ -10,7 +10,7 @@ import { StubbedInstance, stubInterface } from 'sinon-ts' import type { TransportManager } from '@libp2p/interface-transport' import type { PeerId } from '@libp2p/interface-peer-id' import type { Libp2p } from '../../src/index.js' -import type { AddressBook, PeerStore } from '@libp2p/interface-peer-store' +import type { PeerStore } from '@libp2p/interface-peer-store' const listenAddresses = ['/ip4/127.0.0.1/tcp/15006/ws', '/ip4/127.0.0.1/tcp/15008/ws'] const announceAddreses = ['/dns4/peer.io'] @@ -21,8 +21,10 @@ describe('Address Manager', () => { before(async () => { peerId = await createFromJSON(Peers[0]) - peerStore = stubInterface() - peerStore.addressBook = stubInterface() + peerStore = stubInterface({ + // @ts-expect-error incorrect return type + patch: Promise.resolve({}) + }) }) it('should not need any addresses', () => { @@ -147,7 +149,7 @@ describe('Address Manager', () => { am.confirmObservedAddr(multiaddr(ma)) am.confirmObservedAddr(multiaddr(`${ma.toString()}/p2p/${peerId.toString()}`)) - expect(peerStore.addressBook.set).to.have.property('callCount', 1) + expect(peerStore.patch).to.have.property('callCount', 1) }) it('should strip our peer address from added observed addresses', () => { diff --git a/test/autonat/index.spec.ts b/test/autonat/index.spec.ts index 7e84eec471..3d97e0b15d 100644 --- a/test/autonat/index.spec.ts +++ b/test/autonat/index.spec.ts @@ -17,7 +17,7 @@ import { Message } from '../../src/autonat/pb/index.js' import type { PeerId } from '@libp2p/interface-peer-id' import { pushable } from 'it-pushable' import type { Transport, TransportManager } from '@libp2p/interface-transport' -import type { AddressBook, PeerStore } from '@libp2p/interface-peer-store' +import type { PeerStore } from '@libp2p/interface-peer-store' import type { DefaultConnectionManager } from '../../src/connection-manager/index.js' import * as lp from 'it-length-prefixed' import all from 'it-all' @@ -54,7 +54,6 @@ describe('autonat', () => { connectionManager = stubInterface() transportManager = stubInterface() peerStore = stubInterface() - peerStore.addressBook = stubInterface() components = new DefaultComponents({ peerId: await createEd25519PeerId(), diff --git a/test/circuit-relay/hop.spec.ts b/test/circuit-relay/hop.spec.ts index cc55be138a..9373144bb7 100644 --- a/test/circuit-relay/hop.spec.ts +++ b/test/circuit-relay/hop.spec.ts @@ -25,6 +25,7 @@ import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { ConnectionGater } from '@libp2p/interface-connection-gater' import Sinon from 'sinon' import { EventEmitter } from '@libp2p/interfaces/events' +import type { Libp2pEvents } from '@libp2p/interface-libp2p' interface Node { peerId: PeerId @@ -36,6 +37,7 @@ interface Node { connectionManager: ConnectionManager circuitRelayTransport: Transport connectionGater: ConnectionGater + events: EventEmitter } let peerIndex = 0 @@ -63,11 +65,6 @@ describe('circuit-relay hop protocol', function () { ]) const peerStore = stubInterface() - const connectionManager = mockConnectionManager({ - peerId, - registrar - }) - const events = new EventEmitter() events.addEventListener('connection:open', (evt) => { const conn = evt.detail @@ -78,8 +75,15 @@ describe('circuit-relay hop protocol', function () { connections.delete(conn.remotePeer) }) + const connectionManager = mockConnectionManager({ + peerId, + registrar, + events + }) + const upgrader = mockUpgrader({ - registrar + registrar, + events }) const connectionGater = mockConnectionGater() @@ -124,7 +128,8 @@ describe('circuit-relay hop protocol', function () { upgrader, connectionManager, circuitRelayTransport: transport, - connectionGater + connectionGater, + events } mockNetwork.addNode(node) @@ -287,7 +292,15 @@ describe('circuit-relay hop protocol', function () { expect(response).to.have.property('type', HopMessage.Type.STATUS) expect(response).to.have.property('status', Status.OK) - expect(relayNode.peerStore.tagPeer.calledWith(matchPeerId(clientNode.peerId), RELAY_SOURCE_TAG)).to.be.true() + expect(relayNode.peerStore.merge.calledWith(matchPeerId(clientNode.peerId), { + tags: { + [RELAY_SOURCE_TAG]: { + value: 1, + // @ts-expect-error ttl is a number not a matcher + ttl: Sinon.match.number + } + } + })).to.be.true() }) }) diff --git a/test/circuit-relay/relay.node.ts b/test/circuit-relay/relay.node.ts index d58031b7b9..a8d1013bb1 100644 --- a/test/circuit-relay/relay.node.ts +++ b/test/circuit-relay/relay.node.ts @@ -93,8 +93,8 @@ describe('circuit-relay', () => { await usingAsRelay(local, relay1) // peer has relay multicodec - const knownProtocols = await local.peerStore.protoBook.get(relay1.peerId) - expect(knownProtocols).to.include(RELAY_V2_HOP_CODEC) + const peer = await local.peerStore.get(relay1.peerId) + expect(peer.protocols).to.include(RELAY_V2_HOP_CODEC) }) it('should only add discovered relays relayed addresses', async () => { @@ -236,11 +236,12 @@ describe('circuit-relay', () => { // set up listener for address change const deferred = defer() - local.peerStore.addEventListener('change:multiaddrs', ({ detail }) => { - const isLocalPeerId = local.peerId.equals(detail.peerId) - const hasCircuitRelayAddress = detail.multiaddrs.find(ma => Circuit.matches(ma)) != null + local.addEventListener('self:peer:update', ({ detail }) => { + const hasCircuitRelayAddress = detail.peer.addresses + .map(({ multiaddr }) => multiaddr) + .find(ma => Circuit.matches(ma)) != null - if (isLocalPeerId && hasCircuitRelayAddress) { + if (hasCircuitRelayAddress) { deferred.resolve() } }) @@ -270,11 +271,12 @@ describe('circuit-relay', () => { // set up listener for address change const deferred = defer() - local.peerStore.addEventListener('change:multiaddrs', ({ detail }) => { - const isLocalPeerId = local.peerId.equals(detail.peerId) - const hasNoCircuitRelayAddress = detail.multiaddrs.find(ma => Circuit.matches(ma)) == null + local.addEventListener('self:peer:update', ({ detail }) => { + const hasNoCircuitRelayAddress = detail.peer.addresses + .map(({ multiaddr }) => multiaddr) + .find(ma => Circuit.matches(ma)) == null - if (isLocalPeerId && hasNoCircuitRelayAddress) { + if (hasNoCircuitRelayAddress) { deferred.resolve() } }) @@ -363,18 +365,24 @@ describe('circuit-relay', () => { it('should not add listener to a already relayed connection', async () => { // Relay 1 discovers Relay 3 and connect - await relay1.peerStore.addressBook.add(relay3.peerId, relay3.getMultiaddrs()) + await relay1.peerStore.merge(relay3.peerId, { + multiaddrs: relay3.getMultiaddrs() + }) await relay1.dial(relay3.peerId) await usingAsRelay(relay1, relay3) // Relay 2 discovers Relay 3 and connect - await relay2.peerStore.addressBook.add(relay3.peerId, relay3.getMultiaddrs()) + await relay2.peerStore.merge(relay3.peerId, { + multiaddrs: relay3.getMultiaddrs() + }) await relay2.dial(relay3.peerId) await usingAsRelay(relay2, relay3) // Relay 1 discovers Relay 2 relayed multiaddr via Relay 3 const ma2RelayedBy3 = relay2.getMultiaddrs()[relay2.getMultiaddrs().length - 1] - await relay1.peerStore.addressBook.add(relay2.peerId, [ma2RelayedBy3]) + await relay1.peerStore.merge(relay2.peerId, { + multiaddrs: [ma2RelayedBy3] + }) await relay1.dial(relay2.peerId) // Peer not added as listen relay @@ -404,9 +412,11 @@ describe('circuit-relay', () => { expect(maWithoutPeerId.getPeerId()).to.not.equal(remote.peerId.toString()) // ensure this is the only address we have for the peer - await local.peerStore.addressBook.set(remote.peerId, [ - maWithoutPeerId - ]) + await local.peerStore.patch(remote.peerId, { + multiaddrs: [ + maWithoutPeerId + ] + }) // dial via peer id so we load the address from the address book await local.dial(remote.peerId) diff --git a/test/circuit-relay/utils.ts b/test/circuit-relay/utils.ts index 8f3f05710e..fc69e77439 100644 --- a/test/circuit-relay/utils.ts +++ b/test/circuit-relay/utils.ts @@ -85,8 +85,12 @@ export async function hasRelay (node: Libp2p, opts?: PWaitForOptions): P export async function discoveredRelayConfig (node: Libp2p, relay: Libp2p, opts?: PWaitForOptions): Promise { await pWaitFor(async () => { - const peerData = await node.peerStore.get(relay.peerId) - return peerData.protocols.includes(RELAY_V2_HOP_CODEC) + try { + const peerData = await node.peerStore.get(relay.peerId) + return peerData.protocols.includes(RELAY_V2_HOP_CODEC) + } catch { + return false + } }, opts) } diff --git a/test/configuration/protocol-prefix.node.ts b/test/configuration/protocol-prefix.node.ts index e53291bc83..3fdab4fedc 100644 --- a/test/configuration/protocol-prefix.node.ts +++ b/test/configuration/protocol-prefix.node.ts @@ -30,8 +30,8 @@ describe('Protocol prefix is configurable', () => { })) await libp2p.start() - const protocols = await libp2p.peerStore.protoBook.get(libp2p.peerId) - expect(protocols).to.include.members([ + const peer = await libp2p.peerStore.get(libp2p.peerId) + expect(peer.protocols).to.include.members([ `/${testProtocol}/fetch/0.0.1`, `/${testProtocol}/id/1.0.0`, `/${testProtocol}/id/push/1.0.0`, @@ -43,8 +43,8 @@ describe('Protocol prefix is configurable', () => { libp2p = await createLibp2pNode(validateConfig(baseOptions)) await libp2p.start() - const protocols = await libp2p.peerStore.protoBook.get(libp2p.peerId) - expect(protocols).to.include.members([ + const peer = await libp2p.peerStore.get(libp2p.peerId) + expect(peer.protocols).to.include.members([ '/ipfs/id/1.0.0', '/ipfs/id/push/1.0.0', '/ipfs/ping/1.0.0', diff --git a/test/connection-manager/auto-dial.spec.ts b/test/connection-manager/auto-dial.spec.ts index cb6281a1f2..7a43f2683e 100644 --- a/test/connection-manager/auto-dial.spec.ts +++ b/test/connection-manager/auto-dial.spec.ts @@ -12,6 +12,14 @@ import { multiaddr } from '@multiformats/multiaddr' import { EventEmitter } from '@libp2p/interfaces/events' describe('auto-dial', () => { + let autoDialler: AutoDial + + afterEach(() => { + if (autoDialler != null) { + autoDialler.stop() + } + }) + it('should not dial peers without multiaddrs', async () => { // peers with protocols are dialled before peers without protocols const peerWithAddress: Peer = { @@ -23,13 +31,15 @@ describe('auto-dial', () => { multiaddr: multiaddr('/ip4/127.0.0.1/tcp/4001'), isCertified: true }], - metadata: new Map() + metadata: new Map(), + tags: new Map() } const peerWithoutAddress: Peer = { id: await createEd25519PeerId(), protocols: [], addresses: [], - metadata: new Map() + metadata: new Map(), + tags: new Map() } const peerStore = stubInterface() @@ -48,6 +58,7 @@ describe('auto-dial', () => { }, { minConnections: 10 }) + autoDialler.start() await autoDialler.autoDial() await pWaitFor(() => connectionManager.openConnection.callCount === 1) diff --git a/test/connection-manager/direct.node.ts b/test/connection-manager/direct.node.ts index a8ebad1546..d66e096ef0 100644 --- a/test/connection-manager/direct.node.ts +++ b/test/connection-manager/direct.node.ts @@ -37,6 +37,7 @@ import fs from 'node:fs' import { peerIdFromString } from '@libp2p/peer-id' import { stubInterface } from 'sinon-ts' import type { TransportManager } from '@libp2p/interface-transport' +import { EventEmitter } from '@libp2p/interfaces/events' const swarmKeyBuffer = uint8ArrayFromString(swarmKey) const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0') @@ -57,10 +58,12 @@ describe('dialing (direct, TCP)', () => { createFromJSON(Peers[1]) ]) + const remoteEvents = new EventEmitter() remoteComponents = new DefaultComponents({ peerId: remotePeerId, + events: remoteEvents, datastore: new MemoryDatastore(), - upgrader: mockUpgrader(), + upgrader: mockUpgrader({ events: remoteEvents }), connectionGater: mockConnectionGater() }) remoteComponents.peerStore = new PersistentPeerStore(remoteComponents) @@ -72,10 +75,12 @@ describe('dialing (direct, TCP)', () => { remoteTM = new DefaultTransportManager(remoteComponents) remoteTM.add(tcp()()) + const localEvents = new EventEmitter() localComponents = new DefaultComponents({ peerId: localPeerId, + events: localEvents, datastore: new MemoryDatastore(), - upgrader: mockUpgrader(), + upgrader: mockUpgrader({ events: localEvents }), transportManager: stubInterface(), connectionGater: mockConnectionGater() }) @@ -113,9 +118,11 @@ describe('dialing (direct, TCP)', () => { it('should be able to connect to remote node with duplicated addresses', async () => { const remotePeer = peerIdFromString(remoteAddr.getPeerId() ?? '') const dnsaddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remotePeer}`) - await localComponents.peerStore.addressBook.add(remotePeer, [ - dnsaddr - ]) + await localComponents.peerStore.merge(remotePeer, { + multiaddrs: [ + dnsaddr + ] + }) const dialer = new DialQueue(localComponents, { resolvers: { dnsaddr: resolver @@ -149,7 +156,9 @@ describe('dialing (direct, TCP)', () => { }) it('should be able to connect to a given peer id', async () => { - await localComponents.peerStore.addressBook.set(remoteComponents.peerId, remoteTM.getAddrs()) + await localComponents.peerStore.patch(remoteComponents.peerId, { + multiaddrs: remoteTM.getAddrs() + }) const dialer = new DialQueue(localComponents) @@ -159,7 +168,9 @@ describe('dialing (direct, TCP)', () => { }) it('should fail to connect to a given peer with unsupported addresses', async () => { - await localComponents.peerStore.addressBook.add(remoteComponents.peerId, [unsupportedAddr]) + await localComponents.peerStore.patch(remoteComponents.peerId, { + multiaddrs: [unsupportedAddr] + }) const dialer = new DialQueue(localComponents) @@ -172,7 +183,9 @@ describe('dialing (direct, TCP)', () => { const remoteAddrs = remoteTM.getAddrs() const peerId = await createFromJSON(Peers[1]) - await localComponents.peerStore.addressBook.add(peerId, [...remoteAddrs, unsupportedAddr]) + await localComponents.peerStore.patch(peerId, { + multiaddrs: [...remoteAddrs, unsupportedAddr] + }) const dialer = new DialQueue(localComponents) @@ -246,7 +259,9 @@ describe('dialing (direct, TCP)', () => { ] // Inject data into the AddressBook - await localComponents.peerStore.addressBook.add(remoteComponents.peerId, addrs) + await localComponents.peerStore.merge(remoteComponents.peerId, { + multiaddrs: addrs + }) const dialer = new DialQueue(localComponents) @@ -371,7 +386,9 @@ describe('libp2p.dialer (direct, TCP)', () => { const dialerDialSpy = sinon.spy(libp2p.connectionManager, 'openConnection') - await libp2p.components.peerStore.addressBook.set(remotePeerId, remoteLibp2p.getMultiaddrs()) + await libp2p.components.peerStore.patch(remotePeerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) const connection = await libp2p.dial(remotePeerId) expect(connection).to.exist() @@ -412,7 +429,9 @@ describe('libp2p.dialer (direct, TCP)', () => { void pipe(stream, stream) }) - await libp2p.components.peerStore.addressBook.set(remotePeerId, remoteLibp2p.getMultiaddrs()) + await libp2p.components.peerStore.patch(remotePeerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) const connection = await libp2p.dial(remotePeerId) // Create local to remote streams @@ -553,7 +572,9 @@ describe('libp2p.dialer (direct, TCP)', () => { // PeerId should be in multiaddr expect(remoteAddr.getPeerId()).to.equal(remoteLibp2p.peerId.toString()) - await libp2p.components.peerStore.addressBook.set(remotePeerId, remoteLibp2p.getMultiaddrs()) + await libp2p.components.peerStore.patch(remotePeerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) const dialResults = await Promise.all([...new Array(dials)].map(async (_, index) => { if (index % 2 === 0) return await libp2p.dial(remoteLibp2p.peerId) return await libp2p.dial(remoteAddr) @@ -590,7 +611,9 @@ describe('libp2p.dialer (direct, TCP)', () => { const error = new Error('Boom') sinon.stub(libp2p.components.transportManager, 'dial').callsFake(async () => await Promise.reject(error)) - await libp2p.components.peerStore.addressBook.set(remotePeerId, remoteLibp2p.getMultiaddrs()) + await libp2p.components.peerStore.patch(remotePeerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) const dialResults = await Promise.allSettled([...new Array(dials)].map(async (_, index) => { if (index % 2 === 0) return await libp2p.dial(remoteLibp2p.peerId) return await libp2p.dial(remoteAddr) diff --git a/test/connection-manager/direct.spec.ts b/test/connection-manager/direct.spec.ts index 22aa4dad2b..c13bc57c53 100644 --- a/test/connection-manager/direct.spec.ts +++ b/test/connection-manager/direct.spec.ts @@ -41,13 +41,14 @@ describe('dialing (direct, WebSockets)', () => { let remoteComponents: DefaultComponents beforeEach(async () => { + const localEvents = new EventEmitter() localComponents = new DefaultComponents({ peerId: await createFromJSON(Peers[0]), datastore: new MemoryDatastore(), - upgrader: mockUpgrader(), + upgrader: mockUpgrader({ events: localEvents }), connectionGater: mockConnectionGater(), transportManager: stubInterface(), - events: new EventEmitter() + events: localEvents }) localComponents.peerStore = new PersistentPeerStore(localComponents, { addressFilter: localComponents.connectionGater.filterMultiaddrForPeer @@ -77,7 +78,9 @@ describe('dialing (direct, WebSockets)', () => { const connectionManager = new DefaultConnectionManager(localComponents) const remotePeerId = peerIdFromString(remoteAddr.getPeerId() ?? '') - await localComponents.peerStore.addressBook.set(remotePeerId, [remoteAddr]) + await localComponents.peerStore.patch(remotePeerId, { + multiaddrs: [remoteAddr] + }) const connection = await connectionManager.openConnection(remoteAddr) expect(connection).to.exist() @@ -96,7 +99,9 @@ describe('dialing (direct, WebSockets)', () => { const connectionManager = new DefaultConnectionManager(localComponents) const remotePeerId = peerIdFromString(remoteAddr.getPeerId() ?? '') - await localComponents.peerStore.addressBook.set(remotePeerId, [remoteAddr]) + await localComponents.peerStore.patch(remotePeerId, { + multiaddrs: [remoteAddr] + }) const connection = await connectionManager.openConnection(remotePeerId) expect(connection).to.exist() @@ -107,7 +112,9 @@ describe('dialing (direct, WebSockets)', () => { const connectionManager = new DefaultConnectionManager(localComponents) const remotePeerId = peerIdFromString(remoteAddr.getPeerId() ?? '') - await localComponents.peerStore.addressBook.set(remotePeerId, [unsupportedAddr]) + await localComponents.peerStore.patch(remotePeerId, { + multiaddrs: [unsupportedAddr] + }) await expect(connectionManager.openConnection(remotePeerId)) .to.eventually.be.rejectedWith(Error) @@ -120,7 +127,9 @@ describe('dialing (direct, WebSockets)', () => { }) const remotePeerId = peerIdFromString(remoteAddr.getPeerId() ?? '') - await localComponents.peerStore.addressBook.set(remotePeerId, [remoteAddr]) + await localComponents.peerStore.patch(remotePeerId, { + multiaddrs: [remoteAddr] + }) sinon.stub(localTM, 'dial').callsFake(async (addr, options) => { expect(options.signal).to.exist() @@ -142,7 +151,9 @@ describe('dialing (direct, WebSockets)', () => { }) const remotePeerId = peerIdFromString(remoteAddr.getPeerId() ?? '') - await localComponents.peerStore.addressBook.set(remotePeerId, Array.from({ length: 11 }, (_, i) => multiaddr(`/ip4/127.0.0.1/tcp/1500${i}/ws/p2p/12D3KooWHFKTMzwerBtsVmtz4ZZEQy2heafxzWw6wNn5PPYkBxJ5`))) + await localComponents.peerStore.patch(remotePeerId, { + multiaddrs: Array.from({ length: 11 }, (_, i) => multiaddr(`/ip4/127.0.0.1/tcp/1500${i}/ws/p2p/12D3KooWHFKTMzwerBtsVmtz4ZZEQy2heafxzWw6wNn5PPYkBxJ5`)) + }) await expect(connectionManager.openConnection(remotePeerId)) .to.eventually.be.rejected() @@ -165,7 +176,9 @@ describe('dialing (direct, WebSockets)', () => { }) // Inject data into the AddressBook - await localComponents.peerStore.addressBook.add(remoteComponents.peerId, peerMultiaddrs) + await localComponents.peerStore.merge(remoteComponents.peerId, { + multiaddrs: peerMultiaddrs + }) // Perform 3 multiaddr dials await connectionManager.openConnection(remoteComponents.peerId) @@ -190,7 +203,9 @@ describe('dialing (direct, WebSockets)', () => { }) // Inject data into the AddressBook - await localComponents.peerStore.addressBook.add(remoteComponents.peerId, addrs) + await localComponents.peerStore.merge(remoteComponents.peerId, { + multiaddrs: addrs + }) sinon.stub(localTM, 'dial').callsFake(async (_, options) => { const deferredDial = pDefer() @@ -225,7 +240,9 @@ describe('dialing (direct, WebSockets)', () => { ] // Inject data into the AddressBook - await localComponents.peerStore.addressBook.add(remoteComponents.peerId, addrs) + await localComponents.peerStore.merge(remoteComponents.peerId, { + multiaddrs: addrs + }) const connectionManager = new DefaultConnectionManager(localComponents) @@ -247,7 +264,9 @@ describe('dialing (direct, WebSockets)', () => { ] // Inject data into the AddressBook - await localComponents.peerStore.addressBook.add(remoteComponents.peerId, addrs) + await localComponents.peerStore.merge(remoteComponents.peerId, { + multiaddrs: addrs + }) // different address not in the address book, same peer id const dialMultiaddr = multiaddr(`/ip4/0.0.0.0/tcp/8003/ws/p2p/${remoteComponents.peerId.toString()}`) @@ -378,7 +397,7 @@ describe('libp2p.dialer (direct, WebSockets)', () => { } const identifySpy = sinon.spy(libp2p.identifyService, 'identify') - const protobookSetSpy = sinon.spy(libp2p.components.peerStore.protoBook, 'set') + const peerStorePatchSpy = sinon.spy(libp2p.components.peerStore, 'patch') const connectionPromise = pEvent(libp2p, 'connection:open') await libp2p.start() @@ -392,7 +411,7 @@ describe('libp2p.dialer (direct, WebSockets)', () => { expect(identifySpy.callCount).to.equal(1) await identifySpy.firstCall.returnValue - expect(protobookSetSpy.callCount).to.equal(1) + expect(peerStorePatchSpy.callCount).to.equal(1) await libp2p.stop() }) diff --git a/test/connection-manager/index.node.ts b/test/connection-manager/index.node.ts index 3efe122bfb..a69258e087 100644 --- a/test/connection-manager/index.node.ts +++ b/test/connection-manager/index.node.ts @@ -10,7 +10,7 @@ import { DefaultConnectionManager } from '../../src/connection-manager/index.js' import { EventEmitter } from '@libp2p/interfaces/events' import * as STATUS from '@libp2p/interface-connection/status' import { stubInterface } from 'sinon-ts' -import type { KeyBook, PeerStore } from '@libp2p/interface-peer-store' +import type { PeerStore } from '@libp2p/interface-peer-store' import sinon from 'sinon' import pWaitFor from 'p-wait-for' import delay from 'delay' @@ -49,7 +49,6 @@ describe('Connection Manager', () => { it('should filter connections on disconnect, removing the closed one', async () => { const peerStore = stubInterface() - peerStore.keyBook = stubInterface() const components = new DefaultComponents({ peerId: peerIds[0], peerStore, @@ -88,7 +87,6 @@ describe('Connection Manager', () => { it('should close connections on stop', async () => { const peerStore = stubInterface() - peerStore.keyBook = stubInterface() const components = new DefaultComponents({ peerId: peerIds[0], peerStore, @@ -154,7 +152,9 @@ describe('libp2p.connections', () => { }) }) - await libp2p.peerStore.addressBook.set(remoteLibp2p.peerId, remoteLibp2p.getMultiaddrs()) + await libp2p.peerStore.patch(remoteLibp2p.peerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) const conn = await libp2p.dial(remoteLibp2p.peerId) expect(conn).to.be.ok() @@ -211,8 +211,12 @@ describe('libp2p.connections', () => { }) // Populate PeerStore before starting - await libp2p.peerStore.addressBook.set(nodes[0].peerId, nodes[0].getMultiaddrs()) - await libp2p.peerStore.addressBook.set(nodes[1].peerId, nodes[1].getMultiaddrs()) + await libp2p.peerStore.patch(nodes[0].peerId, { + multiaddrs: nodes[0].getMultiaddrs() + }) + await libp2p.peerStore.patch(nodes[1].peerId, { + multiaddrs: nodes[1].getMultiaddrs() + }) await libp2p.start() @@ -238,8 +242,12 @@ describe('libp2p.connections', () => { }) // Populate PeerStore before starting - await libp2p.peerStore.addressBook.set(nodes[0].peerId, nodes[0].getMultiaddrs()) - await libp2p.peerStore.addressBook.set(nodes[1].peerId, nodes[1].getMultiaddrs()) + await libp2p.peerStore.patch(nodes[0].peerId, { + multiaddrs: nodes[0].getMultiaddrs() + }) + await libp2p.peerStore.patch(nodes[1].peerId, { + multiaddrs: nodes[1].getMultiaddrs() + }) await libp2p.start() @@ -270,9 +278,13 @@ describe('libp2p.connections', () => { }) // Populate PeerStore before starting - await libp2p.peerStore.addressBook.set(nodes[0].peerId, nodes[0].getMultiaddrs()) - await libp2p.peerStore.addressBook.set(nodes[1].peerId, nodes[1].getMultiaddrs()) - await libp2p.peerStore.protoBook.set(nodes[1].peerId, ['/protocol-min-conns']) + await libp2p.peerStore.patch(nodes[0].peerId, { + multiaddrs: nodes[0].getMultiaddrs() + }) + await libp2p.peerStore.patch(nodes[1].peerId, { + multiaddrs: nodes[1].getMultiaddrs(), + protocols: ['/protocol-min-conns'] + }) await libp2p.start() @@ -301,7 +313,9 @@ describe('libp2p.connections', () => { }) // Populate PeerStore after starting (discovery) - await libp2p.peerStore.addressBook.set(nodes[0].peerId, nodes[0].getMultiaddrs()) + await libp2p.peerStore.patch(nodes[0].peerId, { + multiaddrs: nodes[0].getMultiaddrs() + }) // Wait for peer to connect const conn = await libp2p.dial(nodes[0].peerId) @@ -336,7 +350,9 @@ describe('libp2p.connections', () => { }) }) - await libp2p.peerStore.addressBook.set(remoteLibp2p.peerId, remoteLibp2p.getMultiaddrs()) + await libp2p.peerStore.patch(remoteLibp2p.peerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) await libp2p.dial(remoteLibp2p.peerId) const conns = libp2p.connectionManager.getConnections() @@ -389,7 +405,9 @@ describe('libp2p.connections', () => { } }) }) - await libp2p.peerStore.addressBook.set(remoteLibp2p.peerId, remoteLibp2p.getMultiaddrs()) + await libp2p.peerStore.patch(remoteLibp2p.peerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) await expect(libp2p.dial(remoteLibp2p.peerId)) .to.eventually.be.rejected().with.property('code', codes.ERR_PEER_DIAL_INTERCEPTED) @@ -409,7 +427,9 @@ describe('libp2p.connections', () => { } }) }) - await libp2p.peerStore.addressBook.set(remoteLibp2p.peerId, remoteLibp2p.getMultiaddrs()) + await libp2p.peerStore.patch(remoteLibp2p.peerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) await libp2p.connectionManager.openConnection(remoteLibp2p.peerId) for (const multiaddr of remoteLibp2p.getMultiaddrs()) { @@ -434,7 +454,9 @@ describe('libp2p.connections', () => { const fullMultiaddr = remoteLibp2p.getMultiaddrs()[0] - await libp2p.peerStore.addressBook.add(remoteLibp2p.peerId, [fullMultiaddr]) + await libp2p.peerStore.merge(remoteLibp2p.peerId, { + multiaddrs: [fullMultiaddr] + }) expect(filterMultiaddrForPeer.callCount).to.equal(2) @@ -457,7 +479,9 @@ describe('libp2p.connections', () => { } }) }) - await remoteLibp2p.peerStore.addressBook.set(libp2p.peerId, libp2p.getMultiaddrs()) + await remoteLibp2p.peerStore.patch(libp2p.peerId, { + multiaddrs: libp2p.getMultiaddrs() + }) await remoteLibp2p.dial(libp2p.peerId) expect(denyInboundConnection.called).to.be.true() @@ -477,7 +501,9 @@ describe('libp2p.connections', () => { } }) }) - await libp2p.peerStore.addressBook.set(remoteLibp2p.peerId, remoteLibp2p.getMultiaddrs()) + await libp2p.peerStore.patch(remoteLibp2p.peerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) await libp2p.dial(remoteLibp2p.peerId) expect(denyOutboundConnection.called).to.be.true() @@ -497,7 +523,9 @@ describe('libp2p.connections', () => { } }) }) - await remoteLibp2p.peerStore.addressBook.set(libp2p.peerId, libp2p.getMultiaddrs()) + await remoteLibp2p.peerStore.patch(libp2p.peerId, { + multiaddrs: libp2p.getMultiaddrs() + }) await remoteLibp2p.dial(libp2p.peerId) expect(denyInboundEncryptedConnection.called).to.be.true() @@ -518,7 +546,9 @@ describe('libp2p.connections', () => { } }) }) - await libp2p.peerStore.addressBook.set(remoteLibp2p.peerId, remoteLibp2p.getMultiaddrs()) + await libp2p.peerStore.patch(remoteLibp2p.peerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) await libp2p.dial(remoteLibp2p.peerId) expect(denyOutboundEncryptedConnection.called).to.be.true() @@ -539,7 +569,9 @@ describe('libp2p.connections', () => { } }) }) - await remoteLibp2p.peerStore.addressBook.set(libp2p.peerId, libp2p.getMultiaddrs()) + await remoteLibp2p.peerStore.patch(libp2p.peerId, { + multiaddrs: libp2p.getMultiaddrs() + }) await remoteLibp2p.dial(libp2p.peerId) expect(denyInboundUpgradedConnection.called).to.be.true() @@ -560,7 +592,9 @@ describe('libp2p.connections', () => { } }) }) - await libp2p.peerStore.addressBook.set(remoteLibp2p.peerId, remoteLibp2p.getMultiaddrs()) + await libp2p.peerStore.patch(remoteLibp2p.peerId, { + multiaddrs: remoteLibp2p.getMultiaddrs() + }) await libp2p.dial(remoteLibp2p.peerId) expect(denyOutboundUpgradedConnection.called).to.be.true() diff --git a/test/connection-manager/index.spec.ts b/test/connection-manager/index.spec.ts index 99ec4ef0e9..3d095548bb 100644 --- a/test/connection-manager/index.spec.ts +++ b/test/connection-manager/index.spec.ts @@ -93,8 +93,12 @@ describe('Connection Manager', () => { const value = i * 10 spies.set(value, spy) - await libp2p.peerStore.tagPeer(connection.remotePeer, 'test-tag', { - value + await libp2p.peerStore.merge(connection.remotePeer, { + tags: { + 'test-tag': { + value + } + } }) libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) @@ -146,8 +150,12 @@ describe('Connection Manager', () => { // The lowest tag value will have the longest connection spies.set(peerTag, spy) - await libp2p.peerStore.tagPeer(connection.remotePeer, peerTag, { - value + await libp2p.peerStore.merge(connection.remotePeer, { + tags: { + [peerTag]: { + value + } + } }) libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) @@ -209,8 +217,12 @@ describe('Connection Manager', () => { const spy = sinon.spy(connection, 'close') const value = (i + 1) * 10 spies.set(value, spy) - await libp2p.peerStore.tagPeer(connection.remotePeer, 'test-tag', { - value + await libp2p.peerStore.merge(connection.remotePeer, { + tags: { + 'test-tag': { + value + } + } }) libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) } @@ -230,8 +242,12 @@ describe('Connection Manager', () => { spies.set(value, spy) // Tag that allowed peer with lowest value - await libp2p.peerStore.tagPeer(remotePeer, 'test-tag', { - value + await libp2p.peerStore.merge(connection.remotePeer, { + tags: { + 'test-tag': { + value + } + } }) libp2p.components.events.safeDispatchEvent('connection:open', { detail: connection }) @@ -319,7 +335,11 @@ describe('Connection Manager', () => { expect(connectionManagerOpenConnectionSpy.called).to.be.false('Attempted to connect to peers') - await libp2p.peerStore.tagPeer(peerId, KEEP_ALIVE) + await libp2p.peerStore.merge(peerId, { + tags: { + [KEEP_ALIVE]: {} + } + }) await libp2p.stop() await libp2p.start() diff --git a/test/connection-manager/resolver.spec.ts b/test/connection-manager/resolver.spec.ts index a7feaee6bc..e10c371faa 100644 --- a/test/connection-manager/resolver.spec.ts +++ b/test/connection-manager/resolver.spec.ts @@ -87,7 +87,9 @@ describe('dialing (resolvable addresses)', () => { // Use the last peer const peerId = await createFromJSON(Peers[Peers.length - 1]) // ensure remote libp2p creates reservation on relay - await remoteLibp2p.components.peerStore.protoBook.add(peerId, [RELAY_V2_HOP_CODEC]) + await remoteLibp2p.components.peerStore.merge(peerId, { + protocols: [RELAY_V2_HOP_CODEC] + }) const remoteId = remoteLibp2p.peerId const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId.toString()}`) const relayedAddrFetched = multiaddr(relayedAddr(remoteId)) @@ -118,7 +120,9 @@ describe('dialing (resolvable addresses)', () => { // Use the last peer const relayId = await createFromJSON(Peers[Peers.length - 1]) // ensure remote libp2p creates reservation on relay - await remoteLibp2p.components.peerStore.protoBook.add(relayId, [RELAY_V2_HOP_CODEC]) + await remoteLibp2p.components.peerStore.merge(relayId, { + protocols: [RELAY_V2_HOP_CODEC] + }) // Transport spy const transport = getTransport(libp2p, 'libp2p/circuit-relay-v2') @@ -184,7 +188,9 @@ describe('dialing (resolvable addresses)', () => { // Use the last peer const relayId = await createFromJSON(Peers[Peers.length - 1]) // ensure remote libp2p creates reservation on relay - await remoteLibp2p.components.peerStore.protoBook.add(relayId, [RELAY_V2_HOP_CODEC]) + await remoteLibp2p.components.peerStore.merge(relayId, { + protocols: [RELAY_V2_HOP_CODEC] + }) // Transport spy const transport = getTransport(libp2p, 'libp2p/circuit-relay-v2') diff --git a/test/content-routing/content-routing.node.ts b/test/content-routing/content-routing.node.ts index 8c8ee224f8..e99703ea49 100644 --- a/test/content-routing/content-routing.node.ts +++ b/test/content-routing/content-routing.node.ts @@ -269,7 +269,7 @@ describe('content-routing', () => { await drain(node.contentRouting.findProviders(CID.parse('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB'))) - expect(await node.peerStore.addressBook.get(providerPeerId)).to.deep.include({ + await expect(node.peerStore.get(providerPeerId)).to.eventually.have.property('addresses').that.deep.include({ isCertified: false, multiaddr: result.multiaddrs[0] }) @@ -376,7 +376,7 @@ describe('content-routing', () => { await drain(node.contentRouting.findProviders(CID.parse('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB'))) - expect(await node.peerStore.addressBook.get(providerPeerId)).to.deep.include({ + await expect(node.peerStore.get(providerPeerId)).to.eventually.have.property('addresses').that.deep.include({ isCertified: false, multiaddr: result1.multiaddrs[0] }).and.to.deep.include({ diff --git a/test/content-routing/dht/operation.node.ts b/test/content-routing/dht/operation.node.ts index ffc2fbae21..cfff93707e 100644 --- a/test/content-routing/dht/operation.node.ts +++ b/test/content-routing/dht/operation.node.ts @@ -15,20 +15,22 @@ const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/8000') const remoteListenAddr = multiaddr('/ip4/127.0.0.1/tcp/8001') async function getRemoteAddr (remotePeerId: PeerId, libp2p: Libp2pNode): Promise { - const addrs = await libp2p.components.peerStore.addressBook.get(remotePeerId) + const { addresses } = await libp2p.components.peerStore.get(remotePeerId) - if (addrs.length === 0) { + if (addresses.length === 0) { throw new Error('No addrs found') } - const addr = addrs[0] + const addr = addresses[0] return addr.multiaddr.encapsulate(`/p2p/${remotePeerId.toString()}`) } describe('DHT subsystem operates correctly', () => { - let peerId: PeerId, remotePeerId: PeerId - let libp2p: Libp2pNode, remoteLibp2p: Libp2pNode + let peerId: PeerId + let remotePeerId: PeerId + let libp2p: Libp2pNode + let remoteLibp2p: Libp2pNode let remAddr: Multiaddr beforeEach(async () => { @@ -59,7 +61,9 @@ describe('DHT subsystem operates correctly', () => { remoteLibp2p.start() ]) - await libp2p.components.peerStore.addressBook.set(remotePeerId, [remoteListenAddr]) + await libp2p.components.peerStore.patch(remotePeerId, { + multiaddrs: [remoteListenAddr] + }) remAddr = await getRemoteAddr(remotePeerId, libp2p) }) @@ -88,7 +92,7 @@ describe('DHT subsystem operates correctly', () => { const key = uint8ArrayFromString('hello') const value = uint8ArrayFromString('world') - await libp2p.dialProtocol(remAddr, subsystemMulticodecs) + await libp2p.dialProtocol(remotePeerId, subsystemMulticodecs) await Promise.all([ pWaitFor(() => libp2p.dht.lan.routingTable.size === 1), pWaitFor(() => remoteLibp2p.dht.lan.routingTable.size === 1) @@ -120,7 +124,9 @@ describe('DHT subsystem operates correctly', () => { await libp2p.start() await remoteLibp2p.start() - await libp2p.components.peerStore.addressBook.set(remotePeerId, [remoteListenAddr]) + await libp2p.components.peerStore.patch(remotePeerId, { + multiaddrs: [remoteListenAddr] + }) remAddr = await getRemoteAddr(remotePeerId, libp2p) }) diff --git a/test/core/consume-peer-record.spec.ts b/test/core/consume-peer-record.spec.ts index c49856b000..18e3525fbe 100644 --- a/test/core/consume-peer-record.spec.ts +++ b/test/core/consume-peer-record.spec.ts @@ -31,8 +31,9 @@ describe('Consume peer record', () => { it('should update addresses when observed addrs are confirmed', async () => { let done: () => void - libp2p.components.peerStore.addressBook.set = async () => { + libp2p.components.peerStore.patch = async () => { done() + return {} as any } const p = new Promise(resolve => { diff --git a/test/core/get-public-key.spec.ts b/test/core/get-public-key.spec.ts index b401902b19..af2fa1b589 100644 --- a/test/core/get-public-key.spec.ts +++ b/test/core/get-public-key.spec.ts @@ -48,7 +48,9 @@ describe('getPublicKey', () => { throw new Error('Public key was missing') } - await libp2p.peerStore.keyBook.set(otherPeer, otherPeer.publicKey) + await libp2p.peerStore.patch(otherPeer, { + publicKey: otherPeer.publicKey + }) const key = await libp2p.getPublicKey(otherPeer) diff --git a/test/fetch/index.spec.ts b/test/fetch/index.spec.ts index 674c3e9642..42f100398e 100644 --- a/test/fetch/index.spec.ts +++ b/test/fetch/index.spec.ts @@ -29,14 +29,15 @@ const defaultInit: FetchServiceInit = { async function createComponents (index: number): Promise { const peerId = await createFromJSON(Peers[index]) + const events = new EventEmitter() const components = new DefaultComponents({ peerId, registrar: mockRegistrar(), - upgrader: mockUpgrader(), + upgrader: mockUpgrader({ events }), datastore: new MemoryDatastore(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { diff --git a/test/identify/index.spec.ts b/test/identify/index.spec.ts index 2f4d0f200a..70912a1ce6 100644 --- a/test/identify/index.spec.ts +++ b/test/identify/index.spec.ts @@ -16,7 +16,6 @@ import drain from 'it-drain' import { pipe } from 'it-pipe' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-mocks' import { createFromJSON } from '@libp2p/peer-id-factory' -import { PeerRecordUpdater } from '../../src/peer-record-updater.js' import { MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH @@ -51,14 +50,15 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createFromJSON(Peers[index]) + const events = new EventEmitter() const components = new DefaultComponents({ peerId, datastore: new MemoryDatastore(), registrar: mockRegistrar(), - upgrader: mockUpgrader(), + upgrader: mockUpgrader({ events }), transportManager: stubInterface(), connectionGater: mockConnectionGater(), - events: new EventEmitter() + events }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { @@ -73,7 +73,9 @@ async function createComponents (index: number): Promise { const transportManager = new DefaultTransportManager(components) components.transportManager = transportManager - await components.peerStore.protoBook.set(peerId, protocols) + await components.peerStore.patch(peerId, { + protocols + }) return components } @@ -82,14 +84,10 @@ describe('identify', () => { let localComponents: DefaultComponents let remoteComponents: DefaultComponents - let remotePeerRecordUpdater: PeerRecordUpdater - beforeEach(async () => { localComponents = await createComponents(0) remoteComponents = await createComponents(1) - remotePeerRecordUpdater = new PeerRecordUpdater(remoteComponents) - await Promise.all([ start(localComponents), start(remoteComponents) @@ -114,65 +112,18 @@ describe('identify', () => { const [localToRemote] = connectionPair(localComponents, remoteComponents) - const localAddressBookConsumePeerRecordSpy = sinon.spy(localComponents.peerStore.addressBook, 'consumePeerRecord') - const localProtoBookSetSpy = sinon.spy(localComponents.peerStore.protoBook, 'set') - - // Make sure the remote peer has a peer record to share during identify - remotePeerRecordUpdater.update() - - // Run identify - await localIdentify.identify(localToRemote) - - expect(localAddressBookConsumePeerRecordSpy.callCount).to.equal(1) - expect(localProtoBookSetSpy.callCount).to.equal(1) - - // Validate the remote peer gets updated in the peer store - const addresses = await localComponents.peerStore.addressBook.get(remoteComponents.peerId) - expect(addresses).to.exist() - - expect(addresses).have.lengthOf(listenMaddrs.length) - expect(addresses.map((a) => a.multiaddr)[0].equals(listenMaddrs[0])) - expect(addresses.map((a) => a.isCertified)[0]).to.be.true() - }) - - // LEGACY - it('should be able to identify another peer with no certified peer records support', async () => { - const agentVersion = 'js-libp2p/5.0.0' - const localIdentify = new IdentifyService(localComponents, { - ...defaultInit, - protocolPrefix: 'ipfs', - host: { - agentVersion - } - }) - await start(localIdentify) - const remoteIdentify = new IdentifyService(remoteComponents, { - ...defaultInit, - protocolPrefix: 'ipfs', - host: { - agentVersion - } - }) - await start(remoteIdentify) - - const [localToRemote] = connectionPair(localComponents, remoteComponents) - - sinon.stub(localComponents.peerStore.addressBook, 'consumePeerRecord').throws() - - const localProtoBookSetSpy = sinon.spy(localComponents.peerStore.protoBook, 'set') + const localPeerStorePatchSpy = sinon.spy(localComponents.peerStore, 'patch') // Run identify await localIdentify.identify(localToRemote) - expect(localProtoBookSetSpy.callCount).to.equal(1) + expect(localPeerStorePatchSpy.callCount).to.equal(1) // Validate the remote peer gets updated in the peer store - const addresses = await localComponents.peerStore.addressBook.get(remoteComponents.peerId) - expect(addresses).to.exist() - - expect(addresses).have.lengthOf(listenMaddrs.length) - expect(addresses.map((a) => a.multiaddr)[0].equals(listenMaddrs[0])) - expect(addresses.map((a) => a.isCertified)[0]).to.be.false() + const peer = await localComponents.peerStore.get(remoteComponents.peerId) + expect(peer.addresses).have.lengthOf(listenMaddrs.length) + expect(peer.addresses.map((a) => a.multiaddr)[0].equals(listenMaddrs[0])) + expect(peer.addresses.map((a) => a.isCertified)[0]).to.be.true() }) it('should throw if identified peer is the wrong peer', async () => { @@ -189,7 +140,7 @@ describe('identify', () => { await remoteComponents.registrar.handle(MULTICODEC_IDENTIFY, (data) => { void Promise.resolve().then(async () => { const { connection, stream } = data - const signedPeerRecord = await remoteComponents.peerStore.addressBook.getRawEnvelope(remoteComponents.peerId) + const peer = await remoteComponents.peerStore.get(remoteComponents.peerId) const message = Message.Identify.encode({ protocolVersion: '123', @@ -197,7 +148,7 @@ describe('identify', () => { // send bad public key publicKey: localComponents.peerId.publicKey ?? new Uint8Array(0), listenAddrs: [], - signedPeerRecord, + signedPeerRecord: peer.peerRecordEnvelope, observedAddr: connection.remoteAddr.bytes, protocols: [] }) @@ -227,17 +178,15 @@ describe('identify', () => { } }) - await expect(localComponents.peerStore.metadataBook.getValue(localComponents.peerId, 'AgentVersion')) - .to.eventually.be.undefined() - await expect(localComponents.peerStore.metadataBook.getValue(localComponents.peerId, 'ProtocolVersion')) - .to.eventually.be.undefined() + const peer = await localComponents.peerStore.get(localComponents.peerId) + expect(peer.metadata.get('AgentVersion')).to.be.undefined() + expect(peer.metadata.get('ProtocolVersion')).to.be.undefined() await start(localIdentify) - await expect(localComponents.peerStore.metadataBook.getValue(localComponents.peerId, 'AgentVersion')) - .to.eventually.deep.equal(uint8ArrayFromString(agentVersion)) - await expect(localComponents.peerStore.metadataBook.getValue(localComponents.peerId, 'ProtocolVersion')) - .to.eventually.be.ok() + const updatedPeer = await localComponents.peerStore.get(localComponents.peerId) + expect(updatedPeer.metadata.get('AgentVersion')).to.deep.equal(uint8ArrayFromString(agentVersion)) + expect(updatedPeer.metadata.get('ProtocolVersion')).to.be.ok() await stop(localIdentify) }) diff --git a/test/identify/push.spec.ts b/test/identify/push.spec.ts index 96eaf7972e..43858ce783 100644 --- a/test/identify/push.spec.ts +++ b/test/identify/push.spec.ts @@ -12,7 +12,6 @@ import drain from 'it-drain' import { pipe } from 'it-pipe' import { mockConnectionGater, mockRegistrar, mockUpgrader, connectionPair } from '@libp2p/interface-mocks' import { createFromJSON } from '@libp2p/peer-id-factory' -import { PeerRecordUpdater } from '../../src/peer-record-updater.js' import { MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH @@ -46,14 +45,15 @@ const protocols = [MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH] async function createComponents (index: number): Promise { const peerId = await createFromJSON(Peers[index]) + const events = new EventEmitter() const components = new DefaultComponents({ peerId, datastore: new MemoryDatastore(), registrar: mockRegistrar(), - upgrader: mockUpgrader(), + upgrader: mockUpgrader({ events }), transportManager: stubInterface(), connectionGater: mockConnectionGater(), - events: new EventEmitter() + events }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { @@ -68,7 +68,9 @@ async function createComponents (index: number): Promise { const transportManager = new DefaultTransportManager(components) components.transportManager = transportManager - await components.peerStore.protoBook.set(peerId, protocols) + await components.peerStore.patch(peerId, { + protocols + }) return components } @@ -77,14 +79,10 @@ describe('identify (push)', () => { let localComponents: DefaultComponents let remoteComponents: DefaultComponents - let localPeerRecordUpdater: PeerRecordUpdater - beforeEach(async () => { localComponents = await createComponents(0) remoteComponents = await createComponents(1) - localPeerRecordUpdater = new PeerRecordUpdater(localComponents) - await Promise.all([ start(localComponents), start(remoteComponents) @@ -124,19 +122,14 @@ describe('identify (push)', () => { const updatedProtocol = '/special-new-protocol/1.0.0' const updatedAddress = multiaddr('/ip4/127.0.0.1/tcp/48322') + const peer = await remoteComponents.peerStore.get(localComponents.peerId) // should have protocols but not our new one - const identifiedProtocols = await remoteComponents.peerStore.protoBook.get(localComponents.peerId) - expect(identifiedProtocols).to.not.be.empty() - expect(identifiedProtocols).to.not.include(updatedProtocol) + expect(peer.protocols).to.not.be.empty() + expect(peer.protocols).to.not.include(updatedProtocol) // should have addresses but not our new one - const identifiedAddresses = await remoteComponents.peerStore.addressBook.get(localComponents.peerId) - expect(identifiedAddresses).to.not.be.empty() - expect(identifiedAddresses.map(a => a.multiaddr.toString())).to.not.include(updatedAddress.toString()) - - // update local data - change event will trigger push - await localComponents.peerStore.protoBook.add(localComponents.peerId, [updatedProtocol]) - await localComponents.peerStore.addressBook.add(localComponents.peerId, [updatedAddress]) + expect(peer.addresses).to.not.be.empty() + expect(peer.addresses.map(a => a.multiaddr.toString())).to.not.include(updatedAddress.toString()) // needed to update the peer record and send our supported addresses const addressManager = localComponents.addressManager @@ -147,25 +140,24 @@ describe('identify (push)', () => { // ensure sequence number of peer record we are about to create is different await delay(1000) - // make sure we have a peer record to send - localPeerRecordUpdater.update() - // wait for the remote peer store to notice the changes - const eventPromise = pEvent(remoteComponents.peerStore, 'change:multiaddrs') + const eventPromise = pEvent(remoteComponents.events, 'peer:update') - // push updated peer record to connections - await localIdentify.pushToPeerStore() + // update local data - change event will trigger push + await localComponents.registrar.handle(updatedProtocol, () => {}) + await localComponents.peerStore.merge(localComponents.peerId, { + multiaddrs: [updatedAddress] + }) await eventPromise // should have new protocol - const updatedProtocols = await remoteComponents.peerStore.protoBook.get(localComponents.peerId) - expect(updatedProtocols).to.not.be.empty() - expect(updatedProtocols).to.include(updatedProtocol) + const updatedPeer = await remoteComponents.peerStore.get(localComponents.peerId) + expect(updatedPeer.protocols).to.not.be.empty() + expect(updatedPeer.protocols).to.include(updatedProtocol) // should have new address - const updatedAddresses = await remoteComponents.peerStore.addressBook.get(localComponents.peerId) - expect(updatedAddresses.map(a => { + expect(updatedPeer.addresses.map(a => { return { multiaddr: a.multiaddr.toString(), isCertified: a.isCertified @@ -229,77 +221,4 @@ describe('identify (push)', () => { // out so we ignore the return value expect(streamEnded).to.be.false() }) - - // LEGACY - it('should be able to push identify updates to another peer with no certified peer records support', async () => { - const localIdentify = new IdentifyService(localComponents, defaultInit) - const remoteIdentify = new IdentifyService(remoteComponents, defaultInit) - - await start(localIdentify) - await start(remoteIdentify) - - const [localToRemote, remoteToLocal] = connectionPair(localComponents, remoteComponents) - - // ensure connections are registered by connection manager - localComponents.events.safeDispatchEvent('connection:open', { - detail: localToRemote - }) - remoteComponents.events.safeDispatchEvent('connection:open', { - detail: remoteToLocal - }) - - // identify both ways - await localIdentify.identify(localToRemote) - await remoteIdentify.identify(remoteToLocal) - - const updatedProtocol = '/special-new-protocol/1.0.0' - const updatedAddress = multiaddr('/ip4/127.0.0.1/tcp/48322') - - // should have protocols but not our new one - const identifiedProtocols = await remoteComponents.peerStore.protoBook.get(localComponents.peerId) - expect(identifiedProtocols).to.not.be.empty() - expect(identifiedProtocols).to.not.include(updatedProtocol) - - // should have addresses but not our new one - const identifiedAddresses = await remoteComponents.peerStore.addressBook.get(localComponents.peerId) - expect(identifiedAddresses).to.not.be.empty() - expect(identifiedAddresses.map(a => a.multiaddr.toString())).to.not.include(updatedAddress.toString()) - - // update local data - change event will trigger push - await localComponents.peerStore.protoBook.add(localComponents.peerId, [updatedProtocol]) - await localComponents.peerStore.addressBook.add(localComponents.peerId, [updatedAddress]) - - // needed to send our supported addresses - const addressManager = localComponents.addressManager - addressManager.getAddresses = () => { - return [updatedAddress] - } - - // wait until remote peer store notices protocol list update - const waitForUpdate = pEvent(remoteComponents.peerStore, 'change:protocols') - - await localIdentify.pushToPeerStore() - - await waitForUpdate - - // should have new protocol - const updatedProtocols = await remoteComponents.peerStore.protoBook.get(localComponents.peerId) - expect(updatedProtocols).to.not.be.empty() - expect(updatedProtocols).to.include(updatedProtocol) - - // should have new address - const updatedAddresses = await remoteComponents.peerStore.addressBook.get(localComponents.peerId) - expect(updatedAddresses.map(a => { - return { - multiaddr: a.multiaddr.toString(), - isCertified: a.isCertified - } - })).to.deep.equal([{ - multiaddr: updatedAddress.toString(), - isCertified: false - }]) - - await stop(localIdentify) - await stop(remoteIdentify) - }) }) diff --git a/test/identify/service.spec.ts b/test/identify/service.spec.ts index 77d1882b77..b0e1a62a1d 100644 --- a/test/identify/service.spec.ts +++ b/test/identify/service.spec.ts @@ -15,6 +15,7 @@ import type { PeerId } from '@libp2p/interface-peer-id' import type { Libp2pNode } from '../../src/libp2p.js' import { pEvent } from 'p-event' import { AGENT_VERSION } from '../../src/identify/consts.js' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' describe('libp2p.dialer.identifyService', () => { let peerId: PeerId @@ -52,13 +53,11 @@ describe('libp2p.dialer.identifyService', () => { } const identityServiceIdentifySpy = sinon.spy(libp2p.identifyService, 'identify') - const peerStoreSpyConsumeRecord = sinon.spy(libp2p.peerStore.addressBook, 'consumePeerRecord') const connection = await libp2p.dial(remoteAddr) expect(connection).to.exist() // Wait for peer store to be updated - await pWaitFor(() => peerStoreSpyConsumeRecord.callCount === 1) expect(identityServiceIdentifySpy.callCount).to.equal(1) // The connection should have no open streams @@ -78,26 +77,22 @@ describe('libp2p.dialer.identifyService', () => { } const identityServiceIdentifySpy = sinon.spy(libp2p.identifyService, 'identify') - const peerStoreSpyConsumeRecord = sinon.spy(libp2p.peerStore.addressBook, 'consumePeerRecord') const connection = await libp2p.dial(remoteAddr) expect(connection).to.exist() // Wait for peer store to be updated - await pWaitFor(() => peerStoreSpyConsumeRecord.callCount === 1) expect(identityServiceIdentifySpy.callCount).to.equal(1) // The connection should have no open streams await pWaitFor(() => connection.streams.length === 0) await connection.close() - const remotePeer = peerIdFromString(remoteAddr.getPeerId() ?? '') + const remotePeerId = peerIdFromString(remoteAddr.getPeerId() ?? '') - const storedAgentVersion = await libp2p.peerStore.metadataBook.getValue(remotePeer, 'AgentVersion') - const storedProtocolVersion = await libp2p.peerStore.metadataBook.getValue(remotePeer, 'ProtocolVersion') - - expect(storedAgentVersion).to.exist() - expect(storedProtocolVersion).to.exist() + const remotePeer = await libp2p.peerStore.get(remotePeerId) + expect(remotePeer.metadata.get('AgentVersion')).to.exist() + expect(remotePeer.metadata.get('ProtocolVersion')).to.exist() }) it('should push protocol updates to an already connected peer', async () => { @@ -170,12 +165,13 @@ describe('libp2p.dialer.identifyService', () => { throw new Error('Identity service was not configured') } - const storedAgentVersion = await libp2p.peerStore.metadataBook.getValue(peerId, 'AgentVersion') + const peer = await libp2p.peerStore.get(peerId) + const storedAgentVersion = peer.metadata.get('AgentVersion') expect(AGENT_VERSION + ' UserAgent=vTEST').to.equal(uint8ArrayToString(storedAgentVersion ?? new Uint8Array())) }) - it('should store host data and protocol version into metadataBook', async () => { + it('should store host data and protocol version into peer store', async () => { const agentVersion = 'js-project/1.0.0' libp2p = await createLibp2pNode(createBaseOptions({ @@ -193,11 +189,9 @@ describe('libp2p.dialer.identifyService', () => { throw new Error('Identity service was not configured') } - const storedAgentVersion = await libp2p.peerStore.metadataBook.getValue(peerId, 'AgentVersion') - const storedProtocolVersion = await libp2p.peerStore.metadataBook.getValue(peerId, 'ProtocolVersion') - - expect(agentVersion).to.equal(uint8ArrayToString(storedAgentVersion ?? new Uint8Array())) - expect(storedProtocolVersion).to.exist() + const remotePeer = await libp2p.peerStore.get(peerId) + expect(remotePeer.metadata.get('AgentVersion')).to.deep.equal(uint8ArrayFromString(agentVersion)) + expect(remotePeer.metadata.get('ProtocolVersion')).to.exist() }) it('should push multiaddr updates to an already connected peer', async () => { @@ -224,7 +218,9 @@ describe('libp2p.dialer.identifyService', () => { await identityServiceIdentifySpy.firstCall.returnValue sinon.stub(libp2p, 'isStarted').returns(true) - await libp2p.peerStore.addressBook.add(libp2p.peerId, [multiaddr('/ip4/180.0.0.1/tcp/15001/ws')]) + await libp2p.peerStore.merge(libp2p.peerId, { + multiaddrs: [multiaddr('/ip4/180.0.0.1/tcp/15001/ws')] + }) // the protocol change event listener in the identity service is async await pWaitFor(() => identityServicePushSpy.callCount === 1) diff --git a/test/nat-manager/nat-manager.node.ts b/test/nat-manager/nat-manager.node.ts index 3cdae123b5..873a1912b5 100644 --- a/test/nat-manager/nat-manager.node.ts +++ b/test/nat-manager/nat-manager.node.ts @@ -17,6 +17,8 @@ import { start, stop } from '@libp2p/interfaces/startable' import { multiaddr } from '@multiformats/multiaddr' import { DefaultComponents } from '../../src/components.js' import { EventEmitter } from '@libp2p/interfaces/events' +import type { PeerData, PeerStore } from '@libp2p/interface-peer-store' +import type { PeerId } from '@libp2p/interface-peer-id' const DEFAULT_ADDRESSES = [ '/ip4/127.0.0.1/tcp/0', @@ -28,11 +30,23 @@ describe('Nat Manager (TCP)', () => { let client: StubbedInstance async function createNatManager (addrs = DEFAULT_ADDRESSES, natManagerOptions = {}): Promise<{ natManager: NatManager, components: DefaultComponents }> { + const events = new EventEmitter() const components: any = { peerId: await createFromJSON(Peers[0]), - upgrader: mockUpgrader(), - events: new EventEmitter() + upgrader: mockUpgrader({ events }), + events, + peerStore: stubInterface() } + + components.peerStore.patch.callsFake(async (peerId: PeerId, details: PeerData) => { + components.events.safeDispatchEvent('self:peer:update', { + peer: { + id: peerId, + ...details + } + }) + }) + components.addressManager = new DefaultAddressManager(components, { listen: addrs }) components.transportManager = new DefaultTransportManager(components, { faultTolerance: FaultTolerance.NO_FATAL diff --git a/test/peer-discovery/index.node.ts b/test/peer-discovery/index.node.ts index 97f0d27a38..742a37bae4 100644 --- a/test/peer-discovery/index.node.ts +++ b/test/peer-discovery/index.node.ts @@ -20,10 +20,12 @@ import type { Libp2pOptions } from '../../src/index.js' const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0') describe('peer discovery scenarios', () => { - let peerId: PeerId, remotePeerId1: PeerId, remotePeerId2: PeerId + let peerId: PeerId + let remotePeerId1: PeerId + let remotePeerId2: PeerId let libp2p: Libp2pNode - before(async () => { + beforeEach(async () => { [peerId, remotePeerId1, remotePeerId2] = await Promise.all([ createPeerId(), createPeerId(), @@ -189,8 +191,12 @@ describe('peer discovery scenarios', () => { remoteLibp2p2.start() ]) - await libp2p.peerStore.addressBook.set(remotePeerId1, remoteLibp2p1.getMultiaddrs()) - await remoteLibp2p2.peerStore.addressBook.set(remotePeerId1, remoteLibp2p1.getMultiaddrs()) + await libp2p.peerStore.patch(remotePeerId1, { + multiaddrs: remoteLibp2p1.getMultiaddrs() + }) + await remoteLibp2p2.peerStore.patch(remotePeerId1, { + multiaddrs: remoteLibp2p1.getMultiaddrs() + }) // Topology: // A -> B diff --git a/test/peer-routing/peer-routing.node.ts b/test/peer-routing/peer-routing.node.ts index ebc2b0e241..49f113efda 100644 --- a/test/peer-routing/peer-routing.node.ts +++ b/test/peer-routing/peer-routing.node.ts @@ -440,7 +440,7 @@ describe('peer-routing', () => { throw new Error('DHT not configured') } - const spy = sinon.spy(node.peerStore.addressBook, 'add') + const spy = sinon.spy(node.peerStore, 'merge') sinon.stub(node.dht, 'findPeer').callsFake(async function * () { yield { @@ -459,7 +459,9 @@ describe('peer-routing', () => { await node.peerRouting.findPeer(remotePeerId) - expect(spy.calledWith(result.id, result.multiaddrs)).to.be.true() + expect(spy.calledWith(result.id, { + multiaddrs: result.multiaddrs + })).to.be.true() }) it('should use the delegate if the dht fails to get the closest peer', async () => { @@ -500,7 +502,7 @@ describe('peer-routing', () => { throw new Error('DHT not configured') } - const spy = sinon.spy(node.peerStore.addressBook, 'add') + const spy = sinon.spy(node.peerStore, 'merge') sinon.stub(node.dht, 'getClosestPeers').callsFake(async function * () { }) @@ -510,7 +512,9 @@ describe('peer-routing', () => { await drain(node.peerRouting.getClosestPeers(remotePeerId.toBytes())) - expect(spy.calledWith(result.id, result.multiaddrs)).to.be.true() + expect(spy.calledWith(result.id, { + multiaddrs: result.multiaddrs + })).to.be.true() }) it('should dedupe closest peers', async () => { @@ -590,7 +594,7 @@ describe('peer-routing', () => { throw new Error('DHT not configured') } - const peerStoreAddressBookAddStub = sinon.spy(node.peerStore.addressBook, 'add') + const peerStoreMergeStub = sinon.spy(node.peerStore, 'merge') const dhtGetClosestPeersStub = sinon.stub(node.dht, 'getClosestPeers').callsFake(async function * () { yield { name: 'FINAL_PEER', @@ -613,19 +617,15 @@ describe('peer-routing', () => { await node.start() await pWaitFor(() => dhtGetClosestPeersStub.callCount === 1) - await pWaitFor(() => peerStoreAddressBookAddStub.callCount === results.length) + await pWaitFor(() => peerStoreMergeStub.callCount >= results.length) - const call0 = peerStoreAddressBookAddStub.getCall(0) - expect(call0.args[0].equals(results[0].id)) - call0.args[1].forEach((m, index) => { - expect(m.equals(results[0].multiaddrs[index])) - }) + const peer0 = await node.peerStore.get(peerIds[0]) + expect(peer0.addresses.map(({ multiaddr }) => multiaddr.toString())) + .to.include.members(results[0].multiaddrs.map(ma => ma.toString())) - const call1 = peerStoreAddressBookAddStub.getCall(1) - expect(call1.args[0].equals(results[1].id)) - call0.args[1].forEach((m, index) => { - expect(m.equals(results[1].multiaddrs[index])) - }) + const peer1 = await node.peerStore.get(peerIds[1]) + expect(peer1.addresses.map(({ multiaddr }) => multiaddr.toString())) + .to.include.members(results[1].multiaddrs.map(ma => ma.toString())) }) it('should support being disabled', async () => { diff --git a/test/ping/index.spec.ts b/test/ping/index.spec.ts index ebd8e1567e..78bdee2f3e 100644 --- a/test/ping/index.spec.ts +++ b/test/ping/index.spec.ts @@ -29,14 +29,15 @@ const defaultInit: PingServiceInit = { async function createComponents (index: number): Promise { const peerId = await createFromJSON(Peers[index]) + const events = new EventEmitter() const components = new DefaultComponents({ peerId, registrar: mockRegistrar(), - upgrader: mockUpgrader(), + upgrader: mockUpgrader({ events }), datastore: new MemoryDatastore(), transportManager: stubInterface(), connectionGater: stubInterface(), - events: new EventEmitter() + events }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { diff --git a/test/ping/ping.node.ts b/test/ping/ping.node.ts index 49dc874fa0..196824da92 100644 --- a/test/ping/ping.node.ts +++ b/test/ping/ping.node.ts @@ -20,8 +20,12 @@ describe('ping', () => { ]) await populateAddressBooks(nodes) - await nodes[0].components.peerStore.addressBook.set(nodes[1].peerId, nodes[1].getMultiaddrs()) - await nodes[1].components.peerStore.addressBook.set(nodes[0].peerId, nodes[0].getMultiaddrs()) + await nodes[0].components.peerStore.patch(nodes[1].peerId, { + multiaddrs: nodes[1].getMultiaddrs() + }) + await nodes[1].components.peerStore.patch(nodes[0].peerId, { + multiaddrs: nodes[0].getMultiaddrs() + }) }) afterEach(async () => await Promise.all(nodes.map(async n => { await n.stop() }))) @@ -87,7 +91,9 @@ describe('ping', () => { } }) }) - await client.components.peerStore.addressBook.set(remote.peerId, remote.getMultiaddrs()) + await client.components.peerStore.patch(remote.peerId, { + multiaddrs: remote.getMultiaddrs() + }) // register our new node for shutdown after the test finishes // otherwise the Mocha/Node.js process never finishes nodes.push(client) diff --git a/test/registrar/registrar.spec.ts b/test/registrar/registrar.spec.ts index b661781619..2bb532ed6a 100644 --- a/test/registrar/registrar.spec.ts +++ b/test/registrar/registrar.spec.ts @@ -36,13 +36,14 @@ describe('registrar', () => { describe('errors', () => { beforeEach(() => { + const events = new EventEmitter() components = new DefaultComponents({ peerId, + events, datastore: new MemoryDatastore(), - upgrader: mockUpgrader(), + upgrader: mockUpgrader({ events }), transportManager: stubInterface(), - connectionGater: stubInterface(), - events: new EventEmitter() + connectionGater: stubInterface() }) components.peerStore = new PersistentPeerStore(components) components.connectionManager = new DefaultConnectionManager(components, { @@ -143,7 +144,9 @@ describe('registrar', () => { await libp2p.components.registrar.register(protocol, topology) // Add connected peer with protocol to peerStore and registrar - await libp2p.peerStore.protoBook.set(remotePeerId, [protocol]) + await libp2p.peerStore.patch(remotePeerId, { + protocols: [protocol] + }) // remote peer connects libp2p.components.events.safeDispatchEvent('connection:open', { @@ -181,7 +184,9 @@ describe('registrar', () => { await libp2p.components.registrar.register(protocol, topology) // Add connected peer to peerStore and registrar - await libp2p.peerStore.protoBook.set(remotePeerId, []) + await libp2p.peerStore.patch(remotePeerId, { + protocols: [] + }) // remote peer connects libp2p.components.events.safeDispatchEvent('connection:open', { diff --git a/test/transports/transport-manager.node.ts b/test/transports/transport-manager.node.ts index 2e1feeb925..0447c66e3c 100644 --- a/test/transports/transport-manager.node.ts +++ b/test/transports/transport-manager.node.ts @@ -5,17 +5,15 @@ import { MemoryDatastore } from 'datastore-core/memory' import { DefaultAddressManager } from '../../src/address-manager/index.js' import { DefaultTransportManager } from '../../src/transport-manager.js' import { PersistentPeerStore } from '@libp2p/peer-store' -import { PeerRecord } from '@libp2p/peer-record' import { tcp } from '@libp2p/tcp' import { multiaddr } from '@multiformats/multiaddr' import { mockUpgrader } from '@libp2p/interface-mocks' import sinon from 'sinon' import Peers from '../fixtures/peers.js' -import pWaitFor from 'p-wait-for' import type { PeerId } from '@libp2p/interface-peer-id' import { createFromJSON } from '@libp2p/peer-id-factory' -import { PeerRecordUpdater } from '../../src/peer-record-updater.js' import { DefaultComponents } from '../../src/components.js' +import { EventEmitter } from '@libp2p/interfaces/events' const addrs = [ multiaddr('/ip4/127.0.0.1/tcp/0'), @@ -32,10 +30,12 @@ describe('Transport Manager (TCP)', () => { }) beforeEach(() => { + const events = new EventEmitter() components = new DefaultComponents({ peerId: localPeer, + events, datastore: new MemoryDatastore(), - upgrader: mockUpgrader() + upgrader: mockUpgrader({ events }) }) components.addressManager = new DefaultAddressManager(components, { listen: addrs.map(addr => addr.toString()) }) components.peerStore = new PersistentPeerStore(components) @@ -76,34 +76,6 @@ describe('Transport Manager (TCP)', () => { expect(spyListener.called).to.be.true() }) - it('should create self signed peer record on listen', async () => { - const peerRecordUpdater = new PeerRecordUpdater(components) - await peerRecordUpdater.start() - - let signedPeerRecord = await components.peerStore.addressBook.getPeerRecord(localPeer) - expect(signedPeerRecord).to.not.exist() - - tm.add(tcp()()) - await tm.listen(addrs) - - // Should created Self Peer record on new listen address, but it is done async - // with no event so we have to wait a bit - await pWaitFor(async () => { - signedPeerRecord = await components.peerStore.addressBook.getPeerRecord(localPeer) - - return signedPeerRecord != null - }, { interval: 100, timeout: 2000 }) - - if (signedPeerRecord == null) { - throw new Error('Could not get signed peer record') - } - - const record = PeerRecord.createFromProtobuf(signedPeerRecord.payload) - expect(record).to.exist() - expect(record.multiaddrs.length).to.equal(addrs.length) - await peerRecordUpdater.stop() - }) - it('should be able to dial', async () => { tm.add(tcp()()) await tm.listen(addrs) diff --git a/test/transports/transport-manager.spec.ts b/test/transports/transport-manager.spec.ts index 07caa19ad0..287306106a 100644 --- a/test/transports/transport-manager.spec.ts +++ b/test/transports/transport-manager.spec.ts @@ -17,6 +17,7 @@ import { createEd25519PeerId, createFromJSON } from '@libp2p/peer-id-factory' import type { PeerId } from '@libp2p/interface-peer-id' import { createLibp2pNode, Libp2pNode } from '../../src/libp2p.js' import type { DefaultComponents } from '../../src/components.js' +import { EventEmitter } from '@libp2p/interfaces/events' const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0') @@ -25,9 +26,11 @@ describe('Transport Manager (WebSockets)', () => { let components: DefaultComponents before(async () => { + const events = new EventEmitter() components = { peerId: await createEd25519PeerId(), - upgrader: mockUpgrader() + events, + upgrader: mockUpgrader({ events }) } as any components.addressManager = new DefaultAddressManager(components, { listen: [listenAddr.toString()] }) diff --git a/test/utils/creators/peer.ts b/test/utils/creators/peer.ts index 895f5c2be5..ca57e6b23f 100644 --- a/test/utils/creators/peer.ts +++ b/test/utils/creators/peer.ts @@ -67,7 +67,9 @@ export async function populateAddressBooks (peers: Libp2pNode[]): Promise for (let i = 0; i < peers.length; i++) { for (let j = 0; j < peers.length; j++) { if (i !== j) { - await peers[i].components.peerStore.addressBook.set(peers[j].peerId, peers[j].components.addressManager.getAddresses()) + await peers[i].components.peerStore.patch(peers[j].peerId, { + multiaddrs: peers[j].components.addressManager.getAddresses() + }) } } } From 057534375d84375667b8f95bc667a28dd04c883f Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 24 Apr 2023 20:21:29 +0100 Subject: [PATCH 05/10] chore: update deps --- doc/GETTING_STARTED.md | 2 +- examples/delegated-routing/package.json | 6 +++--- examples/libp2p-in-the-browser/package.json | 4 ++-- examples/package.json | 2 +- examples/webrtc-direct/listener.js | 2 +- examples/webrtc-direct/package.json | 2 +- package.json | 6 +++--- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/GETTING_STARTED.md b/doc/GETTING_STARTED.md index a39a11b1d8..3a349ab30c 100644 --- a/doc/GETTING_STARTED.md +++ b/doc/GETTING_STARTED.md @@ -216,7 +216,7 @@ node.addEventListener('peer:discovery', (evt) => { console.log('Discovered %s', evt.detail.id.toString()) // Log discovered peer }) -node.connectionManager.addEventListener('peer:connect', (evt) => { +node.addEventListener('peer:connect', (evt) => { console.log('Connected to %s', evt.detail.remotePeer.toString()) // Log connected peer }) ``` diff --git a/examples/delegated-routing/package.json b/examples/delegated-routing/package.json index 6f3d1b8ead..4e396a5f4f 100644 --- a/examples/delegated-routing/package.json +++ b/examples/delegated-routing/package.json @@ -9,10 +9,10 @@ "libp2p": "file:../../", "@libp2p/delegated-content-routing": "^4.0.0", "@libp2p/delegated-peer-routing": "^4.0.0", - "@libp2p/kad-dht": "^8.0.7", + "@libp2p/kad-dht": "^9.0.0", "@libp2p/mplex": "^7.1.6", - "@libp2p/webrtc-star": "^6.0.0", - "@libp2p/websockets": "^5.0.0", + "@libp2p/webrtc-star": "^7.0.0", + "@libp2p/websockets": "^6.0.1", "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "5.0.0" diff --git a/examples/libp2p-in-the-browser/package.json b/examples/libp2p-in-the-browser/package.json index 1d222ddbf8..92f04a69f9 100644 --- a/examples/libp2p-in-the-browser/package.json +++ b/examples/libp2p-in-the-browser/package.json @@ -12,8 +12,8 @@ "@chainsafe/libp2p-noise": "^11.0.0", "@libp2p/bootstrap": "^7.0.0", "@libp2p/mplex": "^7.1.6", - "@libp2p/webrtc-star": "^6.0.0", - "@libp2p/websockets": "^5.0.0", + "@libp2p/webrtc-star": "^7.0.0", + "@libp2p/websockets": "^6.0.1", "libp2p": "file:../../" }, "devDependencies": { diff --git a/examples/package.json b/examples/package.json index 2becf7cd0e..4537b2b2d2 100644 --- a/examples/package.json +++ b/examples/package.json @@ -9,7 +9,7 @@ }, "license": "MIT", "dependencies": { - "@libp2p/floodsub": "^6.0.0", + "@libp2p/floodsub": "^7.0.1", "@libp2p/pubsub-peer-discovery": "^8.0.0", "@nodeutils/defaults-deep": "^1.1.0", "execa": "^6.1.0", diff --git a/examples/webrtc-direct/listener.js b/examples/webrtc-direct/listener.js index 014ea0f96b..c789321303 100644 --- a/examples/webrtc-direct/listener.js +++ b/examples/webrtc-direct/listener.js @@ -23,7 +23,7 @@ import wrtc from 'wrtc' connectionEncryption: [noise()] }) - node.connectionManager.addEventListener('peer:connect', (evt) => { + node.addEventListener('peer:connect', (evt) => { console.info(`Connected to ${evt.detail.remotePeer.toString()}!`) }) diff --git a/examples/webrtc-direct/package.json b/examples/webrtc-direct/package.json index a02feb1a29..358a1c4172 100644 --- a/examples/webrtc-direct/package.json +++ b/examples/webrtc-direct/package.json @@ -9,7 +9,7 @@ }, "license": "ISC", "dependencies": { - "@libp2p/webrtc-direct": "^5.0.0", + "@libp2p/webrtc-direct": "^6.0.0", "@chainsafe/libp2p-noise": "^11.0.0", "@libp2p/bootstrap": "^7.0.0", "@libp2p/mplex": "^7.1.6", diff --git a/package.json b/package.json index fe430b63c3..b38626f259 100644 --- a/package.json +++ b/package.json @@ -182,12 +182,12 @@ "@libp2p/interface-connection-encrypter-compliance-tests": "^5.0.0", "@libp2p/interface-mocks": "^11.0.0", "@libp2p/interop": "^8.0.0", - "@libp2p/kad-dht": "^8.0.11", + "@libp2p/kad-dht": "^9.0.0", "@libp2p/mdns": "^7.0.0", "@libp2p/mplex": "^8.0.0", "@libp2p/pubsub": "^7.0.1", - "@libp2p/tcp": "^7.0.0", - "@libp2p/websockets": "^6.0.0", + "@libp2p/tcp": "^7.0.1", + "@libp2p/websockets": "^6.0.1", "@types/p-fifo": "^1.0.0", "@types/varint": "^6.0.0", "@types/xsalsa20": "^1.1.0", From 18ddd50bdeb8ba8959d40f9f1bab927e8fc92d64 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 24 Apr 2023 21:15:27 +0100 Subject: [PATCH 06/10] chore: fix linting --- src/connection-manager/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/connection-manager/index.ts b/src/connection-manager/index.ts index fee68888be..cc064aa5da 100644 --- a/src/connection-manager/index.ts +++ b/src/connection-manager/index.ts @@ -22,8 +22,7 @@ import { PeerMap } from '@libp2p/peer-collections' import { publicAddressesFirst } from '@libp2p/utils/address-sort' import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_PRIORITY, DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, MAX_CONNECTIONS, MAX_INCOMING_PENDING_CONNECTIONS, MAX_PARALLEL_DIALS, MAX_PEER_ADDRS_TO_DIAL, MIN_CONNECTIONS } from './constants.js' import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers' -import type { PendingDial } from '@libp2p/interface-libp2p' -import type { AddressSorter, Libp2pEvents } from '@libp2p/interface-libp2p' +import type { PendingDial, AddressSorter, Libp2pEvents } from '@libp2p/interface-libp2p' const log = logger('libp2p:connection-manager') From e6c6ea345f752255590b631c2dea42d73be50e4a Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 24 Apr 2023 21:21:36 +0100 Subject: [PATCH 07/10] chore: fix rogue timeout --- test/connection-manager/auto-dial.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/connection-manager/auto-dial.spec.ts b/test/connection-manager/auto-dial.spec.ts index 7a43f2683e..df267ad4a4 100644 --- a/test/connection-manager/auto-dial.spec.ts +++ b/test/connection-manager/auto-dial.spec.ts @@ -51,7 +51,7 @@ describe('auto-dial', () => { const connectionManager = stubInterface() connectionManager.getConnections.returns([]) - const autoDialler = new AutoDial({ + autoDialler = new AutoDial({ peerStore, connectionManager, events: new EventEmitter() From 82aefe11c167d5acfbe768a9c7bfb83c1470b150 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 25 Apr 2023 08:28:09 +0100 Subject: [PATCH 08/10] fix: fix up examples --- examples/discovery-mechanisms/1.js | 8 ++++---- examples/libp2p-in-the-browser/index.js | 16 ++++++++-------- examples/peer-and-content-routing/1.js | 2 +- package.json | 1 + 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/examples/discovery-mechanisms/1.js b/examples/discovery-mechanisms/1.js index 65b39d4e34..1292818fea 100644 --- a/examples/discovery-mechanisms/1.js +++ b/examples/discovery-mechanisms/1.js @@ -23,13 +23,13 @@ import bootstrappers from './bootstrappers.js' }) node.addEventListener('peer:connect', (evt) => { - const connection = evt.detail - console.log('Connection established to:', connection.remotePeer.toString()) // Emitted when a peer has been found + const peerId = evt.detail + console.log('Connection established to:', peerId.toString()) // Emitted when a peer has been found }) node.addEventListener('peer:discovery', (evt) => { - const peer = evt.detail + const peerId = evt.detail - console.log('Discovered:', peer.id.toString()) + console.log('Discovered:', peerId.toString()) }) })(); diff --git a/examples/libp2p-in-the-browser/index.js b/examples/libp2p-in-the-browser/index.js index d26dc2bea8..08d73ce64b 100644 --- a/examples/libp2p-in-the-browser/index.js +++ b/examples/libp2p-in-the-browser/index.js @@ -52,25 +52,25 @@ document.addEventListener('DOMContentLoaded', async () => { // Listen for new peers libp2p.addEventListener('peer:discovery', (evt) => { - const peer = evt.detail - log(`Found peer ${peer.id.toString()}`) + const peerInfo = evt.detail + log(`Found peer ${peerInfo.id.toString()}`) // dial them when we discover them - libp2p.dial(evt.detail.id).catch(err => { - log(`Could not dial ${evt.detail.id}`, err) + libp2p.dial(peerInfo.id).catch(err => { + log(`Could not dial ${peerInfo.id.toString()}`, err) }) }) // Listen for new connections to peers libp2p.addEventListener('peer:connect', (evt) => { - const connection = evt.detail - log(`Connected to ${connection.remotePeer.toString()}`) + const peerId = evt.detail + log(`Connected to ${peerId.toString()}`) }) // Listen for peers disconnecting libp2p.addEventListener('peer:disconnect', (evt) => { - const connection = evt.detail - log(`Disconnected from ${connection.remotePeer.toString()}`) + const peerId = evt.detail + log(`Disconnected from ${peerId.toString()}`) }) status.innerText = 'libp2p started!' diff --git a/examples/peer-and-content-routing/1.js b/examples/peer-and-content-routing/1.js index 5717ebe71c..aa48549d26 100644 --- a/examples/peer-and-content-routing/1.js +++ b/examples/peer-and-content-routing/1.js @@ -31,7 +31,7 @@ const createNode = async () => { await node1.peerStore.patch(node2.peerId, { multiaddrs: node2.getMultiaddrs() }) - await node2.peerStore(node3.peerId, { + await node2.peerStore.patch(node3.peerId, { multiaddrs: node3.getMultiaddrs() }) diff --git a/package.json b/package.json index b38626f259..5636a12d14 100644 --- a/package.json +++ b/package.json @@ -167,6 +167,7 @@ "uint8arraylist": "^2.3.2", "uint8arrays": "^4.0.2", "wherearewe": "^2.0.0", + "why-is-node-running": "^2.2.2", "xsalsa20": "^1.1.0" }, "devDependencies": { From bfaa469bf68129d0e9b6bce306428e0076b8e89a Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 25 Apr 2023 08:47:11 +0100 Subject: [PATCH 09/10] docs: add upgrade guide --- doc/migrations/v0.44-v0.45.md | 76 ++++++++++++++++++++++++++++++ examples/webrtc-direct/listener.js | 2 +- 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 doc/migrations/v0.44-v0.45.md diff --git a/doc/migrations/v0.44-v0.45.md b/doc/migrations/v0.44-v0.45.md new file mode 100644 index 0000000000..7cee745a66 --- /dev/null +++ b/doc/migrations/v0.44-v0.45.md @@ -0,0 +1,76 @@ +# Migrating to libp2p@45 + +A migration guide for refactoring your application code from libp2p v0.44.x to v0.45.0. + +## Table of Contents + +- [Events](#events) + - [Emitters](#emitters) + - [Event changes](#event-changes) + - [`peer:connect`](#peerconnect) + - [`peer:disconnect`](#peerdisconnect) + - [`peer:update`](#peerupdate) + - [`self:peer:update`](#selfpeerupdate) + +## Events + +The events emitted by libp2p have been refactored to be more consistent and to give more insight into the inner workings of libp2p. + +> Please see the [API docs](https://libp2p.github.io/js-libp2p-interfaces/interfaces/_libp2p_interface_libp2p.Libp2pEvents.html) for an exhaustive list of events emitted by Libp2p. + +### Emitters + +The primary interaction point for events is now the libp2p node itself, no need to access internal properties to set up listeners. + +**Before** + +```js +import { createLibp2p } from 'libp2p' + +const node = await createLibp2p({ /* ... */ }) +node.connectionManager.addEventListener('peer:connect', () => {}) +``` + +**After** + +```js +import { createLibp2p } from 'libp2p' + +const node = await createLibp2p({ /* ... */ }) +node.addEventListener('peer:connect', () => {}) +``` + +### Event changes + +Some types have changed. + +> Please see the [API docs](https://libp2p.github.io/js-libp2p-interfaces/interfaces/_libp2p_interface_libp2p.Libp2pEvents.html) for an exhaustive list of events emitted by Libp2p. + +#### `peer:connect` + +The detail field for this event was a [Connection] now it is a [PeerId] + +It is emitted when a new peer opens it's first connection. + +To receive notifications of the opening of individual connections, listen for the `connection:open` event instead. + +#### `peer:disconnect` + +The detail field for this event was a [Connection] now it is a [PeerId] + +It is emitted when all connections for the peer have been closed. + +To receive notifications of the closing of individual connections, listen for the `connection:close` event instead. + +#### `peer:update` + +This event is emitted when a peer's data has been changed in the peer store. This can be in response to a user manually updating the peer, or after the [Identify] protocol has completed. + +#### `self:peer:update` + +This event occurs when the data of the running node has changed. It may have started listening on a new multiaddr, [AutoNAT] may have given us new confidence in an external address or a user may have manually updated the information. + +[Connection]: https://libp2p.github.io/js-libp2p-interfaces/interfaces/_libp2p_interface_connection.Connection.html +[PeerId]: https://libp2p.github.io/js-libp2p-interfaces/types/_libp2p_interface_peer_id.PeerId.html +[Identify]: https://github.com/libp2p/specs/blob/master/identify/README.md +[AutoNAT]: https://github.com/libp2p/specs/blob/master/autonat/README.md \ No newline at end of file diff --git a/examples/webrtc-direct/listener.js b/examples/webrtc-direct/listener.js index c789321303..d3cf97f6bc 100644 --- a/examples/webrtc-direct/listener.js +++ b/examples/webrtc-direct/listener.js @@ -24,7 +24,7 @@ import wrtc from 'wrtc' }) node.addEventListener('peer:connect', (evt) => { - console.info(`Connected to ${evt.detail.remotePeer.toString()}!`) + console.info(`Connected to ${evt.detail.toString()}!`) }) console.log('Listening on:') From 76aa8cefb81da1c25712c7fe4af73a4ac0c3c14a Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 25 Apr 2023 09:25:50 +0100 Subject: [PATCH 10/10] docs: update migaration docs --- doc/migrations/v0.44-v0.45.md | 96 ++++++++++++++++++++- examples/delegated-routing/package.json | 2 +- examples/libp2p-in-the-browser/package.json | 2 +- examples/webrtc-direct/dialer.js | 10 +-- examples/webrtc-direct/listener.js | 4 +- examples/webrtc-direct/package.json | 2 +- examples/webrtc-direct/test.js | 8 +- package.json | 2 +- 8 files changed, 110 insertions(+), 16 deletions(-) diff --git a/doc/migrations/v0.44-v0.45.md b/doc/migrations/v0.44-v0.45.md index 7cee745a66..53c9864aae 100644 --- a/doc/migrations/v0.44-v0.45.md +++ b/doc/migrations/v0.44-v0.45.md @@ -11,6 +11,7 @@ A migration guide for refactoring your application code from libp2p v0.44.x to v - [`peer:disconnect`](#peerdisconnect) - [`peer:update`](#peerupdate) - [`self:peer:update`](#selfpeerupdate) +- [Atomic peer store methods](#atomic-peer-store-methods) ## Events @@ -70,7 +71,100 @@ This event is emitted when a peer's data has been changed in the peer store. Th This event occurs when the data of the running node has changed. It may have started listening on a new multiaddr, [AutoNAT] may have given us new confidence in an external address or a user may have manually updated the information. +## Atomic peer store methods + +The libp2p peer store has been refactored to reduce the number of methods it exposes. + +Previously it had separate components for managing addresses, protocols, metadata, etc, all of which exposed async methods which meant updating the data for a peer could involve multiple async calls which required complicated internal locking mechanisms which introduced a lot of latency into libp2p nodes performing many peer operations. + +The updated peer store has simple `save`, `patch` and `merge` methods which update all fields in a peer's stored data at once. + +**Before** + +```js +import { createLibp2p } from 'libp2p' + +const node = await createLibp2p({ /* ... */ }) + +// add addresses +await node.peerStore.addressBook.add(peerId, [ + multiaddr('/ip4/43.14.67.21/tcp/3847') +]) + +// set protocols +await node.peerStore.protoBook.set(peerId, [ + '/a-proto/1.0.0', + '/another-proto/1.0.0' +]) + +// add metadata +await node.peerStore.metadataBook.set(peerId, 'key', Uint8Array.from([0, 1, 2, 3])) + +// add tags +await node.peerStore.tagPeer(peerId, 'tag-name', { value: 10 }) +``` + +**After** + +```js +import { createLibp2p } from 'libp2p' + +const node = await createLibp2p({ /* ... */ }) + +// `save` replaces all data for the peer. Use with caution - any fields not passed +// will be deleted +await node.peerStore.save(peerId, { + multiaddrs: [ + multiaddr('/ip4/43.14.67.21/tcp/3847') + ], + protocols: [ + '/a-proto/1.0.0', + '/another-proto/1.0.0' + ], + metadata: { + key: Uint8Array.from([0, 1, 2, 3]) + }, + tags: { + 'tag-name': { value: 10 } + } +}) +``` + +Other ways to update peers are available which are more concise and allow you to just update specific fields: + +```js +// `patch` replaces only the passed fields and retains all other data +await node.peerStore.patch(peerId, { + multiaddrs: [ + multiaddr('/ip4/43.14.67.21/tcp/3847') + ] +}) + +// `merge` behaves like `patch` but deeply merges multiaddrs, protocols, metadata, +// and tags, removing duplicates. any existing metadata/tags with the same +// keys/tag names will be overwritten. +await node.peerStore.merge(peerId, { + multiaddrs: [ + multiaddr('/ip4/43.14.67.21/tcp/3847') + ] +}) +``` + +You can also remove fields quickly: + +```js +// passing `undefined` to `merge` is a quick way of deleting metadata/tags +await node.peerStore.merge(peerId, { + metadata: { + key: undefined + }, + tags: { + 'tag-name': undefined + } +}) +``` + [Connection]: https://libp2p.github.io/js-libp2p-interfaces/interfaces/_libp2p_interface_connection.Connection.html [PeerId]: https://libp2p.github.io/js-libp2p-interfaces/types/_libp2p_interface_peer_id.PeerId.html [Identify]: https://github.com/libp2p/specs/blob/master/identify/README.md -[AutoNAT]: https://github.com/libp2p/specs/blob/master/autonat/README.md \ No newline at end of file +[AutoNAT]: https://github.com/libp2p/specs/blob/master/autonat/README.md diff --git a/examples/delegated-routing/package.json b/examples/delegated-routing/package.json index 4e396a5f4f..1235ca22ca 100644 --- a/examples/delegated-routing/package.json +++ b/examples/delegated-routing/package.json @@ -10,7 +10,7 @@ "@libp2p/delegated-content-routing": "^4.0.0", "@libp2p/delegated-peer-routing": "^4.0.0", "@libp2p/kad-dht": "^9.0.0", - "@libp2p/mplex": "^7.1.6", + "@libp2p/mplex": "^8.0.1", "@libp2p/webrtc-star": "^7.0.0", "@libp2p/websockets": "^6.0.1", "react": "^17.0.2", diff --git a/examples/libp2p-in-the-browser/package.json b/examples/libp2p-in-the-browser/package.json index 92f04a69f9..a47e6c3e30 100644 --- a/examples/libp2p-in-the-browser/package.json +++ b/examples/libp2p-in-the-browser/package.json @@ -11,7 +11,7 @@ "dependencies": { "@chainsafe/libp2p-noise": "^11.0.0", "@libp2p/bootstrap": "^7.0.0", - "@libp2p/mplex": "^7.1.6", + "@libp2p/mplex": "^8.0.1", "@libp2p/webrtc-star": "^7.0.0", "@libp2p/websockets": "^6.0.1", "libp2p": "file:../../" diff --git a/examples/webrtc-direct/dialer.js b/examples/webrtc-direct/dialer.js index 07d75ff922..913e9d4119 100644 --- a/examples/webrtc-direct/dialer.js +++ b/examples/webrtc-direct/dialer.js @@ -30,24 +30,24 @@ document.addEventListener('DOMContentLoaded', async () => { // Listen for new peers libp2p.addEventListener('peer:discovery', (evt) => { - log(`Found peer ${evt.detail.id.toString()}`) + log(`Dialer found peer ${evt.detail.id.toString()}`) // dial them when we discover them libp2p.dial(evt.detail.id).catch(err => { - log(`Could not dial ${evt.detail.id}`, err) + log(`Dialer could not dial ${evt.detail.id}`, err) }) }) // Listen for new connections to peers libp2p.addEventListener('peer:connect', (evt) => { - log(`Connected to ${evt.detail.remotePeer.toString()}`) + log(`Dialer connected to ${evt.detail.toString()}`) }) // Listen for peers disconnecting libp2p.addEventListener('peer:disconnect', (evt) => { - log(`Disconnected from ${evt.detail.remotePeer.toString()}`) + log(`Dialer disconnected from ${evt.detail.remotePeer.toString()}`) }) status.innerText = 'libp2p started!' - log(`libp2p id is ${libp2p.peerId.toString()}`) + log(`Dialer libp2p id is ${libp2p.peerId.toString()}`) }) diff --git a/examples/webrtc-direct/listener.js b/examples/webrtc-direct/listener.js index d3cf97f6bc..6f9ee030a9 100644 --- a/examples/webrtc-direct/listener.js +++ b/examples/webrtc-direct/listener.js @@ -24,9 +24,9 @@ import wrtc from 'wrtc' }) node.addEventListener('peer:connect', (evt) => { - console.info(`Connected to ${evt.detail.toString()}!`) + console.info(`Listener connected to ${evt.detail.toString()}!`) }) - console.log('Listening on:') + console.log('Listener listening on:') node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) })() diff --git a/examples/webrtc-direct/package.json b/examples/webrtc-direct/package.json index 358a1c4172..f5f2c8eaf0 100644 --- a/examples/webrtc-direct/package.json +++ b/examples/webrtc-direct/package.json @@ -12,7 +12,7 @@ "@libp2p/webrtc-direct": "^6.0.0", "@chainsafe/libp2p-noise": "^11.0.0", "@libp2p/bootstrap": "^7.0.0", - "@libp2p/mplex": "^7.1.6", + "@libp2p/mplex": "^8.0.1", "libp2p": "file:../../", "wrtc": "^0.4.7" }, diff --git a/examples/webrtc-direct/test.js b/examples/webrtc-direct/test.js index 23181b879f..24143ce86f 100644 --- a/examples/webrtc-direct/test.js +++ b/examples/webrtc-direct/test.js @@ -33,7 +33,7 @@ export async function test () { listenerProc.all.on('data', async (data) => { process.stdout.write(data) listenerOutput += uint8ArrayToString(data) - if (listenerOutput.includes('Listening on:') && listenerOutput.includes('12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m')) { + if (listenerOutput.includes('Listener listening on:') && listenerOutput.includes('12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m')) { listenerProcReady.resolve() } }) @@ -59,9 +59,9 @@ export async function test () { await page.waitForFunction( selector => { const text = document.querySelector(selector).innerText - return text.includes('libp2p id is') && - text.includes('Found peer 12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m') && - text.includes('Connected to 12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m') + return text.includes('Dialer libp2p id is') && + text.includes('Dialer found peer 12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m') && + text.includes('Dialer connected to 12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m') }, '#output', { timeout: 10000 } diff --git a/package.json b/package.json index 5636a12d14..b5df58e0b2 100644 --- a/package.json +++ b/package.json @@ -185,7 +185,7 @@ "@libp2p/interop": "^8.0.0", "@libp2p/kad-dht": "^9.0.0", "@libp2p/mdns": "^7.0.0", - "@libp2p/mplex": "^8.0.0", + "@libp2p/mplex": "^8.0.1", "@libp2p/pubsub": "^7.0.1", "@libp2p/tcp": "^7.0.1", "@libp2p/websockets": "^6.0.1",