From 58abe8702f0c28d87b54f29e19155ea5c00c407d Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 9 Jul 2025 11:02:58 +0200 Subject: [PATCH 01/10] feat: allow creating scoped loggers (#3214) Adds `newScope` function to loggers that creates a logger under the current context. This is ultimately to allow unambiguous cascading log prefixes of: `libp2p` -> `transport` -> `connection` -> `muxer` -> `stream` E.g. `libp2p:tcp:connection:outbound:1:yamux:stream:inbound:1` --- packages/interface/src/index.ts | 36 ++++++++++++++++++++++++++++++ packages/logger/src/index.ts | 16 ++++--------- packages/logger/test/index.spec.ts | 14 ++++++++++++ 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/packages/interface/src/index.ts b/packages/interface/src/index.ts index 9a6af78b48..a668840097 100644 --- a/packages/interface/src/index.ts +++ b/packages/interface/src/index.ts @@ -127,10 +127,46 @@ export interface IdentifyResult { * Logger component for libp2p */ export interface Logger { + /** + * Log a message + */ (formatter: any, ...args: any[]): void + + /** + * Log an error message + */ error(formatter: any, ...args: any[]): void + + /** + * Log a trace message + */ trace(formatter: any, ...args: any[]): void + + /** + * `true` if this logger is enabled + */ enabled: boolean + + /** + * Create a logger scoped below this one + * + * @example + * + * ```ts + * import { defaultLogger } from '@libp2p/logger' + * + * const log = defaultLogger().forComponent('foo') + * + * log('hello') + * // foo hello + * + * const subLog = log.newScope('bar') + * + * subLog('hello') + * // foo:bar hello + * ``` + */ + newScope(name: string): Logger } /** diff --git a/packages/logger/src/index.ts b/packages/logger/src/index.ts index bc59a16d29..356b88fca6 100644 --- a/packages/logger/src/index.ts +++ b/packages/logger/src/index.ts @@ -37,7 +37,7 @@ import { base58btc } from 'multiformats/bases/base58' import { base64 } from 'multiformats/bases/base64' import debug from 'weald' import { truncatePeerId } from './utils.js' -import type { PeerId } from '@libp2p/interface' +import type { PeerId, Logger, ComponentLogger } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' import type { Key } from 'interface-datastore' import type { CID } from 'multiformats/cid' @@ -82,16 +82,7 @@ debug.formatters.e = (v?: Error): string => { return v == null ? 'undefined' : notEmpty(v.stack) ?? notEmpty(v.message) ?? v.toString() } -export interface Logger { - (formatter: any, ...args: any[]): void - error(formatter: any, ...args: any[]): void - trace(formatter: any, ...args: any[]): void - enabled: boolean -} - -export interface ComponentLogger { - forComponent(name: string): Logger -} +export type { Logger, ComponentLogger } function createDisabledLogger (namespace: string): debug.Debugger { const logger = (): void => {} @@ -205,7 +196,8 @@ export function logger (name: string): Logger { return Object.assign(debug(name), { error: debug(`${name}:error`), - trace + trace, + newScope: (scope: string) => logger(`${name}:${scope}`) }) } diff --git a/packages/logger/test/index.spec.ts b/packages/logger/test/index.spec.ts index 17164e06fa..200a205a0f 100644 --- a/packages/logger/test/index.spec.ts +++ b/packages/logger/test/index.spec.ts @@ -79,6 +79,20 @@ describe('logger', () => { expect(log).to.have.nested.property('trace.enabled').that.is.true() }) + it('creates a sub logger', () => { + debug.enable('enabled-with-trace-logger*,*:trace') + + const log = logger('enabled-with-trace-logger') + const subLog = log.newScope('sub-component') + + expect(subLog).to.be.a('function') + expect(subLog).to.have.property('enabled').that.is.true() + expect(subLog).to.have.property('error').that.is.a('function') + expect(subLog).to.have.nested.property('error.enabled').that.is.true() + expect(subLog).to.have.property('trace').that.is.a('function') + expect(subLog).to.have.nested.property('trace.enabled').that.is.true() + }) + it('has all formatters', () => { debug.enable('enabled-with-formatters') From ce6b542a8ea3d42e2238f910cf2a113370515058 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 9 Jul 2025 17:06:33 +0200 Subject: [PATCH 02/10] fix: scope logging to connection and stream (#3215) Updates log scope for streams to use the muxer scope, which uses the connection scope so we can trace log lines per stream/connection instead of having component scope. --- .../package.json | 1 - .../src/index.ts | 17 +- packages/connection-encrypter-tls/src/tls.ts | 17 +- .../test/index.spec.ts | 24 +- .../src/mocks/connection.ts | 1 + .../src/mocks/muxer.ts | 4 +- .../src/stream-muxer/base-test.ts | 8 +- .../src/stream-muxer/close-test.ts | 32 +- .../src/stream-muxer/spawner.ts | 4 +- .../interface/src/connection-encrypter.ts | 13 +- packages/interface/src/stream-muxer.ts | 7 +- packages/libp2p/package.json | 3 +- .../src/address-manager/dns-mappings.ts | 2 +- .../libp2p/src/connection-manager/index.ts | 4 +- packages/libp2p/src/connection.ts | 395 ++++++++++++++++++ packages/libp2p/src/connection/index.ts | 199 --------- packages/libp2p/src/upgrader.ts | 301 +------------ .../libp2p/test/connection/compliance.spec.ts | 153 +++++++ .../libp2p/test/connection/fixtures/pair.ts | 28 -- packages/libp2p/test/connection/index.spec.ts | 262 +----------- packages/libp2p/test/connection/utils.ts | 102 +++++ .../libp2p/test/upgrading/upgrader.spec.ts | 3 +- packages/protocol-autonat/src/autonat.ts | 44 +- packages/protocol-echo/src/echo.ts | 10 +- packages/protocol-echo/src/index.ts | 3 +- packages/protocol-echo/test/index.spec.ts | 14 +- packages/protocol-fetch/src/fetch.ts | 40 +- packages/protocol-fetch/src/index.ts | 3 +- packages/protocol-fetch/test/index.spec.ts | 10 +- .../protocol-identify/src/identify-push.ts | 8 +- packages/protocol-identify/src/identify.ts | 26 +- .../protocol-identify/test/fixtures/index.ts | 4 +- packages/protocol-identify/test/index.spec.ts | 3 +- packages/protocol-perf/src/perf-service.ts | 20 +- packages/protocol-perf/test/index.spec.ts | 16 +- packages/protocol-ping/src/index.ts | 3 +- packages/protocol-ping/src/ping.ts | 21 +- packages/protocol-ping/test/index.spec.ts | 22 +- .../stream-multiplexer-mplex/src/index.ts | 2 +- .../stream-multiplexer-mplex/src/mplex.ts | 4 +- .../stream-multiplexer-mplex/src/stream.ts | 9 +- .../test/mplex.spec.ts | 1 + .../test/stream.spec.ts | 134 +++++- .../src/transport/transport.ts | 16 +- packages/transport-memory/src/connections.ts | 4 +- packages/transport-tcp/src/socket-to-conn.ts | 23 +- packages/transport-webrtc/src/muxer.ts | 8 +- .../src/private-to-public/utils/connect.ts | 2 +- packages/transport-webrtc/src/stream.ts | 13 +- packages/transport-webrtc/test/stream.spec.ts | 13 +- .../src/socket-to-conn.ts | 39 +- packages/transport-webtransport/src/index.ts | 2 +- packages/transport-webtransport/src/muxer.ts | 16 +- packages/transport-webtransport/src/stream.ts | 8 +- packages/utils/src/stream-to-ma-conn.ts | 13 +- packages/utils/test/stream-to-ma-conn.spec.ts | 4 +- 56 files changed, 1128 insertions(+), 1010 deletions(-) create mode 100644 packages/libp2p/src/connection.ts delete mode 100644 packages/libp2p/src/connection/index.ts create mode 100644 packages/libp2p/test/connection/compliance.spec.ts delete mode 100644 packages/libp2p/test/connection/fixtures/pair.ts create mode 100644 packages/libp2p/test/connection/utils.ts diff --git a/packages/connection-encrypter-plaintext/package.json b/packages/connection-encrypter-plaintext/package.json index c4bde5c27c..4949a815eb 100644 --- a/packages/connection-encrypter-plaintext/package.json +++ b/packages/connection-encrypter-plaintext/package.json @@ -49,7 +49,6 @@ "@libp2p/interface": "^2.10.5", "@libp2p/peer-id": "^5.1.8", "it-protobuf-stream": "^2.0.2", - "it-stream-types": "^2.0.2", "protons-runtime": "^5.5.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" diff --git a/packages/connection-encrypter-plaintext/src/index.ts b/packages/connection-encrypter-plaintext/src/index.ts index 976e1ac24e..ba2b0796d9 100644 --- a/packages/connection-encrypter-plaintext/src/index.ts +++ b/packages/connection-encrypter-plaintext/src/index.ts @@ -27,9 +27,7 @@ import { peerIdFromPublicKey } from '@libp2p/peer-id' import { pbStream } from 'it-protobuf-stream' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' import { Exchange, KeyType } from './pb/proto.js' -import type { ComponentLogger, Logger, MultiaddrConnection, ConnectionEncrypter, SecuredConnection, PrivateKey, SecureConnectionOptions } from '@libp2p/interface' -import type { Duplex } from 'it-stream-types' -import type { Uint8ArrayList } from 'uint8arraylist' +import type { ComponentLogger, Logger, MultiaddrConnection, ConnectionEncrypter, SecuredConnection, PrivateKey, SecureConnectionOptions, SecurableStream } from '@libp2p/interface' const PROTOCOL = '/plaintext/2.0.0' @@ -54,21 +52,22 @@ class Plaintext implements ConnectionEncrypter { '@libp2p/connection-encryption' ] - async secureInbound> = MultiaddrConnection>(conn: Stream, options?: SecureConnectionOptions): Promise> { + async secureInbound(conn: Stream, options?: SecureConnectionOptions): Promise> { return this._encrypt(conn, options) } - async secureOutbound> = MultiaddrConnection>(conn: Stream, options?: SecureConnectionOptions): Promise> { + async secureOutbound(conn: Stream, options?: SecureConnectionOptions): Promise> { return this._encrypt(conn, options) } /** * Encrypt connection */ - async _encrypt> = MultiaddrConnection>(conn: Stream, options?: SecureConnectionOptions): Promise> { + async _encrypt(conn: Stream, options?: SecureConnectionOptions): Promise> { + const log = conn.log?.newScope('plaintext') ?? this.log const pb = pbStream(conn).pb(Exchange) - this.log('write pubkey exchange to peer %p', options?.remotePeer) + log('write pubkey exchange to peer %p', options?.remotePeer) const publicKey = this.privateKey.publicKey @@ -108,7 +107,7 @@ class Plaintext implements ConnectionEncrypter { throw new InvalidCryptoExchangeError('Public key did not match id') } } catch (err: any) { - this.log.error(err) + log.error(err) throw new InvalidCryptoExchangeError('Invalid public key - ' + err.message) } @@ -116,7 +115,7 @@ class Plaintext implements ConnectionEncrypter { throw new UnexpectedPeerError() } - this.log('plaintext key exchange completed successfully with peer %p', peerId) + log('plaintext key exchange completed successfully with peer %p', peerId) return { conn: pb.unwrap().unwrap(), diff --git a/packages/connection-encrypter-tls/src/tls.ts b/packages/connection-encrypter-tls/src/tls.ts index 328631e423..d88b59c6bf 100644 --- a/packages/connection-encrypter-tls/src/tls.ts +++ b/packages/connection-encrypter-tls/src/tls.ts @@ -24,10 +24,8 @@ import { HandshakeTimeoutError } from './errors.js' import { generateCertificate, verifyPeerCertificate, itToStream, streamToIt } from './utils.js' import { PROTOCOL } from './index.js' import type { TLSComponents } from './index.js' -import type { MultiaddrConnection, ConnectionEncrypter, SecuredConnection, Logger, SecureConnectionOptions, CounterGroup, StreamMuxerFactory } from '@libp2p/interface' -import type { Duplex } from 'it-stream-types' +import type { MultiaddrConnection, ConnectionEncrypter, SecuredConnection, Logger, SecureConnectionOptions, CounterGroup, StreamMuxerFactory, SecurableStream } from '@libp2p/interface' import type { TLSSocketOptions } from 'node:tls' -import type { Uint8ArrayList } from 'uint8arraylist' export class TLS implements ConnectionEncrypter { public protocol: string = PROTOCOL @@ -77,18 +75,19 @@ export class TLS implements ConnectionEncrypter { '@libp2p/connection-encryption' ] - async secureInbound > = MultiaddrConnection> (conn: Stream, options?: SecureConnectionOptions): Promise> { + async secureInbound (conn: Stream, options?: SecureConnectionOptions): Promise> { return this._encrypt(conn, true, options) } - async secureOutbound > = MultiaddrConnection> (conn: Stream, options?: SecureConnectionOptions): Promise> { + async secureOutbound (conn: Stream, options?: SecureConnectionOptions): Promise> { return this._encrypt(conn, false, options) } /** * Encrypt connection */ - async _encrypt > = MultiaddrConnection> (conn: Stream, isServer: boolean, options?: SecureConnectionOptions): Promise> { + async _encrypt (conn: Stream, isServer: boolean, options?: SecureConnectionOptions): Promise> { + const log = conn.log?.newScope('tls') ?? this.log let streamMuxer: StreamMuxerFactory | undefined let streamMuxers: string[] = [] @@ -112,7 +111,7 @@ export class TLS implements ConnectionEncrypter { 'libp2p' ], ALPNCallback: ({ protocols }) => { - this.log.trace('received protocols %s', protocols) + log.trace('received protocols %s', protocols) let chosenProtocol: string | undefined for (const protocol of protocols) { @@ -165,7 +164,7 @@ export class TLS implements ConnectionEncrypter { verifyPeerCertificate(remote.raw, options?.remotePeer, this.log) .then(remotePeer => { - this.log('remote certificate ok, remote peer %p', remotePeer) + log('remote certificate ok, remote peer %p', remotePeer) // 'libp2p' is a special protocol - if it's sent the remote does not // support early muxer negotiation @@ -175,7 +174,7 @@ export class TLS implements ConnectionEncrypter { if (streamMuxer == null) { const err = new InvalidCryptoExchangeError(`Selected muxer ${socket.alpnProtocol} did not exist`) - this.log.error(`Selected muxer ${socket.alpnProtocol} did not exist - %e`, err) + log.error(`Selected muxer ${socket.alpnProtocol} did not exist - %e`, err) if (isAbortable(conn)) { conn.abort(err) diff --git a/packages/connection-encrypter-tls/test/index.spec.ts b/packages/connection-encrypter-tls/test/index.spec.ts index 6f7a051305..dec2532f41 100644 --- a/packages/connection-encrypter-tls/test/index.spec.ts +++ b/packages/connection-encrypter-tls/test/index.spec.ts @@ -47,12 +47,14 @@ describe('tls', () => { await Promise.all([ encrypter.secureInbound(stubInterface({ - ...inbound + ...inbound, + log: defaultLogger().forComponent('inbound') }), { remotePeer }), encrypter.secureOutbound(stubInterface({ - ...outbound + ...outbound, + log: defaultLogger().forComponent('outbound') }), { remotePeer: wrongPeer }) @@ -81,12 +83,14 @@ describe('tls', () => { await expect(Promise.all([ encrypter.secureInbound(stubInterface({ - ...inbound + ...inbound, + log: defaultLogger().forComponent('inbound') }), { remotePeer }), encrypter.secureOutbound(stubInterface({ - ...outbound + ...outbound, + log: defaultLogger().forComponent('outbound') }), { remotePeer: localPeer }) @@ -99,12 +103,14 @@ describe('tls', () => { const result = await Promise.all([ encrypter.secureInbound(stubInterface({ - ...inbound + ...inbound, + log: defaultLogger().forComponent('inbound') }), { remotePeer: localPeer }), encrypter.secureOutbound(stubInterface({ - ...outbound + ...outbound, + log: defaultLogger().forComponent('outbound') }), { remotePeer: localPeer }) @@ -119,13 +125,15 @@ describe('tls', () => { const result = await Promise.all([ encrypter.secureInbound(stubInterface({ - ...inbound + ...inbound, + log: defaultLogger().forComponent('inbound') }), { remotePeer: localPeer, skipStreamMuxerNegotiation: true }), encrypter.secureOutbound(stubInterface({ - ...outbound + ...outbound, + log: defaultLogger().forComponent('outbound') }), { remotePeer: localPeer, skipStreamMuxerNegotiation: true diff --git a/packages/interface-compliance-tests/src/mocks/connection.ts b/packages/interface-compliance-tests/src/mocks/connection.ts index 7cc2c34a0e..9cb596e918 100644 --- a/packages/interface-compliance-tests/src/mocks/connection.ts +++ b/packages/interface-compliance-tests/src/mocks/connection.ts @@ -137,6 +137,7 @@ export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectio const log = logger.forComponent('libp2p:mock-muxer') const muxer = muxerFactory.createStreamMuxer({ + log, direction, onIncomingStream: (muxedStream) => { try { diff --git a/packages/interface-compliance-tests/src/mocks/muxer.ts b/packages/interface-compliance-tests/src/mocks/muxer.ts index 139817e317..8a7b87f154 100644 --- a/packages/interface-compliance-tests/src/mocks/muxer.ts +++ b/packages/interface-compliance-tests/src/mocks/muxer.ts @@ -1,4 +1,4 @@ -import { logger } from '@libp2p/logger' +import { defaultLogger, logger } from '@libp2p/logger' import { AbstractStream } from '@libp2p/utils/abstract-stream' import { abortableSource } from 'abortable-iterator' import map from 'it-map' @@ -131,7 +131,7 @@ class MockMuxer implements StreamMuxer { this.registryInitiatorStreams = new Map() this.registryRecipientStreams = new Map() this.log('create muxer') - this.options = init ?? { direction: 'inbound' } + this.options = init ?? { direction: 'inbound', log: defaultLogger().forComponent('mock-muxer') } this.closeController = new AbortController() // receives data from the muxer at the other end of the stream this.source = this.input = pushable({ diff --git a/packages/interface-compliance-tests/src/stream-muxer/base-test.ts b/packages/interface-compliance-tests/src/stream-muxer/base-test.ts index d7117297bd..fb7ef9ea07 100644 --- a/packages/interface-compliance-tests/src/stream-muxer/base-test.ts +++ b/packages/interface-compliance-tests/src/stream-muxer/base-test.ts @@ -22,7 +22,9 @@ export default (common: TestSetup): void => { const onStreamEndPromise: DeferredPromise = defer() const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) const listenerFactory = await common.setup() const listener = listenerFactory.createStreamMuxer({ @@ -88,7 +90,9 @@ export default (common: TestSetup): void => { }) const listenerFactory = await common.setup() - const listener = listenerFactory.createStreamMuxer({ direction: 'inbound' }) + const listener = listenerFactory.createStreamMuxer({ + direction: 'inbound' + }) void pipe(p[0], dialer, p[0]) void pipe(p[1], listener, p[1]) diff --git a/packages/interface-compliance-tests/src/stream-muxer/close-test.ts b/packages/interface-compliance-tests/src/stream-muxer/close-test.ts index 2188676066..d3603f4bbb 100644 --- a/packages/interface-compliance-tests/src/stream-muxer/close-test.ts +++ b/packages/interface-compliance-tests/src/stream-muxer/close-test.ts @@ -72,7 +72,9 @@ export default (common: TestSetup): void => { let openedStreams = 0 const expectedStreams = 5 const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) // Listener is echo server :) const listenerFactory = await common.setup() @@ -114,7 +116,9 @@ export default (common: TestSetup): void => { let openedStreams = 0 const expectedStreams = 5 const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) // Listener is echo server :) const listenerFactory = await common.setup() @@ -157,7 +161,9 @@ export default (common: TestSetup): void => { let openedStreams = 0 const expectedStreams = 5 const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) // Listener is echo server :) const listenerFactory = await common.setup() @@ -212,7 +218,9 @@ export default (common: TestSetup): void => { it('calling newStream after close throws an error', async () => { const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) await dialer.close() @@ -227,7 +235,9 @@ export default (common: TestSetup): void => { it('closing one of the muxed streams doesn\'t close others', async () => { const p = duplexPair() const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) // Listener is echo server :) const listenerFactory = await common.setup() @@ -280,7 +290,9 @@ export default (common: TestSetup): void => { const p = duplexPair() const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) const data = [randomBuffer(), randomBuffer()] const listenerFactory = await common.setup() @@ -325,7 +337,9 @@ export default (common: TestSetup): void => { const deferred = pDefer() const p = duplexPair() const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) const data = [randomBuffer(), randomBuffer()].map(d => new Uint8ArrayList(d)) const expected = toBuffer(data.map(d => d.subarray())) @@ -391,7 +405,9 @@ export default (common: TestSetup): void => { const p = duplexPair() const dialerFactory = await common.setup() - const dialer = dialerFactory.createStreamMuxer({ direction: 'outbound' }) + const dialer = dialerFactory.createStreamMuxer({ + direction: 'outbound' + }) const listenerFactory = await common.setup() const listener = listenerFactory.createStreamMuxer({ diff --git a/packages/interface-compliance-tests/src/stream-muxer/spawner.ts b/packages/interface-compliance-tests/src/stream-muxer/spawner.ts index 30bb238bf2..cd97dfe0f2 100644 --- a/packages/interface-compliance-tests/src/stream-muxer/spawner.ts +++ b/packages/interface-compliance-tests/src/stream-muxer/spawner.ts @@ -25,7 +25,9 @@ export default async (createMuxer: (init?: StreamMuxerInit) => Promise { stream.abort(err) }) } }) - const dialer = await createMuxer({ direction: 'outbound' }) + const dialer = await createMuxer({ + direction: 'outbound' + }) void pipe(listenerSocket, listener, listenerSocket) void pipe(dialerSocket, dialer, dialerSocket) diff --git a/packages/interface/src/connection-encrypter.ts b/packages/interface/src/connection-encrypter.ts index 05607b5c20..e4ef74b469 100644 --- a/packages/interface/src/connection-encrypter.ts +++ b/packages/interface/src/connection-encrypter.ts @@ -1,5 +1,5 @@ import type { MultiaddrConnection } from './connection.js' -import type { AbortOptions, StreamMuxerFactory } from './index.js' +import type { AbortOptions, Logger, StreamMuxerFactory } from './index.js' import type { PeerId } from './peer-id.js' import type { Duplex } from 'it-stream-types' import type { Uint8ArrayList } from 'uint8arraylist' @@ -21,6 +21,13 @@ export interface SecureConnectionOptions extends AbortOptions { skipStreamMuxerNegotiation?: boolean } +/** + * A stream with an optional logger + */ +export interface SecurableStream extends Duplex> { + log?: Logger +} + /** * A libp2p connection encrypter module must be compliant to this interface * to ensure all exchanged data between two peers is encrypted. @@ -33,14 +40,14 @@ export interface ConnectionEncrypter { * pass it for extra verification, otherwise it will be determined during * the handshake. */ - secureOutbound > = MultiaddrConnection> (connection: Stream, options?: SecureConnectionOptions): Promise> + secureOutbound (connection: Stream, options?: SecureConnectionOptions): Promise> /** * Decrypt incoming data. If the remote PeerId is known, * pass it for extra verification, otherwise it will be determined during * the handshake */ - secureInbound > = MultiaddrConnection> (connection: Stream, options?: SecureConnectionOptions): Promise> + secureInbound (connection: Stream, options?: SecureConnectionOptions): Promise> } export interface SecuredConnection { diff --git a/packages/interface/src/stream-muxer.ts b/packages/interface/src/stream-muxer.ts index 58979a12a9..fe75df5a51 100644 --- a/packages/interface/src/stream-muxer.ts +++ b/packages/interface/src/stream-muxer.ts @@ -1,5 +1,5 @@ import type { Direction, Stream } from './connection.js' -import type { AbortOptions } from './index.js' +import type { AbortOptions, Logger } from './index.js' import type { Duplex } from 'it-stream-types' import type { Uint8ArrayList } from 'uint8arraylist' @@ -60,4 +60,9 @@ export interface StreamMuxerInit { * Outbound stream muxers are opened by the local node, inbound stream muxers are opened by the remote */ direction?: Direction + + /** + * The logger used by the connection + */ + log?: Logger } diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 181999aef9..4e9cf817ca 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -115,13 +115,12 @@ "it-length-prefixed": "^10.0.1", "it-map": "^3.1.3", "it-pair": "^2.0.6", - "it-stream-types": "^2.0.2", + "it-pipe": "^3.0.1", "it-take": "^3.0.8", "p-event": "^6.0.1", "p-wait-for": "^5.0.2", "sinon": "^20.0.0", "sinon-ts": "^2.0.0", - "uint8arraylist": "^2.4.8", "wherearewe": "^2.0.1" }, "browser": { diff --git a/packages/libp2p/src/address-manager/dns-mappings.ts b/packages/libp2p/src/address-manager/dns-mappings.ts index f14ed8b267..841af6b886 100644 --- a/packages/libp2p/src/address-manager/dns-mappings.ts +++ b/packages/libp2p/src/address-manager/dns-mappings.ts @@ -72,7 +72,7 @@ export class DNSMappings { for (const [ip, mapping] of this.mappings.entries()) { if (mapping.domain === host) { - this.log('removing %s to %s DNS mapping %e', ip, mapping.domain, new Error('where')) + this.log('removing %s to %s DNS mapping %e', ip, mapping.domain) this.mappings.delete(ip) wasConfident = wasConfident || mapping.verified } diff --git a/packages/libp2p/src/connection-manager/index.ts b/packages/libp2p/src/connection-manager/index.ts index 3fbce06ef9..8545d74373 100644 --- a/packages/libp2p/src/connection-manager/index.ts +++ b/packages/libp2p/src/connection-manager/index.ts @@ -500,7 +500,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable { if (filteredPeerConns.length === 0) { // trigger disconnect event if no connections remain - this.log('onDisconnect remove all connections for peer %p', peerId) + this.log.trace('peer %p disconnected, removing connection map entry', peerId) this.connections.delete(peerId) // broadcast disconnect event @@ -548,7 +548,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable { .find(conn => conn.limits == null) if (existingConnection != null) { - this.log('had an existing non-limited connection to %p', peerId) + this.log('had an existing non-limited connection to %p as %a', peerId, existingConnection.remoteAddr) options.onProgress?.(new CustomProgressEvent('dial-queue:already-connected')) return existingConnection diff --git a/packages/libp2p/src/connection.ts b/packages/libp2p/src/connection.ts new file mode 100644 index 0000000000..0ba1a7ae4a --- /dev/null +++ b/packages/libp2p/src/connection.ts @@ -0,0 +1,395 @@ +import { connectionSymbol, LimitedConnectionError, ConnectionClosedError, ConnectionClosingError, TooManyOutboundProtocolStreamsError, TooManyInboundProtocolStreamsError } from '@libp2p/interface' +import * as mss from '@libp2p/multistream-select' +import { setMaxListeners } from 'main-event' +import { PROTOCOL_NEGOTIATION_TIMEOUT } from './connection-manager/constants.defaults.ts' +import { MuxerUnavailableError } from './errors.ts' +import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from './registrar.ts' +import type { AbortOptions, Logger, Direction, Connection as ConnectionInterface, Stream, ConnectionTimeline, ConnectionStatus, NewStreamOptions, PeerId, ConnectionLimits, StreamMuxerFactory, StreamMuxer, Metrics, PeerStore, MultiaddrConnection } from '@libp2p/interface' +import type { Registrar } from '@libp2p/interface-internal' +import type { Multiaddr } from '@multiformats/multiaddr' + +const CLOSE_TIMEOUT = 500 + +export interface ConnectionComponents { + peerStore: PeerStore + registrar: Registrar + metrics?: Metrics +} + +export interface ConnectionInit { + id: string + maConn: MultiaddrConnection + remotePeer: PeerId + direction?: Direction + muxerFactory?: StreamMuxerFactory + encryption?: string + limits?: ConnectionLimits + outboundStreamProtocolNegotiationTimeout?: number + inboundStreamProtocolNegotiationTimeout?: number +} + +/** + * An implementation of the js-libp2p connection. + * Any libp2p transport should use an upgrader to return this connection. + */ +export class Connection implements ConnectionInterface { + public readonly id: string + public readonly remoteAddr: Multiaddr + public readonly remotePeer: PeerId + public direction: Direction + public timeline: ConnectionTimeline + public multiplexer?: string + public encryption?: string + public status: ConnectionStatus + public limits?: ConnectionLimits + public readonly log: Logger + public tags: string[] + + private readonly maConn: MultiaddrConnection + private readonly muxer?: StreamMuxer + private readonly components: ConnectionComponents + private readonly outboundStreamProtocolNegotiationTimeout: number + private readonly inboundStreamProtocolNegotiationTimeout: number + + constructor (components: ConnectionComponents, init: ConnectionInit) { + this.components = components + + this.id = init.id + this.remoteAddr = init.maConn.remoteAddr + this.remotePeer = init.remotePeer + this.direction = init.direction ?? 'outbound' + this.status = 'open' + this.timeline = init.maConn.timeline + this.encryption = init.encryption + this.limits = init.limits + this.maConn = init.maConn + this.log = init.maConn.log + this.outboundStreamProtocolNegotiationTimeout = init.outboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT + this.inboundStreamProtocolNegotiationTimeout = init.inboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT + + if (this.remoteAddr.getPeerId() == null) { + this.remoteAddr = this.remoteAddr.encapsulate(`/p2p/${this.remotePeer}`) + } + + this.tags = [] + + if (init.muxerFactory != null) { + this.multiplexer = init.muxerFactory.protocol + + this.muxer = init.muxerFactory.createStreamMuxer({ + direction: this.direction, + log: this.log, + // Run anytime a remote stream is created + onIncomingStream: (stream) => { + this.onIncomingStream(stream) + } + }) + + // Pipe all data through the muxer + void Promise.all([ + this.muxer.sink(this.maConn.source), + this.maConn.sink(this.muxer.source) + ]).catch(err => { + this.log.error('error piping data through muxer - %e', err) + }) + } + } + + readonly [Symbol.toStringTag] = 'Connection' + + readonly [connectionSymbol] = true + + get streams (): Stream[] { + return this.muxer?.streams ?? [] + } + + /** + * Create a new stream over this connection + */ + newStream = async (protocols: string[], options: NewStreamOptions = {}): Promise => { + if (this.status === 'closing') { + throw new ConnectionClosingError('the connection is being closed') + } + + if (this.status === 'closed') { + throw new ConnectionClosedError('the connection is closed') + } + + if (!Array.isArray(protocols)) { + protocols = [protocols] + } + + if (this.limits != null && options?.runOnLimitedConnection !== true) { + throw new LimitedConnectionError('Cannot open protocol stream on limited connection') + } + + if (this.muxer == null) { + throw new MuxerUnavailableError('Connection is not multiplexed') + } + + this.log.trace('starting new stream for protocols %s', protocols) + const muxedStream = await this.muxer.newStream() + this.log.trace('started new stream %s for protocols %s', muxedStream.id, protocols) + + try { + if (options.signal == null) { + muxedStream.log('no abort signal was passed while trying to negotiate protocols %s falling back to default timeout', protocols) + + const signal = AbortSignal.timeout(this.outboundStreamProtocolNegotiationTimeout) + setMaxListeners(Infinity, signal) + + options = { + ...options, + signal + } + } + + muxedStream.log.trace('selecting protocol from protocols %s', protocols) + + const { + stream, + protocol + } = await mss.select(muxedStream, protocols, { + ...options, + log: muxedStream.log, + yieldBytes: true + }) + + muxedStream.log('selected protocol %s', protocol) + + const outgoingLimit = findOutgoingStreamLimit(protocol, this.components.registrar, options) + const streamCount = countStreams(protocol, 'outbound', this) + + if (streamCount >= outgoingLimit) { + const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${protocol}" - ${streamCount}/${outgoingLimit}`) + muxedStream.abort(err) + + throw err + } + + // If a protocol stream has been successfully negotiated and is to be passed to the application, + // the peer store should ensure that the peer is registered with that protocol + await this.components.peerStore.merge(this.remotePeer, { + protocols: [protocol] + }) + + // after the handshake the returned stream can have early data so override + // the source/sink + muxedStream.source = stream.source + muxedStream.sink = stream.sink + muxedStream.protocol = protocol + + // allow closing the write end of a not-yet-negotiated stream + if (stream.closeWrite != null) { + muxedStream.closeWrite = stream.closeWrite + } + + // allow closing the read end of a not-yet-negotiated stream + if (stream.closeRead != null) { + muxedStream.closeRead = stream.closeRead + } + + // make sure we don't try to negotiate a stream we are closing + if (stream.close != null) { + muxedStream.close = stream.close + } + + this.components.metrics?.trackProtocolStream(muxedStream, this) + + muxedStream.direction = 'outbound' + + return muxedStream + } catch (err: any) { + this.log.error('could not create new outbound stream on connection %s %a for protocols %s - %e', this.direction === 'inbound' ? 'from' : 'to', this.remoteAddr, protocols, err) + + if (muxedStream.timeline.close == null) { + muxedStream.abort(err) + } + + throw err + } + } + + private onIncomingStream (muxedStream: Stream): void { + const signal = AbortSignal.timeout(this.inboundStreamProtocolNegotiationTimeout) + setMaxListeners(Infinity, signal) + + void Promise.resolve() + .then(async () => { + const protocols = this.components.registrar.getProtocols() + + const { stream, protocol } = await mss.handle(muxedStream, protocols, { + signal, + log: muxedStream.log, + yieldBytes: false + }) + + this.log('incoming %s stream opened', protocol) + + const incomingLimit = findIncomingStreamLimit(protocol, this.components.registrar) + const streamCount = countStreams(protocol, 'inbound', this) + + if (streamCount === incomingLimit) { + const err = new TooManyInboundProtocolStreamsError(`Too many inbound protocol streams for protocol "${protocol}" - limit ${incomingLimit}`) + muxedStream.abort(err) + + throw err + } + + // after the handshake the returned stream can have early data so override + // the source/sink + muxedStream.source = stream.source + muxedStream.sink = stream.sink + muxedStream.protocol = protocol + + // allow closing the write end of a not-yet-negotiated stream + if (stream.closeWrite != null) { + muxedStream.closeWrite = stream.closeWrite + } + + // allow closing the read end of a not-yet-negotiated stream + if (stream.closeRead != null) { + muxedStream.closeRead = stream.closeRead + } + + // make sure we don't try to negotiate a stream we are closing + if (stream.close != null) { + muxedStream.close = stream.close + } + + // If a protocol stream has been successfully negotiated and is to be passed to the application, + // the peer store should ensure that the peer is registered with that protocol + await this.components.peerStore.merge(this.remotePeer, { + protocols: [protocol] + }, { + signal + }) + + this.components.metrics?.trackProtocolStream(muxedStream, this) + + const { handler, options } = this.components.registrar.getHandler(protocol) + + if (this.limits != null && options.runOnLimitedConnection !== true) { + throw new LimitedConnectionError('Cannot open protocol stream on limited connection') + } + + handler({ connection: this, stream: muxedStream }) + }) + .catch(async err => { + this.log.error('error handling incoming stream id %s - %e', muxedStream.id, err) + + if (muxedStream.timeline.close == null) { + await muxedStream.close({ + signal + }) + .catch(err => muxedStream.abort(err)) + } + }) + } + + /** + * Close the connection + */ + async close (options: AbortOptions = {}): Promise { + if (this.status === 'closed' || this.status === 'closing') { + return + } + + this.log('closing connection to %a', this.remoteAddr) + + this.status = 'closing' + + if (options.signal == null) { + const signal = AbortSignal.timeout(CLOSE_TIMEOUT) + setMaxListeners(Infinity, signal) + + options = { + ...options, + signal + } + } + + try { + this.log.trace('closing underlying transport') + + // ensure remaining streams are closed gracefully + await this.muxer?.close(options) + + // close the underlying transport + await this.maConn.close(options) + + this.log.trace('updating timeline with close time') + + this.status = 'closed' + this.timeline.close = Date.now() + } catch (err: any) { + this.log.error('error encountered during graceful close of connection to %a', this.remoteAddr, err) + this.abort(err) + } + } + + abort (err: Error): void { + if (this.status === 'closed') { + return + } + + this.log.error('aborting connection to %a due to error', this.remoteAddr, err) + + this.status = 'closing' + + // ensure remaining streams are aborted + this.muxer?.abort(err) + + // abort the underlying transport + this.maConn.abort(err) + + this.status = 'closed' + this.timeline.close = Date.now() + } +} + +export function createConnection (components: ConnectionComponents, init: ConnectionInit): ConnectionInterface { + return new Connection(components, init) +} + +function findIncomingStreamLimit (protocol: string, registrar: Registrar): number | undefined { + try { + const { options } = registrar.getHandler(protocol) + + return options.maxInboundStreams + } catch (err: any) { + if (err.name !== 'UnhandledProtocolError') { + throw err + } + } + + return DEFAULT_MAX_INBOUND_STREAMS +} + +function findOutgoingStreamLimit (protocol: string, registrar: Registrar, options: NewStreamOptions = {}): number { + try { + const { options } = registrar.getHandler(protocol) + + if (options.maxOutboundStreams != null) { + return options.maxOutboundStreams + } + } catch (err: any) { + if (err.name !== 'UnhandledProtocolError') { + throw err + } + } + + return options.maxOutboundStreams ?? DEFAULT_MAX_OUTBOUND_STREAMS +} + +function countStreams (protocol: string, direction: 'inbound' | 'outbound', connection: Connection): number { + let streamCount = 0 + + connection.streams.forEach(stream => { + if (stream.direction === direction && stream.protocol === protocol) { + streamCount++ + } + }) + + return streamCount +} diff --git a/packages/libp2p/src/connection/index.ts b/packages/libp2p/src/connection/index.ts deleted file mode 100644 index 03b27f90d2..0000000000 --- a/packages/libp2p/src/connection/index.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { connectionSymbol, LimitedConnectionError, ConnectionClosedError, ConnectionClosingError } from '@libp2p/interface' -import { setMaxListeners } from 'main-event' -import type { AbortOptions, Logger, ComponentLogger, Direction, Connection, Stream, ConnectionTimeline, ConnectionStatus, NewStreamOptions, PeerId, ConnectionLimits } from '@libp2p/interface' -import type { Multiaddr } from '@multiformats/multiaddr' - -const CLOSE_TIMEOUT = 500 - -interface ConnectionInit { - remoteAddr: Multiaddr - remotePeer: PeerId - newStream(protocols: string[], options?: AbortOptions): Promise - close(options?: AbortOptions): Promise - abort(err: Error): void - getStreams(): Stream[] - status: ConnectionStatus - direction: Direction - timeline: ConnectionTimeline - multiplexer?: string - encryption?: string - limits?: ConnectionLimits - logger: ComponentLogger -} - -/** - * An implementation of the js-libp2p connection. - * Any libp2p transport should use an upgrader to return this connection. - */ -export class ConnectionImpl implements Connection { - /** - * Connection identifier. - */ - public readonly id: string - - /** - * Observed multiaddr of the remote peer - */ - public readonly remoteAddr: Multiaddr - - /** - * Remote peer id - */ - public readonly remotePeer: PeerId - - public direction: Direction - public timeline: ConnectionTimeline - public multiplexer?: string - public encryption?: string - public status: ConnectionStatus - public limits?: ConnectionLimits - public readonly log: Logger - - /** - * User provided tags - * - */ - public tags: string[] - - /** - * Reference to the new stream function of the multiplexer - */ - private readonly _newStream: (protocols: string[], options?: NewStreamOptions) => Promise - - /** - * Reference to the close function of the raw connection - */ - private readonly _close: (options?: AbortOptions) => Promise - - private readonly _abort: (err: Error) => void - - /** - * Reference to the getStreams function of the muxer - */ - private readonly _getStreams: () => Stream[] - - /** - * An implementation of the js-libp2p connection. - * Any libp2p transport should use an upgrader to return this connection. - */ - constructor (init: ConnectionInit) { - const { remoteAddr, remotePeer, newStream, close, abort, getStreams } = init - - this.id = `${(parseInt(String(Math.random() * 1e9))).toString(36)}${Date.now()}` - this.remoteAddr = remoteAddr - this.remotePeer = remotePeer - this.direction = init.direction - this.status = 'open' - this.timeline = init.timeline - this.multiplexer = init.multiplexer - this.encryption = init.encryption - this.limits = init.limits - this.log = init.logger.forComponent(`libp2p:connection:${this.direction}:${this.id}`) - - if (this.remoteAddr.getPeerId() == null) { - this.remoteAddr = this.remoteAddr.encapsulate(`/p2p/${this.remotePeer}`) - } - - this._newStream = newStream - this._close = close - this._abort = abort - this._getStreams = getStreams - this.tags = [] - } - - readonly [Symbol.toStringTag] = 'Connection' - - readonly [connectionSymbol] = true - - /** - * Get all the streams of the muxer - */ - get streams (): Stream[] { - return this._getStreams() - } - - /** - * Create a new stream from this connection - */ - async newStream (protocols: string | string[], options?: NewStreamOptions): Promise { - if (this.status === 'closing') { - throw new ConnectionClosingError('the connection is being closed') - } - - if (this.status === 'closed') { - throw new ConnectionClosedError('the connection is closed') - } - - if (!Array.isArray(protocols)) { - protocols = [protocols] - } - - if (this.limits != null && options?.runOnLimitedConnection !== true) { - throw new LimitedConnectionError('Cannot open protocol stream on limited connection') - } - - const stream = await this._newStream(protocols, options) - - stream.direction = 'outbound' - - return stream - } - - /** - * Close the connection - */ - async close (options: AbortOptions = {}): Promise { - if (this.status === 'closed' || this.status === 'closing') { - return - } - - this.log('closing connection to %a', this.remoteAddr) - - this.status = 'closing' - - if (options.signal == null) { - const signal = AbortSignal.timeout(CLOSE_TIMEOUT) - setMaxListeners(Infinity, signal) - - options = { - ...options, - signal - } - } - - try { - this.log.trace('closing underlying transport') - - // close raw connection - await this._close(options) - - this.log.trace('updating timeline with close time') - - this.status = 'closed' - this.timeline.close = Date.now() - } catch (err: any) { - this.log.error('error encountered during graceful close of connection to %a', this.remoteAddr, err) - this.abort(err) - } - } - - abort (err: Error): void { - if (this.status === 'closed') { - return - } - - this.log.error('aborting connection to %a due to error', this.remoteAddr, err) - - this.status = 'closing' - - // Abort raw connection - this._abort(err) - - this.status = 'closed' - this.timeline.close = Date.now() - } -} - -export function createConnection (init: ConnectionInit): Connection { - return new ConnectionImpl(init) -} diff --git a/packages/libp2p/src/upgrader.ts b/packages/libp2p/src/upgrader.ts index 833e6e6872..7db1817524 100644 --- a/packages/libp2p/src/upgrader.ts +++ b/packages/libp2p/src/upgrader.ts @@ -1,4 +1,4 @@ -import { InvalidMultiaddrError, TooManyInboundProtocolStreamsError, TooManyOutboundProtocolStreamsError, LimitedConnectionError, InvalidPeerIdError } from '@libp2p/interface' +import { InvalidMultiaddrError, InvalidPeerIdError } from '@libp2p/interface' import * as mss from '@libp2p/multistream-select' import { peerIdFromString } from '@libp2p/peer-id' import { trackedMap } from '@libp2p/utils/tracked-map' @@ -6,15 +6,15 @@ import { anySignal } from 'any-signal' import { setMaxListeners } from 'main-event' import { CustomProgressEvent } from 'progress-events' import { raceSignal } from 'race-signal' -import { createConnection } from './connection/index.js' import { PROTOCOL_NEGOTIATION_TIMEOUT, INBOUND_UPGRADE_TIMEOUT } from './connection-manager/constants.js' +import { createConnection } from './connection.js' import { ConnectionDeniedError, ConnectionInterceptedError, EncryptionFailedError, MuxerUnavailableError } from './errors.js' -import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from './registrar.js' -import type { Libp2pEvents, AbortOptions, ComponentLogger, MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions, ConnectionEncrypter, SecuredConnection, ConnectionGater, Metrics, PeerId, PeerStore, StreamMuxer, StreamMuxerFactory, Upgrader as UpgraderInterface, UpgraderOptions, ConnectionLimits, SecureConnectionOptions, CounterGroup, ClearableSignal } from '@libp2p/interface' +import type { Libp2pEvents, AbortOptions, ComponentLogger, MultiaddrConnection, Connection, ConnectionProtector, ConnectionEncrypter, SecuredConnection, ConnectionGater, Metrics, PeerId, PeerStore, StreamMuxerFactory, Upgrader as UpgraderInterface, UpgraderOptions, ConnectionLimits, SecureConnectionOptions, CounterGroup, ClearableSignal } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { TypedEventTarget } from 'main-event' interface CreateConnectionOptions { + id: string cryptoProtocol: string direction: 'inbound' | 'outbound' maConn: MultiaddrConnection @@ -24,12 +24,6 @@ interface CreateConnectionOptions { limits?: ConnectionLimits } -interface OnStreamOptions { - connection: Connection - stream: Stream - protocol: string -} - export interface CryptoResult extends SecuredConnection { protocol: string } @@ -62,48 +56,6 @@ export interface UpgraderInit { outboundStreamProtocolNegotiationTimeout?: number } -function findIncomingStreamLimit (protocol: string, registrar: Registrar): number | undefined { - try { - const { options } = registrar.getHandler(protocol) - - return options.maxInboundStreams - } catch (err: any) { - if (err.name !== 'UnhandledProtocolError') { - throw err - } - } - - return DEFAULT_MAX_INBOUND_STREAMS -} - -function findOutgoingStreamLimit (protocol: string, registrar: Registrar, options: NewStreamOptions = {}): number { - try { - const { options } = registrar.getHandler(protocol) - - if (options.maxOutboundStreams != null) { - return options.maxOutboundStreams - } - } catch (err: any) { - if (err.name !== 'UnhandledProtocolError') { - throw err - } - } - - return options.maxOutboundStreams ?? DEFAULT_MAX_OUTBOUND_STREAMS -} - -function countStreams (protocol: string, direction: 'inbound' | 'outbound', connection: Connection): number { - let streamCount = 0 - - connection.streams.forEach(stream => { - if (stream.direction === direction && stream.protocol === protocol) { - streamCount++ - } - }) - - return streamCount -} - export interface UpgraderComponents { peerId: PeerId metrics?: Metrics @@ -281,6 +233,9 @@ export class Upgrader implements UpgraderInterface { let muxerFactory: StreamMuxerFactory | undefined let cryptoProtocol + const id = `${(parseInt(String(Math.random() * 1e9))).toString(36)}${Date.now()}` + maConn.log = maConn.log.newScope(`${direction}:${id}`) + this.components.metrics?.trackMultiaddrConnection(maConn) maConn.log.trace('starting the %s connection upgrade', direction) @@ -366,9 +321,8 @@ export class Upgrader implements UpgraderInterface { await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundUpgradedConnection' : 'denyOutboundUpgradedConnection', remotePeer, maConn) - maConn.log('successfully upgraded %s connection', direction) - - return this._createConnection({ + const conn = this._createConnection({ + id, cryptoProtocol, direction, maConn, @@ -377,6 +331,10 @@ export class Upgrader implements UpgraderInterface { remotePeer, limits: opts?.limits }) + + conn.log('successfully upgraded %s connection', direction) + + return conn } /** @@ -384,6 +342,7 @@ export class Upgrader implements UpgraderInterface { */ _createConnection (opts: CreateConnectionOptions): Connection { const { + id, cryptoProtocol, direction, maConn, @@ -393,190 +352,8 @@ export class Upgrader implements UpgraderInterface { limits } = opts - let muxer: StreamMuxer | undefined - let newStream: ((multicodecs: string[], options?: AbortOptions) => Promise) | undefined let connection: Connection // eslint-disable-line prefer-const - if (muxerFactory != null) { - // Create the muxer - muxer = muxerFactory.createStreamMuxer({ - direction, - // Run anytime a remote stream is created - onIncomingStream: muxedStream => { - if (connection == null) { - return - } - - const signal = AbortSignal.timeout(this.inboundStreamProtocolNegotiationTimeout) - setMaxListeners(Infinity, signal) - - void Promise.resolve() - .then(async () => { - const protocols = this.components.registrar.getProtocols() - - const { stream, protocol } = await mss.handle(muxedStream, protocols, { - signal, - log: muxedStream.log, - yieldBytes: false - }) - - if (connection == null) { - return - } - - connection.log('incoming stream opened on %s', protocol) - - const incomingLimit = findIncomingStreamLimit(protocol, this.components.registrar) - const streamCount = countStreams(protocol, 'inbound', connection) - - if (streamCount === incomingLimit) { - const err = new TooManyInboundProtocolStreamsError(`Too many inbound protocol streams for protocol "${protocol}" - limit ${incomingLimit}`) - muxedStream.abort(err) - - throw err - } - - // after the handshake the returned stream can have early data so override - // the source/sink - muxedStream.source = stream.source - muxedStream.sink = stream.sink - muxedStream.protocol = protocol - - // allow closing the write end of a not-yet-negotiated stream - if (stream.closeWrite != null) { - muxedStream.closeWrite = stream.closeWrite - } - - // allow closing the read end of a not-yet-negotiated stream - if (stream.closeRead != null) { - muxedStream.closeRead = stream.closeRead - } - - // make sure we don't try to negotiate a stream we are closing - if (stream.close != null) { - muxedStream.close = stream.close - } - - // If a protocol stream has been successfully negotiated and is to be passed to the application, - // the peer store should ensure that the peer is registered with that protocol - await this.components.peerStore.merge(remotePeer, { - protocols: [protocol] - }, { - signal - }) - - this.components.metrics?.trackProtocolStream(muxedStream, connection) - - this._onStream({ connection, stream: muxedStream, protocol }) - }) - .catch(async err => { - connection.log.error('error handling incoming stream id %s - %e', muxedStream.id, err) - - if (muxedStream.timeline.close == null) { - await muxedStream.close({ - signal - }) - .catch(err => muxedStream.abort(err)) - } - }) - } - }) - - newStream = async (protocols: string[], options: NewStreamOptions = {}): Promise => { - if (muxer == null) { - throw new MuxerUnavailableError('Connection is not multiplexed') - } - - connection.log.trace('starting new stream for protocols %s', protocols) - const muxedStream = await muxer.newStream() - connection.log.trace('started new stream %s for protocols %s', muxedStream.id, protocols) - - try { - if (options.signal == null) { - muxedStream.log('no abort signal was passed while trying to negotiate protocols %s falling back to default timeout', protocols) - - const signal = AbortSignal.timeout(this.outboundStreamProtocolNegotiationTimeout) - setMaxListeners(Infinity, signal) - - options = { - ...options, - signal - } - } - - muxedStream.log.trace('selecting protocol from protocols %s', protocols) - - const { - stream, - protocol - } = await mss.select(muxedStream, protocols, { - ...options, - log: muxedStream.log, - yieldBytes: true - }) - - muxedStream.log.trace('selected protocol %s', protocol) - - const outgoingLimit = findOutgoingStreamLimit(protocol, this.components.registrar, options) - const streamCount = countStreams(protocol, 'outbound', connection) - - if (streamCount >= outgoingLimit) { - const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${protocol}" - ${streamCount}/${outgoingLimit}`) - muxedStream.abort(err) - - throw err - } - - // If a protocol stream has been successfully negotiated and is to be passed to the application, - // the peer store should ensure that the peer is registered with that protocol - await this.components.peerStore.merge(remotePeer, { - protocols: [protocol] - }) - - // after the handshake the returned stream can have early data so override - // the source/sink - muxedStream.source = stream.source - muxedStream.sink = stream.sink - muxedStream.protocol = protocol - - // allow closing the write end of a not-yet-negotiated stream - if (stream.closeWrite != null) { - muxedStream.closeWrite = stream.closeWrite - } - - // allow closing the read end of a not-yet-negotiated stream - if (stream.closeRead != null) { - muxedStream.closeRead = stream.closeRead - } - - // make sure we don't try to negotiate a stream we are closing - if (stream.close != null) { - muxedStream.close = stream.close - } - - this.components.metrics?.trackProtocolStream(muxedStream, connection) - - return muxedStream - } catch (err: any) { - connection.log.error('could not create new outbound stream on connection %s %a for protocols %s - %e', direction === 'inbound' ? 'from' : 'to', opts.maConn.remoteAddr, protocols, err) - - if (muxedStream.timeline.close == null) { - muxedStream.abort(err) - } - - throw err - } - } - - // Pipe all data through the muxer - void Promise.all([ - muxer.sink(upgradedConn.source), - upgradedConn.sink(muxer.source) - ]).catch(err => { - connection.log.error('error piping data through muxer - %e', err) - }) - } - const _timeline = maConn.timeline maConn.timeline = new Proxy(_timeline, { set: (...args) => { @@ -604,64 +381,26 @@ export class Upgrader implements UpgraderInterface { }) maConn.timeline.upgraded = Date.now() - const errConnectionNotMultiplexed = (): any => { - throw new MuxerUnavailableError('Connection is not multiplexed') - } - // Create the connection - connection = createConnection({ - remoteAddr: maConn.remoteAddr, + connection = createConnection(this.components, { + id, + maConn: upgradedConn, remotePeer, - status: 'open', direction, - timeline: maConn.timeline, - multiplexer: muxer?.protocol, + muxerFactory, encryption: cryptoProtocol, limits, - logger: this.components.logger, - newStream: newStream ?? errConnectionNotMultiplexed, - getStreams: () => { - return muxer?.streams ?? [] - }, - close: async (options?: AbortOptions) => { - // ensure remaining streams are closed gracefully - await muxer?.close(options) - - // close the underlying transport - await maConn.close(options) - }, - abort: (err) => { - maConn.abort(err) - - // ensure remaining streams are aborted - muxer?.abort(err) - } + outboundStreamProtocolNegotiationTimeout: this.outboundStreamProtocolNegotiationTimeout, + inboundStreamProtocolNegotiationTimeout: this.inboundStreamProtocolNegotiationTimeout }) this.events.safeDispatchEvent('connection:open', { detail: connection }) - // @ts-expect-error nah - connection.__maConnTimeline = _timeline - return connection } - /** - * Routes incoming streams to the correct handler - */ - _onStream (opts: OnStreamOptions): void { - const { connection, stream, protocol } = opts - const { handler, options } = this.components.registrar.getHandler(protocol) - - if (connection.limits != null && options.runOnLimitedConnection !== true) { - throw new LimitedConnectionError('Cannot open protocol stream on limited connection') - } - - handler({ connection, stream }) - } - /** * Attempts to encrypt the incoming `connection` with the provided `cryptos` */ diff --git a/packages/libp2p/test/connection/compliance.spec.ts b/packages/libp2p/test/connection/compliance.spec.ts new file mode 100644 index 0000000000..59b3634dda --- /dev/null +++ b/packages/libp2p/test/connection/compliance.spec.ts @@ -0,0 +1,153 @@ +import { expect } from 'aegir/chai' +import Sinon from 'sinon' +import { createConnection } from '../../src/connection.js' +import { defaultConnectionComponents, defaultConnectionInit, ECHO_PROTOCOL } from './utils.ts' +import type { ConnectionComponents, ConnectionInit } from '../../src/connection.js' +import type { Connection } from '@libp2p/interface' + +describe('connection - compliance', () => { + let components: ConnectionComponents + let init: ConnectionInit + let connection: Connection + let timelineProxy + const proxyHandler = { + set () { + // @ts-expect-error - TS fails to infer here + return Reflect.set(...arguments) + } + } + + beforeEach(async () => { + components = defaultConnectionComponents() + init = await defaultConnectionInit() + + connection = createConnection(components, init) + + timelineProxy = new Proxy({ + open: Date.now() - 10, + upgraded: Date.now() + }, proxyHandler) + + connection.timeline = timelineProxy + }) + + it('should have properties set', () => { + expect(connection.id).to.exist() + expect(connection.remotePeer).to.exist() + expect(connection.remoteAddr).to.exist() + expect(connection.status).to.equal('open') + expect(connection.timeline.open).to.exist() + expect(connection.timeline.close).to.not.exist() + expect(connection.direction).to.exist() + expect(connection.streams).to.eql([]) + expect(connection.tags).to.eql([]) + }) + + it('should get the metadata of an open connection', () => { + expect(connection.status).to.equal('open') + expect(connection.direction).to.exist() + expect(connection.timeline.open).to.exist() + expect(connection.timeline.close).to.not.exist() + }) + + it('should return an empty array of streams', () => { + const streams = connection.streams + + expect(streams).to.eql([]) + }) + + it('should be able to create a new stream', async () => { + expect(connection.streams).to.be.empty() + + const protocolToUse = '/echo/0.0.1' + const stream = await connection.newStream([protocolToUse]) + + expect(stream).to.have.property('protocol', protocolToUse) + + const connStreams = connection.streams + + expect(stream).to.exist() + expect(connStreams).to.exist() + expect(connStreams).to.have.lengthOf(1) + expect(connStreams[0]).to.equal(stream) + }) + + it('should be able to close the connection after being created', async () => { + expect(connection.timeline.close).to.not.exist() + await connection.close() + + expect(connection.timeline.close).to.exist() + expect(connection.status).to.equal('closed') + }) + + it('should be able to close the connection after opening a stream', async () => { + // Open stream + const protocol = ECHO_PROTOCOL + await connection.newStream([protocol]) + + // Close connection + expect(connection.timeline.close).to.not.exist() + await connection.close() + + expect(connection.timeline.close).to.exist() + expect(connection.status).to.equal('closed') + }) + + it('should properly track streams', async () => { + // Open stream + const protocol = ECHO_PROTOCOL + const stream = await connection.newStream([protocol]) + expect(stream).to.have.property('protocol', protocol) + + // Close stream + await stream.close() + + expect(connection.streams.filter(s => s.id === stream.id)).to.be.empty() + }) + + it('should track outbound streams', async () => { + // Open stream + const protocol = ECHO_PROTOCOL + const stream = await connection.newStream(protocol) + expect(stream).to.have.property('direction', 'outbound') + }) + + it('should support a proxy on the timeline', async () => { + Sinon.spy(proxyHandler, 'set') + expect(connection.timeline.close).to.not.exist() + + await connection.close() + // @ts-expect-error - fails to infer callCount + expect(proxyHandler.set.callCount).to.equal(1) + // @ts-expect-error - fails to infer getCall + const [obj, key, value] = proxyHandler.set.getCall(0).args + expect(obj).to.eql(connection.timeline) + expect(key).to.equal('close') + expect(value).to.be.a('number').that.equals(connection.timeline.close) + }) + + it('should fail to create a new stream if the connection is closing', async () => { + expect(connection.timeline.close).to.not.exist() + const p = connection.close() + + try { + const protocol = ECHO_PROTOCOL + await connection.newStream([protocol]) + } catch (err: any) { + expect(err).to.exist() + return + } finally { + await p + } + + throw new Error('should fail to create a new stream if the connection is closing') + }) + + it('should fail to create a new stream if the connection is closed', async () => { + expect(connection.timeline.close).to.not.exist() + await connection.close() + + await expect(connection.newStream(['/echo/0.0.1'])).to.eventually.be.rejected + .with.property('name', 'ConnectionClosedError') + }) +}) diff --git a/packages/libp2p/test/connection/fixtures/pair.ts b/packages/libp2p/test/connection/fixtures/pair.ts deleted file mode 100644 index eed462356b..0000000000 --- a/packages/libp2p/test/connection/fixtures/pair.ts +++ /dev/null @@ -1,28 +0,0 @@ -import map from 'it-map' -import defer from 'p-defer' -import { Uint8ArrayList } from 'uint8arraylist' -import type { Source, Duplex } from 'it-stream-types' - -/** - * A pair of streams where one drains from the other - */ -export function pair (): Duplex, Source, Promise> { - const deferred = defer>() - let piped = false - - return { - sink: async source => { - if (piped) { - throw new Error('already piped') - } - - piped = true - deferred.resolve(source) - }, - source: (async function * () { - const source = await deferred.promise - - yield * map(source, (buf) => buf instanceof Uint8Array ? new Uint8ArrayList(buf) : buf) - }()) - } -} diff --git a/packages/libp2p/test/connection/index.spec.ts b/packages/libp2p/test/connection/index.spec.ts index 9c8f217414..65326ac5c0 100644 --- a/packages/libp2p/test/connection/index.spec.ts +++ b/packages/libp2p/test/connection/index.spec.ts @@ -1,257 +1,41 @@ -import { generateKeyPair } from '@libp2p/crypto/keys' -import { defaultLogger, logger, peerLogger } from '@libp2p/logger' -import { peerIdFromPrivateKey } from '@libp2p/peer-id' +import { peerIdFromString } from '@libp2p/peer-id' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' -import Sinon from 'sinon' -import { createConnection } from '../../src/connection/index.js' -import { pair } from './fixtures/pair.js' -import type { Connection, Stream } from '@libp2p/interface' - -function defaultConnectionInit (): any { - return { - timeline: { - open: Date.now() - 10, - upgraded: Date.now() - }, - direction: 'outbound', - encryption: '/secio/1.0.0', - multiplexer: '/mplex/6.7.0', - status: 'open', - newStream: Sinon.stub(), - close: Sinon.stub(), - abort: Sinon.stub(), - getStreams: Sinon.stub(), - logger: defaultLogger() - } -} +import { createConnection } from '../../src/connection.js' +import { defaultConnectionComponents, defaultConnectionInit } from './utils.ts' +import type { ConnectionComponents, ConnectionInit } from '../../src/connection.js' describe('connection', () => { - it('should not require local or remote addrs', async () => { - const remotePeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519')) - - return createConnection({ - remotePeer, - remoteAddr: multiaddr('/ip4/127.0.0.1/tcp/4002'), - ...defaultConnectionInit() - }) - }) - - it('should append remote peer id to address if not already present', async () => { - const remotePeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519')) - - const conn = createConnection({ - remotePeer, - remoteAddr: multiaddr('/ip4/127.0.0.1/tcp/4002'), - ...defaultConnectionInit() - }) - - expect(conn.remoteAddr.getPeerId()).to.equal(remotePeer.toString()) - }) - - it('should not append remote peer id to address if present', async () => { - const remotePeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519')) - const otherPeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519')) - - const conn = createConnection({ - remotePeer, - remoteAddr: multiaddr(`/ip4/127.0.0.1/tcp/4002/p2p/${otherPeer}`), - ...defaultConnectionInit() - }) - - expect(conn.remoteAddr.getPeerId()).to.equal(otherPeer.toString()) - }) -}) - -describe('compliance', () => { - let connection: Connection - let timelineProxy - const proxyHandler = { - set () { - // @ts-expect-error - TS fails to infer here - return Reflect.set(...arguments) - } - } + let components: ConnectionComponents + let init: ConnectionInit beforeEach(async () => { - const localPeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519')) - const remoteAddr = multiaddr('/ip4/127.0.0.1/tcp/8081') - const remotePeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519')) - let openStreams: Stream[] = [] - let streamId = 0 - - connection = createConnection({ - remotePeer, - remoteAddr, - timeline: { - open: Date.now() - 10, - upgraded: Date.now() - }, - direction: 'outbound', - encryption: '/secio/1.0.0', - multiplexer: '/mplex/6.7.0', - status: 'open', - logger: peerLogger(localPeer), - newStream: async (protocols) => { - const id = `${streamId++}` - const stream: Stream = { - ...pair(), - close: async () => { - void stream.sink(async function * () {}()) - openStreams = openStreams.filter(s => s.id !== id) - }, - closeRead: async () => {}, - closeWrite: async () => { - void stream.sink(async function * () {}()) - }, - id, - abort: () => {}, - direction: 'outbound', - protocol: protocols[0], - timeline: { - open: 0 - }, - metadata: {}, - status: 'open', - writeStatus: 'ready', - readStatus: 'ready', - log: logger('test') - } - - openStreams.push(stream) - - return stream - }, - close: async () => {}, - abort: () => {}, - getStreams: () => openStreams - }) - - timelineProxy = new Proxy({ - open: Date.now() - 10, - upgraded: Date.now() - }, proxyHandler) - - connection.timeline = timelineProxy + components = defaultConnectionComponents() + init = await defaultConnectionInit() }) - it('should have properties set', () => { - expect(connection.id).to.exist() - expect(connection.remotePeer).to.exist() - expect(connection.remoteAddr).to.exist() - expect(connection.status).to.equal('open') - expect(connection.timeline.open).to.exist() - expect(connection.timeline.close).to.not.exist() - expect(connection.direction).to.exist() - expect(connection.streams).to.eql([]) - expect(connection.tags).to.eql([]) - }) - - it('should get the metadata of an open connection', () => { - expect(connection.status).to.equal('open') - expect(connection.direction).to.exist() - expect(connection.timeline.open).to.exist() - expect(connection.timeline.close).to.not.exist() - }) - - it('should return an empty array of streams', () => { - const streams = connection.streams - - expect(streams).to.eql([]) - }) - - it('should be able to create a new stream', async () => { - expect(connection.streams).to.be.empty() - - const protocolToUse = '/echo/0.0.1' - const stream = await connection.newStream([protocolToUse]) - - expect(stream).to.have.property('protocol', protocolToUse) - - const connStreams = connection.streams - - expect(stream).to.exist() - expect(connStreams).to.exist() - expect(connStreams).to.have.lengthOf(1) - expect(connStreams[0]).to.equal(stream) - }) - - it('should be able to close the connection after being created', async () => { - expect(connection.timeline.close).to.not.exist() - await connection.close() - - expect(connection.timeline.close).to.exist() - expect(connection.status).to.equal('closed') - }) - - it('should be able to close the connection after opening a stream', async () => { - // Open stream - const protocol = '/echo/0.0.1' - await connection.newStream([protocol]) - - // Close connection - expect(connection.timeline.close).to.not.exist() - await connection.close() - - expect(connection.timeline.close).to.exist() - expect(connection.status).to.equal('closed') - }) - - it('should properly track streams', async () => { - // Open stream - const protocol = '/echo/0.0.1' - const stream = await connection.newStream([protocol]) - expect(stream).to.have.property('protocol', protocol) - - // Close stream - await stream.close() - - expect(connection.streams.filter(s => s.id === stream.id)).to.be.empty() - }) + it('should not require local or remote addrs', async () => { + const conn = createConnection(components, init) - it('should track outbound streams', async () => { - // Open stream - const protocol = '/echo/0.0.1' - const stream = await connection.newStream(protocol) - expect(stream).to.have.property('direction', 'outbound') + expect(conn).to.be.ok() }) - it('should support a proxy on the timeline', async () => { - Sinon.spy(proxyHandler, 'set') - expect(connection.timeline.close).to.not.exist() + it('should append remote peer id to address if not already present', async () => { + const conn = createConnection(components, await defaultConnectionInit({ + remoteAddr: multiaddr('/ip4/123.123.123.123/tcp/1234') + })) - await connection.close() - // @ts-expect-error - fails to infer callCount - expect(proxyHandler.set.callCount).to.equal(1) - // @ts-expect-error - fails to infer getCall - const [obj, key, value] = proxyHandler.set.getCall(0).args - expect(obj).to.eql(connection.timeline) - expect(key).to.equal('close') - expect(value).to.be.a('number').that.equals(connection.timeline.close) + expect(conn.remoteAddr.getComponents().filter(component => component.name === 'p2p')).to.have.lengthOf(1) }) - it('should fail to create a new stream if the connection is closing', async () => { - expect(connection.timeline.close).to.not.exist() - const p = connection.close() - - try { - const protocol = '/echo/0.0.1' - await connection.newStream([protocol]) - } catch (err: any) { - expect(err).to.exist() - return - } finally { - await p - } - - throw new Error('should fail to create a new stream if the connection is closing') - }) + it('should not append remote peer id to address if present', async () => { + const remotePeer = peerIdFromString('QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN') - it('should fail to create a new stream if the connection is closed', async () => { - expect(connection.timeline.close).to.not.exist() - await connection.close() + const conn = createConnection(components, await defaultConnectionInit({ + remotePeer, + remoteAddr: multiaddr(`/ip4/123.123.123.123/tcp/1234/p2p/${remotePeer}`) + })) - await expect(connection.newStream(['/echo/0.0.1'])).to.eventually.be.rejected - .with.property('name', 'ConnectionClosedError') + expect(conn.remoteAddr.getComponents().filter(component => component.name === 'p2p')).to.have.lengthOf(1) }) }) diff --git a/packages/libp2p/test/connection/utils.ts b/packages/libp2p/test/connection/utils.ts new file mode 100644 index 0000000000..8c549c745d --- /dev/null +++ b/packages/libp2p/test/connection/utils.ts @@ -0,0 +1,102 @@ +import { generateKeyPair } from '@libp2p/crypto/keys' +import { defaultLogger } from '@libp2p/logger' +import { peerIdFromPrivateKey } from '@libp2p/peer-id' +import { multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import drain from 'it-drain' +import { encode } from 'it-length-prefixed' +import map from 'it-map' +import { pipe } from 'it-pipe' +import { stubInterface } from 'sinon-ts' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { Registrar } from '../../src/registrar.ts' +import type { ConnectionComponents, ConnectionInit } from '../../src/connection.js' +import type { PeerStore, PeerId, StreamMuxerFactory, MultiaddrConnection, StreamMuxer, Stream } from '@libp2p/interface' +import type { Multiaddr } from '@multiformats/multiaddr' + +export const ECHO_PROTOCOL = '/echo/0.0.1' + +const registrar = stubInterface({ + getProtocols: () => [ + ECHO_PROTOCOL + ], + getHandler: (proto) => { + expect(proto).to.equal(ECHO_PROTOCOL) + + return { + handler: ({ stream }) => { + void pipe(stream, stream) + }, + options: { + + } + } + } +}) + +export function defaultConnectionComponents (): ConnectionComponents { + return { + peerStore: stubInterface(), + registrar + } +} + +interface DefaultConnectionInit { + remotePeer?: PeerId + remoteAddr?: Multiaddr +} + +export async function defaultConnectionInit (init: DefaultConnectionInit = {}): Promise { + const remotePeer = init.remotePeer ?? peerIdFromPrivateKey(await generateKeyPair('Ed25519')) + const log = defaultLogger().forComponent('connection') + const streams: Stream[] = [] + + return { + id: `${(parseInt(String(Math.random() * 1e9))).toString(36)}${Date.now()}`, + remotePeer, + maConn: stubInterface({ + log, + remoteAddr: multiaddr('/ip4/123.123.123.123/tcp/1234'), + sink: async (source) => { + await drain(source) + }, + source: (async function * () {})() + }), + direction: 'outbound', + encryption: '/secio/1.0.0', + muxerFactory: stubInterface({ + createStreamMuxer: () => stubInterface({ + sink: async (source) => { + await drain(source) + }, + source: (async function * () {})(), + streams, + newStream: () => { + const stream = stubInterface({ + log, + sink: async (source) => { + await drain(source) + }, + source: map((async function * () { + yield '/multistream/1.0.0\n' + yield `${ECHO_PROTOCOL}\n` + yield 'hello' + })(), str => encode.single(uint8ArrayFromString(str))), + close: async () => { + for (let i = 0; i < streams.length; i++) { + if (streams[i] === stream) { + streams.splice(i, 1) + i-- + } + } + } + }) + + streams.push(stream) + + return stream + } + }) + }) + } +} diff --git a/packages/libp2p/test/upgrading/upgrader.spec.ts b/packages/libp2p/test/upgrading/upgrader.spec.ts index 5fd14e8cc8..98ba20e73c 100644 --- a/packages/libp2p/test/upgrading/upgrader.spec.ts +++ b/packages/libp2p/test/upgrading/upgrader.spec.ts @@ -476,7 +476,8 @@ describe('upgrader', () => { source: map((async function * () { yield '/multistream/1.0.0\n' yield `${protocol}\n` - })(), str => encode.single(uint8ArrayFromString(str))) + })(), str => encode.single(uint8ArrayFromString(str))), + close: async () => {} }) streamMuxer?.streams.push(incomingStream) diff --git a/packages/protocol-autonat/src/autonat.ts b/packages/protocol-autonat/src/autonat.ts index c9b00eb2f4..3d4fcbbec3 100644 --- a/packages/protocol-autonat/src/autonat.ts +++ b/packages/protocol-autonat/src/autonat.ts @@ -323,31 +323,37 @@ export class AutoNATService implements Startable { const multiaddrs = peer.addrs .map(buf => multiaddr(buf)) .filter(ma => { - const options = ma.toOptions() + try { + const options = ma.toOptions() - if (isPrivate(ma)) { - // don't try to dial private addresses - return false - } + if (isPrivate(ma)) { + // don't try to dial private addresses + return false + } - if (options.host !== connection.remoteAddr.toOptions().host) { - // skip any Multiaddrs where the target node's IP does not match the sending node's IP - this.log.trace('not dialing %a - target host did not match remote host %a', ma, connection.remoteAddr) - return false - } + if (options.host !== connection.remoteAddr.toOptions().host) { + // skip any Multiaddrs where the target node's IP does not match the sending node's IP + this.log.trace('not dialing %a - target host did not match remote host %a', ma, connection.remoteAddr) + return false + } - if (ourHosts.includes(options.host)) { - // don't try to dial nodes on the same host as us - return false - } + if (ourHosts.includes(options.host)) { + // don't try to dial nodes on the same host as us + return false + } - if (this.components.transportManager.dialTransportForMultiaddr(ma) == null) { - // skip any Multiaddrs that have transports we do not support - this.log.trace('not dialing %a - transport unsupported', ma) + if (this.components.transportManager.dialTransportForMultiaddr(ma) == null) { + // skip any Multiaddrs that have transports we do not support + this.log.trace('not dialing %a - transport unsupported', ma) + return false + } + + return true + } catch { + // skip any addresses that cannot be parsed (memory, webrtc incoming, + // etc) return false } - - return true }) .map(ma => { if (ma.getPeerId() == null) { diff --git a/packages/protocol-echo/src/echo.ts b/packages/protocol-echo/src/echo.ts index c0f253bc87..8ed0560d11 100644 --- a/packages/protocol-echo/src/echo.ts +++ b/packages/protocol-echo/src/echo.ts @@ -2,7 +2,7 @@ import { byteStream } from 'it-byte-stream' import { pipe } from 'it-pipe' import { PROTOCOL_NAME, PROTOCOL_VERSION } from './constants.js' import type { Echo as EchoInterface, EchoComponents, EchoInit } from './index.js' -import type { AbortOptions, Logger, PeerId, Startable } from '@libp2p/interface' +import type { AbortOptions, PeerId, Startable } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' /** @@ -13,10 +13,8 @@ export class Echo implements Startable, EchoInterface { private readonly components: EchoComponents private started: boolean private readonly init: EchoInit - private readonly log: Logger constructor (components: EchoComponents, init: EchoInit = {}) { - this.log = components.logger.forComponent('libp2p:echo') this.started = false this.components = components this.protocol = `/${[init.protocolPrefix, PROTOCOL_NAME, PROTOCOL_VERSION].filter(Boolean).join('/')}` @@ -26,10 +24,12 @@ export class Echo implements Startable, EchoInterface { readonly [Symbol.toStringTag] = '@libp2p/echo' async start (): Promise { - await this.components.registrar.handle(this.protocol, ({ stream }) => { + await this.components.registrar.handle(this.protocol, ({ stream, connection }) => { + const log = connection.log.newScope('echo') + void pipe(stream, stream) .catch((err: any) => { - this.log.error('error piping stream', err) + log.error('error piping stream', err) }) }, { maxInboundStreams: this.init.maxInboundStreams, diff --git a/packages/protocol-echo/src/index.ts b/packages/protocol-echo/src/index.ts index d45def33cf..7d16c57eea 100644 --- a/packages/protocol-echo/src/index.ts +++ b/packages/protocol-echo/src/index.ts @@ -43,7 +43,7 @@ */ import { Echo as EchoClass } from './echo.js' -import type { AbortOptions, ComponentLogger, PeerId } from '@libp2p/interface' +import type { AbortOptions, PeerId } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' @@ -57,7 +57,6 @@ export interface EchoInit { export interface EchoComponents { registrar: Registrar connectionManager: ConnectionManager - logger: ComponentLogger } export interface Echo { diff --git a/packages/protocol-echo/test/index.spec.ts b/packages/protocol-echo/test/index.spec.ts index c02754436d..0f0771513e 100644 --- a/packages/protocol-echo/test/index.spec.ts +++ b/packages/protocol-echo/test/index.spec.ts @@ -11,21 +11,19 @@ import sinon from 'sinon' import { stubInterface } from 'sinon-ts' import { Uint8ArrayList } from 'uint8arraylist' import { Echo } from '../src/echo.js' -import type { ComponentLogger, Connection, Stream } from '@libp2p/interface' +import type { Connection, Stream } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { StubbedInstance } from 'sinon-ts' interface StubbedFetchComponents { registrar: StubbedInstance connectionManager: StubbedInstance - logger: ComponentLogger } async function createComponents (): Promise { return { registrar: stubInterface(), - connectionManager: stubInterface(), - logger: defaultLogger() + connectionManager: stubInterface() } } @@ -63,7 +61,9 @@ describe('echo', () => { const handler = components.registrar.handle.getCall(0).args[1] handler({ stream: incomingStream, - connection: stubInterface() + connection: stubInterface({ + log: defaultLogger().forComponent('connection') + }) }) const input = Uint8Array.from([0, 1, 2, 3]) @@ -94,7 +94,9 @@ describe('echo', () => { const handler = components.registrar.handle.getCall(0).args[1] handler({ stream: incomingStream, - connection: stubInterface() + connection: stubInterface({ + log: defaultLogger().forComponent('connection') + }) }) const ma = multiaddr('/ip4/123.123.123.123/tcp/1234') diff --git a/packages/protocol-fetch/src/fetch.ts b/packages/protocol-fetch/src/fetch.ts index ecc35a8624..739fed0d25 100644 --- a/packages/protocol-fetch/src/fetch.ts +++ b/packages/protocol-fetch/src/fetch.ts @@ -6,9 +6,9 @@ import { toString as uint8arrayToString } from 'uint8arrays/to-string' import { PROTOCOL_NAME, PROTOCOL_VERSION } from './constants.js' import { FetchRequest, FetchResponse } from './pb/proto.js' import type { Fetch as FetchInterface, FetchComponents, FetchInit, LookupFunction } from './index.js' -import type { AbortOptions, Logger, Stream, PeerId, Startable, IncomingStreamData } from '@libp2p/interface' +import type { AbortOptions, Stream, PeerId, Startable, IncomingStreamData } from '@libp2p/interface' -const DEFAULT_TIMEOUT = 10000 +const DEFAULT_TIMEOUT = 10_000 /** * A simple libp2p protocol for requesting a value corresponding to a key from a peer. @@ -22,10 +22,8 @@ export class Fetch implements Startable, FetchInterface { private readonly lookupFunctions: Map private started: boolean private readonly init: FetchInit - private readonly log: Logger constructor (components: FetchComponents, init: FetchInit = {}) { - this.log = components.logger.forComponent('libp2p:fetch') this.started = false this.components = components this.protocol = `/${init.protocolPrefix ?? 'libp2p'}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` @@ -38,12 +36,14 @@ export class Fetch implements Startable, FetchInterface { async start (): Promise { await this.components.registrar.handle(this.protocol, (data) => { + const log = data.connection.log.newScope('fetch') + void this.handleMessage(data) .then(async () => { await data.stream.close() }) .catch(err => { - this.log.error('error handling message - %e', err) + log.error('error handling message - %e', err) }) }, { maxInboundStreams: this.init.maxInboundStreams, @@ -69,9 +69,8 @@ export class Fetch implements Startable, FetchInterface { key = uint8arrayFromString(key) } - this.log.trace('dialing %s to %p', this.protocol, peer) - const connection = await this.components.connectionManager.openConnection(peer, options) + const log = connection.log.newScope('fetch') let signal = options.signal let stream: Stream | undefined let onAbort = (): void => {} @@ -79,7 +78,7 @@ export class Fetch implements Startable, FetchInterface { // create a timeout if no abort signal passed if (signal == null) { const timeout = this.init.timeout ?? DEFAULT_TIMEOUT - this.log.trace('using default timeout of %d ms', timeout) + log.trace('using default timeout of %d ms', timeout) signal = AbortSignal.timeout(timeout) setMaxListeners(Infinity, signal) @@ -97,7 +96,7 @@ export class Fetch implements Startable, FetchInterface { // make stream abortable signal.addEventListener('abort', onAbort, { once: true }) - this.log.trace('fetch %m', key) + log.trace('fetch %m', key) const pb = pbStream(stream) await pb.write({ @@ -109,20 +108,20 @@ export class Fetch implements Startable, FetchInterface { switch (response.status) { case (FetchResponse.StatusCode.OK): { - this.log.trace('received status OK for %m', key) + log.trace('received status OK for %m', key) return response.data } case (FetchResponse.StatusCode.NOT_FOUND): { - this.log('received status NOT_FOUND for %m', key) + log('received status NOT_FOUND for %m', key) return } case (FetchResponse.StatusCode.ERROR): { - this.log('received status ERROR for %m', key) + log('received status ERROR for %m', key) const errMsg = uint8arrayToString(response.data) throw new ProtocolError('Error in fetch protocol response: ' + errMsg) } default: { - this.log('received status unknown for %m', key) + log('received status unknown for %m', key) throw new InvalidMessageError('Unknown response status') } } @@ -143,7 +142,8 @@ export class Fetch implements Startable, FetchInterface { * to the key's prefix. */ async handleMessage (data: IncomingStreamData): Promise { - const { stream } = data + const { stream, connection } = data + const log = connection.log.newScope('fetch') const signal = AbortSignal.timeout(this.init.timeout ?? DEFAULT_TIMEOUT) try { @@ -158,24 +158,24 @@ export class Fetch implements Startable, FetchInterface { const lookup = this._getLookupFunction(key) if (lookup == null) { - this.log.trace('sending status ERROR for %m', request.identifier) + log.trace('sending status ERROR for %m', request.identifier) const errMsg = uint8arrayFromString('No lookup function registered for key') response = { status: FetchResponse.StatusCode.ERROR, data: errMsg } } else { - this.log.trace('lookup data with identifier %s', lookup.prefix) + log.trace('lookup data with identifier %s', lookup.prefix) try { const data = await lookup.fn(request.identifier) if (data == null) { - this.log.trace('sending status NOT_FOUND for %m', request.identifier) + log.trace('sending status NOT_FOUND for %m', request.identifier) response = { status: FetchResponse.StatusCode.NOT_FOUND, data: new Uint8Array(0) } } else { - this.log.trace('sending status OK for %m', request.identifier) + log.trace('sending status OK for %m', request.identifier) response = { status: FetchResponse.StatusCode.OK, data } } } catch (err: any) { - this.log.error('error during lookup of %m - %e', request.identifier, err) + log.error('error during lookup of %m - %e', request.identifier, err) const errMsg = uint8arrayFromString(err.message) response = { status: FetchResponse.StatusCode.ERROR, data: errMsg } } @@ -189,7 +189,7 @@ export class Fetch implements Startable, FetchInterface { signal }) } catch (err: any) { - this.log.error('error answering fetch request - %e', err) + log.error('error answering fetch request - %e', err) stream.abort(err) } } diff --git a/packages/protocol-fetch/src/index.ts b/packages/protocol-fetch/src/index.ts index d74edac18c..95ec20a5bd 100644 --- a/packages/protocol-fetch/src/index.ts +++ b/packages/protocol-fetch/src/index.ts @@ -43,7 +43,7 @@ */ import { Fetch as FetchClass } from './fetch.js' -import type { AbortOptions, ComponentLogger, PeerId } from '@libp2p/interface' +import type { AbortOptions, PeerId } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' export interface FetchInit { @@ -71,7 +71,6 @@ export interface LookupFunction { export interface FetchComponents { registrar: Registrar connectionManager: ConnectionManager - logger: ComponentLogger } export interface Fetch { diff --git a/packages/protocol-fetch/test/index.spec.ts b/packages/protocol-fetch/test/index.spec.ts index 197fbeb3cd..73c01f27eb 100644 --- a/packages/protocol-fetch/test/index.spec.ts +++ b/packages/protocol-fetch/test/index.spec.ts @@ -13,21 +13,19 @@ import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' import { toString as uint8arrayToString } from 'uint8arrays/to-string' import { Fetch } from '../src/fetch.js' import { FetchRequest, FetchResponse } from '../src/pb/proto.js' -import type { ComponentLogger, Connection, Stream, PeerId } from '@libp2p/interface' +import type { Connection, Stream, PeerId } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { StubbedInstance } from 'sinon-ts' interface StubbedFetchComponents { registrar: StubbedInstance connectionManager: StubbedInstance - logger: ComponentLogger } async function createComponents (): Promise { return { registrar: stubInterface(), - connectionManager: stubInterface(), - logger: defaultLogger() + connectionManager: stubInterface() } } @@ -41,7 +39,9 @@ function createStreams (components: StubbedFetchComponents, remotePeer?: PeerId) incomingStream.source = duplex[1].source incomingStream.sink.callsFake(async source => duplex[1].sink(source)) - const connection = stubInterface() + const connection = stubInterface({ + log: defaultLogger().forComponent('connection') + }) if (remotePeer != null) { connection.newStream.withArgs('/libp2p/fetch/0.0.1').resolves(outgoingStream) diff --git a/packages/protocol-identify/src/identify-push.ts b/packages/protocol-identify/src/identify-push.ts index f651b4e9a8..f555cd6162 100644 --- a/packages/protocol-identify/src/identify-push.ts +++ b/packages/protocol-identify/src/identify-push.ts @@ -79,6 +79,7 @@ export class IdentifyPush extends AbstractIdentify implements Startable, Identif async function * pushToConnections (): AsyncGenerator<() => Promise> { for (const connection of self.connectionManager.getConnections()) { const peer = await self.peerStore.get(connection.remotePeer) + const log = connection.log.newScope('identify-push') if (!peer.protocols.includes(self.protocol)) { continue @@ -115,7 +116,7 @@ export class IdentifyPush extends AbstractIdentify implements Startable, Identif }) } catch (err: any) { // Just log errors - self.log.error('could not push identify update to peer', err) + log.error('could not push identify update to peer', err) stream?.abort(err) } } @@ -135,6 +136,7 @@ export class IdentifyPush extends AbstractIdentify implements Startable, Identif */ async handleProtocol (data: IncomingStreamData): Promise { const { connection, stream } = data + const log = connection.log.newScope('identify-push') try { if (this.peerId.equals(connection.remotePeer)) { @@ -154,11 +156,11 @@ export class IdentifyPush extends AbstractIdentify implements Startable, Identif await consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message) } catch (err: any) { - this.log.error('received invalid message', err) + log.error('received invalid message', err) stream.abort(err) return } - this.log.trace('handled push from %p', connection.remotePeer) + log.trace('handled push from %p', connection.remotePeer) } } diff --git a/packages/protocol-identify/src/identify.ts b/packages/protocol-identify/src/identify.ts index 6e1574bf4b..edc35b02e8 100644 --- a/packages/protocol-identify/src/identify.ts +++ b/packages/protocol-identify/src/identify.ts @@ -15,7 +15,7 @@ import { import { Identify as IdentifyMessage } from './pb/message.js' import { AbstractIdentify, consumeIdentifyMessage, defaultValues, getCleanMultiaddr } from './utils.js' import type { Identify as IdentifyInterface, IdentifyComponents, IdentifyInit } from './index.js' -import type { IdentifyResult, AbortOptions, Connection, Stream, Startable, IncomingStreamData } from '@libp2p/interface' +import type { IdentifyResult, AbortOptions, Connection, Stream, Startable, IncomingStreamData, Logger } from '@libp2p/interface' export class Identify extends AbstractIdentify implements Startable, IdentifyInterface { constructor (components: IdentifyComponents, init: IdentifyInit = {}) { @@ -89,37 +89,38 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt } = message if (publicKey == null) { - throw new InvalidMessageError('public key was missing from identify message') + throw new InvalidMessageError('Public key was missing from identify message') } const key = publicKeyFromProtobuf(publicKey) const id = peerIdFromCID(key.toCID()) + const log = connection.log.newScope('identify') if (!connection.remotePeer.equals(id)) { - throw new InvalidMessageError('identified peer does not match the expected peer') + throw new InvalidMessageError('Identified peer does not match the expected peer') } if (this.peerId.equals(id)) { - throw new InvalidMessageError('identified peer is our own peer id?') + throw new InvalidMessageError('Identified peer is our own peer id?') } // if the observed address is publicly routable, add it to the address // manager for verification via AutoNAT - this.maybeAddObservedAddress(observedAddr) + this.maybeAddObservedAddress(observedAddr, log) - this.log('identify completed for peer %p and protocols %o', id, protocols) + log('completed for peer %p and protocols %o', id, protocols) - return consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message) + return consumeIdentifyMessage(this.peerStore, this.events, log, connection, message) } - private maybeAddObservedAddress (observedAddr: Uint8Array | undefined): void { + private maybeAddObservedAddress (observedAddr: Uint8Array | undefined, log: Logger): void { const cleanObservedAddr = getCleanMultiaddr(observedAddr) if (cleanObservedAddr == null) { return } - this.log.trace('our observed address was %a', cleanObservedAddr) + log.trace('our observed address was %a', cleanObservedAddr) if (isPrivate(cleanObservedAddr)) { this.log.trace('our observed address was private') @@ -129,7 +130,7 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt const tuples = cleanObservedAddr.getComponents() if (((tuples[0].code === CODE_IP6) || (tuples[0].code === CODE_IP6ZONE && tuples[1].code === CODE_IP6)) && !isGlobalUnicast(cleanObservedAddr)) { - this.log.trace('our observed address was IPv6 but not a global unicast address') + log.trace('our observed address was IPv6 but not a global unicast address') return } @@ -141,7 +142,7 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt return } - this.log.trace('storing the observed address') + log.trace('storing the observed address') this.addressManager.addObservedAddr(cleanObservedAddr) } @@ -151,6 +152,7 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt */ async handleProtocol (data: IncomingStreamData): Promise { const { connection, stream } = data + const log = connection.log.newScope('identify') const signal = AbortSignal.timeout(this.timeout) @@ -195,7 +197,7 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt signal }) } catch (err: any) { - this.log.error('could not respond to identify request', err) + log.error('could not respond to identify request', err) stream.abort(err) } } diff --git a/packages/protocol-identify/test/fixtures/index.ts b/packages/protocol-identify/test/fixtures/index.ts index 112a327df9..0da0e5e1f4 100644 --- a/packages/protocol-identify/test/fixtures/index.ts +++ b/packages/protocol-identify/test/fixtures/index.ts @@ -1,3 +1,4 @@ +import { defaultLogger } from '@libp2p/logger' import drain from 'it-drain' import * as lp from 'it-length-prefixed' import { pushable } from 'it-pushable' @@ -23,7 +24,8 @@ export interface StubbedIdentifyComponents { export function connectionStream (remotePeer: PeerId, protocol: string): { connection: StubbedInstance, stream: StubbedInstance } { const connection = stubInterface({ - remotePeer + remotePeer, + log: defaultLogger().forComponent('connection') }) const stream = stubInterface() connection.newStream.withArgs(protocol).resolves(stream) diff --git a/packages/protocol-identify/test/index.spec.ts b/packages/protocol-identify/test/index.spec.ts index de98e10e3f..39dcb3c6b2 100644 --- a/packages/protocol-identify/test/index.spec.ts +++ b/packages/protocol-identify/test/index.spec.ts @@ -367,7 +367,8 @@ describe('identify', () => { void identify.handleProtocol({ stream: incomingStream, connection: stubInterface({ - remoteAddr: multiaddr('/webrtc/p2p/QmR5VwgsL7jyfZHAGyp66tguVrQhCRQuRc3NokocsCZ3fA') + remoteAddr: multiaddr('/webrtc/p2p/QmR5VwgsL7jyfZHAGyp66tguVrQhCRQuRc3NokocsCZ3fA'), + log: defaultLogger().forComponent('connection') }) }) diff --git a/packages/protocol-perf/src/perf-service.ts b/packages/protocol-perf/src/perf-service.ts index 5d9a97f97e..a052ff79ea 100644 --- a/packages/protocol-perf/src/perf-service.ts +++ b/packages/protocol-perf/src/perf-service.ts @@ -32,7 +32,7 @@ export class Perf implements Startable, PerfInterface { async start (): Promise { await this.components.registrar.handle(this.protocol, (data: IncomingStreamData) => { void this.handleMessage(data).catch((err) => { - this.log.error('error handling perf protocol message', err) + this.log.error('error handling perf protocol message - %e', err) }) }, { maxInboundStreams: this.maxInboundStreams, @@ -91,8 +91,6 @@ export class Perf implements Startable, PerfInterface { } async * measurePerformance (ma: Multiaddr, sendBytes: number, receiveBytes: number, options: PerfOptions = {}): AsyncGenerator { - this.log('opening stream on protocol %s to %a', this.protocol, ma) - const uint8Buf = new Uint8Array(this.buf) const writeBlockSize = this.writeBlockSize @@ -103,12 +101,14 @@ export class Perf implements Startable, PerfInterface { force: options.reuseExistingConnection !== true }) - this.log('opened connection after %d ms', Date.now() - lastReportedTime) + const log = connection.log.newScope('perf') + + log('opened connection after %d ms', Date.now() - lastReportedTime) lastReportedTime = Date.now() const stream = await connection.newStream(this.protocol, options) - this.log('opened stream after %d ms', Date.now() - lastReportedTime) + log('opened stream after %d ms', Date.now() - lastReportedTime) lastReportedTime = Date.now() let lastAmountOfBytesSent = 0 @@ -120,7 +120,7 @@ export class Perf implements Startable, PerfInterface { const view = new DataView(this.buf) view.setBigUint64(0, BigInt(receiveBytes), false) - this.log('sending %i bytes to %p', sendBytes, connection.remotePeer) + log('sending %i bytes to %p', sendBytes, connection.remotePeer) try { const output = pushable({ @@ -167,7 +167,7 @@ export class Perf implements Startable, PerfInterface { yield * output - this.log('upload complete after %d ms', Date.now() - uploadStart) + log('upload complete after %d ms', Date.now() - uploadStart) // Read the received bytes let lastAmountOfBytesReceived = 0 @@ -194,7 +194,7 @@ export class Perf implements Startable, PerfInterface { totalBytesReceived += buf.byteLength } - this.log('download complete after %d ms', Date.now() - downloadStart) + log('download complete after %d ms', Date.now() - downloadStart) if (totalBytesReceived !== receiveBytes) { throw new Error(`Expected to receive ${receiveBytes} bytes, but received ${totalBytesReceived}`) @@ -207,10 +207,10 @@ export class Perf implements Startable, PerfInterface { downloadBytes: totalBytesReceived } - this.log('performed %s to %p', this.protocol, connection.remotePeer) + log('performed %s to %p', this.protocol, connection.remotePeer) await stream.close() } catch (err: any) { - this.log('error sending %d/%d bytes to %p: %s', totalBytesSent, sendBytes, connection.remotePeer, err) + log('error sending %d/%d bytes to %p: %s', totalBytesSent, sendBytes, connection.remotePeer, err) stream.abort(err) throw err } diff --git a/packages/protocol-perf/test/index.spec.ts b/packages/protocol-perf/test/index.spec.ts index 9b3ffc263c..f48b632436 100644 --- a/packages/protocol-perf/test/index.spec.ts +++ b/packages/protocol-perf/test/index.spec.ts @@ -60,14 +60,18 @@ describe('perf', () => { const duplexes = duplexPair() const streams = streamPair({ duplex: duplexes[0] }, { duplex: duplexes[1] }) - const aToB = stubInterface() + const aToB = stubInterface({ + log: defaultLogger().forComponent('connection') + }) aToB.newStream.resolves(streams[0]) localComponents.connectionManager.openConnection.withArgs(ma, { force: true }).resolves(aToB) localComponents.connectionManager.getConnections.returns([]) - const bToA = stubInterface() + const bToA = stubInterface({ + log: defaultLogger().forComponent('connection') + }) void server.handleMessage({ stream: streams[1], connection: bToA }) // Run Perf @@ -91,12 +95,16 @@ describe('perf', () => { const duplexes = duplexPair() const streams = streamPair({ duplex: duplexes[0] }, { duplex: duplexes[1] }) - const aToB = stubInterface() + const aToB = stubInterface({ + log: defaultLogger().forComponent('connection') + }) aToB.newStream.resolves(streams[0]) localComponents.connectionManager.openConnection.resolves(aToB) localComponents.connectionManager.getConnections.returns([]) - const bToA = stubInterface() + const bToA = stubInterface({ + log: defaultLogger().forComponent('connection') + }) void server.handleMessage({ stream: streams[1], connection: bToA }) // Run Perf diff --git a/packages/protocol-ping/src/index.ts b/packages/protocol-ping/src/index.ts index e3131b43a3..1462fdc9db 100644 --- a/packages/protocol-ping/src/index.ts +++ b/packages/protocol-ping/src/index.ts @@ -23,7 +23,7 @@ */ import { Ping as PingClass } from './ping.js' -import type { AbortOptions, ComponentLogger, PeerId } from '@libp2p/interface' +import type { AbortOptions, PeerId } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' @@ -56,7 +56,6 @@ export type PingServiceInit = PingInit export interface PingComponents { registrar: Registrar connectionManager: ConnectionManager - logger: ComponentLogger } export function ping (init: PingInit = {}): (components: PingComponents) => Ping { diff --git a/packages/protocol-ping/src/ping.ts b/packages/protocol-ping/src/ping.ts index 475b6c2f14..ab6ce1e15b 100644 --- a/packages/protocol-ping/src/ping.ts +++ b/packages/protocol-ping/src/ping.ts @@ -5,7 +5,7 @@ import { setMaxListeners } from 'main-event' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' import { PROTOCOL_PREFIX, PROTOCOL_NAME, PING_LENGTH, PROTOCOL_VERSION, TIMEOUT, MAX_INBOUND_STREAMS, MAX_OUTBOUND_STREAMS } from './constants.js' import type { PingComponents, PingInit, Ping as PingInterface } from './index.js' -import type { AbortOptions, Logger, Stream, PeerId, Startable, IncomingStreamData } from '@libp2p/interface' +import type { AbortOptions, Stream, PeerId, Startable, IncomingStreamData } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' export class Ping implements Startable, PingInterface { @@ -16,11 +16,9 @@ export class Ping implements Startable, PingInterface { private readonly maxInboundStreams: number private readonly maxOutboundStreams: number private readonly runOnLimitedConnection: boolean - private readonly log: Logger constructor (components: PingComponents, init: PingInit = {}) { this.components = components - this.log = components.logger.forComponent('libp2p:ping') this.started = false this.protocol = `/${init.protocolPrefix ?? PROTOCOL_PREFIX}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` this.timeout = init.timeout ?? TIMEOUT @@ -59,7 +57,9 @@ export class Ping implements Startable, PingInterface { * A handler to register with Libp2p to process ping messages */ handleMessage (data: IncomingStreamData): void { - this.log('incoming ping from %p', data.connection.remotePeer) + const log = data.connection.log.newScope('ping') + + log.trace('ping from %p', data.connection.remotePeer) const { stream } = data const start = Date.now() @@ -92,12 +92,12 @@ export class Ping implements Startable, PingInterface { return } - this.log.error('incoming ping from %p failed with error - %e', data.connection.remotePeer, err) + log.error('ping from %p failed with error - %e', data.connection.remotePeer, err) stream?.abort(err) }) .finally(() => { const ms = Date.now() - start - this.log('incoming ping from %p complete in %dms', data.connection.remotePeer, ms) + log('ping from %p complete in %dms', data.connection.remotePeer, ms) const signal = AbortSignal.timeout(this.timeout) setMaxListeners(Infinity, signal) @@ -106,7 +106,7 @@ export class Ping implements Startable, PingInterface { signal }) .catch(err => { - this.log.error('error closing ping stream from %p - %e', data.connection.remotePeer, err) + log.error('error closing ping stream from %p - %e', data.connection.remotePeer, err) stream?.abort(err) }) }) @@ -116,11 +116,10 @@ export class Ping implements Startable, PingInterface { * Ping a given peer and wait for its response, getting the operation latency. */ async ping (peer: PeerId | Multiaddr | Multiaddr[], options: AbortOptions = {}): Promise { - this.log('pinging %p', peer) - const start = Date.now() const data = randomBytes(PING_LENGTH) const connection = await this.components.connectionManager.openConnection(peer, options) + const log = connection.log.newScope('ping') let stream: Stream | undefined if (options.signal == null) { @@ -154,11 +153,11 @@ export class Ping implements Startable, PingInterface { throw new ProtocolError(`Received wrong ping ack after ${ms}ms`) } - this.log('ping %p complete in %dms', connection.remotePeer, ms) + log('ping %p complete in %dms', connection.remotePeer, ms) return ms } catch (err: any) { - this.log.error('error while pinging %p', connection.remotePeer, err) + log.error('error while pinging %p', connection.remotePeer, err) stream?.abort(err) diff --git a/packages/protocol-ping/test/index.spec.ts b/packages/protocol-ping/test/index.spec.ts index 11bcbe3ff6..74c84d6c8d 100644 --- a/packages/protocol-ping/test/index.spec.ts +++ b/packages/protocol-ping/test/index.spec.ts @@ -12,14 +12,13 @@ import pDefer from 'p-defer' import { stubInterface } from 'sinon-ts' import { PING_PROTOCOL } from '../src/constants.js' import { Ping } from '../src/ping.js' -import type { ComponentLogger, Stream, Connection } from '@libp2p/interface' +import type { Stream, Connection } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { StubbedInstance } from 'sinon-ts' interface StubbedPingServiceComponents { registrar: StubbedInstance connectionManager: StubbedInstance - logger: ComponentLogger } function echoStream (): StubbedInstance { @@ -40,8 +39,7 @@ describe('ping', () => { beforeEach(async () => { components = { registrar: stubInterface(), - connectionManager: stubInterface(), - logger: defaultLogger() + connectionManager: stubInterface() } ping = new Ping(components, { @@ -54,7 +52,9 @@ describe('ping', () => { it('should be able to ping another peer', async () => { const remotePeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519')) - const connection = stubInterface() + const connection = stubInterface({ + log: defaultLogger().forComponent('connection') + }) components.connectionManager.openConnection.withArgs(remotePeer).resolves(connection) const stream = echoStream() @@ -68,7 +68,9 @@ describe('ping', () => { const timeout = 10 const remotePeer = peerIdFromPrivateKey(await generateKeyPair('Ed25519')) - const connection = stubInterface() + const connection = stubInterface({ + log: defaultLogger().forComponent('connection') + }) components.connectionManager.openConnection.withArgs(remotePeer).resolves(connection) const stream = echoStream() @@ -105,7 +107,9 @@ describe('ping', () => { // handle incoming ping stream handler({ stream: incomingStream, - connection: stubInterface() + connection: stubInterface({ + log: defaultLogger().forComponent('connection') + }) }) const b = byteStream(outgoingStream) @@ -138,7 +142,9 @@ describe('ping', () => { // handle incoming ping stream handler({ stream: incomingStream, - connection: stubInterface() + connection: stubInterface({ + log: defaultLogger().forComponent('connection') + }) }) const b = byteStream(outgoingStream) diff --git a/packages/stream-multiplexer-mplex/src/index.ts b/packages/stream-multiplexer-mplex/src/index.ts index 20bec4768b..0ccd415ce6 100644 --- a/packages/stream-multiplexer-mplex/src/index.ts +++ b/packages/stream-multiplexer-mplex/src/index.ts @@ -112,7 +112,7 @@ class Mplex implements StreamMuxerFactory { '@libp2p/stream-multiplexing' ] - createStreamMuxer (init: StreamMuxerInit = {}): StreamMuxer { + createStreamMuxer (init: StreamMuxerInit): StreamMuxer { return new MplexStreamMuxer(this.components, { ...init, ...this._init diff --git a/packages/stream-multiplexer-mplex/src/mplex.ts b/packages/stream-multiplexer-mplex/src/mplex.ts index fa08f67bd5..870ab56f3f 100644 --- a/packages/stream-multiplexer-mplex/src/mplex.ts +++ b/packages/stream-multiplexer-mplex/src/mplex.ts @@ -70,7 +70,7 @@ export class MplexStreamMuxer implements StreamMuxer { constructor (components: MplexComponents, init?: MplexStreamMuxerInit) { init = init ?? {} - this.log = components.logger.forComponent('libp2p:mplex') + this.log = init.log?.newScope('mplex') ?? components.logger.forComponent('libp2p:mplex') this.logger = components.logger this._streamId = 0 this._streams = { @@ -233,7 +233,7 @@ export class MplexStreamMuxer implements StreamMuxer { } } - const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._init.maxMsgSize, logger: this.logger }) + const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._init.maxMsgSize, log: this.log }) registry.set(id, stream) return stream } diff --git a/packages/stream-multiplexer-mplex/src/stream.ts b/packages/stream-multiplexer-mplex/src/stream.ts index 2f07a3cdd4..13005ccf17 100644 --- a/packages/stream-multiplexer-mplex/src/stream.ts +++ b/packages/stream-multiplexer-mplex/src/stream.ts @@ -4,17 +4,17 @@ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { MAX_MSG_SIZE } from './decode.js' import { InitiatorMessageTypes, ReceiverMessageTypes } from './message-types.js' import type { Message } from './message-types.js' -import type { ComponentLogger } from '@libp2p/interface' +import type { Logger } from '@libp2p/interface' import type { AbstractStreamInit } from '@libp2p/utils/abstract-stream' export interface Options { id: number send(msg: Message): Promise + log: Logger name?: string onEnd?(err?: Error): void type?: 'initiator' | 'receiver' maxMsgSize?: number - logger: ComponentLogger } interface MplexStreamInit extends AbstractStreamInit { @@ -80,15 +80,16 @@ export class MplexStream extends AbstractStream { export function createStream (options: Options): MplexStream { const { id, name, send, onEnd, type = 'initiator', maxMsgSize = MAX_MSG_SIZE } = options + const direction = type === 'initiator' ? 'outbound' : 'inbound' return new MplexStream({ id: type === 'initiator' ? (`i${id}`) : `r${id}`, streamId: id, name: `${name ?? id}`, - direction: type === 'initiator' ? 'outbound' : 'inbound', + direction, maxDataSize: maxMsgSize, onEnd, send, - log: options.logger.forComponent(`libp2p:mplex:stream:${type}:${id}`) + log: options.log.newScope(`${direction}:${id}`) }) } diff --git a/packages/stream-multiplexer-mplex/test/mplex.spec.ts b/packages/stream-multiplexer-mplex/test/mplex.spec.ts index 2f586d23a8..2f30e89378 100644 --- a/packages/stream-multiplexer-mplex/test/mplex.spec.ts +++ b/packages/stream-multiplexer-mplex/test/mplex.spec.ts @@ -139,6 +139,7 @@ describe('mplex', () => { logger: defaultLogger() }) const muxer = factory.createStreamMuxer({ + log: defaultLogger().forComponent('libp2p:mplex'), onIncomingStream () { // do nothing with the stream so the buffer fills up }, diff --git a/packages/stream-multiplexer-mplex/test/stream.spec.ts b/packages/stream-multiplexer-mplex/test/stream.spec.ts index 1bf654111c..fa9bf52920 100644 --- a/packages/stream-multiplexer-mplex/test/stream.spec.ts +++ b/packages/stream-multiplexer-mplex/test/stream.spec.ts @@ -72,8 +72,18 @@ async function streamPair (n: number, onInitiatorMessage?: onMessage, onReceiver initiator.sourcePush(msgToBuffer(msg)) } - const initiator = createStream({ id, send: mockInitiatorSend, type: 'initiator', logger: defaultLogger() }) - const receiver = createStream({ id, send: mockReceiverSend, type: 'receiver', logger: defaultLogger() }) + const initiator = createStream({ + id, + send: mockInitiatorSend, + type: 'initiator', + log: defaultLogger().forComponent('initiator') + }) + const receiver = createStream({ + id, + send: mockReceiverSend, + type: 'receiver', + log: defaultLogger().forComponent('receiver') + }) const input = new Array(n).fill(0).map((_, i) => new Uint8ArrayList(Uint8Array.from([i]))) void pipe( @@ -128,7 +138,11 @@ describe('stream', () => { const msgs: Message[] = [] const mockSend = async (msg: Message): Promise => { msgs.push(msg) } const id = randomInt(1000) - const stream = createStream({ id, send: mockSend, logger: defaultLogger() }) + const stream = createStream({ + id, + send: mockSend, + log: defaultLogger().forComponent('initiator') + }) const input = randomInput() await pipe(input, stream) @@ -143,7 +157,12 @@ describe('stream', () => { const mockSend = async (msg: Message): Promise => { msgs.push(msg) } const id = randomInt(1000) const name = `STREAM${Date.now()}` - const stream = createStream({ id, name, send: mockSend, logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send: mockSend, + log: defaultLogger().forComponent('initiator') + }) const input = randomInput() await pipe(input, stream) @@ -159,7 +178,13 @@ describe('stream', () => { const id = randomInt(1000) const name = `STREAM${Date.now()}` const deferred = defer() - const stream = createStream({ id, name, onEnd: deferred.resolve, send: mockSend, logger: defaultLogger() }) + const stream = createStream({ + id, + name, + onEnd: deferred.resolve, + send: mockSend, + log: defaultLogger().forComponent('initiator') + }) const error = new Error('boom') stream.abort(error) @@ -174,7 +199,13 @@ describe('stream', () => { const id = randomInt(1000) const name = `STREAM${Date.now()}` const deferred = defer() - const stream = createStream({ id, name, onEnd: deferred.resolve, send: mockSend, logger: defaultLogger() }) + const stream = createStream({ + id, + name, + onEnd: deferred.resolve, + send: mockSend, + log: defaultLogger().forComponent('initiator') + }) stream.reset() @@ -188,7 +219,13 @@ describe('stream', () => { const mockSend = async (msg: Message): Promise => { msgs.push(msg) } const id = randomInt(1000) const name = id.toString() - const stream = createStream({ id, name, send: mockSend, type: 'initiator', logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send: mockSend, + type: 'initiator', + log: defaultLogger().forComponent('initiator') + }) const input = randomInput() await pipe(input, stream) @@ -209,7 +246,14 @@ describe('stream', () => { const mockSend = async (msg: Message): Promise => { msgs.push(msg) } const id = randomInt(1000) const name = id.toString() - const stream = createStream({ id, name, send: mockSend, type: 'receiver', logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send: mockSend, + type: 'receiver', + log: defaultLogger().forComponent('receiver') + }) + const input = randomInput() await pipe(input, stream) @@ -230,7 +274,13 @@ describe('stream', () => { const mockSend = async (msg: Message): Promise => { msgs.push(msg) } const id = randomInt(1000) const name = id.toString() - const stream = createStream({ id, name, send: mockSend, type: 'initiator', logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send: mockSend, + type: 'initiator', + log: defaultLogger().forComponent('initiator') + }) const input = randomInput() await pipe(input, stream) @@ -247,7 +297,13 @@ describe('stream', () => { const mockSend = async (msg: Message): Promise => { msgs.push(msg) } const id = randomInt(1000) const name = id.toString() - const stream = createStream({ id, name, send: mockSend, type: 'receiver', logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send: mockSend, + type: 'receiver', + log: defaultLogger().forComponent('receiver') + }) const input = randomInput() await pipe(input, stream) @@ -264,7 +320,13 @@ describe('stream', () => { const mockSend = async (msg: Message): Promise => { msgs.push(msg) } const id = randomInt(1000) const name = id.toString() - const stream = createStream({ id, name, send: mockSend, type: 'initiator', logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send: mockSend, + type: 'initiator', + log: defaultLogger().forComponent('initiator') + }) const error = new Error(`Boom ${Date.now()}`) const input = { [Symbol.iterator]: function * () { @@ -290,7 +352,13 @@ describe('stream', () => { const mockSend = async (msg: Message): Promise => { msgs.push(msg) } const id = randomInt(1000) const name = id.toString() - const stream = createStream({ id, name, send: mockSend, type: 'receiver', logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send: mockSend, + type: 'receiver', + log: defaultLogger().forComponent('receiver') + }) const error = new Error(`Boom ${Date.now()}`) const input = { [Symbol.iterator]: function * () { @@ -486,7 +554,13 @@ describe('stream', () => { const name = id.toString() const deferred = defer() const onEnd = (err?: any): void => { err != null ? deferred.reject(err) : deferred.resolve() } - const stream = createStream({ id, name, send, onEnd, logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send, + onEnd, + log: defaultLogger().forComponent('initiator') + }) const input = randomInput() void pipe( @@ -505,7 +579,12 @@ describe('stream', () => { const id = randomInt(1000) const deferred = defer() const onEnd = (err?: any): void => { err != null ? deferred.reject(err) : deferred.resolve() } - const stream = createStream({ id, send, onEnd, logger: defaultLogger() }) + const stream = createStream({ + id, + send, + onEnd, + log: defaultLogger().forComponent('initiator') + }) const input = randomInput() pipe( @@ -529,7 +608,12 @@ describe('stream', () => { } const maxMsgSize = 10 const id = randomInt(1000) - const stream = createStream({ id, send, maxMsgSize, logger: defaultLogger() }) + const stream = createStream({ + id, + send, + maxMsgSize, + log: defaultLogger().forComponent('initiator') + }) await pipe( [ @@ -547,7 +631,11 @@ describe('stream', () => { it('should error on double sink', async () => { const send = async (): Promise => {} const id = randomInt(1000) - const stream = createStream({ id, send, logger: defaultLogger() }) + const stream = createStream({ + id, + send, + log: defaultLogger().forComponent('initiator') + }) // first sink is ok void stream.sink([]) @@ -560,7 +648,11 @@ describe('stream', () => { it('should error on double sink after sink has ended', async () => { const send = async (): Promise => {} const id = randomInt(1000) - const stream = createStream({ id, send, logger: defaultLogger() }) + const stream = createStream({ + id, + send, + log: defaultLogger().forComponent('initiator') + }) // first sink is ok await stream.sink([]) @@ -576,7 +668,13 @@ describe('stream', () => { const id = randomInt(1000) const name = `STREAM${Date.now()}` const maxMsgSize = 10 - const stream = createStream({ id, name, send: mockSend, maxMsgSize, logger: defaultLogger() }) + const stream = createStream({ + id, + name, + send: mockSend, + maxMsgSize, + log: defaultLogger().forComponent('initiator') + }) const input = [ new Uint8Array(1024).map(() => randomInt(0, 255)) ] diff --git a/packages/transport-circuit-relay-v2/src/transport/transport.ts b/packages/transport-circuit-relay-v2/src/transport/transport.ts index 8fd693d36a..4f68693b8d 100644 --- a/packages/transport-circuit-relay-v2/src/transport/transport.ts +++ b/packages/transport-circuit-relay-v2/src/transport/transport.ts @@ -233,17 +233,19 @@ export class CircuitRelayTransport implements Transport stream: pbstr.unwrap(), remoteAddr: ma, localAddr: relayAddr.encapsulate(`/p2p-circuit/p2p/${this.peerId.toString()}`), - logger: this.logger, + log: this.log, onDataRead: limits.onData, onDataWrite: limits.onData }) - this.log('new outbound relayed connection %a', maConn.remoteAddr) - - return await this.upgrader.upgradeOutbound(maConn, { + const conn = await this.upgrader.upgradeOutbound(maConn, { ...options, limits: limits.getLimits() }) + + conn.log('outbound relayed connection established to %p with limits %o, over connection %s', conn.remotePeer, status.limit ?? 'none', relayConnection.id) + + return conn } catch (err: any) { this.log.error('circuit relay dial to destination %p via relay %p failed', destinationPeer, relayPeer, err) stream?.abort(err) @@ -363,16 +365,16 @@ export class CircuitRelayTransport implements Transport stream: pbstr.unwrap().unwrap(), remoteAddr, localAddr, - logger: this.logger, + log: this.log, onDataRead: limits.onData, onDataWrite: limits.onData }) - this.log('new inbound relayed connection %a', maConn.remoteAddr) await this.upgrader.upgradeInbound(maConn, { limits: limits.getLimits(), signal }) - this.log('%s connection %a upgraded', 'inbound', maConn.remoteAddr) + + maConn.log('inbound relayed connection established to %p with limits %o, over connection %s', remotePeerId, request.limit ?? 'none', connection.id) } } diff --git a/packages/transport-memory/src/connections.ts b/packages/transport-memory/src/connections.ts index a7205842bf..67fcefa539 100644 --- a/packages/transport-memory/src/connections.ts +++ b/packages/transport-memory/src/connections.ts @@ -118,7 +118,7 @@ export class MemoryConnection { open: Date.now() }, remoteAddr: multiaddr(`${this.init.address}/p2p/${this.components.peerId}`), - log: this.components.logger.forComponent(`libp2p:memory:outgoing:${1}`) + log: this.components.logger.forComponent('libp2p:memory') } const listener: MultiaddrConnection = { @@ -158,7 +158,7 @@ export class MemoryConnection { open: Date.now() }, remoteAddr: multiaddr(`${this.init.address}-outgoing/p2p/${dialingPeerId}`), - log: this.components.logger.forComponent(`libp2p:memory:outgoing:${1}`) + log: this.components.logger.forComponent('libp2p:memory') } this.connections.add(dialer) diff --git a/packages/transport-tcp/src/socket-to-conn.ts b/packages/transport-tcp/src/socket-to-conn.ts index 9e4203a53f..267c2cca16 100644 --- a/packages/transport-tcp/src/socket-to-conn.ts +++ b/packages/transport-tcp/src/socket-to-conn.ts @@ -28,7 +28,6 @@ interface ToConnectionOptions { */ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptions): MultiaddrConnection => { let closePromise: DeferredPromise - const log = options.logger.forComponent('libp2p:tcp:socket') const direction = options.direction const metrics = options.metrics const metricPrefix = options.metricPrefix ?? '' @@ -51,7 +50,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio errored = true if (!timedOut) { - log.error('%s socket error - %e', direction, err) + maConn.log.error('%s socket error - %e', direction, err) metrics?.increment({ [`${metricPrefix}error`]: true }) } @@ -83,7 +82,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio socket.once('timeout', () => { timedOut = true - log('%s %s socket read timeout', direction, lOptsStr) + maConn.log('%s %s socket read timeout', direction, lOptsStr) metrics?.increment({ [`${metricPrefix}timeout`]: true }) // if the socket times out due to inactivity we must manually close the connection @@ -95,7 +94,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio socket.once('close', () => { // record metric for clean exit if (!timedOut && !errored) { - log('%s %s socket close', direction, lOptsStr) + maConn.log('%s %s socket close', direction, lOptsStr) metrics?.increment({ [`${metricPrefix}close`]: true }) } @@ -109,7 +108,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio socket.once('end', () => { // the remote sent a FIN packet which means no more data will be sent // https://nodejs.org/dist/latest-v16.x/docs/api/net.html#event-end - log('%s %s socket end', direction, lOptsStr) + maConn.log('%s %s socket end', direction, lOptsStr) metrics?.increment({ [`${metricPrefix}end`]: true }) }) @@ -131,7 +130,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio // If the source errored the socket will already have been destroyed by // duplex(). If the socket errored it will already be // destroyed. There's nothing to do here except log the error & return. - log.error('%s %s error in sink - %e', direction, lOptsStr, err) + maConn.log.error('%s %s error in sink - %e', direction, lOptsStr, err) } } @@ -148,12 +147,12 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio async close (options: AbortOptions = {}) { if (socket.closed) { - log('the %s %s socket is already closed', direction, lOptsStr) + maConn.log('the %s %s socket is already closed', direction, lOptsStr) return } if (socket.destroyed) { - log('the %s %s socket is already destroyed', direction, lOptsStr) + maConn.log('the %s %s socket is already destroyed', direction, lOptsStr) return } @@ -175,11 +174,11 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio // wait for any unsent data to be sent if (socket.writableLength > 0) { - log('%s %s draining socket', direction, lOptsStr) + maConn.log('%s %s draining socket', direction, lOptsStr) await raceEvent(eventTarget, 'drain', signal, { errorEvent: 'error' }) - log('%s %s socket drained', direction, lOptsStr) + maConn.log('%s %s socket drained', direction, lOptsStr) } await Promise.all([ @@ -198,7 +197,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio }, abort: (err: Error) => { - log('%s %s socket abort due to error - %e', direction, lOptsStr, err) + maConn.log('%s %s socket abort due to error - %e', direction, lOptsStr, err) // the abortSignalListener may already destroyed the socket with an error socket.destroy() @@ -210,7 +209,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio maConn.timeline.close = Date.now() }, - log + log: options.logger.forComponent('libp2p:tcp:connection') } return maConn diff --git a/packages/transport-webrtc/src/muxer.ts b/packages/transport-webrtc/src/muxer.ts index 17e1a31792..b6ba6f616b 100644 --- a/packages/transport-webrtc/src/muxer.ts +++ b/packages/transport-webrtc/src/muxer.ts @@ -78,7 +78,7 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory { onEnd: (err) => { bufferedStream.onEnd(err) }, - logger: components.logger, + log: this.log, ...this.dataChannelOptions }) @@ -129,7 +129,7 @@ export class DataChannelMuxer implements StreamMuxer { private readonly logger: ComponentLogger constructor (components: DataChannelMuxerComponents, readonly init: DataChannelMuxerInit) { - this.log = components.logger.forComponent('libp2p:webrtc:muxer') + this.log = init.log?.newScope('muxer') ?? components.logger.forComponent('libp2p:webrtc:muxer') this.logger = components.logger this.streams = init.streams.map(s => s.stream) this.peerConnection = init.peerConnection @@ -165,7 +165,7 @@ export class DataChannelMuxer implements StreamMuxer { this.#onStreamEnd(stream, channel) this.log('incoming channel %s ended', id) }, - logger: this.logger, + log: this.log, ...this.dataChannelOptions }) @@ -257,7 +257,7 @@ export class DataChannelMuxer implements StreamMuxer { this.#onStreamEnd(stream, channel) this.log('outgoing channel %s ended', id) }, - logger: this.logger, + log: this.log, ...this.dataChannelOptions }) this.streams.push(stream) diff --git a/packages/transport-webrtc/src/private-to-public/utils/connect.ts b/packages/transport-webrtc/src/private-to-public/utils/connect.ts index 74c045ba1a..b568a273db 100644 --- a/packages/transport-webrtc/src/private-to-public/utils/connect.ts +++ b/packages/transport-webrtc/src/private-to-public/utils/connect.ts @@ -117,7 +117,7 @@ export async function connect (peerConnection: DirectRTCPeerConnection, ufrag: s channel: handshakeDataChannel, direction: 'outbound', handshake: true, - logger: options.logger, + log: options.log, ...(options.dataChannel ?? {}) }) diff --git a/packages/transport-webrtc/src/stream.ts b/packages/transport-webrtc/src/stream.ts index 5c87e3e3e7..918a138ce0 100644 --- a/packages/transport-webrtc/src/stream.ts +++ b/packages/transport-webrtc/src/stream.ts @@ -11,7 +11,7 @@ import { Uint8ArrayList } from 'uint8arraylist' import { BUFFERED_AMOUNT_LOW_TIMEOUT, FIN_ACK_TIMEOUT, MAX_BUFFERED_AMOUNT, MAX_MESSAGE_SIZE, OPEN_TIMEOUT, PROTOBUF_OVERHEAD } from './constants.js' import { Message } from './private-to-public/pb/message.js' import type { DataChannelOptions } from './index.js' -import type { AbortOptions, ComponentLogger, Direction } from '@libp2p/interface' +import type { AbortOptions, Direction, Logger } from '@libp2p/interface' import type { AbstractStreamInit } from '@libp2p/utils/abstract-stream' import type { Pushable } from 'it-pushable' import type { DeferredPromise } from 'p-defer' @@ -25,7 +25,7 @@ export interface WebRTCStreamInit extends AbstractStreamInit, DataChannelOptions */ channel: RTCDataChannel - logger: ComponentLogger + log: Logger } export class WebRTCStream extends AbstractStream { @@ -390,7 +390,10 @@ export interface WebRTCStreamOptions extends DataChannelOptions { */ onEnd?(err?: Error | undefined): void - logger: ComponentLogger + /** + * The logger to create a scope from + */ + log: Logger /** * If true the underlying datachannel is being used to perform the noise @@ -403,8 +406,8 @@ export function createStream (options: WebRTCStreamOptions): WebRTCStream { const { channel, direction, handshake } = options return new WebRTCStream({ + ...options, id: `${channel.id}`, - log: options.logger.forComponent(`libp2p:webrtc:stream:${handshake === true ? 'handshake' : direction}:${channel.id}`), - ...options + log: options.log.newScope(`${handshake === true ? 'handshake' : direction}:${channel.id}`) }) } diff --git a/packages/transport-webrtc/test/stream.spec.ts b/packages/transport-webrtc/test/stream.spec.ts index 6ede826569..f4c48478f6 100644 --- a/packages/transport-webrtc/test/stream.spec.ts +++ b/packages/transport-webrtc/test/stream.spec.ts @@ -37,7 +37,7 @@ describe('Max message size', () => { channel, direction: 'outbound', closeTimeout: 1, - logger: defaultLogger() + log: defaultLogger().forComponent('test') }) p.push(data) @@ -69,7 +69,7 @@ describe('Max message size', () => { const webrtcStream = createStream({ channel, direction: 'outbound', - logger: defaultLogger() + log: defaultLogger().forComponent('test') }) p.push(data) @@ -101,7 +101,7 @@ describe('Max message size', () => { onEnd: () => { closed.resolve() }, - logger: defaultLogger() + log: defaultLogger().forComponent('test') }) const t0 = Date.now() @@ -122,7 +122,12 @@ const TEST_MESSAGE = 'test_message' function setup (): { peerConnection: RTCPeerConnection, dataChannel: RTCDataChannel, stream: WebRTCStream } { const peerConnection = new RTCPeerConnection() const dataChannel = peerConnection.createDataChannel('whatever', { negotiated: true, id: 91 }) - const stream = createStream({ channel: dataChannel, direction: 'outbound', closeTimeout: 1, logger: defaultLogger() }) + const stream = createStream({ + channel: dataChannel, + direction: 'outbound', + closeTimeout: 1, + log: defaultLogger().forComponent('test') + }) return { peerConnection, dataChannel, stream } } diff --git a/packages/transport-websockets/src/socket-to-conn.ts b/packages/transport-websockets/src/socket-to-conn.ts index 603e24cf51..8e5ddbbeb7 100644 --- a/packages/transport-websockets/src/socket-to-conn.ts +++ b/packages/transport-websockets/src/socket-to-conn.ts @@ -1,4 +1,4 @@ -import { AbortError } from '@libp2p/interface' +import { AbortError, ConnectionFailedError } from '@libp2p/interface' import { CLOSE_TIMEOUT } from './constants.js' import type { AbortOptions, ComponentLogger, CounterGroup, MultiaddrConnection } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' @@ -14,12 +14,11 @@ export interface SocketToConnOptions { // Convert a stream into a MultiaddrConnection // https://github.com/libp2p/interface-transport#multiaddrconnection export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr, options: SocketToConnOptions): MultiaddrConnection { - const log = options.logger.forComponent('libp2p:websockets:maconn') const metrics = options.metrics const metricPrefix = options.metricPrefix ?? '' const maConn: MultiaddrConnection = { - log, + log: options.logger.forComponent('libp2p:websockets:connection'), async sink (source) { try { @@ -34,7 +33,7 @@ export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr, })()) } catch (err: any) { if (err.type !== 'aborted') { - log.error(err) + maConn.log.error(err) } } }, @@ -59,7 +58,7 @@ export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr, const listener = (): void => { const { host, port } = maConn.remoteAddr.toOptions() - log('timeout closing stream to %s:%s after %dms, destroying it manually', + maConn.log('timeout closing stream to %s:%s after %dms, destroying it manually', host, port, Date.now() - start) this.abort(new AbortError('Socket close timeout')) @@ -70,7 +69,7 @@ export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr, try { await stream.close() } catch (err: any) { - log.error('error closing WebSocket gracefully', err) + maConn.log.error('error closing WebSocket gracefully - %e', err) this.abort(err) } finally { options.signal?.removeEventListener('abort', listener) @@ -79,10 +78,7 @@ export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr, }, abort (err: Error): void { - const { host, port } = maConn.remoteAddr.toOptions() - log('timeout closing stream to %s:%s due to error', - host, port, err) - + maConn.log.error('destroying WebSocket after error - %e', err) stream.destroy() maConn.timeline.close = Date.now() @@ -94,15 +90,24 @@ export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr, } } - stream.socket.addEventListener('close', () => { - metrics?.increment({ [`${metricPrefix}close`]: true }) + // track local vs remote closing + let closedLocally = false + const close = stream.socket.close.bind(stream.socket) + stream.socket.close = (...args) => { + closedLocally = true + return close(...args) + } - // In instances where `close` was not explicitly called, - // such as an iterable stream ending, ensure we have set the close - // timeline - if (maConn.timeline.close == null) { - maConn.timeline.close = Date.now() + stream.socket.addEventListener('close', (evt) => { + maConn.log('closed %s, code %d, reason "%s", wasClean %s', closedLocally ? 'locally' : 'by remote', evt.code, evt.reason, evt.wasClean) + + if (!evt.wasClean) { + maConn.abort(new ConnectionFailedError(`${closedLocally ? 'Local' : 'Remote'} did not close WebSocket cleanly`)) + return } + + metrics?.increment({ [`${metricPrefix}close`]: true }) + maConn.timeline.close = Date.now() }, { once: true }) return maConn diff --git a/packages/transport-webtransport/src/index.ts b/packages/transport-webtransport/src/index.ts index c3cceb4178..59f5a1eac2 100644 --- a/packages/transport-webtransport/src/index.ts +++ b/packages/transport-webtransport/src/index.ts @@ -231,7 +231,7 @@ class WebTransportTransport implements Transport { return await options.upgrader.upgradeOutbound(maConn, { ...options, skipEncryption: true, - muxerFactory: webtransportMuxer(wt, wt.incomingBidirectionalStreams.getReader(), this.components.logger, this.config), + muxerFactory: webtransportMuxer(wt, wt.incomingBidirectionalStreams.getReader(), this.log, this.config), skipProtection: true }) } catch (err: any) { diff --git a/packages/transport-webtransport/src/muxer.ts b/packages/transport-webtransport/src/muxer.ts index a20eb0bff8..50d725f2f0 100644 --- a/packages/transport-webtransport/src/muxer.ts +++ b/packages/transport-webtransport/src/muxer.ts @@ -1,26 +1,20 @@ import { webtransportBiDiStreamToStream } from './stream.js' import { inertDuplex } from './utils/inert-duplex.js' import type WebTransport from './webtransport.js' -import type { ComponentLogger, Stream, StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface' +import type { Logger, Stream, StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface' export interface WebTransportMuxerInit { maxInboundStreams: number } -export function webtransportMuxer (wt: Pick, reader: ReadableStreamDefaultReader, logger: ComponentLogger, config: WebTransportMuxerInit): StreamMuxerFactory { +export function webtransportMuxer (wt: Pick, reader: ReadableStreamDefaultReader, log: Logger, config: WebTransportMuxerInit): StreamMuxerFactory { let streamIDCounter = 0 - const log = logger.forComponent('libp2p:webtransport:muxer') + log = log.newScope('muxer') return { protocol: 'webtransport', createStreamMuxer: (init?: StreamMuxerInit): StreamMuxer => { // !TODO handle abort signal when WebTransport supports this. - - if (typeof init === 'function') { - // The api docs say that init may be a function - init = { onIncomingStream: init } - } - const activeStreams: Stream[] = [] Promise.resolve() @@ -49,7 +43,7 @@ export function webtransportMuxer (wt: Pick void), logger: ComponentLogger): Promise { - const log = logger.forComponent(`libp2p:webtransport:stream:${direction}:${streamId}`) - +export async function webtransportBiDiStreamToStream (bidiStream: WebTransportBidirectionalStream, streamId: string, direction: Direction, activeStreams: Stream[], onStreamEnd: undefined | ((s: Stream) => void), log: Logger): Promise { const stream = new WebTransportStream({ bidiStream, id: streamId, direction, - log, + log: log.newScope(`${direction}:${streamId}`), onEnd: () => { const index = activeStreams.findIndex(s => s === stream) if (index !== -1) { diff --git a/packages/utils/src/stream-to-ma-conn.ts b/packages/utils/src/stream-to-ma-conn.ts index 3c3da0d264..732b71bbe7 100644 --- a/packages/utils/src/stream-to-ma-conn.ts +++ b/packages/utils/src/stream-to-ma-conn.ts @@ -1,6 +1,6 @@ import forEach from 'it-foreach' import { pipe } from 'it-pipe' -import type { ComponentLogger, MultiaddrConnection, Stream } from '@libp2p/interface' +import type { Logger, MultiaddrConnection, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' import type { Uint8ArrayList } from 'uint8arraylist' @@ -8,7 +8,7 @@ export interface StreamProperties { stream: Stream remoteAddr: Multiaddr localAddr: Multiaddr - logger: ComponentLogger + log: Logger /** * A callback invoked when data is read from the stream @@ -26,8 +26,7 @@ export interface StreamProperties { * https://github.com/libp2p/interface-transport#multiaddrconnection */ export function streamToMaConnection (props: StreamProperties): MultiaddrConnection { - const { stream, remoteAddr, logger, onDataRead, onDataWrite } = props - const log = logger.forComponent('libp2p:stream:converter') + const { stream, remoteAddr, log, onDataRead, onDataWrite } = props let closedRead = false let closedWrite = false @@ -57,12 +56,14 @@ export function streamToMaConnection (props: StreamProperties): MultiaddrConnect ) ) } catch (err: any) { + maConn.log.error('errored - %e', err) + // If aborted we can safely ignore if (err.type !== 'aborted') { // If the source errored the socket will already have been destroyed by // toIterable.duplex(). If the socket errored it will already be // destroyed. There's nothing to do here except log the error & return. - log.error('%s error in sink', remoteAddr, err) + maConn.log.error('%s error in sink - %e', remoteAddr, err) } } finally { closedWrite = true @@ -71,7 +72,7 @@ export function streamToMaConnection (props: StreamProperties): MultiaddrConnect } const maConn: MultiaddrConnection = { - log, + log: log.newScope('stream-to-maconn'), sink: stream.sink, source: (async function * (): AsyncGenerator { try { diff --git a/packages/utils/test/stream-to-ma-conn.spec.ts b/packages/utils/test/stream-to-ma-conn.spec.ts index 627b8878c5..8c58331b2e 100644 --- a/packages/utils/test/stream-to-ma-conn.spec.ts +++ b/packages/utils/test/stream-to-ma-conn.spec.ts @@ -45,7 +45,7 @@ describe('Convert stream into a multiaddr connection', () => { stream: toMuxedStream(stream), localAddr, remoteAddr, - logger: defaultLogger() + log: defaultLogger().forComponent('test') }) expect(maConn).to.exist() @@ -66,7 +66,7 @@ describe('Convert stream into a multiaddr connection', () => { stream: toMuxedStream(stream), localAddr, remoteAddr, - logger: defaultLogger() + log: defaultLogger().forComponent('test') }) const data = uint8ArrayFromString('hey') From 79473c99a36e167d7b7fdf4192911e46a2e520d5 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 9 Jul 2025 17:45:17 +0200 Subject: [PATCH 03/10] chore: pass correct log --- packages/protocol-identify/src/identify-push.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol-identify/src/identify-push.ts b/packages/protocol-identify/src/identify-push.ts index f555cd6162..189fe165b0 100644 --- a/packages/protocol-identify/src/identify-push.ts +++ b/packages/protocol-identify/src/identify-push.ts @@ -154,7 +154,7 @@ export class IdentifyPush extends AbstractIdentify implements Startable, Identif const message = await pb.read(options) await stream.close(options) - await consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message) + await consumeIdentifyMessage(this.peerStore, this.events, log, connection, message) } catch (err: any) { log.error('received invalid message', err) stream.abort(err) From 4420fad686921f887854e1b37ecd01f65b276e0d Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Sun, 13 Jul 2025 08:11:38 +0200 Subject: [PATCH 04/10] fix: use failure event instead of error (#3219) Ignore the error event as it causes `raceEvent` to throw. In future we should remove the error event from the queue as all we do with it is log the error, and if we want that, the `failure` event gives more context around the error so can make the logs more informative. --- packages/kad-dht/src/content-routing/index.ts | 4 ++-- packages/kad-dht/src/query/query-path.ts | 4 ++-- .../src/connection-manager/dial-queue.ts | 4 ++-- packages/utils/src/queue/index.ts | 11 ++++++----- packages/utils/test/peer-job-queue.spec.ts | 2 +- packages/utils/test/queue.spec.ts | 18 +++++++++--------- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/kad-dht/src/content-routing/index.ts b/packages/kad-dht/src/content-routing/index.ts index c7a3f627bc..abaf1137df 100644 --- a/packages/kad-dht/src/content-routing/index.ts +++ b/packages/kad-dht/src/content-routing/index.ts @@ -134,8 +134,8 @@ export class ContentRouting { queue.addEventListener('idle', () => { events.end() }) - queue.addEventListener('error', (err) => { - this.log.error('error publishing provider record to peer - %e', err) + queue.addEventListener('failure', (event) => { + this.log.error('error publishing provider record to peer - %e', event.detail.error) }) queue.add(async () => { diff --git a/packages/kad-dht/src/query/query-path.ts b/packages/kad-dht/src/query/query-path.ts index 0e107a413d..baab9f0447 100644 --- a/packages/kad-dht/src/query/query-path.ts +++ b/packages/kad-dht/src/query/query-path.ts @@ -100,8 +100,8 @@ export async function * queryPath (options: QueryPathOptions): AsyncGenerator { - log.error('error during query - %e', evt.detail) + queue.addEventListener('failure', (evt) => { + log.error('error during query - %e', evt.detail.error) }) const onAbort = (): void => { diff --git a/packages/libp2p/src/connection-manager/dial-queue.ts b/packages/libp2p/src/connection-manager/dial-queue.ts index 771abf753f..be314eb327 100644 --- a/packages/libp2p/src/connection-manager/dial-queue.ts +++ b/packages/libp2p/src/connection-manager/dial-queue.ts @@ -101,8 +101,8 @@ export class DialQueue { metrics: components.metrics }) // a started job errored - this.queue.addEventListener('error', (event) => { - if (event.detail?.name !== AbortError.name) { + this.queue.addEventListener('failure', (event) => { + if (event.detail?.error.name !== AbortError.name) { this.log.error('error in dial queue - %e', event.detail) } }) diff --git a/packages/utils/src/queue/index.ts b/packages/utils/src/queue/index.ts index 37f0a3feda..b78b7a9bc7 100644 --- a/packages/utils/src/queue/index.ts +++ b/packages/utils/src/queue/index.ts @@ -101,6 +101,8 @@ export interface QueueEvents @@ -263,7 +265,6 @@ export class Queue): void => { - cleanup(evt.detail) + const onQueueFailure = (evt: CustomEvent>): void => { + cleanup(evt.detail.error) } const onQueueIdle = (): void => { @@ -410,7 +411,7 @@ export class Queue { peerId: peerIdA }).catch(() => {}) - const event = await raceEvent>>(queue, 'failure') + const event = await raceEvent>>(queue, 'failure', AbortSignal.timeout(10_000)) expect(event.detail.job.options.peerId).to.equal(peerIdA) expect(event.detail.error).to.equal(err) diff --git a/packages/utils/test/queue.spec.ts b/packages/utils/test/queue.spec.ts index 85ab374211..5f2356e63d 100644 --- a/packages/utils/test/queue.spec.ts +++ b/packages/utils/test/queue.spec.ts @@ -508,10 +508,10 @@ describe('queue', () => { it('should emit completed / error events', async () => { const queue = new Queue({ concurrency: 1 }) - let errorEvents = 0 + let failureEvents = 0 let completedEvents = 0 - queue.addEventListener('error', () => { - errorEvents++ + queue.addEventListener('failure', () => { + failureEvents++ }) queue.addEventListener('completed', () => { completedEvents++ @@ -522,7 +522,7 @@ describe('queue', () => { expect(queue).to.have.property('size', 1) expect(queue).to.have.property('queued', 0) expect(queue).to.have.property('running', 1) - expect(errorEvents).to.equal(0) + expect(failureEvents).to.equal(0) expect(completedEvents).to.equal(0) const job2 = queue.add(async () => { @@ -533,7 +533,7 @@ describe('queue', () => { expect(queue).to.have.property('size', 2) expect(queue).to.have.property('queued', 1) expect(queue).to.have.property('running', 1) - expect(errorEvents).to.equal(0) + expect(failureEvents).to.equal(0) expect(completedEvents).to.equal(0) await job1 @@ -541,7 +541,7 @@ describe('queue', () => { expect(queue).to.have.property('size', 1) expect(queue).to.have.property('queued', 0) expect(queue).to.have.property('running', 1) - expect(errorEvents).to.equal(0) + expect(failureEvents).to.equal(0) expect(completedEvents).to.equal(1) await expect(job2).to.eventually.be.rejected() @@ -549,7 +549,7 @@ describe('queue', () => { expect(queue).to.have.property('size', 0) expect(queue).to.have.property('queued', 0) expect(queue).to.have.property('running', 0) - expect(errorEvents).to.equal(1) + expect(failureEvents).to.equal(1) expect(completedEvents).to.equal(1) const job3 = queue.add(async () => delay(100)) @@ -557,7 +557,7 @@ describe('queue', () => { expect(queue).to.have.property('size', 1) expect(queue).to.have.property('queued', 0) expect(queue).to.have.property('running', 1) - expect(errorEvents).to.equal(1) + expect(failureEvents).to.equal(1) expect(completedEvents).to.equal(1) await job3 @@ -565,7 +565,7 @@ describe('queue', () => { expect(queue).to.have.property('size', 0) expect(queue).to.have.property('queued', 0) expect(queue).to.have.property('running', 0) - expect(errorEvents).to.equal(1) + expect(failureEvents).to.equal(1) expect(completedEvents).to.equal(2) }) From cb1c14e628d2242988478c3bb856bea20db56bdc Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 24 Jul 2025 17:27:56 +0200 Subject: [PATCH 05/10] feat: allow async stream handlers (#3212) Allow `await`ing promises inside stream handlers. --- .../interface-compliance-tests/src/mocks/connection.ts | 5 +++-- packages/interface/src/stream-handler.ts | 2 +- packages/libp2p/src/connection.ts | 9 ++------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/interface-compliance-tests/src/mocks/connection.ts b/packages/interface-compliance-tests/src/mocks/connection.ts index 9cb596e918..130123c025 100644 --- a/packages/interface-compliance-tests/src/mocks/connection.ts +++ b/packages/interface-compliance-tests/src/mocks/connection.ts @@ -144,7 +144,7 @@ export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectio mss.handle(muxedStream, registrar.getProtocols(), { log }) - .then(({ stream, protocol }) => { + .then(async ({ stream, protocol }) => { log('%s: incoming stream opened on %s', direction, protocol) muxedStream.protocol = protocol muxedStream.sink = stream.sink @@ -153,9 +153,10 @@ export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectio connection.streams.push(muxedStream) const { handler } = registrar.getHandler(protocol) - handler({ connection, stream: muxedStream }) + await handler({ connection, stream: muxedStream }) }).catch(err => { log.error(err) + muxedStream.abort(err) }) } catch (err: any) { log.error(err) diff --git a/packages/interface/src/stream-handler.ts b/packages/interface/src/stream-handler.ts index 39a087a5f9..f6e362a3cb 100644 --- a/packages/interface/src/stream-handler.ts +++ b/packages/interface/src/stream-handler.ts @@ -17,7 +17,7 @@ export interface StreamHandler { /** * A callback function that accepts the incoming stream data */ - (data: IncomingStreamData): void + (data: IncomingStreamData): void | Promise } export interface StreamHandlerOptions extends AbortOptions { diff --git a/packages/libp2p/src/connection.ts b/packages/libp2p/src/connection.ts index 0ba1a7ae4a..4be51ff8a5 100644 --- a/packages/libp2p/src/connection.ts +++ b/packages/libp2p/src/connection.ts @@ -273,17 +273,12 @@ export class Connection implements ConnectionInterface { throw new LimitedConnectionError('Cannot open protocol stream on limited connection') } - handler({ connection: this, stream: muxedStream }) + await handler({ connection: this, stream: muxedStream }) }) .catch(async err => { this.log.error('error handling incoming stream id %s - %e', muxedStream.id, err) - if (muxedStream.timeline.close == null) { - await muxedStream.close({ - signal - }) - .catch(err => muxedStream.abort(err)) - } + muxedStream.abort(err) }) } From cf9aab5c841ec08bc023b9f49083c95ad78a7a07 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 30 Jul 2025 11:55:27 +0200 Subject: [PATCH 06/10] fix: silence max listeners warning for dht routing table (#3233) Increase the maximum number of listeners for the routing table's shutdown controller signal. --- packages/kad-dht/src/routing-table/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/kad-dht/src/routing-table/index.ts b/packages/kad-dht/src/routing-table/index.ts index d373d2889f..e2d58098b4 100644 --- a/packages/kad-dht/src/routing-table/index.ts +++ b/packages/kad-dht/src/routing-table/index.ts @@ -118,6 +118,7 @@ export class RoutingTable extends TypedEventEmitter implemen this.populateFromDatastoreOnStart = init.populateFromDatastoreOnStart ?? POPULATE_FROM_DATASTORE_ON_START this.populateFromDatastoreLimit = init.populateFromDatastoreLimit ?? POPULATE_FROM_DATASTORE_LIMIT this.shutdownController = new AbortController() + setMaxListeners(Infinity, this.shutdownController.signal) this.pingOldContactQueue = new PeerQueue({ concurrency: init.pingOldContactConcurrency ?? PING_OLD_CONTACT_CONCURRENCY, @@ -190,6 +191,8 @@ export class RoutingTable extends TypedEventEmitter implemen this.running = true this.shutdownController = new AbortController() + setMaxListeners(Infinity, this.shutdownController.signal) + await start(this.closestPeerTagger, this.kb) } From 7ce083dca5cc6165dfb634a2edf62a415ab2fe4b Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 14 Aug 2025 12:58:17 +0300 Subject: [PATCH 07/10] test: add connection gater integration tests (#3242) We have unit test for the connection gater, but add integration tests to ensure that any custom configured component is passed through correctly. --- .../test/connection-gater.spec.ts | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 packages/integration-tests/test/connection-gater.spec.ts diff --git a/packages/integration-tests/test/connection-gater.spec.ts b/packages/integration-tests/test/connection-gater.spec.ts new file mode 100644 index 0000000000..cc58f081a4 --- /dev/null +++ b/packages/integration-tests/test/connection-gater.spec.ts @@ -0,0 +1,170 @@ +import { memory } from '@libp2p/memory' +import { mplex } from '@libp2p/mplex' +import { plaintext } from '@libp2p/plaintext' +import { multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import delay from 'delay' +import { createLibp2p } from 'libp2p' +import Sinon from 'sinon' +import { stubInterface } from 'sinon-ts' +import type { ConnectionGater, Libp2p } from '@libp2p/interface' + +async function createLocalNode (connectionGater: ConnectionGater): Promise { + return createLibp2p({ + connectionGater, + addresses: { + listen: [ + '/memory/0' + ] + }, + transports: [ + memory() + ], + connectionEncrypters: [ + plaintext() + ], + streamMuxers: [ + mplex() + ] + }) +} + +describe('connection-gater', () => { + let localNode: Libp2p + let remoteNode: Libp2p + + beforeEach(async () => { + remoteNode = await createLibp2p({ + addresses: { + listen: [ + '/memory/1' + ] + }, + transports: [ + memory() + ], + connectionEncrypters: [ + plaintext() + ], + streamMuxers: [ + mplex() + ] + }) + }) + + afterEach(async () => { + await localNode?.stop() + await remoteNode?.stop() + }) + + it('should deny dialling a peer', async () => { + const connectionGater = stubInterface({ + denyDialPeer: Sinon.stub().returns(true) + }) + + localNode = await createLocalNode(connectionGater) + + const ma = multiaddr(`/memory/1/p2p/${remoteNode.peerId}`) + + await expect(localNode.dial(ma)).to.eventually.be.rejected + .with.property('name', 'DialDeniedError') + + expect(connectionGater.denyDialPeer?.called).to.be.true() + expect(connectionGater.denyDialPeer?.getCall(0).args[0]).to.deep.equal(remoteNode.peerId) + }) + + it('should deny dialling a multiaddr', async () => { + const connectionGater = stubInterface({ + denyDialMultiaddr: Sinon.stub().returns(true) + }) + + localNode = await createLocalNode(connectionGater) + + await expect(localNode.dial(remoteNode.getMultiaddrs())).to.eventually.be.rejected + .with.property('name', 'DialDeniedError') + + expect(connectionGater.denyDialMultiaddr?.called).to.be.true() + }) + + it('should deny an inbound connection', async () => { + const connectionGater = stubInterface({ + denyInboundConnection: Sinon.stub().returns(true) + }) + + localNode = await createLocalNode(connectionGater) + + await expect(remoteNode.dial(localNode.getMultiaddrs())).to.eventually.be.rejected + .with.property('name', 'EncryptionFailedError') + + expect(connectionGater.denyInboundConnection?.called).to.be.true() + }) + + it('should deny an outbound connection', async () => { + const connectionGater = stubInterface({ + denyOutboundConnection: Sinon.stub().returns(true) + }) + + localNode = await createLocalNode(connectionGater) + + await expect(localNode.dial(remoteNode.getMultiaddrs(), { + signal: AbortSignal.timeout(10_000) + })).to.eventually.be.rejected + .with.property('name', 'ConnectionInterceptedError') + + expect(connectionGater.denyOutboundConnection?.called).to.be.true() + }) + + it('should deny an inbound encrypted connection', async () => { + const connectionGater = stubInterface({ + denyInboundEncryptedConnection: Sinon.stub().returns(true) + }) + + localNode = await createLocalNode(connectionGater) + + await expect(remoteNode.dial(localNode.getMultiaddrs())).to.eventually.be.rejected + .with.property('name', 'MuxerUnavailableError') + + expect(connectionGater.denyInboundEncryptedConnection?.called).to.be.true() + }) + + it('should deny an outbound encrypted connection', async () => { + const connectionGater = stubInterface({ + denyOutboundEncryptedConnection: Sinon.stub().returns(true) + }) + + localNode = await createLocalNode(connectionGater) + + await expect(localNode.dial(remoteNode.getMultiaddrs())).to.eventually.be.rejected + .with.property('name', 'ConnectionInterceptedError') + + expect(connectionGater.denyOutboundEncryptedConnection?.called).to.be.true() + }) + + it('should deny an inbound upgraded connection', async () => { + const connectionGater = stubInterface({ + denyInboundUpgradedConnection: Sinon.stub().returns(true) + }) + + localNode = await createLocalNode(connectionGater) + + await remoteNode.dial(localNode.getMultiaddrs()) + + await delay(100) + + expect(localNode.getConnections()).to.be.empty() + expect(connectionGater.denyInboundUpgradedConnection?.called).to.be.true() + }) + + it('should deny an outbound upgraded connection', async () => { + const connectionGater = stubInterface({ + denyOutboundUpgradedConnection: Sinon.stub().returns(true) + }) + + localNode = await createLocalNode(connectionGater) + + await expect(localNode.dial(remoteNode.getMultiaddrs())).to.eventually.be.rejected + .with.property('name', 'ConnectionInterceptedError') + + expect(connectionGater.denyOutboundUpgradedConnection?.called).to.be.true() + }) +}) From aa770ab81b6ca2a86cc2d6df12a3176a292455bf Mon Sep 17 00:00:00 2001 From: Daniel Norman <1992255+2color@users.noreply.github.com> Date: Thu, 14 Aug 2025 13:53:27 +0200 Subject: [PATCH 08/10] fix: avoid wasteful reprovides outside threshold (#3238) --- .github/dictionary.txt | 5 ++ packages/kad-dht/src/constants.ts | 2 - packages/kad-dht/src/reprovider.ts | 40 ++++++++--- .../kad-dht/src/rpc/handlers/get-value.ts | 6 +- packages/kad-dht/test/reprovider.spec.ts | 71 +++++++++++++++++-- .../test/rpc/handlers/get-value.spec.ts | 63 ++++++++++++++++ 6 files changed, 169 insertions(+), 18 deletions(-) diff --git a/.github/dictionary.txt b/.github/dictionary.txt index 71e5ed28d0..9ee454ee8c 100644 --- a/.github/dictionary.txt +++ b/.github/dictionary.txt @@ -14,3 +14,8 @@ additionals SECG Certicom RSAES +reprovide +reprovider +reproviding +reprovides +reprovided diff --git a/packages/kad-dht/src/constants.ts b/packages/kad-dht/src/constants.ts index 520772c189..652af37f28 100644 --- a/packages/kad-dht/src/constants.ts +++ b/packages/kad-dht/src/constants.ts @@ -4,8 +4,6 @@ export const second = 1000 export const minute = 60 * second export const hour = 60 * minute -export const MAX_RECORD_AGE = 36 * hour - export const PROTOCOL = '/ipfs/kad/1.0.0' /** diff --git a/packages/kad-dht/src/reprovider.ts b/packages/kad-dht/src/reprovider.ts index 4420da5997..3cc3328abf 100644 --- a/packages/kad-dht/src/reprovider.ts +++ b/packages/kad-dht/src/reprovider.ts @@ -99,10 +99,10 @@ export class Reprovider extends TypedEventEmitter { setMaxListeners(Infinity, this.shutdownController.signal) this.timeout = setTimeout(() => { - this.cleanUp({ + this.processRecords({ signal: AbortSignal.timeout(REPROVIDE_TIMEOUT) }).catch(err => { - this.log.error('error running reprovide/cleanup - %e', err) + this.log.error('error running process to reprovide/cleanup - %e', err) }) }, this.interval) } @@ -118,10 +118,10 @@ export class Reprovider extends TypedEventEmitter { * Check all provider records. Delete them if they have expired, reprovide * them if the provider is us and the expiry is within the reprovide window. */ - private async cleanUp (options?: AbortOptions): Promise { + private async processRecords (options?: AbortOptions): Promise { try { this.safeDispatchEvent('reprovide:start') - + this.log('starting reprovide/cleanup') // Get all provider entries from the datastore for await (const entry of this.datastore.query({ prefix: this.datastorePrefix @@ -133,17 +133,20 @@ export class Reprovider extends TypedEventEmitter { const expires = created + this.validity const now = Date.now() const expired = now > expires + const isSelf = this.peerId.equals(peerId) - this.log.trace('comparing: %d < %d = %s %s', created, now - this.validity, expired, expired ? '(expired)' : '') + this.log.trace('comparing: %d (now) < %d (expires) = %s %s', now, expires, expired, expired ? '(expired)' : '(valid)') - // delete the record if it has expired - if (expired) { + // delete the record if it has expired and isn't us + // so that if user node is down for a while, we still persist provide intent + if (expired && !isSelf) { await this.datastore.delete(entry.key, options) } // if the provider is us and we are within the reprovide threshold, // reprovide the record - if (this.peerId.equals(peerId) && (now - expires) < this.reprovideThreshold) { + if (this.shouldReprovide(isSelf, expires)) { + this.log('reproviding %c as it is within the reprovide threshold (%d)', cid, this.reprovideThreshold) this.queueReprovide(cid) .catch(err => { this.log.error('could not reprovide %c - %e', cid, err) @@ -159,8 +162,9 @@ export class Reprovider extends TypedEventEmitter { this.safeDispatchEvent('reprovide:end') if (this.running) { + this.log('queuing next re-provide/cleanup run in %d ms', this.interval) this.timeout = setTimeout(() => { - this.cleanUp({ + this.processRecords({ signal: AbortSignal.timeout(REPROVIDE_TIMEOUT) }).catch(err => { this.log.error('error running re-provide - %e', err) @@ -170,6 +174,24 @@ export class Reprovider extends TypedEventEmitter { } } + /** + * Determines if a record should be reprovided + */ + private shouldReprovide (isSelf: boolean, expires: number): boolean { + if (!isSelf) { + return false + } + const now = Date.now() + + if (expires < now) { + // If the record has already expired, reprovide irrespective of the threshold + return true + } + + // if the record is approaching expiration within the reprovide threshold + return expires - now < this.reprovideThreshold + } + private async queueReprovide (cid: CID, options?: AbortOptions): Promise { if (!this.running) { return diff --git a/packages/kad-dht/src/rpc/handlers/get-value.ts b/packages/kad-dht/src/rpc/handlers/get-value.ts index cde2678190..5d8eb7a256 100644 --- a/packages/kad-dht/src/rpc/handlers/get-value.ts +++ b/packages/kad-dht/src/rpc/handlers/get-value.ts @@ -2,7 +2,7 @@ import { publicKeyToProtobuf } from '@libp2p/crypto/keys' import { InvalidMessageError, NotFoundError } from '@libp2p/interface' import { Libp2pRecord } from '@libp2p/record' import { - MAX_RECORD_AGE + PROVIDERS_VALIDITY } from '../../constants.js' import { MessageType } from '../../message/dht.js' import { bufferToRecordKey, isPublicKeyKey, fromPublicKeyKey } from '../../utils.js' @@ -107,7 +107,7 @@ export class GetValueHandler implements DHTMessageHandler { * Try to fetch a given record by from the local datastore. * Returns the record if it is still valid, meaning * - it was either authored by this node, or - * - it was received less than `MAX_RECORD_AGE` ago. + * - it was received less than `PROVIDERS_VALIDITY` ago. */ async _checkLocalDatastore (key: Uint8Array): Promise { this.log('checkLocalDatastore looking for %b', key) @@ -129,7 +129,7 @@ export class GetValueHandler implements DHTMessageHandler { // Check validity: compare time received with max record age if (record.timeReceived == null || - Date.now() - record.timeReceived.getTime() > MAX_RECORD_AGE) { + Date.now() - record.timeReceived.getTime() > PROVIDERS_VALIDITY) { // If record is bad delete it and return await this.datastore.delete(dsKey) return undefined diff --git a/packages/kad-dht/test/reprovider.spec.ts b/packages/kad-dht/test/reprovider.spec.ts index 80f4b6a0d3..803599bd9b 100644 --- a/packages/kad-dht/test/reprovider.spec.ts +++ b/packages/kad-dht/test/reprovider.spec.ts @@ -60,11 +60,9 @@ describe('reprovider', () => { contentRouting, threshold: 100, validity: 200, - interval: 100, + interval: 200, operationMetrics: {} }) - - await start(reprovider) }) afterEach(async () => { @@ -74,6 +72,8 @@ describe('reprovider', () => { it('should reprovide', async () => { const cid = CID.parse('QmZ8eiDPqQqWR17EPxiwCDgrKPVhCHLcyn6xSCNpFAdAZb') + await start(reprovider) + await providers.addProvider(cid, components.peerId) expect(contentRouting.provide).to.have.property('callCount', 0) @@ -88,6 +88,8 @@ describe('reprovider', () => { it('should cancel reprovide', async () => { const cid = CID.parse('QmZ8eiDPqQqWR17EPxiwCDgrKPVhCHLcyn6xSCNpFAdAZb') + await start(reprovider) + await providers.addProvider(cid, components.peerId) expect(contentRouting.provide).to.have.property('callCount', 0) @@ -110,6 +112,9 @@ describe('reprovider', () => { it('should remove expired provider records', async () => { const cid = CID.parse('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n') + + await start(reprovider) + await Promise.all([ providers.addProvider(cid, peers[0].peerId), providers.addProvider(cid, peers[1].peerId) @@ -121,9 +126,67 @@ describe('reprovider', () => { expect(provs[0].toString()).to.be.equal(peers[0].peerId.toString()) expect(provs[1].toString()).to.be.deep.equal(peers[1].peerId.toString()) - await delay(400) + await delay(450) const provsAfter = await providers.getProviders(cid) expect(provsAfter).to.have.length(0) }) + + it('should delete expired records from other peers but preserve own expired records', async () => { + const cid = CID.parse('QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n') + + await start(reprovider) + + // Add provider records - one from us, one from another peer + await providers.addProvider(cid, components.peerId) + await providers.addProvider(cid, peers[0].peerId) + + const provsBefore = await providers.getProviders(cid) + expect(provsBefore).to.have.length(2) + + // Wait for records to expire (validity is 200ms) + await delay(250) + + // Trigger reprovide cycle to process expired records + await pEvent(reprovider, 'reprovide:start') + await pEvent(reprovider, 'reprovide:end') + + const provsAfter = await providers.getProviders(cid) + + // Only our own record should remain, other peer's expired record should be deleted + expect(provsAfter).to.have.length(1) + expect(provsAfter[0].toString()).to.equal(components.peerId.toString()) + }) + + describe('shouldReprovide', () => { + it('should return false for non-self providers', () => { + const expires = Date.now() + 50 + const result = (reprovider as any).shouldReprovide(false, expires) + expect(result).to.be.false() + }) + + it('should return true when within reprovide threshold before expiration', () => { + const expires = Date.now() + 50 + const result = (reprovider as any).shouldReprovide(true, expires) + expect(result).to.be.true() + }) + + it('should return true when within reprovide threshold after expiration', () => { + const expires = Date.now() - 50 + const result = (reprovider as any).shouldReprovide(true, expires) + expect(result).to.be.true() + }) + + it('should return false when outside reprovide threshold before expiration', () => { + const expires = Date.now() + 150 + const result = (reprovider as any).shouldReprovide(true, expires) + expect(result).to.be.false() + }) + + it('should return true when outside reprovide threshold after expiration', () => { + const expires = Date.now() - 150 + const result = (reprovider as any).shouldReprovide(true, expires) + expect(result).to.be.true() + }) + }) }) diff --git a/packages/kad-dht/test/rpc/handlers/get-value.spec.ts b/packages/kad-dht/test/rpc/handlers/get-value.spec.ts index 961089f8ef..cf1a9dc77e 100644 --- a/packages/kad-dht/test/rpc/handlers/get-value.spec.ts +++ b/packages/kad-dht/test/rpc/handlers/get-value.spec.ts @@ -9,6 +9,7 @@ import { MemoryDatastore } from 'datastore-core' import { TypedEventEmitter } from 'main-event' import Sinon from 'sinon' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { PROVIDERS_VALIDITY } from '../../../src/constants.js' import { MessageType } from '../../../src/message/dht.js' import { PeerRouting } from '../../../src/peer-routing/index.js' import { GetValueHandler } from '../../../src/rpc/handlers/get-value.js' @@ -186,4 +187,66 @@ describe('rpc - handlers - GetValue', () => { expect(response.record).to.not.be.ok() }) }) + + describe('record expiration', () => { + it('should return valid record within PROVIDERS_VALIDITY period', async () => { + const key = uint8ArrayFromString('hello') + const value = uint8ArrayFromString('world') + const record = new Libp2pRecord(key, value, new Date()) + + await datastore.put(utils.bufferToRecordKey('/dht/record', key), record.serialize()) + + const msg: Message = { + type: T, + key, + closer: [], + providers: [] + } + + peerRouting.getClosestPeersOffline.withArgs(msg.key).resolves([]) + + const response = await handler.handle(sourcePeer.peerId, msg) + + expect(response).to.not.be.undefined() + expect(response.record).to.not.be.undefined() + + if (response.record != null) { + const responseRecord = Libp2pRecord.deserialize(response.record) + expect(responseRecord.value).to.equalBytes(value) + } + }) + + it('should delete and return no record when expired beyond PROVIDERS_VALIDITY', async () => { + const key = uint8ArrayFromString('hello') + const value = uint8ArrayFromString('world') + // Create record with old timestamp (beyond PROVIDERS_VALIDITY) + const oldTimestamp = new Date(Date.now() - PROVIDERS_VALIDITY - 1000) + const record = new Libp2pRecord(key, value, oldTimestamp) + + const dsKey = utils.bufferToRecordKey('/dht/record', key) + await datastore.put(dsKey, record.serialize()) + + // Verify record exists before the test + const existsBefore = await datastore.has(dsKey) + expect(existsBefore).to.be.true() + + const msg: Message = { + type: T, + key, + closer: [], + providers: [] + } + + peerRouting.getClosestPeersOffline.withArgs(msg.key).resolves([]) + + const response = await handler.handle(sourcePeer.peerId, msg) + + expect(response).to.not.be.undefined() + expect(response.record).to.be.undefined() + + // Verify the expired record was deleted from datastore + const existsAfter = await datastore.has(dsKey) + expect(existsAfter).to.be.false() + }) + }) }) From 5ed83dd69e2988a8e3a9b5cf44c66a94ffc17873 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:14:01 +0300 Subject: [PATCH 09/10] chore: bump actions/checkout from 4 to 5 (#3245) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/examples.yml | 4 ++-- .github/workflows/main.yml | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 53bf2965de..b75b476a97 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -13,7 +13,7 @@ jobs: name: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -118,7 +118,7 @@ jobs: - '@libp2p/websockets@$PWD/packages/transport-websockets' - 'libp2p@$PWD/packages/libp2p' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 68734d19e0..47913ed4ad 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -30,7 +30,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -52,7 +52,7 @@ jobs: node: [lts/*] fail-fast: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} @@ -70,7 +70,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -88,7 +88,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -106,7 +106,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -124,7 +124,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -142,7 +142,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -165,7 +165,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -183,7 +183,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -201,7 +201,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -214,7 +214,7 @@ jobs: needs: build runs-on: ${{ fromJSON(github.repository == 'libp2p/js-libp2p' && '["self-hosted", "linux", "x64", "4xlarge"]' || '"ubuntu-latest"') }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: lts/* @@ -265,7 +265,7 @@ jobs: token: ${{ secrets.UCI_GITHUB_TOKEN || github.token }} manifest-file: .release-please-manifest.json config-file: .release-please.json - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 - uses: actions/setup-node@v4 From f90fb1f2d68c03395f8d04ec0be5a705ad6d592c Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 20 Aug 2025 07:10:23 +0300 Subject: [PATCH 10/10] chore: release main (#3217) --- .release-please-manifest.json | 2 +- packages/config/CHANGELOG.md | 12 ++++++++ packages/config/package.json | 10 +++---- .../CHANGELOG.md | 19 ++++++++++++ .../package.json | 12 ++++---- .../connection-encrypter-tls/CHANGELOG.md | 18 +++++++++++ .../connection-encrypter-tls/package.json | 10 +++---- packages/crypto/CHANGELOG.md | 9 ++++++ packages/crypto/package.json | 4 +-- .../interface-compliance-tests/CHANGELOG.md | 30 +++++++++++++++++++ .../interface-compliance-tests/package.json | 26 ++++++++-------- packages/interface-internal/CHANGELOG.md | 10 +++++++ packages/interface-internal/package.json | 6 ++-- packages/interface/CHANGELOG.md | 13 ++++++++ packages/interface/package.json | 2 +- packages/kad-dht/CHANGELOG.md | 26 ++++++++++++++++ packages/kad-dht/package.json | 22 +++++++------- packages/keychain/CHANGELOG.md | 13 ++++++++ packages/keychain/package.json | 10 +++---- packages/libp2p/CHANGELOG.md | 28 +++++++++++++++++ packages/libp2p/package.json | 20 ++++++------- packages/logger/CHANGELOG.md | 16 ++++++++++ packages/logger/package.json | 6 ++-- packages/metrics-opentelemetry/CHANGELOG.md | 12 ++++++++ packages/metrics-opentelemetry/package.json | 8 ++--- packages/metrics-prometheus/CHANGELOG.md | 14 +++++++++ packages/metrics-prometheus/package.json | 12 ++++---- packages/metrics-simple/CHANGELOG.md | 10 +++++++ packages/metrics-simple/package.json | 6 ++-- packages/multistream-select/CHANGELOG.md | 11 +++++++ packages/multistream-select/package.json | 6 ++-- packages/peer-collections/CHANGELOG.md | 13 ++++++++ packages/peer-collections/package.json | 10 +++---- .../peer-discovery-bootstrap/CHANGELOG.md | 14 +++++++++ .../peer-discovery-bootstrap/package.json | 12 ++++---- packages/peer-discovery-mdns/CHANGELOG.md | 16 ++++++++++ packages/peer-discovery-mdns/package.json | 16 +++++----- packages/peer-id/CHANGELOG.md | 10 +++++++ packages/peer-id/package.json | 6 ++-- packages/peer-record/CHANGELOG.md | 12 ++++++++ packages/peer-record/package.json | 10 +++---- packages/peer-store/CHANGELOG.md | 15 ++++++++++ packages/peer-store/package.json | 14 ++++----- packages/pnet/CHANGELOG.md | 14 +++++++++ packages/pnet/package.json | 12 ++++---- packages/protocol-autonat-v2/CHANGELOG.md | 16 ++++++++++ packages/protocol-autonat-v2/package.json | 16 +++++----- packages/protocol-autonat/CHANGELOG.md | 21 +++++++++++++ packages/protocol-autonat/package.json | 16 +++++----- packages/protocol-dcutr/CHANGELOG.md | 11 +++++++ packages/protocol-dcutr/package.json | 8 ++--- packages/protocol-echo/CHANGELOG.md | 17 +++++++++++ packages/protocol-echo/package.json | 8 ++--- packages/protocol-fetch/CHANGELOG.md | 19 ++++++++++++ packages/protocol-fetch/package.json | 12 ++++---- packages/protocol-identify/CHANGELOG.md | 21 +++++++++++++ packages/protocol-identify/package.json | 16 +++++----- packages/protocol-perf/CHANGELOG.md | 18 +++++++++++ packages/protocol-perf/package.json | 10 +++---- packages/protocol-ping/CHANGELOG.md | 19 ++++++++++++ packages/protocol-ping/package.json | 12 ++++---- packages/pubsub-floodsub/CHANGELOG.md | 16 ++++++++++ packages/pubsub-floodsub/package.json | 16 +++++----- packages/pubsub/CHANGELOG.md | 16 ++++++++++ packages/pubsub/package.json | 16 +++++----- .../stream-multiplexer-mplex/CHANGELOG.md | 18 +++++++++++ .../stream-multiplexer-mplex/package.json | 10 +++---- .../transport-circuit-relay-v2/CHANGELOG.md | 23 ++++++++++++++ .../transport-circuit-relay-v2/package.json | 20 ++++++------- packages/transport-memory/CHANGELOG.md | 17 +++++++++++ packages/transport-memory/package.json | 8 ++--- packages/transport-tcp/CHANGELOG.md | 17 +++++++++++ packages/transport-tcp/package.json | 8 ++--- packages/transport-webrtc/CHANGELOG.md | 22 ++++++++++++++ packages/transport-webrtc/package.json | 18 +++++------ packages/transport-websockets/CHANGELOG.md | 17 +++++++++++ packages/transport-websockets/package.json | 8 ++--- packages/transport-webtransport/CHANGELOG.md | 21 +++++++++++++ packages/transport-webtransport/package.json | 16 +++++----- packages/upnp-nat/CHANGELOG.md | 15 ++++++++++ packages/upnp-nat/package.json | 14 ++++----- packages/utils/CHANGELOG.md | 19 ++++++++++++ packages/utils/package.json | 10 +++---- 83 files changed, 920 insertions(+), 242 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index db5ea8c624..9842d4ab44 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{"packages/config":"1.1.13","packages/connection-encrypter-plaintext":"2.0.28","packages/connection-encrypter-tls":"2.2.6","packages/crypto":"5.1.7","packages/interface":"2.10.5","packages/interface-compliance-tests":"6.4.16","packages/interface-internal":"2.3.18","packages/kad-dht":"15.1.10","packages/keychain":"5.2.8","packages/libp2p":"2.9.0","packages/logger":"5.1.21","packages/metrics-opentelemetry":"1.0.20","packages/metrics-prometheus":"4.3.29","packages/metrics-simple":"1.3.15","packages/multistream-select":"6.0.28","packages/peer-collections":"6.0.34","packages/peer-discovery-bootstrap":"11.0.46","packages/peer-discovery-mdns":"11.0.46","packages/peer-id":"5.1.8","packages/peer-record":"8.0.34","packages/peer-store":"11.2.6","packages/pnet":"2.0.46","packages/protocol-autonat":"2.0.37","packages/protocol-dcutr":"2.0.37","packages/protocol-echo":"2.1.27","packages/protocol-fetch":"3.0.21","packages/protocol-identify":"3.0.38","packages/protocol-perf":"4.0.46","packages/protocol-ping":"2.0.36","packages/pubsub":"10.1.17","packages/pubsub-floodsub":"10.1.45","packages/record":"4.0.7","packages/stream-multiplexer-mplex":"11.0.46","packages/transport-circuit-relay-v2":"3.2.23","packages/transport-memory":"1.1.13","packages/transport-tcp":"10.1.18","packages/transport-webrtc":"5.2.23","packages/transport-websockets":"9.2.18","packages/transport-webtransport":"5.0.50","packages/upnp-nat":"3.1.21","packages/utils":"6.7.1","packages/protocol-autonat-v2":"1.0.0"} +{"packages/config":"1.1.14","packages/connection-encrypter-plaintext":"2.0.29","packages/connection-encrypter-tls":"2.2.7","packages/crypto":"5.1.8","packages/interface":"2.11.0","packages/interface-compliance-tests":"6.5.0","packages/interface-internal":"2.3.19","packages/kad-dht":"15.1.11","packages/keychain":"5.2.9","packages/libp2p":"2.10.0","packages/logger":"5.2.0","packages/metrics-opentelemetry":"1.0.21","packages/metrics-prometheus":"4.3.30","packages/metrics-simple":"1.3.16","packages/multistream-select":"6.0.29","packages/peer-collections":"6.0.35","packages/peer-discovery-bootstrap":"11.0.47","packages/peer-discovery-mdns":"11.0.47","packages/peer-id":"5.1.9","packages/peer-record":"8.0.35","packages/peer-store":"11.2.7","packages/pnet":"2.0.47","packages/protocol-autonat":"2.0.38","packages/protocol-dcutr":"2.0.38","packages/protocol-echo":"2.1.28","packages/protocol-fetch":"3.0.22","packages/protocol-identify":"3.0.39","packages/protocol-perf":"4.0.47","packages/protocol-ping":"2.0.37","packages/pubsub":"10.1.18","packages/pubsub-floodsub":"10.1.46","packages/record":"4.0.7","packages/stream-multiplexer-mplex":"11.0.47","packages/transport-circuit-relay-v2":"3.2.24","packages/transport-memory":"1.1.14","packages/transport-tcp":"10.1.19","packages/transport-webrtc":"5.2.24","packages/transport-websockets":"9.2.19","packages/transport-webtransport":"5.0.51","packages/upnp-nat":"3.1.22","packages/utils":"6.7.2","packages/protocol-autonat-v2":"1.0.1"} diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 9bac988c6b..8cc33fd17d 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [1.1.14](https://github.com/libp2p/js-libp2p/compare/config-v1.1.13...config-v1.1.14) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/keychain bumped from ^5.2.8 to ^5.2.9 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [1.1.13](https://github.com/libp2p/js-libp2p/compare/config-v1.1.12...config-v1.1.13) (2025-06-25) diff --git a/packages/config/package.json b/packages/config/package.json index 8bdde8a53e..539f547654 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/config", - "version": "1.1.13", + "version": "1.1.14", "description": "Helper functions to make dealing with libp2p config easier", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/config#readme", @@ -39,10 +39,10 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/keychain": "^5.2.8", - "@libp2p/logger": "^5.1.21", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/keychain": "^5.2.9", + "@libp2p/logger": "^5.2.0", "interface-datastore": "^8.3.1" }, "devDependencies": { diff --git a/packages/connection-encrypter-plaintext/CHANGELOG.md b/packages/connection-encrypter-plaintext/CHANGELOG.md index 03c2fb196b..e99752b0da 100644 --- a/packages/connection-encrypter-plaintext/CHANGELOG.md +++ b/packages/connection-encrypter-plaintext/CHANGELOG.md @@ -72,6 +72,25 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [2.0.29](https://github.com/libp2p/js-libp2p/compare/plaintext-v2.0.28...plaintext-v2.0.29) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [2.0.28](https://github.com/libp2p/js-libp2p/compare/plaintext-v2.0.27...plaintext-v2.0.28) (2025-06-25) diff --git a/packages/connection-encrypter-plaintext/package.json b/packages/connection-encrypter-plaintext/package.json index 4949a815eb..645244ebd6 100644 --- a/packages/connection-encrypter-plaintext/package.json +++ b/packages/connection-encrypter-plaintext/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/plaintext", - "version": "2.0.28", + "version": "2.0.29", "description": "An insecure connection encrypter", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/connection-encrypter-plaintext#readme", @@ -45,17 +45,17 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/peer-id": "^5.1.9", "it-protobuf-stream": "^2.0.2", "protons-runtime": "^5.5.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/logger": "^5.1.21", + "@libp2p/crypto": "^5.1.8", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "it-pair": "^2.0.6", "protons": "^7.6.1", diff --git a/packages/connection-encrypter-tls/CHANGELOG.md b/packages/connection-encrypter-tls/CHANGELOG.md index 489c52be4b..a967f9fe4c 100644 --- a/packages/connection-encrypter-tls/CHANGELOG.md +++ b/packages/connection-encrypter-tls/CHANGELOG.md @@ -6,6 +6,24 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [2.2.7](https://github.com/libp2p/js-libp2p/compare/tls-v2.2.6...tls-v2.2.7) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [2.2.6](https://github.com/libp2p/js-libp2p/compare/tls-v2.2.5...tls-v2.2.6) (2025-06-25) diff --git a/packages/connection-encrypter-tls/package.json b/packages/connection-encrypter-tls/package.json index a94eb10b30..a2d7baf37c 100644 --- a/packages/connection-encrypter-tls/package.json +++ b/packages/connection-encrypter-tls/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/tls", - "version": "2.2.6", + "version": "2.2.7", "description": "A connection encrypter that uses TLS 1.3", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/connection-encrypter-tls#readme", @@ -41,9 +41,9 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/peer-id": "^5.1.9", "@peculiar/asn1-schema": "^2.3.15", "@peculiar/asn1-x509": "^2.3.15", "@peculiar/webcrypto": "^1.5.0", @@ -56,7 +56,7 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "it-pair": "^2.0.6", "protons": "^7.6.1", diff --git a/packages/crypto/CHANGELOG.md b/packages/crypto/CHANGELOG.md index 898f83663c..1c2804fbe5 100644 --- a/packages/crypto/CHANGELOG.md +++ b/packages/crypto/CHANGELOG.md @@ -17,6 +17,15 @@ * dependencies * @libp2p/interface bumped from ^1.0.2 to ^1.1.0 +## [5.1.8](https://github.com/libp2p/js-libp2p/compare/crypto-v5.1.7...crypto-v5.1.8) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + ## [5.1.7](https://github.com/libp2p/js-libp2p/compare/crypto-v5.1.6...crypto-v5.1.7) (2025-06-25) diff --git a/packages/crypto/package.json b/packages/crypto/package.json index d57de79f00..bde00431b0 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/crypto", - "version": "5.1.7", + "version": "5.1.8", "description": "Crypto primitives for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/crypto#readme", @@ -85,7 +85,7 @@ "generate": "protons ./src/keys/keys.proto" }, "dependencies": { - "@libp2p/interface": "^2.10.5", + "@libp2p/interface": "^2.11.0", "@noble/curves": "^1.9.1", "@noble/hashes": "^1.8.0", "multiformats": "^13.3.6", diff --git a/packages/interface-compliance-tests/CHANGELOG.md b/packages/interface-compliance-tests/CHANGELOG.md index ca5f690066..ab6efb7b61 100644 --- a/packages/interface-compliance-tests/CHANGELOG.md +++ b/packages/interface-compliance-tests/CHANGELOG.md @@ -75,6 +75,36 @@ * dependencies * @libp2p/utils bumped from ^5.2.4 to ^5.2.5 +## [6.5.0](https://github.com/libp2p/js-libp2p/compare/interface-compliance-tests-v6.4.16...interface-compliance-tests-v6.5.0) (2025-08-19) + + +### Features + +* allow async stream handlers ([#3212](https://github.com/libp2p/js-libp2p/issues/3212)) ([cb1c14e](https://github.com/libp2p/js-libp2p/commit/cb1c14e628d2242988478c3bb856bea20db56bdc)) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/echo bumped from ^2.1.27 to ^2.1.28 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/memory bumped from ^1.1.13 to ^1.1.14 + * @libp2p/multistream-select bumped from ^6.0.28 to ^6.0.29 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/plaintext bumped from ^2.0.28 to ^2.0.29 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * libp2p bumped from ^2.9.0 to ^2.10.0 + ## [6.4.16](https://github.com/libp2p/js-libp2p/compare/interface-compliance-tests-v6.4.15...interface-compliance-tests-v6.4.16) (2025-07-08) diff --git a/packages/interface-compliance-tests/package.json b/packages/interface-compliance-tests/package.json index d3794b95ba..cd4e3c100e 100644 --- a/packages/interface-compliance-tests/package.json +++ b/packages/interface-compliance-tests/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface-compliance-tests", - "version": "6.4.16", + "version": "6.5.0", "description": "Compliance tests for JS libp2p interfaces", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/interface-compliance-tests#readme", @@ -97,17 +97,17 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/echo": "^2.1.27", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/logger": "^5.1.21", - "@libp2p/memory": "^1.1.13", - "@libp2p/multistream-select": "^6.0.28", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/plaintext": "^2.0.28", - "@libp2p/utils": "^6.7.1", + "@libp2p/crypto": "^5.1.8", + "@libp2p/echo": "^2.1.28", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/logger": "^5.2.0", + "@libp2p/memory": "^1.1.14", + "@libp2p/multistream-select": "^6.0.29", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/plaintext": "^2.0.29", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "abortable-iterator": "^5.1.0", @@ -125,7 +125,7 @@ "it-pushable": "^3.2.3", "it-stream-types": "^2.0.2", "it-to-buffer": "^4.0.9", - "libp2p": "^2.9.0", + "libp2p": "^2.10.0", "main-event": "^1.0.1", "p-defer": "^4.0.1", "p-event": "^6.0.1", diff --git a/packages/interface-internal/CHANGELOG.md b/packages/interface-internal/CHANGELOG.md index b9a34846c1..0e1de3272f 100644 --- a/packages/interface-internal/CHANGELOG.md +++ b/packages/interface-internal/CHANGELOG.md @@ -32,6 +32,16 @@ * dependencies * @libp2p/peer-collections bumped from ^5.1.3 to ^5.1.4 +## [2.3.19](https://github.com/libp2p/js-libp2p/compare/interface-internal-v2.3.18...interface-internal-v2.3.19) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + ## [2.3.18](https://github.com/libp2p/js-libp2p/compare/interface-internal-v2.3.17...interface-internal-v2.3.18) (2025-06-25) diff --git a/packages/interface-internal/package.json b/packages/interface-internal/package.json index cb90349f79..75b42d434f 100644 --- a/packages/interface-internal/package.json +++ b/packages/interface-internal/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface-internal", - "version": "2.3.18", + "version": "2.3.19", "description": "Interfaces implemented by internal libp2p components", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/interface-internal#readme", @@ -41,8 +41,8 @@ "build": "aegir build" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/peer-collections": "^6.0.34", + "@libp2p/interface": "^2.11.0", + "@libp2p/peer-collections": "^6.0.35", "@multiformats/multiaddr": "^12.4.4", "progress-events": "^1.0.1" }, diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md index ed413f1fa1..276d1817fd 100644 --- a/packages/interface/CHANGELOG.md +++ b/packages/interface/CHANGELOG.md @@ -5,6 +5,19 @@ * add start/stop events to libp2p interface ([#407](https://github.com/libp2p/js-libp2p-interfaces/issues/407)) ([016c1e8](https://github.com/libp2p/js-libp2p-interfaces/commit/016c1e82b060c93c80546cd8c493ec6e6c97cbec)) +## [2.11.0](https://github.com/libp2p/js-libp2p/compare/interface-v2.10.5...interface-v2.11.0) (2025-08-19) + + +### Features + +* allow async stream handlers ([#3212](https://github.com/libp2p/js-libp2p/issues/3212)) ([cb1c14e](https://github.com/libp2p/js-libp2p/commit/cb1c14e628d2242988478c3bb856bea20db56bdc)) +* allow creating scoped loggers ([#3214](https://github.com/libp2p/js-libp2p/issues/3214)) ([58abe87](https://github.com/libp2p/js-libp2p/commit/58abe8702f0c28d87b54f29e19155ea5c00c407d)) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + ## [2.10.5](https://github.com/libp2p/js-libp2p/compare/interface-v2.10.4...interface-v2.10.5) (2025-06-25) diff --git a/packages/interface/package.json b/packages/interface/package.json index ce37de7af7..7f428b3005 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/interface", - "version": "2.10.5", + "version": "2.11.0", "description": "The interface implemented by a libp2p node", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/interface#readme", diff --git a/packages/kad-dht/CHANGELOG.md b/packages/kad-dht/CHANGELOG.md index 0d61ccb1b4..57e8c4722b 100644 --- a/packages/kad-dht/CHANGELOG.md +++ b/packages/kad-dht/CHANGELOG.md @@ -106,6 +106,32 @@ * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 * @libp2p/peer-store bumped from ^10.0.9 to ^10.0.10 +## [15.1.11](https://github.com/libp2p/js-libp2p/compare/kad-dht-v15.1.10...kad-dht-v15.1.11) (2025-08-19) + + +### Bug Fixes + +* avoid wasteful reprovides outside threshold ([#3238](https://github.com/libp2p/js-libp2p/issues/3238)) ([aa770ab](https://github.com/libp2p/js-libp2p/commit/aa770ab81b6ca2a86cc2d6df12a3176a292455bf)) +* silence max listeners warning for dht routing table ([#3233](https://github.com/libp2p/js-libp2p/issues/3233)) ([cf9aab5](https://github.com/libp2p/js-libp2p/commit/cf9aab5c841ec08bc023b9f49083c95ad78a7a07)) +* use failure event instead of error ([#3219](https://github.com/libp2p/js-libp2p/issues/3219)) ([4420fad](https://github.com/libp2p/js-libp2p/commit/4420fad686921f887854e1b37ecd01f65b276e0d)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/ping bumped from ^2.0.36 to ^2.0.37 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-store bumped from ^11.2.6 to ^11.2.7 + ## [15.1.10](https://github.com/libp2p/js-libp2p/compare/kad-dht-v15.1.9...kad-dht-v15.1.10) (2025-07-08) diff --git a/packages/kad-dht/package.json b/packages/kad-dht/package.json index fecb962b9d..203ecdf255 100644 --- a/packages/kad-dht/package.json +++ b/packages/kad-dht/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/kad-dht", - "version": "15.1.10", + "version": "15.1.11", "description": "JavaScript implementation of the Kad-DHT for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/kad-dht#readme", @@ -47,14 +47,14 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/ping": "^2.0.36", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/ping": "^2.0.37", "@libp2p/record": "^4.0.7", - "@libp2p/utils": "^6.7.1", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "any-signal": "^4.1.1", "interface-datastore": "^8.3.1", @@ -80,9 +80,9 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-store": "^11.2.6", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-store": "^11.2.7", "@types/lodash.random": "^3.2.9", "@types/lodash.range": "^3.2.9", "@types/sinon": "^17.0.4", diff --git a/packages/keychain/CHANGELOG.md b/packages/keychain/CHANGELOG.md index e2ca36cdac..ce50ecdcad 100644 --- a/packages/keychain/CHANGELOG.md +++ b/packages/keychain/CHANGELOG.md @@ -47,6 +47,19 @@ * devDependencies * @libp2p/peer-id-factory bumped from ^4.0.3 to ^4.0.4 +## [5.2.9](https://github.com/libp2p/js-libp2p/compare/keychain-v5.2.8...keychain-v5.2.9) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [5.2.8](https://github.com/libp2p/js-libp2p/compare/keychain-v5.2.7...keychain-v5.2.8) (2025-06-25) diff --git a/packages/keychain/package.json b/packages/keychain/package.json index 9e6a980335..39ade3ffcd 100644 --- a/packages/keychain/package.json +++ b/packages/keychain/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/keychain", - "version": "5.2.8", + "version": "5.2.9", "description": "Key management and cryptographically protected messages", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/keychain#readme", @@ -52,9 +52,9 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/utils": "^6.7.1", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/utils": "^6.7.2", "@noble/hashes": "^1.8.0", "asn1js": "^3.0.6", "interface-datastore": "^8.3.1", @@ -63,7 +63,7 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "datastore-core": "^10.0.2" }, diff --git a/packages/libp2p/CHANGELOG.md b/packages/libp2p/CHANGELOG.md index ebd06e55de..ce7dd58088 100644 --- a/packages/libp2p/CHANGELOG.md +++ b/packages/libp2p/CHANGELOG.md @@ -110,6 +110,34 @@ * @libp2p/tcp bumped from ^9.0.14 to ^9.0.15 * @libp2p/websockets bumped from ^8.0.14 to ^8.0.15 +## [2.10.0](https://github.com/libp2p/js-libp2p/compare/libp2p-v2.9.0...libp2p-v2.10.0) (2025-08-19) + + +### Features + +* allow async stream handlers ([#3212](https://github.com/libp2p/js-libp2p/issues/3212)) ([cb1c14e](https://github.com/libp2p/js-libp2p/commit/cb1c14e628d2242988478c3bb856bea20db56bdc)) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) +* use failure event instead of error ([#3219](https://github.com/libp2p/js-libp2p/issues/3219)) ([4420fad](https://github.com/libp2p/js-libp2p/commit/4420fad686921f887854e1b37ecd01f65b276e0d)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/multistream-select bumped from ^6.0.28 to ^6.0.29 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/peer-store bumped from ^11.2.6 to ^11.2.7 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + ## [2.9.0](https://github.com/libp2p/js-libp2p/compare/libp2p-v2.8.14...libp2p-v2.9.0) (2025-07-08) diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 4e9cf817ca..cf956f8ad3 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -1,6 +1,6 @@ { "name": "libp2p", - "version": "2.9.0", + "version": "2.10.0", "description": "JavaScript implementation of libp2p, a modular peer to peer network stack", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/libp2p#readme", @@ -80,15 +80,15 @@ "dependencies": { "@chainsafe/is-ip": "^2.1.0", "@chainsafe/netmask": "^2.0.0", - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/logger": "^5.1.21", - "@libp2p/multistream-select": "^6.0.28", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/peer-store": "^11.2.6", - "@libp2p/utils": "^6.7.1", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/logger": "^5.2.0", + "@libp2p/multistream-select": "^6.0.29", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/peer-store": "^11.2.7", + "@libp2p/utils": "^6.7.2", "@multiformats/dns": "^1.0.6", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", diff --git a/packages/logger/CHANGELOG.md b/packages/logger/CHANGELOG.md index 967f1a4e79..d538d08ebc 100644 --- a/packages/logger/CHANGELOG.md +++ b/packages/logger/CHANGELOG.md @@ -21,6 +21,22 @@ * devDependencies * @libp2p/peer-id bumped from ^4.0.2 to ^4.0.3 +## [5.2.0](https://github.com/libp2p/js-libp2p/compare/logger-v5.1.21...logger-v5.2.0) (2025-08-19) + + +### Features + +* allow creating scoped loggers ([#3214](https://github.com/libp2p/js-libp2p/issues/3214)) ([58abe87](https://github.com/libp2p/js-libp2p/commit/58abe8702f0c28d87b54f29e19155ea5c00c407d)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * devDependencies + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [5.1.21](https://github.com/libp2p/js-libp2p/compare/logger-v5.1.20...logger-v5.1.21) (2025-06-25) diff --git a/packages/logger/package.json b/packages/logger/package.json index 265e247976..0cd6be4ac7 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/logger", - "version": "5.1.21", + "version": "5.2.0", "description": "A logging component for use in js-libp2p modules", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/logger#readme", @@ -47,14 +47,14 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", + "@libp2p/interface": "^2.11.0", "@multiformats/multiaddr": "^12.4.4", "interface-datastore": "^8.3.1", "multiformats": "^13.3.6", "weald": "^1.0.4" }, "devDependencies": { - "@libp2p/peer-id": "^5.1.8", + "@libp2p/peer-id": "^5.1.9", "aegir": "^47.0.14", "sinon": "^20.0.0", "uint8arrays": "^5.1.0" diff --git a/packages/metrics-opentelemetry/CHANGELOG.md b/packages/metrics-opentelemetry/CHANGELOG.md index 859547c0a7..d12d064d5d 100644 --- a/packages/metrics-opentelemetry/CHANGELOG.md +++ b/packages/metrics-opentelemetry/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [1.0.21](https://github.com/libp2p/js-libp2p/compare/opentelemetry-metrics-v1.0.20...opentelemetry-metrics-v1.0.21) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [1.0.20](https://github.com/libp2p/js-libp2p/compare/opentelemetry-metrics-v1.0.19...opentelemetry-metrics-v1.0.20) (2025-06-25) diff --git a/packages/metrics-opentelemetry/package.json b/packages/metrics-opentelemetry/package.json index a82f6c1872..75d3ef767b 100644 --- a/packages/metrics-opentelemetry/package.json +++ b/packages/metrics-opentelemetry/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/opentelemetry-metrics", - "version": "1.0.20", + "version": "1.0.21", "description": "Opentelemetry metrics gathering for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/metrics-opentelemetry#readme", @@ -40,14 +40,14 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/utils": "^6.7.2", "@opentelemetry/api": "^1.9.0", "it-foreach": "^2.1.3", "it-stream-types": "^2.0.2" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14" }, "browser": { diff --git a/packages/metrics-prometheus/CHANGELOG.md b/packages/metrics-prometheus/CHANGELOG.md index be654f37ca..4d777853d8 100644 --- a/packages/metrics-prometheus/CHANGELOG.md +++ b/packages/metrics-prometheus/CHANGELOG.md @@ -81,6 +81,20 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [4.3.30](https://github.com/libp2p/js-libp2p/compare/prometheus-metrics-v4.3.29...prometheus-metrics-v4.3.30) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [4.3.29](https://github.com/libp2p/js-libp2p/compare/prometheus-metrics-v4.3.28...prometheus-metrics-v4.3.29) (2025-07-08) diff --git a/packages/metrics-prometheus/package.json b/packages/metrics-prometheus/package.json index 3523b87240..f54432325b 100644 --- a/packages/metrics-prometheus/package.json +++ b/packages/metrics-prometheus/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/prometheus-metrics", - "version": "4.3.29", + "version": "4.3.30", "description": "Collect libp2p metrics for scraping by Prometheus or Graphana", "author": "", "license": "Apache-2.0 OR MIT", @@ -41,17 +41,17 @@ "test:electron-main": "aegir test -t electron-main --cov" }, "dependencies": { - "@libp2p/interface": "^2.10.5", + "@libp2p/interface": "^2.11.0", "it-foreach": "^2.1.3", "it-stream-types": "^2.0.2", "prom-client": "^15.1.3", "uint8arraylist": "^2.4.8" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-id": "^5.1.9", "@multiformats/multiaddr": "^12.4.4", "aegir": "^47.0.14", "it-drain": "^3.0.9", diff --git a/packages/metrics-simple/CHANGELOG.md b/packages/metrics-simple/CHANGELOG.md index 0ba28862f4..5746a7dfc7 100644 --- a/packages/metrics-simple/CHANGELOG.md +++ b/packages/metrics-simple/CHANGELOG.md @@ -5,6 +5,16 @@ * track stream metrics ([#2](https://github.com/libp2p/js-libp2p-simple-metrics/issues/2)) ([caafb3d](https://github.com/libp2p/js-libp2p-simple-metrics/commit/caafb3d103fd7df0a2a4e6b3e800f4bc9c35c58f)) +## [1.3.16](https://github.com/libp2p/js-libp2p/compare/simple-metrics-v1.3.15...simple-metrics-v1.3.16) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [1.3.15](https://github.com/libp2p/js-libp2p/compare/simple-metrics-v1.3.14...simple-metrics-v1.3.15) (2025-06-25) diff --git a/packages/metrics-simple/package.json b/packages/metrics-simple/package.json index 9962b0c745..4f8b610e50 100644 --- a/packages/metrics-simple/package.json +++ b/packages/metrics-simple/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/simple-metrics", - "version": "1.3.15", + "version": "1.3.16", "description": "Simple in-memory metrics gathering for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/metrics-simple#readme", @@ -42,8 +42,8 @@ "dep-check": "aegir dep-check -i events" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/logger": "^5.1.21", + "@libp2p/interface": "^2.11.0", + "@libp2p/logger": "^5.2.0", "it-foreach": "^2.1.3", "it-stream-types": "^2.0.2", "tdigest": "^0.1.2" diff --git a/packages/multistream-select/CHANGELOG.md b/packages/multistream-select/CHANGELOG.md index bf46506b4e..cb6269877e 100644 --- a/packages/multistream-select/CHANGELOG.md +++ b/packages/multistream-select/CHANGELOG.md @@ -19,6 +19,17 @@ * devDependencies * @libp2p/logger bumped from ^4.0.1 to ^4.0.2 +## [6.0.29](https://github.com/libp2p/js-libp2p/compare/multistream-select-v6.0.28...multistream-select-v6.0.29) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [6.0.28](https://github.com/libp2p/js-libp2p/compare/multistream-select-v6.0.27...multistream-select-v6.0.28) (2025-06-25) diff --git a/packages/multistream-select/package.json b/packages/multistream-select/package.json index 8431888df7..401284d5aa 100644 --- a/packages/multistream-select/package.json +++ b/packages/multistream-select/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/multistream-select", - "version": "6.0.28", + "version": "6.0.29", "description": "JavaScript implementation of multistream-select", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/multistream-select#readme", @@ -51,7 +51,7 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", + "@libp2p/interface": "^2.11.0", "it-length-prefixed": "^10.0.1", "it-length-prefixed-stream": "^2.0.2", "it-stream-types": "^2.0.2", @@ -62,7 +62,7 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "iso-random-stream": "^2.0.2", "it-all": "^3.0.8", diff --git a/packages/peer-collections/CHANGELOG.md b/packages/peer-collections/CHANGELOG.md index a218837b83..0f44d96fc2 100644 --- a/packages/peer-collections/CHANGELOG.md +++ b/packages/peer-collections/CHANGELOG.md @@ -35,6 +35,19 @@ * devDependencies * @libp2p/peer-id-factory bumped from ^4.0.3 to ^4.0.4 +## [6.0.35](https://github.com/libp2p/js-libp2p/compare/peer-collections-v6.0.34...peer-collections-v6.0.35) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + ## [6.0.34](https://github.com/libp2p/js-libp2p/compare/peer-collections-v6.0.33...peer-collections-v6.0.34) (2025-06-25) diff --git a/packages/peer-collections/package.json b/packages/peer-collections/package.json index 536443fc9f..7b188d01d0 100644 --- a/packages/peer-collections/package.json +++ b/packages/peer-collections/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-collections", - "version": "6.0.34", + "version": "6.0.35", "description": "Stores values against a peer id", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/peer-collections#readme", @@ -47,13 +47,13 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/utils": "^6.7.2", "multiformats": "^13.3.6" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", + "@libp2p/crypto": "^5.1.8", "@types/sinon": "^17.0.4", "aegir": "^47.0.14", "sinon": "^20.0.0", diff --git a/packages/peer-discovery-bootstrap/CHANGELOG.md b/packages/peer-discovery-bootstrap/CHANGELOG.md index 89c1f66190..d62e74b1b4 100644 --- a/packages/peer-discovery-bootstrap/CHANGELOG.md +++ b/packages/peer-discovery-bootstrap/CHANGELOG.md @@ -83,6 +83,20 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [11.0.47](https://github.com/libp2p/js-libp2p/compare/bootstrap-v11.0.46...bootstrap-v11.0.47) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [11.0.46](https://github.com/libp2p/js-libp2p/compare/bootstrap-v11.0.45...bootstrap-v11.0.46) (2025-07-08) diff --git a/packages/peer-discovery-bootstrap/package.json b/packages/peer-discovery-bootstrap/package.json index 62ad84d025..f87a1d4713 100644 --- a/packages/peer-discovery-bootstrap/package.json +++ b/packages/peer-discovery-bootstrap/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/bootstrap", - "version": "11.0.46", + "version": "11.0.47", "description": "Peer discovery via a list of bootstrap peers", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/peer-discovery-bootstrap#readme", @@ -47,16 +47,16 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/peer-id": "^5.1.9", "@multiformats/mafmt": "^12.1.6", "@multiformats/multiaddr": "^12.4.4", "main-event": "^1.0.1" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "sinon-ts": "^2.0.0" }, diff --git a/packages/peer-discovery-mdns/CHANGELOG.md b/packages/peer-discovery-mdns/CHANGELOG.md index 8f20a9c5ac..52547a82dc 100644 --- a/packages/peer-discovery-mdns/CHANGELOG.md +++ b/packages/peer-discovery-mdns/CHANGELOG.md @@ -105,6 +105,22 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [11.0.47](https://github.com/libp2p/js-libp2p/compare/mdns-v11.0.46...mdns-v11.0.47) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [11.0.46](https://github.com/libp2p/js-libp2p/compare/mdns-v11.0.45...mdns-v11.0.46) (2025-07-08) diff --git a/packages/peer-discovery-mdns/package.json b/packages/peer-discovery-mdns/package.json index a40062cd5a..0749226a8a 100644 --- a/packages/peer-discovery-mdns/package.json +++ b/packages/peer-discovery-mdns/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/mdns", - "version": "11.0.46", + "version": "11.0.47", "description": "Node.js libp2p mDNS discovery implementation for peer discovery", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/peer-discovery-mdns#readme", @@ -43,10 +43,10 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@types/multicast-dns": "^7.2.4", "dns-packet": "^5.6.1", @@ -54,9 +54,9 @@ "multicast-dns": "^7.2.5" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "p-wait-for": "^5.0.2", "sinon-ts": "^2.0.0" diff --git a/packages/peer-id/CHANGELOG.md b/packages/peer-id/CHANGELOG.md index f8d36a281e..4d3e2b5d71 100644 --- a/packages/peer-id/CHANGELOG.md +++ b/packages/peer-id/CHANGELOG.md @@ -11,6 +11,16 @@ * dependencies * @libp2p/interface bumped from ^1.0.1 to ^1.0.2 +## [5.1.9](https://github.com/libp2p/js-libp2p/compare/peer-id-v5.1.8...peer-id-v5.1.9) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + ## [5.1.8](https://github.com/libp2p/js-libp2p/compare/peer-id-v5.1.7...peer-id-v5.1.8) (2025-06-25) diff --git a/packages/peer-id/package.json b/packages/peer-id/package.json index 801ee912b7..ffac365f7b 100644 --- a/packages/peer-id/package.json +++ b/packages/peer-id/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-id", - "version": "5.1.8", + "version": "5.1.9", "description": "Implementation of @libp2p/interface-peer-id", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/peer-id#readme", @@ -47,8 +47,8 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", "multiformats": "^13.3.6", "uint8arrays": "^5.1.0" }, diff --git a/packages/peer-record/CHANGELOG.md b/packages/peer-record/CHANGELOG.md index a75d5bcdfa..192dcaba25 100644 --- a/packages/peer-record/CHANGELOG.md +++ b/packages/peer-record/CHANGELOG.md @@ -60,6 +60,18 @@ * dependencies * @libp2p/utils bumped from ^5.2.4 to ^5.2.5 +## [8.0.35](https://github.com/libp2p/js-libp2p/compare/peer-record-v8.0.34...peer-record-v8.0.35) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + ## [8.0.34](https://github.com/libp2p/js-libp2p/compare/peer-record-v8.0.33...peer-record-v8.0.34) (2025-06-25) diff --git a/packages/peer-record/package.json b/packages/peer-record/package.json index 8e38b15e6a..9207ce128f 100644 --- a/packages/peer-record/package.json +++ b/packages/peer-record/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-record", - "version": "8.0.34", + "version": "8.0.35", "description": "Used to transfer signed peer data across the network", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/peer-record#readme", @@ -48,10 +48,10 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/utils": "^6.7.1", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "multiformats": "^13.3.6", "protons-runtime": "^5.5.0", diff --git a/packages/peer-store/CHANGELOG.md b/packages/peer-store/CHANGELOG.md index dbf3ad0024..75852ad15b 100644 --- a/packages/peer-store/CHANGELOG.md +++ b/packages/peer-store/CHANGELOG.md @@ -68,6 +68,21 @@ * dependencies * @libp2p/peer-record bumped from ^7.0.8 to ^7.0.9 +## [11.2.7](https://github.com/libp2p/js-libp2p/compare/peer-store-v11.2.6...peer-store-v11.2.7) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/peer-record bumped from ^8.0.34 to ^8.0.35 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [11.2.6](https://github.com/libp2p/js-libp2p/compare/peer-store-v11.2.5...peer-store-v11.2.6) (2025-06-25) diff --git a/packages/peer-store/package.json b/packages/peer-store/package.json index 8c55f54179..cea774c853 100644 --- a/packages/peer-store/package.json +++ b/packages/peer-store/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/peer-store", - "version": "11.2.6", + "version": "11.2.7", "description": "Stores information about peers libp2p knows on the network", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/peer-store#readme", @@ -48,11 +48,11 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/peer-record": "^8.0.34", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/peer-record": "^8.0.35", "@multiformats/multiaddr": "^12.4.4", "interface-datastore": "^8.3.1", "it-all": "^3.0.8", @@ -64,7 +64,7 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "@types/sinon": "^17.0.4", "aegir": "^47.0.14", "benchmark": "^2.1.4", diff --git a/packages/pnet/CHANGELOG.md b/packages/pnet/CHANGELOG.md index 2e08fd9201..46d45b0fd5 100644 --- a/packages/pnet/CHANGELOG.md +++ b/packages/pnet/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.0.47](https://github.com/libp2p/js-libp2p/compare/pnet-v2.0.46...pnet-v2.0.47) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [2.0.46](https://github.com/libp2p/js-libp2p/compare/pnet-v2.0.45...pnet-v2.0.46) (2025-07-08) diff --git a/packages/pnet/package.json b/packages/pnet/package.json index 34ebe65e27..dbeba0d3b8 100644 --- a/packages/pnet/package.json +++ b/packages/pnet/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/pnet", - "version": "2.0.46", + "version": "2.0.47", "description": "Implementation of Connection protection management via a shared secret", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/pnet#readme", @@ -43,8 +43,8 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", "it-byte-stream": "^2.0.2", "it-map": "^3.1.3", "it-pair": "^2.0.6", @@ -55,9 +55,9 @@ "xsalsa20": "^1.2.0" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-id": "^5.1.9", "@multiformats/multiaddr": "^12.4.4", "@types/xsalsa20": "^1.1.3", "aegir": "^47.0.14", diff --git a/packages/protocol-autonat-v2/CHANGELOG.md b/packages/protocol-autonat-v2/CHANGELOG.md index 43ac6e2f50..6ce4197633 100644 --- a/packages/protocol-autonat-v2/CHANGELOG.md +++ b/packages/protocol-autonat-v2/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [1.0.1](https://github.com/libp2p/js-libp2p/compare/autonat-v2-v1.0.0...autonat-v2-v1.0.1) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## 1.0.0 (2025-06-25) diff --git a/packages/protocol-autonat-v2/package.json b/packages/protocol-autonat-v2/package.json index bdf0bf938c..e2b897bfec 100644 --- a/packages/protocol-autonat-v2/package.json +++ b/packages/protocol-autonat-v2/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/autonat-v2", - "version": "1.0.0", + "version": "1.0.1", "description": "Implementation of the AutoNAT Protocol v2", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/protocol-autonat-v2#readme", @@ -45,10 +45,10 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "any-signal": "^4.1.1", "it-protobuf-stream": "^2.0.2", @@ -58,9 +58,9 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/crypto": "^5.1.8", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-id": "^5.1.9", "aegir": "^47.0.14", "it-all": "^3.0.8", "it-length-prefixed": "^10.0.1", diff --git a/packages/protocol-autonat/CHANGELOG.md b/packages/protocol-autonat/CHANGELOG.md index b9fe350f8c..47c6dfed3a 100644 --- a/packages/protocol-autonat/CHANGELOG.md +++ b/packages/protocol-autonat/CHANGELOG.md @@ -55,6 +55,27 @@ * dependencies * @libp2p/utils bumped from ^5.2.4 to ^5.2.5 +## [2.0.38](https://github.com/libp2p/js-libp2p/compare/autonat-v2.0.37...autonat-v2.0.38) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [2.0.37](https://github.com/libp2p/js-libp2p/compare/autonat-v2.0.36...autonat-v2.0.37) (2025-06-25) diff --git a/packages/protocol-autonat/package.json b/packages/protocol-autonat/package.json index c8cadcdb6f..1eb09fcf36 100644 --- a/packages/protocol-autonat/package.json +++ b/packages/protocol-autonat/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/autonat", - "version": "2.0.37", + "version": "2.0.38", "description": "Implementation of Autonat Protocol", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/protocol-autonat#readme", @@ -45,11 +45,11 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "any-signal": "^4.1.1", "it-protobuf-stream": "^2.0.2", @@ -59,8 +59,8 @@ "uint8arraylist": "^2.4.8" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/logger": "^5.1.21", + "@libp2p/crypto": "^5.1.8", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "it-all": "^3.0.8", "it-drain": "^3.0.9", diff --git a/packages/protocol-dcutr/CHANGELOG.md b/packages/protocol-dcutr/CHANGELOG.md index 20f0306973..776e374b80 100644 --- a/packages/protocol-dcutr/CHANGELOG.md +++ b/packages/protocol-dcutr/CHANGELOG.md @@ -44,6 +44,17 @@ * dependencies * @libp2p/utils bumped from ^5.2.4 to ^5.2.5 +## [2.0.38](https://github.com/libp2p/js-libp2p/compare/dcutr-v2.0.37...dcutr-v2.0.38) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + ## [2.0.37](https://github.com/libp2p/js-libp2p/compare/dcutr-v2.0.36...dcutr-v2.0.37) (2025-07-07) diff --git a/packages/protocol-dcutr/package.json b/packages/protocol-dcutr/package.json index f7bbf55838..62aa25e43e 100644 --- a/packages/protocol-dcutr/package.json +++ b/packages/protocol-dcutr/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/dcutr", - "version": "2.0.37", + "version": "2.0.38", "description": "Implementation of the DCUtR Protocol", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/protocol-dcutr#readme", @@ -45,9 +45,9 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "delay": "^6.0.0", diff --git a/packages/protocol-echo/CHANGELOG.md b/packages/protocol-echo/CHANGELOG.md index febe8052f6..7e0cdb58d9 100644 --- a/packages/protocol-echo/CHANGELOG.md +++ b/packages/protocol-echo/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [2.1.28](https://github.com/libp2p/js-libp2p/compare/echo-v2.1.27...echo-v2.1.28) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [2.1.27](https://github.com/libp2p/js-libp2p/compare/echo-v2.1.26...echo-v2.1.27) (2025-06-25) diff --git a/packages/protocol-echo/package.json b/packages/protocol-echo/package.json index e5e497eafe..98944195e6 100644 --- a/packages/protocol-echo/package.json +++ b/packages/protocol-echo/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/echo", - "version": "2.1.27", + "version": "2.1.28", "description": "Implementation of an Echo protocol", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/protocol-echo#readme", @@ -44,14 +44,14 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", "@multiformats/multiaddr": "^12.4.4", "it-byte-stream": "^2.0.2", "it-pipe": "^3.0.1" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "it-all": "^3.0.8", "it-pair": "^2.0.6", diff --git a/packages/protocol-fetch/CHANGELOG.md b/packages/protocol-fetch/CHANGELOG.md index 80e1dcee12..997a31fd05 100644 --- a/packages/protocol-fetch/CHANGELOG.md +++ b/packages/protocol-fetch/CHANGELOG.md @@ -48,6 +48,25 @@ * devDependencies * @libp2p/peer-id-factory bumped from ^4.0.3 to ^4.0.4 +## [3.0.22](https://github.com/libp2p/js-libp2p/compare/fetch-v3.0.21...fetch-v3.0.22) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [3.0.21](https://github.com/libp2p/js-libp2p/compare/fetch-v3.0.20...fetch-v3.0.21) (2025-06-25) diff --git a/packages/protocol-fetch/package.json b/packages/protocol-fetch/package.json index eb61efc771..6285a81fc2 100644 --- a/packages/protocol-fetch/package.json +++ b/packages/protocol-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/fetch", - "version": "3.0.21", + "version": "3.0.22", "description": "Implementation of the Fetch Protocol", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/protocol-fetch#readme", @@ -45,8 +45,8 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", "it-protobuf-stream": "^2.0.2", "main-event": "^1.0.1", "protons-runtime": "^5.5.0", @@ -54,9 +54,9 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/crypto": "^5.1.8", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-id": "^5.1.9", "aegir": "^47.0.14", "it-pair": "^2.0.6", "protons": "^7.6.1", diff --git a/packages/protocol-identify/CHANGELOG.md b/packages/protocol-identify/CHANGELOG.md index 39dbef4742..405b136956 100644 --- a/packages/protocol-identify/CHANGELOG.md +++ b/packages/protocol-identify/CHANGELOG.md @@ -76,6 +76,27 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [3.0.39](https://github.com/libp2p/js-libp2p/compare/identify-v3.0.38...identify-v3.0.39) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/peer-record bumped from ^8.0.34 to ^8.0.35 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [3.0.38](https://github.com/libp2p/js-libp2p/compare/identify-v3.0.37...identify-v3.0.38) (2025-07-07) diff --git a/packages/protocol-identify/package.json b/packages/protocol-identify/package.json index 108bddfaf5..bd243c7d21 100644 --- a/packages/protocol-identify/package.json +++ b/packages/protocol-identify/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/identify", - "version": "3.0.38", + "version": "3.0.39", "description": "Implementation of the Identify Protocol", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/protocol-identify#readme", @@ -45,12 +45,12 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/peer-record": "^8.0.34", - "@libp2p/utils": "^6.7.1", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/peer-record": "^8.0.35", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "it-drain": "^3.0.9", @@ -62,7 +62,7 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "delay": "^6.0.0", "it-length-prefixed": "^10.0.1", diff --git a/packages/protocol-perf/CHANGELOG.md b/packages/protocol-perf/CHANGELOG.md index 8c349cecef..99a9ab7d0a 100644 --- a/packages/protocol-perf/CHANGELOG.md +++ b/packages/protocol-perf/CHANGELOG.md @@ -82,6 +82,24 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [4.0.47](https://github.com/libp2p/js-libp2p/compare/perf-v4.0.46...perf-v4.0.47) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [4.0.46](https://github.com/libp2p/js-libp2p/compare/perf-v4.0.45...perf-v4.0.46) (2025-07-08) diff --git a/packages/protocol-perf/package.json b/packages/protocol-perf/package.json index 64f7c6c1dc..4249403234 100644 --- a/packages/protocol-perf/package.json +++ b/packages/protocol-perf/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/perf", - "version": "4.0.46", + "version": "4.0.47", "description": "Implementation of Perf Protocol", "author": "@maschad / @marcopolo", "license": "Apache-2.0 OR MIT", @@ -45,14 +45,14 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", "@multiformats/multiaddr": "^12.4.4", "it-pushable": "^3.2.3" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "it-last": "^3.0.8", "it-pair": "^2.0.6", diff --git a/packages/protocol-ping/CHANGELOG.md b/packages/protocol-ping/CHANGELOG.md index 76072e2d64..c1d193ab35 100644 --- a/packages/protocol-ping/CHANGELOG.md +++ b/packages/protocol-ping/CHANGELOG.md @@ -50,6 +50,25 @@ * devDependencies * @libp2p/peer-id-factory bumped from ^4.0.3 to ^4.0.4 +## [2.0.37](https://github.com/libp2p/js-libp2p/compare/ping-v2.0.36...ping-v2.0.37) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [2.0.36](https://github.com/libp2p/js-libp2p/compare/ping-v2.0.35...ping-v2.0.36) (2025-06-25) diff --git a/packages/protocol-ping/package.json b/packages/protocol-ping/package.json index 860bbd2674..088aafd34b 100644 --- a/packages/protocol-ping/package.json +++ b/packages/protocol-ping/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/ping", - "version": "2.0.36", + "version": "2.0.37", "description": "Implementation of Ping Protocol", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/protocol-ping#readme", @@ -43,17 +43,17 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", "@multiformats/multiaddr": "^12.4.4", "it-byte-stream": "^2.0.2", "main-event": "^1.0.1", "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-id": "^5.1.9", "aegir": "^47.0.14", "it-pair": "^2.0.6", "p-defer": "^4.0.1", diff --git a/packages/pubsub-floodsub/CHANGELOG.md b/packages/pubsub-floodsub/CHANGELOG.md index e8dd00f2a8..735a482035 100644 --- a/packages/pubsub-floodsub/CHANGELOG.md +++ b/packages/pubsub-floodsub/CHANGELOG.md @@ -98,6 +98,22 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [10.1.46](https://github.com/libp2p/js-libp2p/compare/floodsub-v10.1.45...floodsub-v10.1.46) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/pubsub bumped from ^10.1.17 to ^10.1.18 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [10.1.45](https://github.com/libp2p/js-libp2p/compare/floodsub-v10.1.44...floodsub-v10.1.45) (2025-07-08) diff --git a/packages/pubsub-floodsub/package.json b/packages/pubsub-floodsub/package.json index b70a0d457d..5faab6f913 100644 --- a/packages/pubsub-floodsub/package.json +++ b/packages/pubsub-floodsub/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/floodsub", - "version": "10.1.45", + "version": "10.1.46", "description": "libp2p-floodsub, also known as pubsub-flood or just dumbsub, this implementation of pubsub focused on delivering an API for Publish/Subscribe, but with no CastTree Forming (it just floods the network).", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/pubsub-floodsub#readme", @@ -53,18 +53,18 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/pubsub": "^10.1.17", + "@libp2p/interface": "^2.11.0", + "@libp2p/pubsub": "^10.1.18", "protons-runtime": "^5.5.0", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/peer-id": "^5.1.9", "@multiformats/multiaddr": "^12.4.4", "@types/sinon": "^17.0.4", "aegir": "^47.0.14", diff --git a/packages/pubsub/CHANGELOG.md b/packages/pubsub/CHANGELOG.md index 23600355ac..05bd2010ac 100644 --- a/packages/pubsub/CHANGELOG.md +++ b/packages/pubsub/CHANGELOG.md @@ -75,6 +75,22 @@ * dependencies * @libp2p/utils bumped from ^5.2.4 to ^5.2.5 +## [10.1.18](https://github.com/libp2p/js-libp2p/compare/pubsub-v10.1.17...pubsub-v10.1.18) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [10.1.17](https://github.com/libp2p/js-libp2p/compare/pubsub-v10.1.16...pubsub-v10.1.17) (2025-06-25) diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index 3cd470ffbf..5d2f39dfaa 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/pubsub", - "version": "10.1.17", + "version": "10.1.18", "description": "libp2p pubsub base class", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/pubsub#readme", @@ -73,12 +73,12 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/utils": "^6.7.1", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/utils": "^6.7.2", "it-length-prefixed": "^10.0.1", "it-pipe": "^3.0.1", "it-pushable": "^3.2.3", @@ -89,7 +89,7 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "@types/sinon": "^17.0.4", "aegir": "^47.0.14", "delay": "^6.0.0", diff --git a/packages/stream-multiplexer-mplex/CHANGELOG.md b/packages/stream-multiplexer-mplex/CHANGELOG.md index e1161f7794..e4cf940e4f 100644 --- a/packages/stream-multiplexer-mplex/CHANGELOG.md +++ b/packages/stream-multiplexer-mplex/CHANGELOG.md @@ -78,6 +78,24 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [11.0.47](https://github.com/libp2p/js-libp2p/compare/mplex-v11.0.46...mplex-v11.0.47) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [11.0.46](https://github.com/libp2p/js-libp2p/compare/mplex-v11.0.45...mplex-v11.0.46) (2025-07-08) diff --git a/packages/stream-multiplexer-mplex/package.json b/packages/stream-multiplexer-mplex/package.json index 4400e48c7c..81bbd45d9b 100644 --- a/packages/stream-multiplexer-mplex/package.json +++ b/packages/stream-multiplexer-mplex/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/mplex", - "version": "11.0.46", + "version": "11.0.47", "description": "JavaScript implementation of https://github.com/libp2p/mplex", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/stream-multiplexer-mplex#readme", @@ -55,8 +55,8 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/utils": "^6.7.2", "it-pipe": "^3.0.1", "it-pushable": "^3.2.3", "it-stream-types": "^2.0.2", @@ -65,8 +65,8 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "benchmark": "^2.1.4", "cborg": "^4.2.11", diff --git a/packages/transport-circuit-relay-v2/CHANGELOG.md b/packages/transport-circuit-relay-v2/CHANGELOG.md index 7097d9ddf6..08bd7e4302 100644 --- a/packages/transport-circuit-relay-v2/CHANGELOG.md +++ b/packages/transport-circuit-relay-v2/CHANGELOG.md @@ -101,6 +101,29 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [3.2.24](https://github.com/libp2p/js-libp2p/compare/circuit-relay-v2-v3.2.23...circuit-relay-v2-v3.2.24) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/peer-collections bumped from ^6.0.34 to ^6.0.35 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/peer-record bumped from ^8.0.34 to ^8.0.35 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [3.2.23](https://github.com/libp2p/js-libp2p/compare/circuit-relay-v2-v3.2.22...circuit-relay-v2-v3.2.23) (2025-07-08) diff --git a/packages/transport-circuit-relay-v2/package.json b/packages/transport-circuit-relay-v2/package.json index a4ec64c068..7f6b59213a 100644 --- a/packages/transport-circuit-relay-v2/package.json +++ b/packages/transport-circuit-relay-v2/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/circuit-relay-v2", - "version": "3.2.23", + "version": "3.2.24", "description": "Implementation of Circuit Relay v2", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/transport-circuit-relay-v2#readme", @@ -45,13 +45,13 @@ "doc-check": "aegir doc-check" }, "dependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/peer-collections": "^6.0.34", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/peer-record": "^8.0.34", - "@libp2p/utils": "^6.7.1", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/peer-collections": "^6.0.35", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/peer-record": "^8.0.35", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "any-signal": "^4.1.1", @@ -67,8 +67,8 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "delay": "^6.0.0", "it-drain": "^3.0.9", diff --git a/packages/transport-memory/CHANGELOG.md b/packages/transport-memory/CHANGELOG.md index 0409edf281..a3628764b5 100644 --- a/packages/transport-memory/CHANGELOG.md +++ b/packages/transport-memory/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.1.14](https://github.com/libp2p/js-libp2p/compare/memory-v1.1.13...memory-v1.1.14) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [1.1.13](https://github.com/libp2p/js-libp2p/compare/memory-v1.1.12...memory-v1.1.13) (2025-07-07) diff --git a/packages/transport-memory/package.json b/packages/transport-memory/package.json index f664b207b0..1d958567bf 100644 --- a/packages/transport-memory/package.json +++ b/packages/transport-memory/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/memory", - "version": "1.1.13", + "version": "1.1.14", "description": "A memory transport for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/transport-memory#readme", @@ -44,7 +44,7 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", + "@libp2p/interface": "^2.11.0", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "@types/sinon": "^17.0.4", @@ -57,8 +57,8 @@ "uint8arraylist": "^2.4.8" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-id": "^5.1.9", "aegir": "^47.0.14", "sinon": "^20.0.0", "sinon-ts": "^2.0.0" diff --git a/packages/transport-tcp/CHANGELOG.md b/packages/transport-tcp/CHANGELOG.md index 43d06e80e5..30f0b3b376 100644 --- a/packages/transport-tcp/CHANGELOG.md +++ b/packages/transport-tcp/CHANGELOG.md @@ -89,6 +89,23 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [10.1.19](https://github.com/libp2p/js-libp2p/compare/tcp-v10.1.18...tcp-v10.1.19) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [10.1.18](https://github.com/libp2p/js-libp2p/compare/tcp-v10.1.17...tcp-v10.1.18) (2025-07-07) diff --git a/packages/transport-tcp/package.json b/packages/transport-tcp/package.json index da799c4fa8..ae935b480b 100644 --- a/packages/transport-tcp/package.json +++ b/packages/transport-tcp/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/tcp", - "version": "10.1.18", + "version": "10.1.19", "description": "A TCP transport for libp2p", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/transport-tcp#readme", @@ -53,8 +53,8 @@ "test:electron-main": "aegir test -t electron-main" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "@types/sinon": "^17.0.4", @@ -66,7 +66,7 @@ "stream-to-it": "^1.0.1" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "p-wait-for": "^5.0.2", "sinon": "^20.0.0", diff --git a/packages/transport-webrtc/CHANGELOG.md b/packages/transport-webrtc/CHANGELOG.md index 94d3a73cea..a6043e7065 100644 --- a/packages/transport-webrtc/CHANGELOG.md +++ b/packages/transport-webrtc/CHANGELOG.md @@ -111,6 +111,28 @@ * @libp2p/websockets bumped from ^8.0.14 to ^8.0.15 * libp2p bumped from ^1.2.2 to ^1.2.3 +## [5.2.24](https://github.com/libp2p/js-libp2p/compare/webrtc-v5.2.23...webrtc-v5.2.24) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/keychain bumped from ^5.2.8 to ^5.2.9 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/interface-compliance-tests bumped from ^6.4.16 to ^6.5.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [5.2.23](https://github.com/libp2p/js-libp2p/compare/webrtc-v5.2.22...webrtc-v5.2.23) (2025-07-08) diff --git a/packages/transport-webrtc/package.json b/packages/transport-webrtc/package.json index 007a317c74..6e93e2c2ff 100644 --- a/packages/transport-webrtc/package.json +++ b/packages/transport-webrtc/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/webrtc", - "version": "5.2.23", + "version": "5.2.24", "description": "A libp2p transport using WebRTC connections", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/transport-webrtc#readme", @@ -47,12 +47,12 @@ "@chainsafe/is-ip": "^2.1.0", "@chainsafe/libp2p-noise": "^16.1.3", "@ipshipyard/node-datachannel": "^0.26.6", - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/keychain": "^5.2.8", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/utils": "^6.7.1", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/keychain": "^5.2.9", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "@peculiar/webcrypto": "^1.5.0", @@ -80,8 +80,8 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.4.16", - "@libp2p/logger": "^5.1.21", + "@libp2p/interface-compliance-tests": "^6.5.0", + "@libp2p/logger": "^5.2.0", "@types/sinon": "^17.0.4", "aegir": "^47.0.14", "datastore-core": "^10.0.2", diff --git a/packages/transport-websockets/CHANGELOG.md b/packages/transport-websockets/CHANGELOG.md index 038d77b2b1..1564dd937f 100644 --- a/packages/transport-websockets/CHANGELOG.md +++ b/packages/transport-websockets/CHANGELOG.md @@ -70,6 +70,23 @@ * devDependencies * @libp2p/interface-compliance-tests bumped from ^5.3.0 to ^5.3.1 +## [9.2.19](https://github.com/libp2p/js-libp2p/compare/websockets-v9.2.18...websockets-v9.2.19) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + ## [9.2.18](https://github.com/libp2p/js-libp2p/compare/websockets-v9.2.17...websockets-v9.2.18) (2025-07-07) diff --git a/packages/transport-websockets/package.json b/packages/transport-websockets/package.json index 8f572c3d6b..15de32bc29 100644 --- a/packages/transport-websockets/package.json +++ b/packages/transport-websockets/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/websockets", - "version": "9.2.18", + "version": "9.2.19", "description": "JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport spec", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/transport-websockets#readme", @@ -67,8 +67,8 @@ "test:electron-main": "aegir test -t electron-main -f ./dist/test/node.js --cov" }, "dependencies": { - "@libp2p/interface": "^2.10.5", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "@multiformats/multiaddr-to-uri": "^11.0.0", @@ -82,7 +82,7 @@ "ws": "^8.18.2" }, "devDependencies": { - "@libp2p/logger": "^5.1.21", + "@libp2p/logger": "^5.2.0", "aegir": "^47.0.14", "is-loopback-addr": "^2.0.2", "p-wait-for": "^5.0.2", diff --git a/packages/transport-webtransport/CHANGELOG.md b/packages/transport-webtransport/CHANGELOG.md index 1d24c4b59a..7fc087d1c2 100644 --- a/packages/transport-webtransport/CHANGELOG.md +++ b/packages/transport-webtransport/CHANGELOG.md @@ -96,6 +96,27 @@ * devDependencies * libp2p bumped from ^1.2.2 to ^1.2.3 +## [5.0.51](https://github.com/libp2p/js-libp2p/compare/webtransport-v5.0.50...webtransport-v5.0.51) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/ping bumped from ^2.0.36 to ^2.0.37 + * libp2p bumped from ^2.9.0 to ^2.10.0 + ## [5.0.50](https://github.com/libp2p/js-libp2p/compare/webtransport-v5.0.49...webtransport-v5.0.50) (2025-07-08) diff --git a/packages/transport-webtransport/package.json b/packages/transport-webtransport/package.json index 1c381da838..4ed80662ce 100644 --- a/packages/transport-webtransport/package.json +++ b/packages/transport-webtransport/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/webtransport", - "version": "5.0.50", + "version": "5.0.51", "description": "JavaScript implementation of the WebTransport module that libp2p uses and that implements the interface-transport spec", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/transport-webtransport#readme", @@ -44,9 +44,9 @@ }, "dependencies": { "@chainsafe/libp2p-noise": "^16.1.3", - "@libp2p/interface": "^2.10.5", - "@libp2p/peer-id": "^5.1.8", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/peer-id": "^5.1.9", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "it-stream-types": "^2.0.2", @@ -57,17 +57,17 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", + "@libp2p/crypto": "^5.1.8", "@libp2p/daemon-client": "^9.0.6", - "@libp2p/logger": "^5.1.21", - "@libp2p/ping": "^2.0.36", + "@libp2p/logger": "^5.2.0", + "@libp2p/ping": "^2.0.37", "@noble/hashes": "^1.8.0", "aegir": "^47.0.14", "execa": "^9.5.3", "go-libp2p": "^1.6.0", "it-map": "^3.1.3", "it-to-buffer": "^4.0.9", - "libp2p": "^2.9.0", + "libp2p": "^2.10.0", "p-defer": "^4.0.1", "p-wait-for": "^5.0.2", "sinon-ts": "^2.0.0" diff --git a/packages/upnp-nat/CHANGELOG.md b/packages/upnp-nat/CHANGELOG.md index ed8e0af8ea..493f6cd88b 100644 --- a/packages/upnp-nat/CHANGELOG.md +++ b/packages/upnp-nat/CHANGELOG.md @@ -64,6 +64,21 @@ * dependencies * @libp2p/utils bumped from ^5.2.4 to ^5.2.5 +## [3.1.22](https://github.com/libp2p/js-libp2p/compare/upnp-nat-v3.1.21...upnp-nat-v3.1.22) (2025-08-19) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/interface-internal bumped from ^2.3.18 to ^2.3.19 + * @libp2p/utils bumped from ^6.7.1 to ^6.7.2 + * devDependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [3.1.21](https://github.com/libp2p/js-libp2p/compare/upnp-nat-v3.1.20...upnp-nat-v3.1.21) (2025-07-07) diff --git a/packages/upnp-nat/package.json b/packages/upnp-nat/package.json index 9e11d49d77..24b54e2f0c 100644 --- a/packages/upnp-nat/package.json +++ b/packages/upnp-nat/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/upnp-nat", - "version": "3.1.21", + "version": "3.1.22", "description": "UPnP NAT hole punching", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/upnp-nat#readme", @@ -49,9 +49,9 @@ "dependencies": { "@achingbrain/nat-port-mapper": "^4.0.2", "@chainsafe/is-ip": "^2.1.0", - "@libp2p/interface": "^2.10.5", - "@libp2p/interface-internal": "^2.3.18", - "@libp2p/utils": "^6.7.1", + "@libp2p/interface": "^2.11.0", + "@libp2p/interface-internal": "^2.3.19", + "@libp2p/utils": "^6.7.2", "@multiformats/multiaddr": "^12.4.4", "@multiformats/multiaddr-matcher": "^2.0.0", "main-event": "^1.0.1", @@ -59,9 +59,9 @@ "race-signal": "^1.1.3" }, "devDependencies": { - "@libp2p/crypto": "^5.1.7", - "@libp2p/logger": "^5.1.21", - "@libp2p/peer-id": "^5.1.8", + "@libp2p/crypto": "^5.1.8", + "@libp2p/logger": "^5.2.0", + "@libp2p/peer-id": "^5.1.9", "aegir": "^47.0.14", "sinon-ts": "^2.0.0", "wherearewe": "^2.0.1" diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index a921e83342..1ff5026773 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -36,6 +36,25 @@ * @libp2p/logger bumped from ^4.0.2 to ^4.0.3 * @libp2p/peer-id-factory bumped from ^4.0.1 to ^4.0.2 +## [6.7.2](https://github.com/libp2p/js-libp2p/compare/utils-v6.7.1...utils-v6.7.2) (2025-08-19) + + +### Bug Fixes + +* scope logging to connection and stream ([#3215](https://github.com/libp2p/js-libp2p/issues/3215)) ([ce6b542](https://github.com/libp2p/js-libp2p/commit/ce6b542a8ea3d42e2238f910cf2a113370515058)) +* use failure event instead of error ([#3219](https://github.com/libp2p/js-libp2p/issues/3219)) ([4420fad](https://github.com/libp2p/js-libp2p/commit/4420fad686921f887854e1b37ecd01f65b276e0d)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @libp2p/crypto bumped from ^5.1.7 to ^5.1.8 + * @libp2p/interface bumped from ^2.10.5 to ^2.11.0 + * @libp2p/logger bumped from ^5.1.21 to ^5.2.0 + * devDependencies + * @libp2p/peer-id bumped from ^5.1.8 to ^5.1.9 + ## [6.7.1](https://github.com/libp2p/js-libp2p/compare/utils-v6.7.0...utils-v6.7.1) (2025-06-25) diff --git a/packages/utils/package.json b/packages/utils/package.json index c7a9ae9eed..4cd5c6f191 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@libp2p/utils", - "version": "6.7.1", + "version": "6.7.2", "description": "Package to aggregate shared logic and dependencies for the libp2p ecosystem", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/utils#readme", @@ -191,9 +191,9 @@ "dependencies": { "@chainsafe/is-ip": "^2.1.0", "@chainsafe/netmask": "^2.0.0", - "@libp2p/crypto": "^5.1.7", - "@libp2p/interface": "^2.10.5", - "@libp2p/logger": "^5.1.21", + "@libp2p/crypto": "^5.1.8", + "@libp2p/interface": "^2.11.0", + "@libp2p/logger": "^5.2.0", "@multiformats/multiaddr": "^12.4.4", "@sindresorhus/fnv1a": "^3.1.0", "any-signal": "^4.1.1", @@ -214,7 +214,7 @@ "uint8arrays": "^5.1.0" }, "devDependencies": { - "@libp2p/peer-id": "^5.1.8", + "@libp2p/peer-id": "^5.1.9", "@types/netmask": "^2.0.5", "aegir": "^47.0.14", "benchmark": "^2.1.4",