Skip to content

Commit 893e068

Browse files
committed
feat: refactored config to validate before returning service (libp2p#1573)
1 parent 73f9fc7 commit 893e068

File tree

12 files changed

+67
-86
lines changed

12 files changed

+67
-86
lines changed

packages/libp2p/.aegir.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export default {
5252
fetch: fetchService(),
5353
relay: circuitRelayServer({
5454
reservations: {
55-
maxReservations: Infinity
55+
maxReservations: 100000
5656
}
5757
})
5858
}

packages/libp2p/src/circuit-relay/server/index.ts

+19
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import pDefer from 'p-defer'
99
import { MAX_CONNECTIONS } from '../../connection-manager/constants.js'
1010
import {
1111
CIRCUIT_PROTO_CODE,
12+
DEFAULT_DURATION_LIMIT,
1213
DEFAULT_HOP_TIMEOUT,
14+
DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL,
15+
DEFAULT_MAX_RESERVATION_STORE_SIZE,
16+
DEFAULT_MAX_RESERVATION_TTL,
1317
RELAY_SOURCE_TAG
1418
, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC
1519
} from '../constants.js'
@@ -28,6 +32,8 @@ import type { AddressManager } from '@libp2p/interface-internal/address-manager'
2832
import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager'
2933
import type { IncomingStreamData, Registrar } from '@libp2p/interface-internal/registrar'
3034
import type { PeerMap } from '@libp2p/peer-collections'
35+
import { object, number, boolean } from 'yup'
36+
import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from '../../registrar.js'
3137

3238
const log = logger('libp2p:circuit-relay:server')
3339

@@ -438,6 +444,19 @@ class CircuitRelayServer extends EventEmitter<RelayServerEvents> implements Star
438444
}
439445

