From e9099d405b205b741fcd0958569bfb06d6211e65 Mon Sep 17 00:00:00 2001 From: Chad Nehemiah Date: Thu, 5 Oct 2023 18:34:21 -0500 Subject: [PATCH] feat: configuration validation (#1778) Co-authored-by: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> --- packages/libp2p/.aegir.js | 6 +- packages/libp2p/package.json | 3 +- packages/libp2p/src/address-manager/utils.ts | 14 ++++ packages/libp2p/src/autonat/index.ts | 22 ++++-- .../libp2p/src/circuit-relay/constants.ts | 5 ++ .../libp2p/src/circuit-relay/server/index.ts | 32 ++++++-- .../circuit-relay/server/reservation-store.ts | 22 ++++-- .../src/circuit-relay/transport/index.ts | 30 ++++---- packages/libp2p/src/config.ts | 41 ---------- packages/libp2p/src/config/config.ts | 44 +++++++++++ packages/libp2p/src/config/helpers.ts | 12 +++ .../libp2p/src/connection-manager/utils.ts | 23 ++++++ packages/libp2p/src/dcutr/dcutr.ts | 27 +++---- packages/libp2p/src/fetch/constants.ts | 4 + packages/libp2p/src/fetch/index.ts | 31 +++++--- packages/libp2p/src/identify/consts.ts | 13 ++++ packages/libp2p/src/identify/identify.ts | 75 +++++++++++-------- packages/libp2p/src/identify/index.ts | 5 +- packages/libp2p/src/libp2p.ts | 2 +- packages/libp2p/src/ping/index.ts | 20 +++-- packages/libp2p/src/upnp-nat/index.ts | 28 +++++-- .../test/circuit-relay/discovery.node.ts | 2 + .../configuration/protocol-prefix.node.ts | 3 +- .../test/connection-manager/index.node.ts | 4 +- .../test/connection-manager/index.spec.ts | 20 +++-- .../test/connection-manager/resolver.spec.ts | 4 +- packages/libp2p/test/ping/ping.node.ts | 5 ++ packages/transport-webrtc/.aegir.js | 3 +- 28 files changed, 338 insertions(+), 162 deletions(-) delete mode 100644 packages/libp2p/src/config.ts create mode 100644 packages/libp2p/src/config/config.ts create mode 100644 packages/libp2p/src/config/helpers.ts diff --git a/packages/libp2p/.aegir.js b/packages/libp2p/.aegir.js index a0d8cbc706..36fea1dd21 100644 --- a/packages/libp2p/.aegir.js +++ b/packages/libp2p/.aegir.js @@ -24,7 +24,9 @@ export default { const peerId = await createEd25519PeerId() const libp2p = await createLibp2p({ connectionManager: { - inboundConnectionThreshold: Infinity, + inboundConnectionThreshold: 1000, + maxIncomingPendingConnections: 1000, + maxConnections: 1000, minConnections: 0 }, addresses: { @@ -51,7 +53,7 @@ export default { fetch: fetchService(), relay: circuitRelayServer({ reservations: { - maxReservations: Infinity + maxReservations: 100000 } }) } diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 10b4827403..3b5b1879da 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -164,7 +164,8 @@ "uint8arraylist": "^2.4.3", "uint8arrays": "^4.0.6", "wherearewe": "^2.0.1", - "xsalsa20": "^1.1.0" + "xsalsa20": "^1.1.0", + "yup": "^1.2.0" }, "devDependencies": { "@chainsafe/libp2p-gossipsub": "^10.0.0", diff --git a/packages/libp2p/src/address-manager/utils.ts b/packages/libp2p/src/address-manager/utils.ts index 7062446a86..c0b53ec010 100644 --- a/packages/libp2p/src/address-manager/utils.ts +++ b/packages/libp2p/src/address-manager/utils.ts @@ -1,3 +1,8 @@ +import { type ObjectSchema, object, array, string, mixed } from 'yup' +import { validateMultiaddr } from '../config/helpers.js' +import type { AddressManagerInit } from '.' +import type { Multiaddr } from '@multiformats/multiaddr' + export function debounce (func: () => void, wait: number): () => void { let timeout: ReturnType | undefined @@ -11,3 +16,12 @@ export function debounce (func: () => void, wait: number): () => void { timeout = setTimeout(later, wait) } } + +export function validateAddressManagerConfig (opts: AddressManagerInit): ObjectSchema> { + return object({ + listen: array().of(string()).test('is multiaddr', validateMultiaddr).default([]), + announce: array().of(string()).test('is multiaddr', validateMultiaddr).default([]), + noAnnounce: array().of(string()).test('is multiaddr', validateMultiaddr).default([]), + announceFilter: mixed().default(() => (addrs: Multiaddr[]): Multiaddr[] => addrs) + }) +} diff --git a/packages/libp2p/src/autonat/index.ts b/packages/libp2p/src/autonat/index.ts index 3f70e6a850..319493d39b 100644 --- a/packages/libp2p/src/autonat/index.ts +++ b/packages/libp2p/src/autonat/index.ts @@ -31,6 +31,7 @@ import map from 'it-map' import parallel from 'it-parallel' import { pipe } from 'it-pipe' import isPrivateIp from 'private-ip' +import { number, object, string } from 'yup' import { codes } from '../errors.js' import { MAX_INBOUND_STREAMS, @@ -108,14 +109,23 @@ class DefaultAutoNATService implements Startable { private started: boolean constructor (components: AutoNATComponents, init: AutoNATServiceInit) { + const validatedConfig = object({ + protocolPrefix: string().default(PROTOCOL_PREFIX), + timeout: number().integer().default(TIMEOUT), + startupDelay: number().integer().default(STARTUP_DELAY), + refreshInterval: number().integer().default(REFRESH_INTERVAL), + maxInboundStreams: number().integer().default(MAX_INBOUND_STREAMS), + maxOutboundStreams: number().integer().default(MAX_OUTBOUND_STREAMS) + }).validateSync(init) + this.components = components this.started = false - this.protocol = `/${init.protocolPrefix ?? PROTOCOL_PREFIX}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` - this.timeout = init.timeout ?? TIMEOUT - this.maxInboundStreams = init.maxInboundStreams ?? MAX_INBOUND_STREAMS - this.maxOutboundStreams = init.maxOutboundStreams ?? MAX_OUTBOUND_STREAMS - this.startupDelay = init.startupDelay ?? STARTUP_DELAY - this.refreshInterval = init.refreshInterval ?? REFRESH_INTERVAL + this.protocol = `/${validatedConfig.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` + this.timeout = validatedConfig.timeout + this.maxInboundStreams = validatedConfig.maxInboundStreams + this.maxOutboundStreams = validatedConfig.maxOutboundStreams + this.startupDelay = validatedConfig.startupDelay + this.refreshInterval = validatedConfig.refreshInterval this._verifyExternalAddresses = this._verifyExternalAddresses.bind(this) } diff --git a/packages/libp2p/src/circuit-relay/constants.ts b/packages/libp2p/src/circuit-relay/constants.ts index d35f45881a..7907ed5817 100644 --- a/packages/libp2p/src/circuit-relay/constants.ts +++ b/packages/libp2p/src/circuit-relay/constants.ts @@ -70,3 +70,8 @@ export const DEFAULT_HOP_TIMEOUT = 30 * second * How long to wait before starting to advertise the relay service */ export const DEFAULT_ADVERT_BOOT_DELAY = 30 * second + +/** + * The default timeout for Incoming STOP requests from the relay + */ +export const DEFAULT_STOP_TIMEOUT = 30 * second diff --git a/packages/libp2p/src/circuit-relay/server/index.ts b/packages/libp2p/src/circuit-relay/server/index.ts index aed3d5be8b..758db09e4d 100644 --- a/packages/libp2p/src/circuit-relay/server/index.ts +++ b/packages/libp2p/src/circuit-relay/server/index.ts @@ -6,10 +6,16 @@ import { RecordEnvelope } from '@libp2p/peer-record' import { type Multiaddr, multiaddr } from '@multiformats/multiaddr' import { pbStream, type ProtobufStream } from 'it-protobuf-stream' import pDefer from 'p-defer' +import { object, number, boolean } from 'yup' import { MAX_CONNECTIONS } from '../../connection-manager/constants.js' +import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from '../../registrar.js' import { CIRCUIT_PROTO_CODE, + DEFAULT_DURATION_LIMIT, DEFAULT_HOP_TIMEOUT, + DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL, + DEFAULT_MAX_RESERVATION_STORE_SIZE, + DEFAULT_MAX_RESERVATION_TTL, RELAY_SOURCE_TAG, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC @@ -95,10 +101,6 @@ export interface RelayServerEvents { 'relay:advert:error': CustomEvent } -const defaults = { - maxOutboundStopStreams: MAX_CONNECTIONS -} - class CircuitRelayServer extends EventEmitter implements Startable, CircuitRelayService { private readonly registrar: Registrar private readonly peerStore: PeerStore @@ -121,6 +123,20 @@ class CircuitRelayServer extends EventEmitter implements Star constructor (components: CircuitRelayServerComponents, init: CircuitRelayServerInit = {}) { super() + const validatedConfig = object({ + hopTimeout: number().min(0).integer().default(DEFAULT_HOP_TIMEOUT), + reservations: object({ + maxReservations: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_STORE_SIZE), + reservationClearInterval: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL), + applyDefaultLimit: boolean().default(true), + reservationTtl: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_TTL), + defaultDurationLimit: number().integer().min(0).default(DEFAULT_DURATION_LIMIT).max(init?.reservations?.reservationTtl ?? DEFAULT_MAX_RESERVATION_TTL, `default duration limit must be less than reservation TTL: ${init?.reservations?.reservationTtl}`) + }), + maxInboundHopStreams: number().integer().min(0).default(DEFAULT_MAX_INBOUND_STREAMS), + maxOutboundHopStreams: number().integer().min(0).default(DEFAULT_MAX_OUTBOUND_STREAMS), + maxOutboundStopStreams: number().integer().min(0).default(MAX_CONNECTIONS) + }).validateSync(init) + this.registrar = components.registrar this.peerStore = components.peerStore this.addressManager = components.addressManager @@ -128,11 +144,11 @@ class CircuitRelayServer extends EventEmitter implements Star this.connectionManager = components.connectionManager this.connectionGater = components.connectionGater this.started = false - this.hopTimeout = init?.hopTimeout ?? DEFAULT_HOP_TIMEOUT + this.hopTimeout = validatedConfig.hopTimeout this.shutdownController = new AbortController() - this.maxInboundHopStreams = init.maxInboundHopStreams - this.maxOutboundHopStreams = init.maxOutboundHopStreams - this.maxOutboundStopStreams = init.maxOutboundStopStreams ?? defaults.maxOutboundStopStreams + this.maxInboundHopStreams = validatedConfig.maxInboundHopStreams + this.maxOutboundHopStreams = validatedConfig.maxOutboundHopStreams + this.maxOutboundStopStreams = validatedConfig.maxOutboundStopStreams try { // fails on node < 15.4 diff --git a/packages/libp2p/src/circuit-relay/server/reservation-store.ts b/packages/libp2p/src/circuit-relay/server/reservation-store.ts index 0f5d3bf62e..36a747c99c 100644 --- a/packages/libp2p/src/circuit-relay/server/reservation-store.ts +++ b/packages/libp2p/src/circuit-relay/server/reservation-store.ts @@ -1,4 +1,5 @@ import { PeerMap } from '@libp2p/peer-collections' +import { object, mixed, number, boolean } from 'yup' import { DEFAULT_DATA_LIMIT, DEFAULT_DURATION_LIMIT, DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL, DEFAULT_MAX_RESERVATION_STORE_SIZE, DEFAULT_MAX_RESERVATION_TTL } from '../constants.js' import { type Limit, Status } from '../pb/index.js' import type { RelayReservation } from '../index.js' @@ -50,12 +51,21 @@ export class ReservationStore implements Startable { private readonly defaultDataLimit: bigint constructor (options: ReservationStoreOptions = {}) { - this.maxReservations = options.maxReservations ?? DEFAULT_MAX_RESERVATION_STORE_SIZE - this.reservationClearInterval = options.reservationClearInterval ?? DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL - this.applyDefaultLimit = options.applyDefaultLimit !== false - this.reservationTtl = options.reservationTtl ?? DEFAULT_MAX_RESERVATION_TTL - this.defaultDurationLimit = options.defaultDurationLimit ?? DEFAULT_DURATION_LIMIT - this.defaultDataLimit = options.defaultDataLimit ?? DEFAULT_DATA_LIMIT + const validatedConfig = object({ + maxReservations: number().min(0).integer().default(DEFAULT_MAX_RESERVATION_STORE_SIZE), + reservationClearInterval: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL), + applyDefaultLimit: boolean().default(true), + reservationTtl: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_TTL), + defaultDurationLimit: number().integer().min(0).default(DEFAULT_DURATION_LIMIT), + defaultDataLimit: mixed().test('is-bigint', 'Invalid bigint', value => typeof value === 'bigint').default(DEFAULT_DATA_LIMIT) + }).validateSync(options) + + this.maxReservations = validatedConfig.maxReservations + this.reservationClearInterval = validatedConfig.reservationClearInterval + this.applyDefaultLimit = validatedConfig.applyDefaultLimit + this.reservationTtl = validatedConfig.reservationTtl + this.defaultDurationLimit = validatedConfig.defaultDurationLimit + this.defaultDataLimit = validatedConfig.defaultDataLimit as bigint } isStarted (): boolean { diff --git a/packages/libp2p/src/circuit-relay/transport/index.ts b/packages/libp2p/src/circuit-relay/transport/index.ts index 483f9a0366..6125c55b20 100644 --- a/packages/libp2p/src/circuit-relay/transport/index.ts +++ b/packages/libp2p/src/circuit-relay/transport/index.ts @@ -6,9 +6,10 @@ import { streamToMaConnection } from '@libp2p/utils/stream-to-ma-conn' import * as mafmt from '@multiformats/mafmt' import { multiaddr } from '@multiformats/multiaddr' import { pbStream } from 'it-protobuf-stream' +import { number, object } from 'yup' import { MAX_CONNECTIONS } from '../../connection-manager/constants.js' import { codes } from '../../errors.js' -import { CIRCUIT_PROTO_CODE, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC } from '../constants.js' +import { CIRCUIT_PROTO_CODE, DEFAULT_STOP_TIMEOUT, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC } from '../constants.js' import { StopMessage, HopMessage, Status } from '../pb/index.js' import { RelayDiscovery, type RelayDiscoveryComponents } from './discovery.js' import { createListener } from './listener.js' @@ -100,12 +101,6 @@ export interface CircuitRelayTransportInit extends RelayStoreInit { reservationCompletionTimeout?: number } -const defaults = { - maxInboundStopStreams: MAX_CONNECTIONS, - maxOutboundStopStreams: MAX_CONNECTIONS, - stopTimeout: 30000 -} - class CircuitRelayTransport implements Transport { private readonly discovery?: RelayDiscovery private readonly registrar: Registrar @@ -116,12 +111,19 @@ class CircuitRelayTransport implements Transport { private readonly addressManager: AddressManager private readonly connectionGater: ConnectionGater private readonly reservationStore: ReservationStore - private readonly maxInboundStopStreams: number + private readonly maxInboundStopStreams?: number private readonly maxOutboundStopStreams?: number - private readonly stopTimeout: number + private readonly stopTimeout?: number private started: boolean constructor (components: CircuitRelayTransportComponents, init: CircuitRelayTransportInit) { + const validatedConfig = object({ + discoverRelays: number().min(0).integer().default(0), + maxInboundStopStreams: number().min(0).integer().default(MAX_CONNECTIONS), + maxOutboundStopStreams: number().min(0).integer().default(MAX_CONNECTIONS), + stopTimeout: number().min(0).integer().default(DEFAULT_STOP_TIMEOUT) + }).validateSync(init) + this.registrar = components.registrar this.peerStore = components.peerStore this.connectionManager = components.connectionManager @@ -129,11 +131,11 @@ class CircuitRelayTransport implements Transport { this.upgrader = components.upgrader this.addressManager = components.addressManager this.connectionGater = components.connectionGater - this.maxInboundStopStreams = init.maxInboundStopStreams ?? defaults.maxInboundStopStreams - this.maxOutboundStopStreams = init.maxOutboundStopStreams ?? defaults.maxOutboundStopStreams - this.stopTimeout = init.stopTimeout ?? defaults.stopTimeout + this.maxInboundStopStreams = validatedConfig.maxInboundStopStreams + this.maxOutboundStopStreams = validatedConfig.maxOutboundStopStreams + this.stopTimeout = validatedConfig.stopTimeout - if (init.discoverRelays != null && init.discoverRelays > 0) { + if (validatedConfig.discoverRelays > 0) { this.discovery = new RelayDiscovery(components) this.discovery.addEventListener('relay:discover', (evt) => { this.reservationStore.addRelay(evt.detail, 'discovered') @@ -321,7 +323,7 @@ class CircuitRelayTransport implements Transport { * An incoming STOP request means a remote peer wants to dial us via a relay */ async onStop ({ connection, stream }: IncomingStreamData): Promise { - const signal = AbortSignal.timeout(this.stopTimeout) + const signal = AbortSignal.timeout(this.stopTimeout ?? DEFAULT_STOP_TIMEOUT) const pbstr = pbStream(stream).pb(StopMessage) const request = await pbstr.read({ signal diff --git a/packages/libp2p/src/config.ts b/packages/libp2p/src/config.ts deleted file mode 100644 index a9b83fb532..0000000000 --- a/packages/libp2p/src/config.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { CodeError } from '@libp2p/interface/errors' -import { FaultTolerance } from '@libp2p/interface/transport' -import { defaultAddressSort } from '@libp2p/utils/address-sort' -import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers' -import mergeOptions from 'merge-options' -import { codes, messages } from './errors.js' -import type { Libp2pInit } from './index.js' -import type { ServiceMap, RecursivePartial } from '@libp2p/interface' -import type { Multiaddr } from '@multiformats/multiaddr' - -const DefaultConfig: Partial = { - addresses: { - listen: [], - announce: [], - noAnnounce: [], - announceFilter: (multiaddrs: Multiaddr[]) => multiaddrs - }, - connectionManager: { - resolvers: { - dnsaddr: dnsaddrResolver - }, - addressSorter: defaultAddressSort - }, - transportManager: { - faultTolerance: FaultTolerance.FATAL_ALL - } -} - -export function validateConfig > (opts: RecursivePartial>): Libp2pInit { - const resultingOptions: Libp2pInit = mergeOptions(DefaultConfig, opts) - - if (resultingOptions.transports == null || resultingOptions.transports.length < 1) { - throw new CodeError(messages.ERR_TRANSPORTS_REQUIRED, codes.ERR_TRANSPORTS_REQUIRED) - } - - if (resultingOptions.connectionProtector === null && globalThis.process?.env?.LIBP2P_FORCE_PNET != null) { // eslint-disable-line no-undef - throw new CodeError(messages.ERR_PROTECTOR_REQUIRED, codes.ERR_PROTECTOR_REQUIRED) - } - - return resultingOptions -} diff --git a/packages/libp2p/src/config/config.ts b/packages/libp2p/src/config/config.ts new file mode 100644 index 0000000000..fb928825eb --- /dev/null +++ b/packages/libp2p/src/config/config.ts @@ -0,0 +1,44 @@ +import { FaultTolerance } from '@libp2p/interface/transport' +import { publicAddressesFirst } from '@libp2p/utils/address-sort' +import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers' +import mergeOptions from 'merge-options' +import { object } from 'yup' +import { validateAddressManagerConfig } from '../address-manager/utils.js' +import { validateConnectionManagerConfig } from '../connection-manager/utils.js' +import type { AddressManagerInit } from '../address-manager' +import type { ConnectionManagerInit } from '../connection-manager/index.js' +import type { Libp2pInit } from '../index.js' +import type { ServiceMap, RecursivePartial } from '@libp2p/interface' + +const DefaultConfig: Partial = { + connectionManager: { + resolvers: { + dnsaddr: dnsaddrResolver + }, + addressSorter: publicAddressesFirst + }, + transportManager: { + faultTolerance: FaultTolerance.FATAL_ALL + } +} + +export function validateConfig > (opts: RecursivePartial>): Libp2pInit { + const libp2pConfig = object({ + addresses: validateAddressManagerConfig(opts?.addresses as AddressManagerInit), + connectionManager: validateConnectionManagerConfig(opts?.connectionManager as ConnectionManagerInit) + }) + + if ((opts?.services) != null) { + // @ts-expect-error until we resolve https://github.com/libp2p/js-libp2p/pull/1762 and have a better way of discovering type dependencies + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + if ((opts.services?.kadDHT || opts.services?.relay || opts.services?.ping) && !opts.services.identify) { + throw new Error('identify service is required when using kadDHT, relay, or ping') + } + } + + const parsedOpts = libp2pConfig.validateSync(opts) + + const resultingOptions: Libp2pInit = mergeOptions(DefaultConfig, parsedOpts) + + return resultingOptions +} diff --git a/packages/libp2p/src/config/helpers.ts b/packages/libp2p/src/config/helpers.ts new file mode 100644 index 0000000000..9cb4106ae8 --- /dev/null +++ b/packages/libp2p/src/config/helpers.ts @@ -0,0 +1,12 @@ +import { multiaddr } from '@multiformats/multiaddr' + +export const validateMultiaddr = (value: Array | undefined): boolean => { + value?.forEach((addr) => { + try { + multiaddr(addr) + } catch (err) { + throw new Error(`invalid multiaddr: ${addr}`) + } + }) + return true +} diff --git a/packages/libp2p/src/connection-manager/utils.ts b/packages/libp2p/src/connection-manager/utils.ts index e195e48bf6..760461beab 100644 --- a/packages/libp2p/src/connection-manager/utils.ts +++ b/packages/libp2p/src/connection-manager/utils.ts @@ -2,6 +2,10 @@ import { setMaxListeners } from 'events' import { logger } from '@libp2p/logger' import { type AbortOptions, multiaddr, type Multiaddr } from '@multiformats/multiaddr' import { type ClearableSignal, anySignal } from 'any-signal' +import { type ObjectSchema, array, number, object, string } from 'yup' +import { validateMultiaddr } from '../config/helpers.js' +import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_INTERVAL, AUTO_DIAL_PRIORITY, DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, INBOUND_UPGRADE_TIMEOUT, MAX_CONNECTIONS, MAX_INCOMING_PENDING_CONNECTIONS, MAX_PARALLEL_DIALS, MAX_PARALLEL_DIALS_PER_PEER, MAX_PEER_ADDRS_TO_DIAL, MIN_CONNECTIONS } from './constants.js' +import type { ConnectionManagerInit } from '.' const log = logger('libp2p:connection-manager:utils') @@ -73,3 +77,22 @@ export function combineSignals (...signals: Array): Cle return signal } + +export const validateConnectionManagerConfig = (opts: ConnectionManagerInit): ObjectSchema> => { + return object({ + maxConnections: number().min(opts?.minConnections ?? MIN_CONNECTIONS, `maxConnections must be greater than the min connections limit: ${opts?.minConnections}`).integer().default(MAX_CONNECTIONS), + minConnections: number().min(0).integer().max(opts?.maxConnections ?? MAX_CONNECTIONS, `minConnections must be less than the max connections limit: ${opts?.maxConnections}`).default(MIN_CONNECTIONS), + autoDialInterval: number().min(0).integer().default(AUTO_DIAL_INTERVAL), + autoDialConcurrency: number().min(0).integer().default(AUTO_DIAL_CONCURRENCY), + autoDialPriority: number().min(0).integer().default(AUTO_DIAL_PRIORITY), + maxParallelDials: number().min(0).integer().default(MAX_PARALLEL_DIALS), + maxParallelDialsPerPeer: number().max(opts?.autoDialConcurrency ?? AUTO_DIAL_CONCURRENCY, `maxParallelDialsPerPeer must be less than the min auto dial conccurency limit: ${opts?.autoDialConcurrency}`).default(MAX_PARALLEL_DIALS_PER_PEER), + maxPeerAddrsToDialed: number().min(0).integer().default(MAX_PEER_ADDRS_TO_DIAL), + dialTimeout: number().min(0).integer().default(DIAL_TIMEOUT), + inboundUpgradeTimeout: number().integer().default(INBOUND_UPGRADE_TIMEOUT), + allow: array().of(string()).test('is multiaddr', validateMultiaddr).optional(), + deny: array().of(string()).test('is multiaddr', validateMultiaddr).optional(), + inboundConnectionThreshold: number().max(opts?.maxConnections ?? MAX_CONNECTIONS, `inboundConnectionThreshold must be less than the max connections limit: ${opts?.inboundConnectionThreshold}`).integer().default(INBOUND_CONNECTION_THRESHOLD), + maxIncomingPendingConnections: number().integer().max(opts?.maxConnections ?? MAX_CONNECTIONS, `maxIncomingPendingConnections must be less than the max connections limit: ${opts?.maxIncomingPendingConnections}`).default(MAX_INCOMING_PENDING_CONNECTIONS) + }) +} diff --git a/packages/libp2p/src/dcutr/dcutr.ts b/packages/libp2p/src/dcutr/dcutr.ts index 190766bfa2..6639a356f1 100644 --- a/packages/libp2p/src/dcutr/dcutr.ts +++ b/packages/libp2p/src/dcutr/dcutr.ts @@ -5,6 +5,7 @@ import { Circuit, IP, DNS } from '@multiformats/multiaddr-matcher' import delay from 'delay' import { pbStream } from 'it-protobuf-stream' import isPrivate from 'private-ip' +import { number, object } from 'yup' import { codes } from '../errors.js' import { HolePunch } from './pb/message.js' import { multicodec } from './index.js' @@ -24,15 +25,6 @@ const MAX_DCUTR_MESSAGE_SIZE = 1024 * 4 // ensure the dial has a high priority to jump to the head of the dial queue const DCUTR_DIAL_PRIORITY = 100 -const defaultValues = { - // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/holepunch/holepuncher.go#L27 - timeout: 5000, - // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/holepunch/holepuncher.go#L28 - retries: 3, - maxInboundStreams: 1, - maxOutboundStreams: 1 -} - export class DefaultDCUtRService implements Startable { private started: boolean private readonly timeout: number @@ -54,10 +46,19 @@ export class DefaultDCUtRService implements Startable { this.connectionManager = components.connectionManager this.transportManager = components.transportManager - this.timeout = init.timeout ?? defaultValues.timeout - this.retries = init.retries ?? defaultValues.retries - this.maxInboundStreams = init.maxInboundStreams ?? defaultValues.maxInboundStreams - this.maxOutboundStreams = init.maxOutboundStreams ?? defaultValues.maxOutboundStreams + const validatedConfig = object({ + // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/holepunch/holepuncher.go#L27 + timeout: number().integer().default(5000).min(1), + // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/holepunch/holepuncher.go#L28 + retries: number().integer().default(3).min(1), + maxInboundStreams: number().integer().default(1).min(1), + maxOutboundStreams: number().integer().default(1).min(1) + }).validateSync(init) + + this.timeout = validatedConfig.timeout + this.retries = validatedConfig.retries + this.maxInboundStreams = validatedConfig.maxInboundStreams + this.maxOutboundStreams = validatedConfig.maxOutboundStreams } isStarted (): boolean { diff --git a/packages/libp2p/src/fetch/constants.ts b/packages/libp2p/src/fetch/constants.ts index cbab081bcd..d0be9327b2 100644 --- a/packages/libp2p/src/fetch/constants.ts +++ b/packages/libp2p/src/fetch/constants.ts @@ -1,3 +1,7 @@ // https://github.com/libp2p/specs/tree/master/fetch#wire-protocol export const PROTOCOL_VERSION = '0.0.1' export const PROTOCOL_NAME = 'fetch' + +export const MAX_INBOUND_STREAMS = 1 +export const MAX_OUTBOUND_STREAMS = 1 +export const TIMEOUT = 60000 diff --git a/packages/libp2p/src/fetch/index.ts b/packages/libp2p/src/fetch/index.ts index 604fb15f3b..378919526b 100644 --- a/packages/libp2p/src/fetch/index.ts +++ b/packages/libp2p/src/fetch/index.ts @@ -6,8 +6,9 @@ import * as lp from 'it-length-prefixed' import { pipe } from 'it-pipe' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' import { toString as uint8arrayToString } from 'uint8arrays/to-string' +import { number, object, string } from 'yup' import { codes } from '../errors.js' -import { PROTOCOL_NAME, PROTOCOL_VERSION } from './constants.js' +import { MAX_INBOUND_STREAMS, MAX_OUTBOUND_STREAMS, PROTOCOL_NAME, PROTOCOL_VERSION, TIMEOUT } from './constants.js' import { FetchRequest, FetchResponse } from './pb/proto.js' import type { AbortOptions } from '@libp2p/interface' import type { Stream } from '@libp2p/interface/connection' @@ -18,8 +19,6 @@ import type { IncomingStreamData, Registrar } from '@libp2p/interface-internal/r const log = logger('libp2p:fetch') -const DEFAULT_TIMEOUT = 10000 - export interface FetchServiceInit { protocolPrefix?: string maxInboundStreams?: number @@ -94,15 +93,27 @@ class DefaultFetchService implements Startable, FetchService { private readonly components: FetchServiceComponents private readonly lookupFunctions: Map private started: boolean - private readonly init: FetchServiceInit + private readonly timeout: number + private readonly maxInboundStreams: number + private readonly maxOutboundStreams: number constructor (components: FetchServiceComponents, init: FetchServiceInit) { + const validatedConfig = object({ + protocolPrefix: string().default('libp2p'), + timeout: number().integer().default(TIMEOUT), + maxInboundStreams: number().integer().min(0).default(MAX_INBOUND_STREAMS), + maxOutboundStreams: number().integer().min(0).default(MAX_OUTBOUND_STREAMS) + }).validateSync(init) + this.started = false this.components = components - this.protocol = `/${init.protocolPrefix ?? 'libp2p'}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` + this.protocol = `/${validatedConfig.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` + this.timeout = validatedConfig.timeout + this.maxInboundStreams = validatedConfig.maxInboundStreams + this.maxOutboundStreams = validatedConfig.maxOutboundStreams + this.lookupFunctions = new Map() // Maps key prefix to value lookup function this.handleMessage = this.handleMessage.bind(this) - this.init = init } async start (): Promise { @@ -115,8 +126,8 @@ class DefaultFetchService implements Startable, FetchService { log.error(err) }) }, { - maxInboundStreams: this.init.maxInboundStreams, - maxOutboundStreams: this.init.maxOutboundStreams + maxInboundStreams: this.maxInboundStreams, + maxOutboundStreams: this.maxOutboundStreams }) this.started = true } @@ -143,8 +154,8 @@ class DefaultFetchService implements Startable, FetchService { // create a timeout if no abort signal passed if (signal == null) { - log('using default timeout of %d ms', this.init.timeout) - signal = AbortSignal.timeout(this.init.timeout ?? DEFAULT_TIMEOUT) + log('using default timeout of %d ms', this.timeout) + signal = AbortSignal.timeout(this.timeout) try { // fails on node < 15.4 diff --git a/packages/libp2p/src/identify/consts.ts b/packages/libp2p/src/identify/consts.ts index e65f222951..ae3356018e 100644 --- a/packages/libp2p/src/identify/consts.ts +++ b/packages/libp2p/src/identify/consts.ts @@ -5,8 +5,21 @@ export const AGENT_VERSION = `js-libp2p/${version}` export const MULTICODEC_IDENTIFY = '/ipfs/id/1.0.0' // deprecated export const MULTICODEC_IDENTIFY_PUSH = '/ipfs/id/push/1.0.0' // deprecated +export const PROTOCOL_PREFIX = 'ipfs' +export const MAX_IDENTIFY_MESSAGE_SIZE = 1024 * 8 // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L52 +export const MAX_INBOUND_STREAMS = 1 +export const MAX_OUTBOUND_STREAMS = 1 +export const MAX_PUSH_INCOMING_STREAMS = 1 +export const MAX_PUSH_OUTGOING_STREAMS = 1 +export const MAX_OBSERVED_ADDRESSES = 10 + +export const RUN_ON_TRANSIENT_CONNECTION = true +export const RUN_ON_CONNECTION_OPEN = true + export const IDENTIFY_PROTOCOL_VERSION = '0.1.0' export const MULTICODEC_IDENTIFY_PROTOCOL_NAME = 'id' export const MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME = 'id/push' export const MULTICODEC_IDENTIFY_PROTOCOL_VERSION = '1.0.0' export const MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION = '1.0.0' + +export const TIMEOUT = 60000 diff --git a/packages/libp2p/src/identify/identify.ts b/packages/libp2p/src/identify/identify.ts index caa5248b45..3e992da045 100644 --- a/packages/libp2p/src/identify/identify.ts +++ b/packages/libp2p/src/identify/identify.ts @@ -8,6 +8,7 @@ import { pbStream } from 'it-protobuf-stream' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { isNode, isBrowser, isWebWorker, isElectronMain, isElectronRenderer, isReactNative } from 'wherearewe' +import { boolean, number, object, string } from 'yup' import { codes } from '../errors.js' import { AGENT_VERSION, @@ -15,7 +16,17 @@ import { MULTICODEC_IDENTIFY_PROTOCOL_NAME, MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME, MULTICODEC_IDENTIFY_PROTOCOL_VERSION, - MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION + MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION, + MAX_INBOUND_STREAMS, + MAX_OUTBOUND_STREAMS, + MAX_IDENTIFY_MESSAGE_SIZE, + TIMEOUT, + RUN_ON_CONNECTION_OPEN, + PROTOCOL_PREFIX, + RUN_ON_TRANSIENT_CONNECTION, + MAX_PUSH_INCOMING_STREAMS, + MAX_PUSH_OUTGOING_STREAMS, + MAX_OBSERVED_ADDRESSES } from './consts.js' import { Identify } from './pb/message.js' import type { IdentifyService, IdentifyServiceComponents, IdentifyServiceInit } from './index.js' @@ -31,24 +42,6 @@ import type { IncomingStreamData, Registrar } from '@libp2p/interface-internal/r const log = logger('libp2p:identify') -// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L52 -const MAX_IDENTIFY_MESSAGE_SIZE = 1024 * 8 - -const defaultValues = { - protocolPrefix: 'ipfs', - agentVersion: AGENT_VERSION, - // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48 - timeout: 60000, - maxInboundStreams: 1, - maxOutboundStreams: 1, - maxPushIncomingStreams: 1, - maxPushOutgoingStreams: 1, - maxObservedAddresses: 10, - maxIdentifyMessageSize: 8192, - runOnConnectionOpen: true, - runOnTransientConnection: true -} - export class DefaultIdentifyService implements Startable, IdentifyService { private readonly identifyProtocolStr: string private readonly identifyPushProtocolStr: string @@ -72,8 +65,23 @@ export class DefaultIdentifyService implements Startable, IdentifyService { private readonly maxObservedAddresses: number private readonly events: EventEmitter private readonly runOnTransientConnection: boolean + private readonly runOnConnectionOpen: boolean constructor (components: IdentifyServiceComponents, init: IdentifyServiceInit) { + const validatedConfig = object({ + protocolPrefix: string().default(PROTOCOL_PREFIX), + agentVersion: string().default(AGENT_VERSION), + timeout: number().integer().default(TIMEOUT), + maxIdentifyMessageSize: number().integer().min(0).default(MAX_IDENTIFY_MESSAGE_SIZE), + maxInboundStreams: number().integer().min(0).default(MAX_INBOUND_STREAMS), + maxPushIncomingStreams: number().integer().min(0).default(MAX_PUSH_INCOMING_STREAMS), + maxPushOutgoingStreams: number().integer().min(0).default(MAX_PUSH_OUTGOING_STREAMS), + maxOutboundStreams: number().integer().min(0).default(MAX_OUTBOUND_STREAMS), + maxObservedAddresses: number().integer().min(0).default(MAX_OBSERVED_ADDRESSES), + runOnConnectionOpen: boolean().default(RUN_ON_CONNECTION_OPEN), + runOnTransientConnection: boolean().default(RUN_ON_TRANSIENT_CONNECTION) + }).validateSync(init) + this.started = false this.peerId = components.peerId this.peerStore = components.peerStore @@ -82,24 +90,25 @@ export class DefaultIdentifyService implements Startable, IdentifyService { this.connectionManager = components.connectionManager this.events = components.events - this.identifyProtocolStr = `/${init.protocolPrefix ?? defaultValues.protocolPrefix}/${MULTICODEC_IDENTIFY_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PROTOCOL_VERSION}` - this.identifyPushProtocolStr = `/${init.protocolPrefix ?? defaultValues.protocolPrefix}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION}` - this.timeout = init.timeout ?? defaultValues.timeout - this.maxInboundStreams = init.maxInboundStreams ?? defaultValues.maxInboundStreams - this.maxOutboundStreams = init.maxOutboundStreams ?? defaultValues.maxOutboundStreams - this.maxPushIncomingStreams = init.maxPushIncomingStreams ?? defaultValues.maxPushIncomingStreams - this.maxPushOutgoingStreams = init.maxPushOutgoingStreams ?? defaultValues.maxPushOutgoingStreams - this.maxIdentifyMessageSize = init.maxIdentifyMessageSize ?? defaultValues.maxIdentifyMessageSize - this.maxObservedAddresses = init.maxObservedAddresses ?? defaultValues.maxObservedAddresses - this.runOnTransientConnection = init.runOnTransientConnection ?? defaultValues.runOnTransientConnection + this.identifyProtocolStr = `/${validatedConfig.protocolPrefix}/${MULTICODEC_IDENTIFY_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PROTOCOL_VERSION}` + this.identifyPushProtocolStr = `/${validatedConfig.protocolPrefix}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION}` + this.timeout = validatedConfig.timeout + this.maxInboundStreams = validatedConfig.maxInboundStreams + this.maxOutboundStreams = validatedConfig.maxOutboundStreams + this.maxPushIncomingStreams = validatedConfig.maxPushIncomingStreams + this.maxPushOutgoingStreams = validatedConfig.maxPushOutgoingStreams + this.maxIdentifyMessageSize = validatedConfig.maxIdentifyMessageSize + this.maxObservedAddresses = validatedConfig.maxObservedAddresses + this.runOnTransientConnection = validatedConfig.runOnTransientConnection + this.runOnConnectionOpen = validatedConfig.runOnConnectionOpen // Store self host metadata this.host = { - protocolVersion: `${init.protocolPrefix ?? defaultValues.protocolPrefix}/${IDENTIFY_PROTOCOL_VERSION}`, - agentVersion: init.agentVersion ?? defaultValues.agentVersion + protocolVersion: `${validatedConfig.protocolPrefix}/${IDENTIFY_PROTOCOL_VERSION}`, + agentVersion: validatedConfig.agentVersion } - if (init.runOnConnectionOpen ?? defaultValues.runOnConnectionOpen) { + if (this.runOnConnectionOpen) { // When a new connection happens, trigger identify components.events.addEventListener('connection:open', (evt) => { const connection = evt.detail @@ -313,7 +322,7 @@ export class DefaultIdentifyService implements Startable, IdentifyService { log('our observed address is %a', cleanObservedAddr) if (cleanObservedAddr != null && - this.addressManager.getObservedAddrs().length < (this.maxObservedAddresses ?? Infinity)) { + this.addressManager.getObservedAddrs().length < (this.maxObservedAddresses)) { log('storing our observed address %a', cleanObservedAddr) this.addressManager.addObservedAddr(cleanObservedAddr) } diff --git a/packages/libp2p/src/identify/index.ts b/packages/libp2p/src/identify/index.ts index a61309b3d3..cd8e6a7ab4 100644 --- a/packages/libp2p/src/identify/index.ts +++ b/packages/libp2p/src/identify/index.ts @@ -1,7 +1,4 @@ -import { - MULTICODEC_IDENTIFY, - MULTICODEC_IDENTIFY_PUSH -} from './consts.js' +import { MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH } from './consts.js' import { DefaultIdentifyService } from './identify.js' import { Identify } from './pb/message.js' import type { AbortOptions, IdentifyResult, Libp2pEvents } from '@libp2p/interface' diff --git a/packages/libp2p/src/libp2p.ts b/packages/libp2p/src/libp2p.ts index 29c80f0cc7..d5c829b142 100644 --- a/packages/libp2p/src/libp2p.ts +++ b/packages/libp2p/src/libp2p.ts @@ -18,8 +18,8 @@ import { concat as uint8ArrayConcat } from 'uint8arrays/concat' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { DefaultAddressManager } from './address-manager/index.js' import { defaultComponents } from './components.js' +import { validateConfig } from './config/config.js' import { connectionGater } from './config/connection-gater.js' -import { validateConfig } from './config.js' import { DefaultConnectionManager } from './connection-manager/index.js' import { CompoundContentRouting } from './content-routing/index.js' import { codes } from './errors.js' diff --git a/packages/libp2p/src/ping/index.ts b/packages/libp2p/src/ping/index.ts index 49c813b72e..74491dc267 100644 --- a/packages/libp2p/src/ping/index.ts +++ b/packages/libp2p/src/ping/index.ts @@ -4,6 +4,7 @@ import { logger } from '@libp2p/logger' import first from 'it-first' import { pipe } from 'it-pipe' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' +import { boolean, number, object, string } from 'yup' import { codes } from '../errors.js' import { PROTOCOL_PREFIX, PROTOCOL_NAME, PING_LENGTH, PROTOCOL_VERSION, TIMEOUT, MAX_INBOUND_STREAMS, MAX_OUTBOUND_STREAMS } from './constants.js' import type { AbortOptions } from '@libp2p/interface' @@ -49,11 +50,20 @@ class DefaultPingService implements Startable, PingService { constructor (components: PingServiceComponents, init: PingServiceInit) { this.components = components this.started = false - this.protocol = `/${init.protocolPrefix ?? PROTOCOL_PREFIX}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` - this.timeout = init.timeout ?? TIMEOUT - this.maxInboundStreams = init.maxInboundStreams ?? MAX_INBOUND_STREAMS - this.maxOutboundStreams = init.maxOutboundStreams ?? MAX_OUTBOUND_STREAMS - this.runOnTransientConnection = init.runOnTransientConnection ?? true + + const validatedConfig = object({ + protocolPrefix: string().default(PROTOCOL_PREFIX), + timeout: number().integer().default(TIMEOUT), + maxInboundStreams: number().integer().min(0).default(MAX_INBOUND_STREAMS), + maxOutboundStreams: number().integer().min(0).default(MAX_OUTBOUND_STREAMS), + runOnTransientConnection: boolean().default(true) + }).validateSync(init) + + this.protocol = `/${validatedConfig.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` + this.timeout = validatedConfig.timeout + this.maxInboundStreams = validatedConfig.maxInboundStreams + this.maxOutboundStreams = validatedConfig.maxOutboundStreams + this.runOnTransientConnection = validatedConfig.runOnTransientConnection } async start (): Promise { diff --git a/packages/libp2p/src/upnp-nat/index.ts b/packages/libp2p/src/upnp-nat/index.ts index 8e422f6b1a..6969263b66 100644 --- a/packages/libp2p/src/upnp-nat/index.ts +++ b/packages/libp2p/src/upnp-nat/index.ts @@ -5,6 +5,7 @@ import { isLoopback } from '@libp2p/utils/multiaddr/is-loopback' import { fromNodeAddress } from '@multiformats/multiaddr' import isPrivateIp from 'private-ip' import { isBrowser } from 'wherearewe' +import { boolean, number, object, string } from 'yup' import { codes } from '../errors.js' import * as pkg from '../version.js' import type { PeerId } from '@libp2p/interface/peer-id' @@ -70,21 +71,32 @@ class UPnPNAT implements Startable { private readonly localAddress?: string private readonly description: string private readonly ttl: number - private readonly keepAlive: boolean + private readonly keepAlive?: boolean private readonly gateway?: string private started: boolean private client?: NatAPI constructor (components: UPnPNATComponents, init: UPnPNATInit) { this.components = components - this.started = false - this.externalAddress = init.externalAddress - this.localAddress = init.localAddress - this.description = init.description ?? `${pkg.name}@${pkg.version} ${this.components.peerId.toString()}` - this.ttl = init.ttl ?? DEFAULT_TTL - this.keepAlive = init.keepAlive ?? true - this.gateway = init.gateway + + const validIPRegex = /^(?:(?:^|\.)(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])){4}$/ + + const validatedConfig = object({ + externalAddress: string().matches(validIPRegex, 'Invalid IP address'), + localAddress: string().matches(validIPRegex, 'Invalid IP address'), + description: string().default(`${pkg.name}@${pkg.version} ${this.components.peerId.toString()}`), + ttl: number().integer().default(DEFAULT_TTL), + keepAlive: boolean().default(true), + gateway: string().optional() + }).validateSync(init) + + this.externalAddress = validatedConfig.externalAddress + this.localAddress = validatedConfig.localAddress + this.description = validatedConfig.description + this.ttl = validatedConfig.ttl + this.keepAlive = validatedConfig.keepAlive + this.gateway = validatedConfig.gateway if (this.ttl < DEFAULT_TTL) { throw new CodeError(`NatManager ttl should be at least ${DEFAULT_TTL} seconds`, codes.ERR_INVALID_PARAMETERS) diff --git a/packages/libp2p/test/circuit-relay/discovery.node.ts b/packages/libp2p/test/circuit-relay/discovery.node.ts index 19517e67be..b6c434d6d7 100644 --- a/packages/libp2p/test/circuit-relay/discovery.node.ts +++ b/packages/libp2p/test/circuit-relay/discovery.node.ts @@ -5,6 +5,7 @@ import { tcp } from '@libp2p/tcp' import { expect } from 'aegir/chai' import { pEvent } from 'p-event' import { circuitRelayServer, type CircuitRelayService, circuitRelayTransport } from '../../src/circuit-relay/index.js' +import { identifyService } from '../../src/identify/index.js' import { createLibp2p } from '../../src/index.js' import { plaintext } from '../../src/insecure/index.js' import { getRelayAddress, hasRelay, MockContentRouting, mockContentRouting } from './utils.js' @@ -34,6 +35,7 @@ describe('circuit-relay discovery', () => { mockContentRouting() ], services: { + identify: identifyService(), relay: circuitRelayServer({ advertise: { bootDelay: 10 diff --git a/packages/libp2p/test/configuration/protocol-prefix.node.ts b/packages/libp2p/test/configuration/protocol-prefix.node.ts index db4ecea61c..93eb2af4f5 100644 --- a/packages/libp2p/test/configuration/protocol-prefix.node.ts +++ b/packages/libp2p/test/configuration/protocol-prefix.node.ts @@ -67,7 +67,8 @@ describe('Protocol prefix is configurable', () => { '/ipfs/id/1.0.0', '/ipfs/id/push/1.0.0', '/ipfs/ping/1.0.0', - '/libp2p/fetch/0.0.1' + '/libp2p/fetch/0.0.1', + '/libp2p/circuit/relay/0.2.0/stop' ]) }) }) diff --git a/packages/libp2p/test/connection-manager/index.node.ts b/packages/libp2p/test/connection-manager/index.node.ts index add7158a47..9a45635f4d 100644 --- a/packages/libp2p/test/connection-manager/index.node.ts +++ b/packages/libp2p/test/connection-manager/index.node.ts @@ -235,7 +235,9 @@ describe('libp2p.connections', () => { }, connectionManager: { minConnections, - maxConnections: 1 + maxConnections: 1, + inboundConnectionThreshold: 1, + maxIncomingPendingConnections: 1 } } }) diff --git a/packages/libp2p/test/connection-manager/index.spec.ts b/packages/libp2p/test/connection-manager/index.spec.ts index 699339da03..4189969895 100644 --- a/packages/libp2p/test/connection-manager/index.spec.ts +++ b/packages/libp2p/test/connection-manager/index.spec.ts @@ -77,7 +77,9 @@ describe('Connection Manager', () => { config: createBaseOptions({ connectionManager: { maxConnections: max, - minConnections: 2 + minConnections: 2, + inboundConnectionThreshold: max, + maxIncomingPendingConnections: max } }), started: false @@ -136,7 +138,9 @@ describe('Connection Manager', () => { config: createBaseOptions({ connectionManager: { maxConnections: max, - minConnections: 2 + minConnections: 2, + maxIncomingPendingConnections: max, + inboundConnectionThreshold: max } }), started: false @@ -202,6 +206,8 @@ describe('Connection Manager', () => { connectionManager: { maxConnections: max, minConnections: 0, + maxIncomingPendingConnections: max, + inboundConnectionThreshold: max, allow: [ '/ip4/83.13.55.32' ] @@ -286,7 +292,9 @@ describe('Connection Manager', () => { config: createBaseOptions({ connectionManager: { maxConnections: max, - minConnections: 0 + minConnections: 0, + maxIncomingPendingConnections: max, + inboundConnectionThreshold: max } }), started: false @@ -319,11 +327,13 @@ describe('Connection Manager', () => { config: createBaseOptions({ connectionManager: { maxConnections: 5, - minConnections: 6 + minConnections: 6, + maxIncomingPendingConnections: 5, + inboundConnectionThreshold: 5 } }), started: false - })).to.eventually.rejected('maxConnections must be greater') + })).to.eventually.rejectedWith('minConnections must be less than the max connections limit: 5') }) it('should reconnect to important peers on startup', async () => { diff --git a/packages/libp2p/test/connection-manager/resolver.spec.ts b/packages/libp2p/test/connection-manager/resolver.spec.ts index adccf3976d..ef8ed7f905 100644 --- a/packages/libp2p/test/connection-manager/resolver.spec.ts +++ b/packages/libp2p/test/connection-manager/resolver.spec.ts @@ -14,6 +14,7 @@ import sinon from 'sinon' import { RELAY_V2_HOP_CODEC } from '../../src/circuit-relay/constants.js' import { circuitRelayServer, type CircuitRelayService, circuitRelayTransport } from '../../src/circuit-relay/index.js' import { codes as ErrorCodes } from '../../src/errors.js' +import { identifyService } from '../../src/identify/index.js' import { plaintext } from '../../src/insecure/index.js' import { createLibp2pNode, type Libp2pNode } from '../../src/libp2p.js' import type { PeerId } from '@libp2p/interface/peer-id' @@ -93,7 +94,8 @@ describe('dialing (resolvable addresses)', () => { plaintext() ], services: { - relay: circuitRelayServer() + relay: circuitRelayServer(), + identify: identifyService() }, connectionGater: mockConnectionGater() }) diff --git a/packages/libp2p/test/ping/ping.node.ts b/packages/libp2p/test/ping/ping.node.ts index aba6537aa7..6c5e0f299e 100644 --- a/packages/libp2p/test/ping/ping.node.ts +++ b/packages/libp2p/test/ping/ping.node.ts @@ -4,6 +4,7 @@ import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import { pipe } from 'it-pipe' import pDefer from 'p-defer' +import { identifyService } from '../../src/identify/index.js' import { PROTOCOL } from '../../src/ping/constants.js' import { pingService, type PingService } from '../../src/ping/index.js' import { createBaseOptions } from '../fixtures/base-options.js' @@ -18,6 +19,7 @@ describe('ping', () => { createNode({ config: createBaseOptions({ services: { + identify: identifyService(), ping: pingService() } }) @@ -25,6 +27,7 @@ describe('ping', () => { createNode({ config: createBaseOptions({ services: { + identify: identifyService(), ping: pingService() } }) @@ -32,6 +35,7 @@ describe('ping', () => { createNode({ config: createBaseOptions({ services: { + identify: identifyService(), ping: pingService() } }) @@ -106,6 +110,7 @@ describe('ping', () => { const client = await createNode({ config: createBaseOptions({ services: { + identify: identifyService(), ping: pingService({ // Allow two outbound ping streams. // It is not allowed by the spec, but this test needs to open two concurrent streams. diff --git a/packages/transport-webrtc/.aegir.js b/packages/transport-webrtc/.aegir.js index 491576df87..dfbb5439dc 100644 --- a/packages/transport-webrtc/.aegir.js +++ b/packages/transport-webrtc/.aegir.js @@ -1,4 +1,3 @@ - /** @type {import('aegir').PartialOptions} */ export default { build: { @@ -32,7 +31,7 @@ export default { services: { relay: circuitRelayServer({ reservations: { - maxReservations: Infinity + maxReservations: 10000 } }), identify: identifyService()