Skip to content

Commit 788d188

Browse files
committed
fix: remove peer refresh
js-libp2p occasionally gets all peer routers to run a query for it's own node id. The only module that actually requires this is kad-dht in order to insure it has peers when it runs a query and it does this anyway since it's part of the spec. libp2p/js-libp2p-kad-dht#457 also updates kad-dht to pause all executed queries until the self-query has run. Consequently this is redundant and just creates unecessary work.
1 parent 5c643c3 commit 788d188

File tree

5 files changed

+1
-316
lines changed

5 files changed

+1
-316
lines changed

src/config.ts

-55
Original file line numberDiff line numberDiff line change
@@ -24,62 +24,7 @@ const DefaultConfig: Partial<Libp2pInit> = {
2424
},
2525
transportManager: {
2626
faultTolerance: FaultTolerance.FATAL_ALL
27-
},
28-
peerRouting: {
29-
refreshManager: {
30-
enabled: true,
31-
interval: 6e5,
32-
bootDelay: 10e3
33-
}
3427
}
35-
/*
36-
37-
nat: {
38-
enabled: true,
39-
ttl: 7200,
40-
keepAlive: true
41-
},
42-
identify: {
43-
protocolPrefix: 'ipfs',
44-
host: {
45-
agentVersion: AGENT_VERSION
46-
},
47-
// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48
48-
timeout: 60000,
49-
maxInboundStreams: 1,
50-
maxOutboundStreams: 1,
51-
maxPushIncomingStreams: 1,
52-
maxPushOutgoingStreams: 1,
53-
maxObservedAddresses: 10
54-
},
55-
ping: {
56-
protocolPrefix: 'ipfs',
57-
// See https://github.com/libp2p/specs/blob/d4b5fb0152a6bb86cfd9ea/ping/ping.md?plain=1#L38-L43
58-
// The dialing peer MUST NOT keep more than one outbound stream for the ping protocol per peer.
59-
// The listening peer SHOULD accept at most two streams per peer since cross-stream behavior is
60-
// non-linear and stream writes occur asynchronously. The listening peer may perceive the
61-
// dialing peer closing and opening the wrong streams (for instance, closing stream B and
62-
// opening stream A even though the dialing peer is opening stream B and closing stream A).
63-
maxInboundStreams: 2,
64-
maxOutboundStreams: 1,
65-
timeout: 10000
66-
},
67-
fetch: {
68-
protocolPrefix: 'libp2p',
69-
maxInboundStreams: 1,
70-
maxOutboundStreams: 1,
71-
timeout: 10000
72-
},
73-
autonat: {
74-
protocolPrefix: 'libp2p',
75-
maxInboundStreams: 1,
76-
maxOutboundStreams: 1,
77-
timeout: 30000,
78-
startupDelay: 5000,
79-
refreshInterval: 60000
80-
}
81-
82-
*/
8328
}
8429