440446
export function circuitRelayServer (init: CircuitRelayServerInit = {}): (components: CircuitRelayServerComponents) => CircuitRelayService {
447+
object({
448+
hopTimeout: number().min(0).integer().default(DEFAULT_HOP_TIMEOUT),
449+
reservations: object({
450+
maxReservations: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_STORE_SIZE),
451+
reservationClearInterval: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL),
452+
applyDefaultLimit: boolean().default(true),
453+
reservationTtl: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_TTL),
454+
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}`)
455+
}),
456+
maxInboundHopStreams: number().integer().min(0).default(DEFAULT_MAX_INBOUND_STREAMS),
457+
maxOutboundHopStreams: number().integer().min(0).default(DEFAULT_MAX_OUTBOUND_STREAMS)
458+
}).validateSync(init)
459+
441460
return (components) => {
442461
return new CircuitRelayServer(components, init)
443462
}

packages/libp2p/src/circuit-relay/utils.ts

+1-20
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@ import { abortableSource } from 'abortable-iterator'
33
import { anySignal } from 'any-signal'
44
import { CID } from 'multiformats/cid'
55
import { sha256 } from 'multiformats/hashes/sha2'
6-
import { object, number, boolean } from 'yup'
7-
import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from '../registrar.js'
8-
import { DEFAULT_DATA_LIMIT, DEFAULT_DURATION_LIMIT, DEFAULT_HOP_TIMEOUT, DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL, DEFAULT_MAX_RESERVATION_STORE_SIZE, DEFAULT_MAX_RESERVATION_TTL } from './constants.js'
9-
import { type CircuitRelayServerInit, circuitRelayServer, type CircuitRelayServerComponents } from './server/index.js'
10-
import type { CircuitRelayService } from './index.js'
6+
import { DEFAULT_DATA_LIMIT, DEFAULT_DURATION_LIMIT } from './constants.js'
117
import type { Limit } from './pb/index.js'
128
import type { Stream } from '@libp2p/interface/connection'
139
import type { Source } from 'it-stream-types'
@@ -128,18 +124,3 @@ export function getExpirationMilliseconds (expireTimeSeconds: bigint): number {
128124
// downcast to number to use with setTimeout
129125
return Number(expireTimeMillis - BigInt(currentTime))
130126
}
131-
132-
export const validateCircuitRelayServicesConfig = (opts: CircuitRelayServerInit): (components: CircuitRelayServerComponents) => CircuitRelayService => {
133-
return circuitRelayServer(object({
134-
hopTimeout: number().min(0).integer().default(DEFAULT_HOP_TIMEOUT).optional(),
135-
reservations: object({
136-
maxReservations: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_STORE_SIZE).optional(),
137-
reservationClearInterval: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_CLEAR_INTERVAL).optional(),
138-
applyDefaultLimit: boolean().default(true).optional(),
139-
reservationTtl: number().integer().min(0).default(DEFAULT_MAX_RESERVATION_TTL).optional(),
140-
defaultDurationLimit: number().integer().min(0).default(DEFAULT_DURATION_LIMIT).max(opts?.reservations?.reservationTtl ?? DEFAULT_MAX_RESERVATION_TTL, `default duration limit must be less than reservation TTL: ${opts?.reservations?.reservationTtl}`).optional()
141-
}),
142-
maxInboundHopStreams: number().integer().min(0).default(DEFAULT_MAX_INBOUND_STREAMS).optional(),
143-
maxOutboundHopStreams: number().integer().min(0).default(DEFAULT_MAX_OUTBOUND_STREAMS).optional()
144-
}).validateSync(opts))
145-
}

packages/libp2p/src/config/config.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ import { publicAddressesFirst } from '@libp2p/utils/address-sort'
33
import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers'
44
import mergeOptions from 'merge-options'
55
import type { ServiceMap, RecursivePartial } from '@libp2p/interface'
6-
import type { Libp2pInit, ServiceFactoryMap } from '../index.js'
6+
import type { Libp2pInit } from '../index.js'
77
import type { AddressManagerInit } from '../address-manager'
88
import { validateAddressManagerConfig } from '../address-manager/utils.js'
99
import { object } from 'yup'
1010
import { validateConnectionManagerConfig } from '../connection-manager/utils.js'
1111
import type { ConnectionManagerInit } from '../connection-manager/index.js'
12-
import { validateServicesConfig } from './helpers.js'
1312

1413
const DefaultConfig: Partial<Libp2pInit> = {
1514
connectionManager: {
@@ -29,8 +28,12 @@ export function validateConfig <T extends ServiceMap = Record<string, unknown>>
2928
connectionManager: validateConnectionManagerConfig(opts?.connectionManager as ConnectionManagerInit),
3029
})
3130

32-
//@ts-expect-error
33-
opts.services = validateServicesConfig(opts?.services as ServiceFactoryMap<T>) as ServiceFactoryMap<T>
31+
if (opts?.services) {
32+
// @ts-expect-error
33+
if ((opts.services?.kadDHT || opts.services?.relay || opts.services?.ping) && !opts.services.identify) {
34+
throw new Error('identify service is required when using kadDHT, relay, or ping')
35+
}
36+
}
3437

3538
const parsedOpts = libp2pConfig.validateSync(opts)
3639

packages/libp2p/src/config/helpers.ts

-19
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
11
import { multiaddr } from '@multiformats/multiaddr'
2-
import { validateCircuitRelayServicesConfig } from '../circuit-relay/utils.js'
3-
import { validateIdentifyConfig } from '../identify/config.js'
4-
import type { CircuitRelayServerInit } from '../circuit-relay/server/index.js'
5-
import type { IdentifyServiceInit } from '../identify/index.js'
6-
import type { ServiceMap } from '@libp2p/interface-libp2p'
7-
import type { PingServiceInit } from '../ping/index.js'
8-
import { validatePingConfig } from '../ping/config.js'
9-
import type { FetchServiceInit } from '../fetch/index.js'
10-
import { validateFetchConfig } from '../fetch/config.js'
112

123
export const validateMultiaddr = (value: Array<string | undefined> | undefined): boolean => {
134
value?.forEach((addr) => {
@@ -19,13 +10,3 @@ export const validateMultiaddr = (value: Array<string | undefined> | undefined):
1910
})
2011
return true
2112
}
22-
23-
export const validateServicesConfig = (opts: ServiceMap): ServiceMap => {
24-
return {
25-
ping: validatePingConfig(opts?.ping as PingServiceInit),
26-
fetch: validateFetchConfig(opts?.fetch as FetchServiceInit),
27-
identify: validateIdentifyConfig(opts?.identify as IdentifyServiceInit),
28-
relay: validateCircuitRelayServicesConfig(opts?.relay as CircuitRelayServerInit),
29-
...opts,
30-
}
31-
}

packages/libp2p/src/fetch/config.ts

-12
This file was deleted.

packages/libp2p/src/fetch/index.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ import { pipe } from 'it-pipe'
88
import { fromString as uint8arrayFromString } from 'uint8arrays/from-string'
99
import { toString as uint8arrayToString } from 'uint8arrays/to-string'
1010
import { codes } from '../errors.js'
11-
import { PROTOCOL_NAME, PROTOCOL_VERSION } from './constants.js'
11+
import { MAX_INBOUND_STREAMS, MAX_OUTBOUND_STREAMS, PROTOCOL_NAME, PROTOCOL_VERSION, TIMEOUT } from './constants.js'
1212
import { FetchRequest, FetchResponse } from './pb/proto.js'
1313
import type { AbortOptions } from '@libp2p/interface'
1414
import type { Stream } from '@libp2p/interface/connection'
1515
import type { PeerId } from '@libp2p/interface/peer-id'
1616
import type { Startable } from '@libp2p/interface/startable'
1717
import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager'
1818
import type { IncomingStreamData, Registrar } from '@libp2p/interface-internal/registrar'
19+
import { number, object, string } from 'yup'
1920

2021
const log = logger('libp2p:fetch')
2122

@@ -309,5 +310,13 @@ class DefaultFetchService implements Startable, FetchService {
309310
}
310311

311312
export function fetchService (init: FetchServiceInit = {}): (components: FetchServiceComponents) => FetchService {
313+
314+
object({
315+
protocolPrefix: string().default('ipfs'),
316+
timeout: number().integer().default(TIMEOUT),
317+
maxInboundStreams: number().integer().min(0).default(MAX_INBOUND_STREAMS),
318+
maxOutboundStreams: number().integer().min(0).default(MAX_OUTBOUND_STREAMS),
319+
}).validateSync(init)
320+
312321
return (components) => new DefaultFetchService(components, init)
313322
}

packages/libp2p/src/identify/config.ts

-15
This file was deleted.

packages/libp2p/src/identify/index.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import {
2+
AGENT_VERSION,
3+
MAX_IDENTIFY_MESSAGE_SIZE,
4+
MAX_INBOUND_STREAMS,
5+
MAX_OUTBOUND_STREAMS,
26
MULTICODEC_IDENTIFY,
3-
MULTICODEC_IDENTIFY_PUSH
7+
MULTICODEC_IDENTIFY_PUSH,
8+
PROTOCOL_PREFIX,
9+
TIMEOUT
410
} from './consts.js'
511
import { DefaultIdentifyService } from './identify.js'
612
import { Identify } from './pb/message.js'
@@ -11,6 +17,7 @@ import type { PeerStore } from '@libp2p/interface/peer-store'
1117
import type { AddressManager } from '@libp2p/interface-internal/address-manager'
1218
import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager'
1319
import type { Registrar } from '@libp2p/interface-internal/registrar'
20+
import { number, object, string } from 'yup'
1421

1522
export interface IdentifyServiceInit {
1623
/**
@@ -61,5 +68,14 @@ export const multicodecs = {
6168
export const Message = { Identify }
6269

6370
export function identifyService (init: IdentifyServiceInit = {}): (components: IdentifyServiceComponents) => DefaultIdentifyService {
71+
object({
72+
protocolPrefix: string().default(PROTOCOL_PREFIX),
73+
agentVersion: string().default(AGENT_VERSION),
74+
timeout: number().integer().default(TIMEOUT),
75+
maxIdentifyMessageSize: number().integer().min(0).default(MAX_IDENTIFY_MESSAGE_SIZE),
76+
maxInboundStreams: number().integer().min(0).default(MAX_INBOUND_STREAMS),
77+
maxOutboundStreams: number().integer().min(0).default(MAX_OUTBOUND_STREAMS),
78+
}).validateSync(init)
79+
6480
return (components) => new DefaultIdentifyService(components, init)
6581
}

packages/libp2p/src/ping/config.ts

-12
This file was deleted.

packages/libp2p/src/ping/index.ts

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type { Startable } from '@libp2p/interface/startable'
1616
import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager'
1717
import type { IncomingStreamData, Registrar } from '@libp2p/interface-internal/registrar'
1818
import type { Multiaddr } from '@multiformats/multiaddr'
19+
import { number, object, string } from 'yup'
1920

2021
const log = logger('libp2p:ping')
2122

@@ -136,5 +137,13 @@ class DefaultPingService implements Startable, PingService {
136137
}
137138

138139
export function pingService (init: PingServiceInit = {}): (components: PingServiceComponents) => PingService {
140+
141+
object({
142+
protocolPrefix: string().default(PROTOCOL_PREFIX),
143+
timeout: number().integer().default(TIMEOUT),
144+
maxInboundStreams: number().integer().min(0).default(MAX_INBOUND_STREAMS),
145+
maxOutboundStreams: number().integer().min(0).default(MAX_OUTBOUND_STREAMS)
146+
}).validateSync(init)
147+
139148
return (components) => new DefaultPingService(components, init)
140149
}

packages/libp2p/test/connection-manager/resolver.spec.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { createLibp2pNode, type Libp2pNode } from '../../src/libp2p.js'
1919
import type { PeerId } from '@libp2p/interface/peer-id'
2020
import type { Transport } from '@libp2p/interface/transport'
2121
import type { Multiaddr } from '@multiformats/multiaddr'
22+
import { identifyService } from '../../src/identify/index.js'
2223

2324
const relayAddr = multiaddr(process.env.RELAY_MULTIADDR)
2425

@@ -93,7 +94,8 @@ describe('dialing (resolvable addresses)', () => {
9394
plaintext()
9495
],
9596
services: {
96-
relay: circuitRelayServer()
97+
relay: circuitRelayServer(),
98+
identify: identifyService()
9799
},
98100
connectionGater: mockConnectionGater()
99101
})

0 commit comments

Comments
 (0)