libp2p 0.43.4 → 0.44.0-17eb162a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/dist/index.min.js +29 -29
  2. package/dist/src/address-manager/index.d.ts +4 -4
  3. package/dist/src/address-manager/index.d.ts.map +1 -1
  4. package/dist/src/address-manager/index.js +9 -6
  5. package/dist/src/address-manager/index.js.map +1 -1
  6. package/dist/src/autonat/index.d.ts +1 -2
  7. package/dist/src/autonat/index.d.ts.map +1 -1
  8. package/dist/src/autonat/index.js +4 -6
  9. package/dist/src/autonat/index.js.map +1 -1
  10. package/dist/src/circuit-relay/server/advert-service.d.ts.map +1 -1
  11. package/dist/src/circuit-relay/server/advert-service.js +2 -2
  12. package/dist/src/circuit-relay/server/advert-service.js.map +1 -1
  13. package/dist/src/circuit-relay/server/index.d.ts.map +1 -1
  14. package/dist/src/circuit-relay/server/index.js +7 -3
  15. package/dist/src/circuit-relay/server/index.js.map +1 -1
  16. package/dist/src/circuit-relay/transport/discovery.d.ts.map +1 -1
  17. package/dist/src/circuit-relay/transport/discovery.js +3 -1
  18. package/dist/src/circuit-relay/transport/discovery.js.map +1 -1
  19. package/dist/src/circuit-relay/transport/index.d.ts +3 -0
  20. package/dist/src/circuit-relay/transport/index.d.ts.map +1 -1
  21. package/dist/src/circuit-relay/transport/index.js +6 -2
  22. package/dist/src/circuit-relay/transport/index.js.map +1 -1
  23. package/dist/src/circuit-relay/transport/listener.d.ts +3 -0
  24. package/dist/src/circuit-relay/transport/listener.d.ts.map +1 -1
  25. package/dist/src/circuit-relay/transport/listener.js +5 -4
  26. package/dist/src/circuit-relay/transport/listener.js.map +1 -1
  27. package/dist/src/circuit-relay/transport/reservation-store.d.ts +4 -1
  28. package/dist/src/circuit-relay/transport/reservation-store.d.ts.map +1 -1
  29. package/dist/src/circuit-relay/transport/reservation-store.js +11 -6
  30. package/dist/src/circuit-relay/transport/reservation-store.js.map +1 -1
  31. package/dist/src/circuit-relay/utils.d.ts.map +1 -1
  32. package/dist/src/circuit-relay/utils.js +3 -1
  33. package/dist/src/circuit-relay/utils.js.map +1 -1
  34. package/dist/src/components.d.ts +8 -6
  35. package/dist/src/components.d.ts.map +1 -1
  36. package/dist/src/components.js +10 -10
  37. package/dist/src/components.js.map +1 -1
  38. package/dist/src/config.d.ts.map +1 -1
  39. package/dist/src/config.js +0 -9
  40. package/dist/src/config.js.map +1 -1
  41. package/dist/src/connection-manager/auto-dial.d.ts +39 -0
  42. package/dist/src/connection-manager/auto-dial.d.ts.map +1 -0
  43. package/dist/src/connection-manager/auto-dial.js +131 -0
  44. package/dist/src/connection-manager/auto-dial.js.map +1 -0
  45. package/dist/src/connection-manager/connection-pruner.d.ts +32 -0
  46. package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -0
  47. package/dist/src/connection-manager/connection-pruner.js +111 -0
  48. package/dist/src/connection-manager/connection-pruner.js.map +1 -0
  49. package/dist/src/connection-manager/constants.d.ts +49 -0
  50. package/dist/src/connection-manager/constants.d.ts.map +1 -0
  51. package/dist/src/connection-manager/constants.js +49 -0
  52. package/dist/src/connection-manager/constants.js.map +1 -0
  53. package/dist/src/connection-manager/dial-queue.d.ts +78 -0
  54. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -0
  55. package/dist/src/connection-manager/dial-queue.js +374 -0
  56. package/dist/src/connection-manager/dial-queue.js.map +1 -0
  57. package/dist/src/connection-manager/index.d.ts +70 -73
  58. package/dist/src/connection-manager/index.d.ts.map +1 -1
  59. package/dist/src/connection-manager/index.js +116 -248
  60. package/dist/src/connection-manager/index.js.map +1 -1
  61. package/dist/src/connection-manager/utils.d.ts +9 -0
  62. package/dist/src/connection-manager/utils.d.ts.map +1 -0
  63. package/dist/src/connection-manager/utils.js +66 -0
  64. package/dist/src/connection-manager/utils.js.map +1 -0
  65. package/dist/src/content-routing/index.js +1 -1
  66. package/dist/src/content-routing/index.js.map +1 -1
  67. package/dist/src/content-routing/utils.d.ts.map +1 -1
  68. package/dist/src/content-routing/utils.js +3 -1
  69. package/dist/src/content-routing/utils.js.map +1 -1
  70. package/dist/src/fetch/index.js +3 -3
  71. package/dist/src/fetch/index.js.map +1 -1
  72. package/dist/src/identify/index.d.ts +4 -0
  73. package/dist/src/identify/index.d.ts.map +1 -1
  74. package/dist/src/identify/index.js +104 -128
  75. package/dist/src/identify/index.js.map +1 -1
  76. package/dist/src/index.d.ts +2 -19
  77. package/dist/src/index.d.ts.map +1 -1
  78. package/dist/src/index.js.map +1 -1
  79. package/dist/src/insecure/index.d.ts.map +1 -1
  80. package/dist/src/insecure/index.js +3 -1
  81. package/dist/src/insecure/index.js.map +1 -1
  82. package/dist/src/libp2p.d.ts +5 -3
  83. package/dist/src/libp2p.d.ts.map +1 -1
  84. package/dist/src/libp2p.js +47 -50
  85. package/dist/src/libp2p.js.map +1 -1
  86. package/dist/src/registrar.d.ts +5 -2
  87. package/dist/src/registrar.d.ts.map +1 -1
  88. package/dist/src/registrar.js +25 -23
  89. package/dist/src/registrar.js.map +1 -1
  90. package/dist/src/transport-manager.d.ts +9 -3
  91. package/dist/src/transport-manager.d.ts.map +1 -1
  92. package/dist/src/transport-manager.js +23 -9
  93. package/dist/src/transport-manager.js.map +1 -1
  94. package/dist/src/upgrader.d.ts +14 -11
  95. package/dist/src/upgrader.d.ts.map +1 -1
  96. package/dist/src/upgrader.js +14 -10
  97. package/dist/src/upgrader.js.map +1 -1
  98. package/package.json +46 -45
  99. package/src/address-manager/index.ts +12 -8
  100. package/src/autonat/index.ts +6 -9
  101. package/src/circuit-relay/server/advert-service.ts +2 -2
  102. package/src/circuit-relay/server/index.ts +7 -3
  103. package/src/circuit-relay/transport/discovery.ts +3 -1
  104. package/src/circuit-relay/transport/index.ts +10 -2
  105. package/src/circuit-relay/transport/listener.ts +8 -4
  106. package/src/circuit-relay/transport/reservation-store.ts +15 -7
  107. package/src/circuit-relay/utils.ts +3 -1
  108. package/src/components.ts +19 -17
  109. package/src/config.ts +0 -9
  110. package/src/connection-manager/auto-dial.ts +183 -0
  111. package/src/connection-manager/connection-pruner.ts +157 -0
  112. package/src/connection-manager/constants.ts +60 -0
  113. package/src/connection-manager/dial-queue.ts +512 -0
  114. package/src/connection-manager/index.ts +191 -340
  115. package/src/connection-manager/utils.ts +76 -0
  116. package/src/content-routing/index.ts +1 -1
  117. package/src/content-routing/utils.ts +3 -1
  118. package/src/fetch/index.ts +4 -4
  119. package/src/identify/index.ts +100 -140
  120. package/src/index.ts +2 -20
  121. package/src/insecure/index.ts +9 -5
  122. package/src/libp2p.ts +54 -60
  123. package/src/registrar.ts +29 -25
  124. package/src/transport-manager.ts +31 -11
  125. package/src/upgrader.ts +31 -22
  126. package/src/version.ts +1 -1
  127. package/dist/src/connection-manager/auto-dialler.d.ts +0 -42
  128. package/dist/src/connection-manager/auto-dialler.d.ts.map +0 -1
  129. package/dist/src/connection-manager/auto-dialler.js +0 -105
  130. package/dist/src/connection-manager/auto-dialler.js.map +0 -1
  131. package/dist/src/connection-manager/dialer/dial-request.d.ts +0 -27
  132. package/dist/src/connection-manager/dialer/dial-request.d.ts.map +0 -1
  133. package/dist/src/connection-manager/dialer/dial-request.js +0 -114
  134. package/dist/src/connection-manager/dialer/dial-request.js.map +0 -1
  135. package/dist/src/connection-manager/dialer/index.d.ts +0 -121
  136. package/dist/src/connection-manager/dialer/index.d.ts.map +0 -1
  137. package/dist/src/connection-manager/dialer/index.js +0 -324
  138. package/dist/src/connection-manager/dialer/index.js.map +0 -1
  139. package/dist/src/connection-manager/latency-monitor.d.ts +0 -120
  140. package/dist/src/connection-manager/latency-monitor.d.ts.map +0 -1
  141. package/dist/src/connection-manager/latency-monitor.js +0 -220
  142. package/dist/src/connection-manager/latency-monitor.js.map +0 -1
  143. package/dist/src/connection-manager/visibility-change-emitter.d.ts +0 -66
  144. package/dist/src/connection-manager/visibility-change-emitter.d.ts.map +0 -1
  145. package/dist/src/connection-manager/visibility-change-emitter.js +0 -118
  146. package/dist/src/connection-manager/visibility-change-emitter.js.map +0 -1
  147. package/dist/src/constants.d.ts +0 -27
  148. package/dist/src/constants.d.ts.map +0 -1
  149. package/dist/src/constants.js +0 -31
  150. package/dist/src/constants.js.map +0 -1
  151. package/dist/src/peer-record-updater.d.ts +0 -24
  152. package/dist/src/peer-record-updater.d.ts.map +0 -1
  153. package/dist/src/peer-record-updater.js +0 -44
  154. package/dist/src/peer-record-updater.js.map +0 -1
  155. package/dist/typedoc-urls.json +0 -41
  156. package/src/connection-manager/auto-dialler.ts +0 -158
  157. package/src/connection-manager/dialer/dial-request.ts +0 -144
  158. package/src/connection-manager/dialer/index.ts +0 -461
  159. package/src/connection-manager/latency-monitor.ts +0 -319
  160. package/src/connection-manager/visibility-change-emitter.ts +0 -135
  161. package/src/constants.ts +0 -36
  162. package/src/peer-record-updater.ts +0 -65