8530
export function validateConfig <T extends ServiceMap = {}> (opts: RecursivePartial<Libp2pInit<T>>): Libp2pInit<T> {

src/index.ts

-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import type { Components } from './components.js'
3232
import type { Libp2p, ServiceMap } from '@libp2p/interface-libp2p'
3333
import type { KeyChainInit } from '@libp2p/keychain'
3434
import type { AddressManagerInit } from './address-manager/index.js'
35-
import type { PeerRoutingInit } from './peer-routing.js'
3635
import type { ConnectionManagerInit } from './connection-manager/index.js'
3736
import type { PersistentPeerStoreInit } from '@libp2p/peer-store'
3837

@@ -81,11 +80,6 @@ export interface Libp2pInit<T extends ServiceMap = {}> {
8180
*/
8281
peerStore: PersistentPeerStoreInit
8382

84-
/**
85-
* libp2p Peer routing service configuration
86-
*/
87-
peerRouting: PeerRoutingInit
88-
8983
/**
9084
* keychain configuration
9185
*/

src/libp2p.ts

-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ export class Libp2pNode<T extends ServiceMap = {}> extends EventEmitter<Libp2pEv
147147
// Peer routers
148148
const peerRouters: PeerRouting[] = (init.peerRouters ?? []).map((fn, index) => this.configureComponent(`peer-router-${index}`, fn(this.components)))
149149
this.peerRouting = this.components.peerRouting = this.configureComponent('peerRouting', new DefaultPeerRouting(this.components, {
150-
...init.peerRouting,
151150
routers: peerRouters
152151
}))
153152

src/peer-routing.ts

+1-103
Original file line numberDiff line numberDiff line change
@@ -9,133 +9,31 @@ import {
99
import merge from 'it-merge'
1010
import { pipe } from 'it-pipe'
1111
import first from 'it-first'
12-
import drain from 'it-drain'
1312
import filter from 'it-filter'
14-
import {
15-
setDelayedInterval,
16-
clearDelayedInterval
17-
// @ts-expect-error module with no types
18-
} from 'set-delayed-interval'
19-
import { setMaxListeners } from 'events'
2013
import type { PeerId } from '@libp2p/interface-peer-id'
2114
import type { PeerRouting } from '@libp2p/interface-peer-routing'
2215
import type { AbortOptions } from '@libp2p/interfaces'
23-
import type { Startable } from '@libp2p/interfaces/startable'
2416
import type { PeerInfo } from '@libp2p/interface-peer-info'
2517
import type { PeerStore } from '@libp2p/interface-peer-store'
26-
import { anySignal } from 'any-signal'
2718

2819
const log = logger('libp2p:peer-routing')
2920

30-
export interface RefreshManagerInit {
31-
/**
32-
* Whether to enable the Refresh manager
33-
*/
34-
enabled?: boolean
35-
36-
/**
37-
* Boot delay to start the Refresh Manager (in ms)
38-
*/
39-
bootDelay?: number
40-
41-
/**
42-
* Interval between each Refresh Manager run (in ms)
43-
*/
44-
interval?: number
45-
46-
/**
47-
* How long to let each refresh run (in ms)
48-
*/
49-
timeout?: number
50-
}
51-
5221
export interface PeerRoutingInit {
5322
routers?: PeerRouting[]
54-
refreshManager?: RefreshManagerInit
5523
}
5624

5725
export interface DefaultPeerRoutingComponents {
5826
peerId: PeerId
5927
peerStore: PeerStore
6028
}
6129

62-
export class DefaultPeerRouting implements PeerRouting, Startable {
30+
export class DefaultPeerRouting implements PeerRouting {
6331
private readonly components: DefaultPeerRoutingComponents
6432
private readonly routers: PeerRouting[]
65-
private readonly refreshManagerInit: RefreshManagerInit
66-
private timeoutId?: ReturnType<typeof setTimeout>
67-
private started: boolean
68-
private abortController?: AbortController
6933

7034
constructor (components: DefaultPeerRoutingComponents, init: PeerRoutingInit) {
7135
this.components = components
7236
this.routers = init.routers ?? []
73-
this.refreshManagerInit = init.refreshManager ?? {}
74-
this.started = false
75-
76-
this._findClosestPeersTask = this._findClosestPeersTask.bind(this)
77-
}
78-
79-
isStarted (): boolean {
80-
return this.started
81-
}
82-
83-
/**
84-
* Start peer routing service.
85-
*/
86-
async start (): Promise<void> {
87-
if (this.started || this.routers.length === 0 || this.timeoutId != null || this.refreshManagerInit.enabled === false) {
88-
return
89-
}
90-
91-
this.timeoutId = setDelayedInterval(
92-
this._findClosestPeersTask, this.refreshManagerInit.interval, this.refreshManagerInit.bootDelay
93-
)
94-
95-
this.started = true
96-
}
97-
98-
/**
99-
* Recurrent task to find closest peers and add their addresses to the Address Book.
100-
*/
101-
async _findClosestPeersTask (): Promise<void> {
102-
if (this.abortController != null) {
103-
// we are already running the query
104-
return
105-
}
106-
107-
this.abortController = new AbortController()
108-
109-
const signal = anySignal([this.abortController.signal, AbortSignal.timeout(this.refreshManagerInit.timeout ?? 10e3)])
110-
111-
try {
112-
// this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning
113-
// appearing in the console
114-
try {
115-
setMaxListeners?.(Infinity, signal)
116-
} catch {}
117-
118-
// nb getClosestPeers adds the addresses to the address book
119-
await drain(this.getClosestPeers(this.components.peerId.toBytes(), { signal }))
120-
} catch (err: any) {
121-
log.error(err)
122-
} finally {
123-
this.abortController?.abort()
124-
this.abortController = undefined
125-
signal.clear()
126-
}
127-
}
128-
129-
/**
130-
* Stop peer routing service.
131-
*/
132-
async stop (): Promise<void> {
133-
clearDelayedInterval(this.timeoutId)
134-
135-
// abort query if it is in-flight
136-
this.abortController?.abort()
137-
138-
this.started = false
13937
}
14038

14139
/**

test/peer-routing/peer-routing.node.ts

-151
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { expect } from 'aegir/chai'
44
import sinon from 'sinon'
55
import delay from 'delay'
66
import pDefer from 'p-defer'
7-
import pWaitFor from 'p-wait-for'
87
import drain from 'it-drain'
98
import all from 'it-all'
109
import { multiaddr } from '@multiformats/multiaddr'
@@ -550,154 +549,4 @@ describe('peer-routing', () => {
550549
expect(peers).to.be.an('array').with.a.lengthOf(1).that.deep.equals(results)
551550
})
552551
})
553-
554-
describe('peer routing refresh manager service', () => {
555-
let node: Libp2p<{ dht: DHT }>
556-
let peerIds: PeerId[]
557-
558-
before(async () => {
559-
peerIds = await Promise.all([
560-
createPeerId(),
561-
createPeerId()
562-
])
563-
})
564-
565-
afterEach(async () => {
566-
sinon.restore()
567-
568-
if (node != null) {
569-
await node.stop()
570-
}
571-
})
572-
573-
it('should be enabled and start by default', async () => {
574-
const results: PeerInfo[] = [
575-
{ id: peerIds[0], multiaddrs: [multiaddr('/ip4/30.0.0.1/tcp/2000')], protocols: [] },
576-
{ id: peerIds[1], multiaddrs: [multiaddr('/ip4/32.0.0.1/tcp/2000')], protocols: [] }
577-
]
578-
579-
node = await createNode({
580-
config: createRoutingOptions({
581-
start: false,
582-
peerRouting: {
583-
refreshManager: {
584-
enabled: true,
585-
bootDelay: 100
586-
}
587-
}
588-
}),
589-
started: false
590-
})
591-
592-
if (node.services.dht == null) {
593-
throw new Error('DHT not configured')
594-
}
595-
596-
const peerStoreMergeStub = sinon.spy(node.peerStore, 'merge')
597-
const dhtGetClosestPeersStub = sinon.stub(node.services.dht, 'getClosestPeers').callsFake(async function * () {
598-
yield {
599-
name: 'FINAL_PEER',
600-
type: EventTypes.FINAL_PEER,
601-
messageName: 'FIND_NODE',
602-
messageType: MessageType.FIND_NODE,
603-
from: peerIds[0],
604-
peer: results[0]
605-
}
606-
yield {
607-
name: 'FINAL_PEER',
608-
type: EventTypes.FINAL_PEER,
609-
messageName: 'FIND_NODE',
610-
messageType: MessageType.FIND_NODE,
611-
from: peerIds[0],
612-
peer: results[1]
613-
}
614-
})
615-
616-
await node.start()
617-
618-
await pWaitFor(() => dhtGetClosestPeersStub.callCount === 1)
619-
await pWaitFor(() => peerStoreMergeStub.callCount >= results.length)
620-
621-
const peer0 = await node.peerStore.get(peerIds[0])
622-
expect(peer0.addresses.map(({ multiaddr }) => multiaddr.toString()))
623-
.to.include.members(results[0].multiaddrs.map(ma => ma.toString()))
624-
625-
const peer1 = await node.peerStore.get(peerIds[1])
626-
expect(peer1.addresses.map(({ multiaddr }) => multiaddr.toString()))
627-
.to.include.members(results[1].multiaddrs.map(ma => ma.toString()))
628-
})
629-
630-
it('should support being disabled', async () => {
631-
node = await createNode({
632-
config: createRoutingOptions({
633-
start: false,
634-
peerRouting: {
635-
refreshManager: {
636-
bootDelay: 100,
637-
enabled: false
638-
}
639-
}
640-
}),
641-
started: false
642-
})
643-
644-
if (node.services.dht == null) {
645-
throw new Error('DHT not configured')
646-
}
647-
648-
const dhtGetClosestPeersStub = sinon.stub(node.services.dht, 'getClosestPeers').callsFake(async function * () {
649-
yield {
650-
name: 'SENDING_QUERY',
651-
type: EventTypes.SENDING_QUERY,
652-
to: peerIds[0],
653-
messageName: 'FIND_NODE',
654-
messageType: MessageType.FIND_NODE
655-
}
656-
throw new Error('should not be called')
657-
})
658-
659-
await node.start()
660-
await delay(100)
661-
662-
expect(dhtGetClosestPeersStub.callCount === 0)
663-
})
664-
665-
it('should start and run on interval', async () => {
666-
node = await createNode({
667-
config: createRoutingOptions({
668-
start: false,
669-
peerRouting: {
670-
refreshManager: {
671-
interval: 500,
672-
bootDelay: 200
673-
}
674-
}
675-
}),
676-
started: false
677-
})
678-
679-
if (node.services.dht == null) {
680-
throw new Error('DHT not configured')
681-
}
682-
683-
const dhtGetClosestPeersStub = sinon.stub(node.services.dht, 'getClosestPeers').callsFake(async function * () {
684-
yield {
685-
name: 'PEER_RESPONSE',
686-
type: EventTypes.PEER_RESPONSE,
687-
messageName: 'FIND_NODE',
688-
messageType: MessageType.FIND_NODE,
689-
from: peerIds[0],
690-
closer: [
691-
{ id: peerIds[0], multiaddrs: [multiaddr('/ip4/30.0.0.1/tcp/2000')], protocols: [] }
692-
],
693-
providers: []
694-
}
695-
})
696-
697-
await node.start()
698-
699-
// should run more than once
700-
await pWaitFor(() => dhtGetClosestPeersStub.callCount === 2)
701-
})
702-
})
703552
})

0 commit comments

Comments
 (0)