@@ -0,0 +1,76 @@
1
+ import { AbortOptions, multiaddr } from '@multiformats/multiaddr'
2
+ import type { Multiaddr } from '@multiformats/multiaddr'
3
+ import { logger } from '@libp2p/logger'
4
+ import { ClearableSignal, anySignal } from 'any-signal'
5
+ import { setMaxListeners } from 'events'
6
+
7
+ const log = logger('libp2p:connection-manager:utils')
8
+
9
+ /**
10
+ * Resolve multiaddr recursively
11
+ */
12
+ export async function resolveMultiaddrs (ma: Multiaddr, options: AbortOptions): Promise<Multiaddr[]> {
13
+ // TODO: recursive logic should live in multiaddr once dns4/dns6 support is in place
14
+ // Now only supporting resolve for dnsaddr
15
+ const resolvableProto = ma.protoNames().includes('dnsaddr')
16
+
17
+ // Multiaddr is not resolvable? End recursion!
18
+ if (!resolvableProto) {
19
+ return [ma]
20
+ }
21
+
22
+ const resolvedMultiaddrs = await resolveRecord(ma, options)
23
+ const recursiveMultiaddrs = await Promise.all(resolvedMultiaddrs.map(async (nm) => {
24
+ return await resolveMultiaddrs(nm, options)
25
+ }))
26
+
27
+ const addrs = recursiveMultiaddrs.flat()
28
+ const output = addrs.reduce<Multiaddr[]>((array, newM) => {
29
+ if (array.find(m => m.equals(newM)) == null) {
30
+ array.push(newM)
31
+ }
32
+ return array
33
+ }, ([]))
34
+
35
+ log('resolved %s to', ma, output.map(ma => ma.toString()))
36
+
37
+ return output
38
+ }
39
+
40
+ /**
41
+ * Resolve a given multiaddr. If this fails, an empty array will be returned
42
+ */
43
+ async function resolveRecord (ma: Multiaddr, options: AbortOptions): Promise<Multiaddr[]> {
44
+ try {
45
+ ma = multiaddr(ma.toString()) // Use current multiaddr module
46
+ const multiaddrs = await ma.resolve(options)
47
+ return multiaddrs
48
+ } catch (err) {
49
+ log.error(`multiaddr ${ma.toString()} could not be resolved`, err)
50
+ return []
51
+ }
52
+ }
53
+
54
+ export function combineSignals (...signals: Array<AbortSignal | undefined>): ClearableSignal {
55
+ const sigs: AbortSignal[] = []
56
+
57
+ for (const sig of signals) {
58
+ if (sig != null) {
59
+ try {
60
+ // fails on node < 15.4
61
+ setMaxListeners?.(Infinity, sig)
62
+ } catch { }
63
+ sigs.push(sig)
64
+ }
65
+ }
66
+
67
+ // let any signal abort the dial
68
+ const signal = anySignal(sigs)
69
+
70
+ try {
71
+ // fails on node < 15.4
72
+ setMaxListeners?.(Infinity, signal)
73
+ } catch {}
74
+
75
+ return signal
76
+ }
@@ -54,7 +54,7 @@ export class CompoundContentRouting implements ContentRouting, Startable {
54
54
  */
55
55
  async * findProviders (key: CID, options: AbortOptions = {}): AsyncIterable<PeerInfo> {
56
56
  if (this.routers.length === 0) {
57
- throw new CodeError('No content this.routers available', codes.ERR_NO_ROUTERS_AVAILABLE)
57
+ throw new CodeError('No content routers available', codes.ERR_NO_ROUTERS_AVAILABLE)
58
58
  }
59
59
 
60
60
  yield * pipe(
@@ -11,7 +11,9 @@ import type { PeerStore } from '@libp2p/interface-peer-store'
11
11
  export async function * storeAddresses (source: Source<PeerInfo>, peerStore: PeerStore): AsyncIterable<PeerInfo> {
12
12
  yield * map(source, async (peer) => {
13
13
  // ensure we have the addresses for a given peer
14
- await peerStore.addressBook.add(peer.id, peer.multiaddrs)
14
+ await peerStore.merge(peer.id, {
15
+ multiaddrs: peer.multiaddrs
16
+ })
15
17
 
16
18
  return peer
17
19
  })
@@ -127,9 +127,9 @@ export class FetchService implements Startable {
127
127
 
128
128
  const result = await pipe(
129
129
  [FetchRequest.encode({ identifier: key })],
130
- lp.encode(),
130
+ (source) => lp.encode(source),
131
131
  source,
132
- lp.decode(),
132
+ (source) => lp.decode(source),
133
133
  async function (source) {
134
134
  const buf = await first(source)
135
135
 
@@ -184,7 +184,7 @@ export class FetchService implements Startable {
184
184
 
185
185
  await pipe(
186
186
  stream,
187
- lp.decode(),
187
+ (source) => lp.decode(source),
188
188
  async function * (source) {
189
189
  const buf = await first(source)
190
190
 
@@ -215,7 +215,7 @@ export class FetchService implements Startable {
215
215
 
216
216
  yield FetchResponse.encode(response)
217
217
  },
218
- lp.encode(),
218
+ (source) => lp.encode(source),
219
219
  stream
220
220
  )
221
221
  }
@@ -27,8 +27,12 @@ import { abortableDuplex } from 'abortable-iterator'
27
27
  import { setMaxListeners } from 'events'
28
28
  import type { ConnectionManager } from '@libp2p/interface-connection-manager'
29
29
  import type { PeerId } from '@libp2p/interface-peer-id'
30
- import type { PeerStore } from '@libp2p/interface-peer-store'
30
+ import type { Peer, PeerStore } from '@libp2p/interface-peer-store'
31
31
  import type { AddressManager } from '@libp2p/interface-address-manager'
32
+ import type { EventEmitter } from '@libp2p/interfaces/events'
33
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
34
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
35
+ import { pbStream } from 'it-pb-stream'
32
36
 
33
37
  const log = logger('libp2p:identify')
34
38
 
@@ -74,6 +78,7 @@ export interface IdentifyServiceComponents {
74
78
  connectionManager: ConnectionManager
75
79
  registrar: Registrar
76
80
  addressManager: AddressManager
81
+ events: EventEmitter<Libp2pEvents>
77
82
  }
78
83
 
79
84
  export class IdentifyService implements Startable {
@@ -103,27 +108,14 @@ export class IdentifyService implements Startable {
103
108
  }
104
109
 
105
110
  // When a new connection happens, trigger identify
106
- this.components.connectionManager.addEventListener('peer:connect', (evt) => {
111
+ this.components.events.addEventListener('connection:open', (evt) => {
107
112
  const connection = evt.detail
108
- this.identify(connection).catch(log.error)
113
+ this.identify(connection).catch(err => { log.error('error during identify trigged by connection:open', err) })
109
114
  })
110
115
 
111
- // When self multiaddrs change, trigger identify-push
112
- this.components.peerStore.addEventListener('change:multiaddrs', (evt) => {
113
- const { peerId } = evt.detail
114
-
115
- if (this.components.peerId.equals(peerId)) {
116
- void this.pushToPeerStore().catch(err => { log.error(err) })
117
- }
118
- })
119
-
120
- // When self protocols change, trigger identify-push
121
- this.components.peerStore.addEventListener('change:protocols', (evt) => {
122
- const { peerId } = evt.detail
123
-
124
- if (this.components.peerId.equals(peerId)) {
125
- void this.pushToPeerStore().catch(err => { log.error(err) })
126
- }
116
+ // When self peer record changes, trigger identify-push
117
+ this.components.events.addEventListener('self:peer:update', (evt) => {
118
+ void this.pushToPeerStore().catch(err => { log.error(err) })
127
119
  })
128
120
  }
129
121
 
@@ -136,8 +128,12 @@ export class IdentifyService implements Startable {
136
128
  return
137
129
  }
138
130
 
139
- await this.components.peerStore.metadataBook.setValue(this.components.peerId, 'AgentVersion', uint8ArrayFromString(this.host.agentVersion))
140
- await this.components.peerStore.metadataBook.setValue(this.components.peerId, 'ProtocolVersion', uint8ArrayFromString(this.host.protocolVersion))
131
+ await this.components.peerStore.merge(this.components.peerId, {
132
+ metadata: {
133
+ AgentVersion: uint8ArrayFromString(this.host.agentVersion),
134
+ ProtocolVersion: uint8ArrayFromString(this.host.protocolVersion)
135
+ }
136
+ })
141
137
 
142
138
  await this.components.registrar.handle(this.identifyProtocolStr, (data) => {
143
139
  void this._handleIdentify(data).catch(err => {
@@ -170,9 +166,16 @@ export class IdentifyService implements Startable {
170
166
  * Send an Identify Push update to the list of connections
171
167
  */
172
168
  async push (connections: Connection[]): Promise<void> {
173
- const signedPeerRecord = await this.components.peerStore.addressBook.getRawEnvelope(this.components.peerId)
174
- const listenAddrs = this.components.addressManager.getAddresses().map((ma) => ma.bytes)
175
- const protocols = await this.components.peerStore.protoBook.get(this.components.peerId)
169
+ const listenAddresses = this.components.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code))
170
+ const peerRecord = new PeerRecord({
171
+ peerId: this.components.peerId,
172
+ multiaddrs: listenAddresses
173
+ })
174
+ const signedPeerRecord = await RecordEnvelope.seal(peerRecord, this.components.peerId)
175
+ const supportedProtocols = this.components.registrar.getProtocols()
176
+ const peer = await this.components.peerStore.get(this.components.peerId)
177
+ const agentVersion = uint8ArrayToString(peer.metadata.get('AgentVersion') ?? uint8ArrayFromString(this.host.agentVersion))
178
+ const protocolVersion = uint8ArrayToString(peer.metadata.get('ProtocolVersion') ?? uint8ArrayFromString(this.host.protocolVersion))
176
179
 
177
180
  const pushes = connections.map(async connection => {
178
181
  let stream: Stream | undefined
@@ -193,11 +196,13 @@ export class IdentifyService implements Startable {
193
196
 
194
197
  await source.sink(pipe(
195
198
  [Identify.encode({
196
- listenAddrs,
197
- signedPeerRecord,
198
- protocols
199
+ listenAddrs: listenAddresses.map(ma => ma.bytes),
200
+ signedPeerRecord: signedPeerRecord.marshal(),
201
+ protocols: supportedProtocols,
202
+ agentVersion,
203
+ protocolVersion
199
204
  })],
200
- lp.encode()
205
+ (source) => lp.encode(source)
201
206
  ))
202
207
  } catch (err: any) {
203
208
  // Just log errors
@@ -266,7 +271,7 @@ export class IdentifyService implements Startable {
266
271
  const data = await pipe(
267
272
  [],
268
273
  source,
269
- lp.decode({
274
+ (source) => lp.decode(source, {
270
275
  maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
271
276
  }),
272
277
  async (source) => await first(source)
@@ -299,15 +304,10 @@ export class IdentifyService implements Startable {
299
304
  */
300
305
  async identify (connection: Connection, options: AbortOptions = {}): Promise<void> {
301
306
  const message = await this._identify(connection, options)
302
-
303
307
  const {
304
308
  publicKey,
305
- listenAddrs,
306
309
  protocols,
307
- observedAddr,
308
- signedPeerRecord,
309
- agentVersion,
310
- protocolVersion
310
+ observedAddr
311
311
  } = message
312
312
 
313
313
  if (publicKey == null) {
@@ -327,57 +327,6 @@ export class IdentifyService implements Startable {
327
327
  // Get the observedAddr if there is one
328
328
  const cleanObservedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
329
329
 
330
- if (signedPeerRecord != null) {
331
- log('received signed peer record from %p', id)
332
-
333
- try {
334
- const envelope = await RecordEnvelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN)
335
-
336
- if (!envelope.peerId.equals(id)) {
337
- throw new CodeError('identified peer does not match the expected peer', codes.ERR_INVALID_PEER)
338
- }
339
-
340
- if (await this.components.peerStore.addressBook.consumePeerRecord(envelope)) {
341
- await this.components.peerStore.protoBook.set(id, protocols)
342
-
343
- if (agentVersion != null) {
344
- await this.components.peerStore.metadataBook.setValue(id, 'AgentVersion', uint8ArrayFromString(agentVersion))
345
- }
346
-
347
- if (protocolVersion != null) {
348
- await this.components.peerStore.metadataBook.setValue(id, 'ProtocolVersion', uint8ArrayFromString(protocolVersion))
349
- }
350
-
351
- log('identify completed for peer %p with and protocols %o', id, protocols)
352
-
353
- return
354
- }
355
- } catch (err: any) {
356
- log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
357
- }
358
- } else {
359
- log('no signed peer record received from %p', id)
360
- }
361
-
362
- log('falling back to legacy addresses from %p', id)
363
-
364
- // LEGACY: Update peers data in PeerStore
365
- try {
366
- await this.components.peerStore.addressBook.set(id, listenAddrs.map((addr) => multiaddr(addr)))
367
- } catch (err: any) {
368
- log.error('received invalid addrs', err)
369
- }
370
-
371
- await this.components.peerStore.protoBook.set(id, protocols)
372
-
373
- if (agentVersion != null) {
374
- await this.components.peerStore.metadataBook.setValue(id, 'AgentVersion', uint8ArrayFromString(agentVersion))
375
- }
376
-
377
- if (protocolVersion != null) {
378
- await this.components.peerStore.metadataBook.setValue(id, 'ProtocolVersion', uint8ArrayFromString(protocolVersion))
379
- }
380
-
381
330
  log('identify completed for peer %p and protocols %o', id, protocols)
382
331
  log('our observed address is %s', cleanObservedAddr)
383
332
 
@@ -386,6 +335,8 @@ export class IdentifyService implements Startable {
386
335
  log('storing our observed address %s', cleanObservedAddr?.toString())
387
336
  this.components.addressManager.addObservedAddr(cleanObservedAddr)
388
337
  }
338
+
339
+ await this.#consumeIdentifyMessage(connection.remotePeer, message)
389
340
  }
390
341
 
391
342
  /**
@@ -414,7 +365,6 @@ export class IdentifyService implements Startable {
414
365
  })
415
366
 
416
367
  const envelope = await RecordEnvelope.seal(peerRecord, this.components.peerId)
417
- await this.components.peerStore.addressBook.consumePeerRecord(envelope)
418
368
  signedPeerRecord = envelope.marshal().subarray()
419
369
  }
420
370
 
@@ -431,7 +381,7 @@ export class IdentifyService implements Startable {
431
381
  // make stream abortable
432
382
  const source = abortableDuplex(stream, timeoutController.signal)
433
383
 
434
- const msgWithLenPrefix = pipe([message], lp.encode())
384
+ const msgWithLenPrefix = pipe([message], (source) => lp.encode(source))
435
385
  await source.sink(msgWithLenPrefix)
436
386
  } catch (err: any) {
437
387
  log.error('could not respond to identify request', err)
@@ -446,88 +396,98 @@ export class IdentifyService implements Startable {
446
396
  */
447
397
  async _handlePush (data: IncomingStreamData): Promise<void> {
448
398
  const { connection, stream } = data
449
- const timeoutController = new TimeoutController(this.init.timeout)
450
399
 
451
400
  try {
452
- // fails on node < 15.4
453
- setMaxListeners?.(Infinity, timeoutController.signal)
454
- } catch {}
401
+ if (this.components.peerId.equals(connection.remotePeer)) {
402
+ throw new Error('received push from ourselves?')
403
+ }
455
404
 
456
- let message: Identify | undefined
457
- try {
458
405
  // make stream abortable
459
- const source = abortableDuplex(stream, timeoutController.signal)
460
-
461
- const data = await pipe(
462
- [],
463
- source,
464
- lp.decode({
465
- maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
466
- }),
467
- async (source) => await first(source)
468
- )
406
+ const source = abortableDuplex(stream, AbortSignal.timeout(this.init.timeout))
407
+ const pb = pbStream(source, {
408
+ maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
409
+ })
410
+ const message = await pb.readPB(Identify)
469
411
 
470
- if (data != null) {
471
- message = Identify.decode(data)
472
- }
412
+ await this.#consumeIdentifyMessage(connection.remotePeer, message)
473
413
  } catch (err: any) {
474
414
  log.error('received invalid message', err)
475
415
  return
476
416
  } finally {
477
417
  stream.close()
478
- timeoutController.clear()
479
418
  }
480
419
 
420
+ log('handled push from %p', connection.remotePeer)
421
+ }
422
+
423
+ async #consumeIdentifyMessage (remotePeer: PeerId, message: Identify): Promise<void> {
481
424
  if (message == null) {
482
- log.error('received invalid message')
483
- return
425
+ throw new Error('Message was null or undefined')
484
426
  }
485
427
 
486
- const id = connection.remotePeer
428
+ log('received identify from %p', remotePeer)
487
429
 
488
- if (this.components.peerId.equals(id)) {
489
- log('received push from ourselves?')
430
+ if (message.signedPeerRecord == null) {
490
431
  return
491
432
  }
492
433
 
493
- log('received push from %p', id)
434
+ const envelope = await RecordEnvelope.openAndCertify(message.signedPeerRecord, PeerRecord.DOMAIN)
435
+ const peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
494
436
 
495
- if (message.signedPeerRecord != null) {
496
- log('received signedPeerRecord in push')
437
+ // Verify peerId
438
+ if (!peerRecord.peerId.equals(envelope.peerId)) {
439
+ throw new Error('signing key does not match PeerId in the PeerRecord')
440
+ }
497
441
 
498
- try {
499
- const envelope = await RecordEnvelope.openAndCertify(message.signedPeerRecord, PeerRecord.DOMAIN)
442
+ // Make sure remote peer is the one sending the record
443
+ if (!remotePeer.equals(peerRecord.peerId)) {
444
+ throw new Error('signing key does not match remote PeerId')
445
+ }
500
446
 
501
- if (await this.components.peerStore.addressBook.consumePeerRecord(envelope)) {
502
- log('consumed signedPeerRecord sent in push')
447
+ let peer: Peer | undefined
503
448
 
504
- await this.components.peerStore.protoBook.set(id, message.protocols)
505
- return
506
- } else {
507
- log('failed to consume signedPeerRecord sent in push')
508
- }
509
- } catch (err: any) {
510
- log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
449
+ try {
450
+ peer = await this.components.peerStore.get(peerRecord.peerId)
451
+ } catch (err: any) {
452
+ if (err.code !== 'ERR_NOT_FOUND') {
453
+ throw err
511
454
  }
512
- } else {
513
- log('did not receive signedPeerRecord in push')
514
455
  }
515
456
 
516
- // LEGACY: Update peers data in PeerStore
517
- try {
518
- await this.components.peerStore.addressBook.set(id, message.listenAddrs.map((addr) => multiaddr(addr)))
519
- } catch (err: any) {
520
- log.error('received invalid addrs', err)
457
+ log('received signedPeerRecord in push from %p', remotePeer)
458
+ let metadata = new Map()
459
+
460
+ if (peer?.peerRecordEnvelope != null) {
461
+ const storedEnvelope = await RecordEnvelope.createFromProtobuf(peer.peerRecordEnvelope)
462
+ const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload)
463
+
464
+ // ensure seq is greater than, or equal to, the last received
465
+ if (storedRecord.seqNumber >= peerRecord.seqNumber) {
466
+ log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber)
467
+ }
468
+
469
+ metadata = peer.metadata
521
470
  }
522
471
 
523
- // Update the protocols
524
- try {
525
- await this.components.peerStore.protoBook.set(id, message.protocols)
526
- } catch (err: any) {
527
- log.error('received invalid protocols', err)
472
+ if (message.agentVersion != null) {
473
+ metadata.set('AgentVersion', uint8ArrayFromString(message.agentVersion))
528
474
  }
529
475
 
530
- log('handled push from %p', id)
476
+ if (message.protocolVersion != null) {
477
+ metadata.set('ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
478
+ }
479
+
480
+ await this.components.peerStore.patch(peerRecord.peerId, {
481
+ peerRecordEnvelope: message.signedPeerRecord,
482
+ protocols: message.protocols,
483
+ addresses: peerRecord.multiaddrs.map(multiaddr => ({
484
+ isCertified: true,
485
+ multiaddr
486
+ })),
487
+ metadata
488
+ })
489
+
490
+ log('consumed signedPeerRecord sent in push from %p', remotePeer)
531
491
  }
532
492
 
533
493
  /**
package/src/index.ts CHANGED
@@ -20,7 +20,6 @@ import type { TransportManagerInit } from './transport-manager.js'
20
20
  import type { IdentifyServiceInit } from './identify/index.js'
21
21
  import type { DualDHT } from '@libp2p/interface-dht'
22
22
  import type { Datastore } from 'interface-datastore'
23
- import type { PeerStoreInit } from '@libp2p/interface-peer-store'
24
23
  import type { PeerId } from '@libp2p/interface-peer-id'
25
24
  import type { PeerDiscovery } from '@libp2p/interface-peer-discovery'
26
25
  import type { ConnectionProtector } from '@libp2p/interface-connection'
@@ -32,7 +31,6 @@ import type { PeerRouting } from '@libp2p/interface-peer-routing'
32
31
  import type { ContentRouting } from '@libp2p/interface-content-routing'
33
32
  import type { PubSub } from '@libp2p/interface-pubsub'
34
33
  import type { Metrics } from '@libp2p/interface-metrics'
35
- import type { PeerInfo } from '@libp2p/interface-peer-info'
36
34
  import type { PingServiceInit } from './ping/index.js'
37
35
  import type { FetchServiceInit } from './fetch/index.js'
38
36
  import type { AutonatServiceInit } from './autonat/index.js'
@@ -44,6 +42,7 @@ import type { AddressManagerInit } from './address-manager/index.js'
44
42
  import type { PeerRoutingInit } from './peer-routing.js'
45
43
  import type { ConnectionManagerInit } from './connection-manager/index.js'
46
44
  import type { CircuitRelayService } from './circuit-relay/index.js'
45
+ import type { PersistentPeerStoreInit } from '@libp2p/peer-store'
47
46
 
48
47
  /**
49
48
  * For Libp2p configurations and modules details read the [Configuration Document](./CONFIGURATION.md).
@@ -84,7 +83,7 @@ export interface Libp2pInit {
84
83
  /**
85
84
  * libp2p PeerStore configuration
86
85
  */
87
- peerStore: PeerStoreInit
86
+ peerStore: PersistentPeerStoreInit
88
87
 
89
88
  /**
90
89
  * libp2p Peer routing service configuration
@@ -158,23 +157,6 @@ export interface Libp2pInit {
158
157
  connectionProtector?: (components: Components) => ConnectionProtector
159
158
  }
160
159
 
161
- /**
162
- * Once you have a libp2p instance, you can listen to several events it emits, so that you can be notified of relevant network events.
163
- */
164
- export interface Libp2pEvents {
165
- /**
166
- * @example
167
- *
168
- * ```js
169
- * libp2p.addEventListener('peer:discovery', (event) => {
170
- * const peerInfo = event.detail
171
- * // ...
172
- * })
173
- * ```
174
- */
175
- 'peer:discovery': CustomEvent<PeerInfo>
176
- }
177
-
178
160
  export type { Libp2p }
179
161
 
180
162
  export type Libp2pOptions = RecursivePartial<Libp2pInit> & { start?: boolean }
@@ -30,7 +30,7 @@ import { Exchange, KeyType } from './pb/proto.js'
30
30
  import type { PeerId } from '@libp2p/interface-peer-id'
31
31
  import { peerIdFromBytes, peerIdFromKeys } from '@libp2p/peer-id'
32
32
  import type { ConnectionEncrypter, SecuredConnection } from '@libp2p/interface-connection-encrypter'
33
- import type { Duplex } from 'it-stream-types'
33
+ import type { Duplex, Source } from 'it-stream-types'
34
34
  import map from 'it-map'
35
35
  import type { Uint8ArrayList } from 'uint8arraylist'
36
36
 
@@ -46,7 +46,7 @@ function lpEncodeExchange (exchange: Exchange): Uint8ArrayList {
46
46
  /**
47
47
  * Encrypt connection
48
48
  */
49
- async function encrypt (localId: PeerId, conn: Duplex<Uint8Array>, remoteId?: PeerId): Promise<SecuredConnection> {
49
+ async function encrypt (localId: PeerId, conn: Duplex<AsyncGenerator<Uint8Array>, Source<Uint8Array>, Promise<void>>, remoteId?: PeerId): Promise<SecuredConnection> {
50
50
  const shake = handshake(conn)
51
51
 
52
52
  let type = KeyType.RSA
@@ -71,8 +71,12 @@ async function encrypt (localId: PeerId, conn: Duplex<Uint8Array>, remoteId?: Pe
71
71
  log('write pubkey exchange to peer %p', remoteId)
72
72
 
73
73
  // Get the Exchange message
74
- // @ts-expect-error needs to be generator
75
74
  const response = (await lp.decode.fromReader(shake.reader).next()).value
75
+
76
+ if (response == null) {
77
+ throw new Error('Did not read response')
78
+ }
79
+
76
80
  const id = Exchange.decode(response)
77
81
  log('read pubkey exchange from peer %p', remoteId)
78
82
 
@@ -120,11 +124,11 @@ async function encrypt (localId: PeerId, conn: Duplex<Uint8Array>, remoteId?: Pe
120
124
  class Plaintext implements ConnectionEncrypter {
121
125
  public protocol: string = PROTOCOL
122
126
 
123
- async secureInbound (localId: PeerId, conn: Duplex<Uint8Array>, remoteId?: PeerId): Promise<SecuredConnection> {
127
+ async secureInbound (localId: PeerId, conn: Duplex<AsyncGenerator<Uint8Array>, Source<Uint8Array>, Promise<void>>, remoteId?: PeerId): Promise<SecuredConnection> {
124
128
  return await encrypt(localId, conn, remoteId)
125
129
  }
126
130
 
127
- async secureOutbound (localId: PeerId, conn: Duplex<Uint8Array>, remoteId?: PeerId): Promise<SecuredConnection> {
131
+ async secureOutbound (localId: PeerId, conn: Duplex<AsyncGenerator<Uint8Array>, Source<Uint8Array>, Promise<void>>, remoteId?: PeerId): Promise<SecuredConnection> {
128
132
  return await encrypt(localId, conn, remoteId)
129
133
  }
130
134
  }