@libp2p/identify 1.0.21 → 2.0.0-4ad63bb79

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.
@@ -0,0 +1,146 @@
1
+ /* eslint-disable complexity */
2
+
3
+ import { setMaxListeners } from '@libp2p/interface'
4
+ import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
5
+ import { protocols } from '@multiformats/multiaddr'
6
+ import drain from 'it-drain'
7
+ import parallel from 'it-parallel'
8
+ import { pbStream } from 'it-protobuf-stream'
9
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
10
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
11
+ import {
12
+ MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME,
13
+ MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION
14
+ } from './consts.js'
15
+ import { Identify as IdentifyMessage } from './pb/message.js'
16
+ import { AbstractIdentify, consumeIdentifyMessage, defaultValues } from './utils.js'
17
+ import type { IdentifyPush as IdentifyPushInterface, IdentifyPushComponents, IdentifyPushInit } from './index.js'
18
+ import type { Stream, Startable } from '@libp2p/interface'
19
+ import type { ConnectionManager, IncomingStreamData } from '@libp2p/interface-internal'
20
+
21
+ export class IdentifyPush extends AbstractIdentify implements Startable, IdentifyPushInterface {
22
+ private readonly connectionManager: ConnectionManager
23
+ private readonly concurrency: number
24
+
25
+ constructor (components: IdentifyPushComponents, init: IdentifyPushInit = {}) {
26
+ super(components, {
27
+ ...init,
28
+ protocol: `/${init.protocolPrefix ?? defaultValues.protocolPrefix}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION}`,
29
+ log: components.logger.forComponent('libp2p:identify-push')
30
+ })
31
+
32
+ this.connectionManager = components.connectionManager
33
+ this.concurrency = init.concurrency ?? defaultValues.concurrency
34
+
35
+ if ((init.runOnSelfUpdate ?? defaultValues.runOnSelfUpdate)) {
36
+ // When self peer record changes, trigger identify-push
37
+ components.events.addEventListener('self:peer:update', (evt) => {
38
+ void this.push().catch(err => { this.log.error(err) })
39
+ })
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Calls `push` on all peer connections
45
+ */
46
+ async push (): Promise<void> {
47
+ // Do not try to push if we are not running
48
+ if (!this.isStarted()) {
49
+ return
50
+ }
51
+
52
+ const listenAddresses = this.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code))
53
+ const peerRecord = new PeerRecord({
54
+ peerId: this.peerId,
55
+ multiaddrs: listenAddresses
56
+ })
57
+ const signedPeerRecord = await RecordEnvelope.seal(peerRecord, this.peerId)
58
+ const supportedProtocols = this.registrar.getProtocols()
59
+ const peer = await this.peerStore.get(this.peerId)
60
+ const agentVersion = uint8ArrayToString(peer.metadata.get('AgentVersion') ?? uint8ArrayFromString(this.host.agentVersion))
61
+ const protocolVersion = uint8ArrayToString(peer.metadata.get('ProtocolVersion') ?? uint8ArrayFromString(this.host.protocolVersion))
62
+ const self = this
63
+
64
+ async function * pushToConnections (): AsyncGenerator<() => Promise<void>> {
65
+ for (const connection of self.connectionManager.getConnections()) {
66
+ const peer = await self.peerStore.get(connection.remotePeer)
67
+
68
+ if (!peer.protocols.includes(self.protocol)) {
69
+ continue
70
+ }
71
+
72
+ yield async () => {
73
+ let stream: Stream | undefined
74
+ const signal = AbortSignal.timeout(self.timeout)
75
+
76
+ setMaxListeners(Infinity, signal)
77
+
78
+ try {
79
+ stream = await connection.newStream(self.protocol, {
80
+ signal,
81
+ runOnTransientConnection: self.runOnTransientConnection
82
+ })
83
+
84
+ const pb = pbStream(stream, {
85
+ maxDataLength: self.maxMessageSize
86
+ }).pb(IdentifyMessage)
87
+
88
+ await pb.write({
89
+ listenAddrs: listenAddresses.map(ma => ma.bytes),
90
+ signedPeerRecord: signedPeerRecord.marshal(),
91
+ protocols: supportedProtocols,
92
+ agentVersion,
93
+ protocolVersion
94
+ }, {
95
+ signal
96
+ })
97
+
98
+ await stream.close({
99
+ signal
100
+ })
101
+ } catch (err: any) {
102
+ // Just log errors
103
+ self.log.error('could not push identify update to peer', err)
104
+ stream?.abort(err)
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ await drain(parallel(pushToConnections(), {
111
+ concurrency: this.concurrency
112
+ }))
113
+ }
114
+
115
+ /**
116
+ * Reads the Identify Push message from the given `connection`
117
+ */
118
+ async handleProtocol (data: IncomingStreamData): Promise<void> {
119
+ const { connection, stream } = data
120
+
121
+ try {
122
+ if (this.peerId.equals(connection.remotePeer)) {
123
+ throw new Error('received push from ourselves?')
124
+ }
125
+
126
+ const options = {
127
+ signal: AbortSignal.timeout(this.timeout)
128
+ }
129
+
130
+ const pb = pbStream(stream, {
131
+ maxDataLength: this.maxMessageSize
132
+ }).pb(IdentifyMessage)
133
+
134
+ const message = await pb.read(options)
135
+ await stream.close(options)
136
+
137
+ await consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message)
138
+ } catch (err: any) {
139
+ this.log.error('received invalid message', err)
140
+ stream.abort(err)
141
+ return
142
+ }
143
+
144
+ this.log('handled push from %p', connection.remotePeer)
145
+ }
146
+ }
package/src/identify.ts CHANGED
@@ -1,94 +1,28 @@
1
1
  /* eslint-disable complexity */
2
2
 
3
- import { CodeError, ERR_NOT_FOUND, setMaxListeners } from '@libp2p/interface'
3
+ import { CodeError, setMaxListeners } from '@libp2p/interface'
4
4
  import { peerIdFromKeys } from '@libp2p/peer-id'
5
5
  import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
6
- import { type Multiaddr, multiaddr, protocols } from '@multiformats/multiaddr'
6
+ import { protocols } from '@multiformats/multiaddr'
7
7
  import { IP_OR_DOMAIN } from '@multiformats/multiaddr-matcher'
8
8
  import { pbStream } from 'it-protobuf-stream'
9
- import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
10
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
11
- import { isNode, isBrowser, isWebWorker, isElectronMain, isElectronRenderer, isReactNative } from 'wherearewe'
12
9
  import {
13
- IDENTIFY_PROTOCOL_VERSION,
14
10
  MULTICODEC_IDENTIFY_PROTOCOL_NAME,
15
- MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME,
16
- MULTICODEC_IDENTIFY_PROTOCOL_VERSION,
17
- MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION
11
+ MULTICODEC_IDENTIFY_PROTOCOL_VERSION
18
12
  } from './consts.js'
19
13
  import { Identify as IdentifyMessage } from './pb/message.js'
14
+ import { AbstractIdentify, consumeIdentifyMessage, defaultValues, getCleanMultiaddr } from './utils.js'
20
15
  import type { Identify as IdentifyInterface, IdentifyComponents, IdentifyInit } from './index.js'
21
- import type { Libp2pEvents, IdentifyResult, SignedPeerRecord, AbortOptions, Logger, Connection, Stream, TypedEventTarget, PeerId, Peer, PeerData, PeerStore, Startable } from '@libp2p/interface'
22
- import type { AddressManager, ConnectionManager, IncomingStreamData, Registrar } from '@libp2p/interface-internal'
23
-
24
- // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L52
25
- const MAX_IDENTIFY_MESSAGE_SIZE = 1024 * 8
26
-
27
- const defaultValues = {
28
- protocolPrefix: 'ipfs',
29
- // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48
30
- timeout: 60000,
31
- maxInboundStreams: 1,
32
- maxOutboundStreams: 1,
33
- maxPushIncomingStreams: 1,
34
- maxPushOutgoingStreams: 1,
35
- maxObservedAddresses: 10,
36
- maxIdentifyMessageSize: 8192,
37
- runOnConnectionOpen: true,
38
- runOnTransientConnection: true
39
- }
40
-
41
- export class Identify implements Startable, IdentifyInterface {
42
- private readonly identifyProtocolStr: string
43
- private readonly identifyPushProtocolStr: string
44
- public readonly host: {
45
- protocolVersion: string
46
- agentVersion: string
47
- }
48
-
49
- private started: boolean
50
- private readonly timeout: number
51
- private readonly peerId: PeerId
52
- private readonly peerStore: PeerStore
53
- private readonly registrar: Registrar
54
- private readonly connectionManager: ConnectionManager
55
- private readonly addressManager: AddressManager
56
- private readonly maxInboundStreams: number
57
- private readonly maxOutboundStreams: number
58
- private readonly maxPushIncomingStreams: number
59
- private readonly maxPushOutgoingStreams: number
60
- private readonly maxIdentifyMessageSize: number
61
- private readonly maxObservedAddresses: number
62
- private readonly events: TypedEventTarget<Libp2pEvents>
63
- private readonly runOnTransientConnection: boolean
64
- private readonly log: Logger
16
+ import type { IdentifyResult, AbortOptions, Connection, Stream, Startable } from '@libp2p/interface'
17
+ import type { IncomingStreamData } from '@libp2p/interface-internal'
65
18
 
19
+ export class Identify extends AbstractIdentify implements Startable, IdentifyInterface {
66
20
  constructor (components: IdentifyComponents, init: IdentifyInit = {}) {
67
- this.started = false
68
- this.peerId = components.peerId
69
- this.peerStore = components.peerStore
70
- this.registrar = components.registrar
71
- this.addressManager = components.addressManager
72
- this.connectionManager = components.connectionManager
73
- this.events = components.events
74
- this.log = components.logger.forComponent('libp2p:identify')
75
-
76
- this.identifyProtocolStr = `/${init.protocolPrefix ?? defaultValues.protocolPrefix}/${MULTICODEC_IDENTIFY_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PROTOCOL_VERSION}`
77
- this.identifyPushProtocolStr = `/${init.protocolPrefix ?? defaultValues.protocolPrefix}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION}`
78
- this.timeout = init.timeout ?? defaultValues.timeout
79
- this.maxInboundStreams = init.maxInboundStreams ?? defaultValues.maxInboundStreams
80
- this.maxOutboundStreams = init.maxOutboundStreams ?? defaultValues.maxOutboundStreams
81
- this.maxPushIncomingStreams = init.maxPushIncomingStreams ?? defaultValues.maxPushIncomingStreams
82
- this.maxPushOutgoingStreams = init.maxPushOutgoingStreams ?? defaultValues.maxPushOutgoingStreams
83
- this.maxIdentifyMessageSize = init.maxIdentifyMessageSize ?? defaultValues.maxIdentifyMessageSize
84
- this.maxObservedAddresses = init.maxObservedAddresses ?? defaultValues.maxObservedAddresses
85
- this.runOnTransientConnection = init.runOnTransientConnection ?? defaultValues.runOnTransientConnection
86
-
87
- // Store self host metadata
88
- this.host = {
89
- protocolVersion: `${init.protocolPrefix ?? defaultValues.protocolPrefix}/${IDENTIFY_PROTOCOL_VERSION}`,
90
- agentVersion: init.agentVersion ?? `${components.nodeInfo.name}/${components.nodeInfo.version}`
91
- }
21
+ super(components, {
22
+ ...init,
23
+ protocol: `/${init.protocolPrefix ?? defaultValues.protocolPrefix}/${MULTICODEC_IDENTIFY_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PROTOCOL_VERSION}`,
24
+ log: components.logger.forComponent('libp2p:identify')
25
+ })
92
26
 
93
27
  if (init.runOnConnectionOpen ?? defaultValues.runOnConnectionOpen) {
94
28
  // When a new connection happens, trigger identify
@@ -97,151 +31,6 @@ export class Identify implements Startable, IdentifyInterface {
97
31
  this.identify(connection).catch(err => { this.log.error('error during identify trigged by connection:open', err) })
98
32
  })
99
33
  }
100
-
101
- // When self peer record changes, trigger identify-push
102
- components.events.addEventListener('self:peer:update', (evt) => {
103
- void this.push().catch(err => { this.log.error(err) })
104
- })
105
-
106
- // Append user agent version to default AGENT_VERSION depending on the environment
107
- if (this.host.agentVersion === `${components.nodeInfo.name}/${components.nodeInfo.version}`) {
108
- if (isNode || isElectronMain) {
109
- this.host.agentVersion += ` UserAgent=${globalThis.process.version}`
110
- } else if (isBrowser || isWebWorker || isElectronRenderer || isReactNative) {
111
- this.host.agentVersion += ` UserAgent=${globalThis.navigator.userAgent}`
112
- }
113
- }
114
- }
115
-
116
- isStarted (): boolean {
117
- return this.started
118
- }
119
-
120
- async start (): Promise<void> {
121
- if (this.started) {
122
- return
123
- }
124
-
125
- await this.peerStore.merge(this.peerId, {
126
- metadata: {
127
- AgentVersion: uint8ArrayFromString(this.host.agentVersion),
128
- ProtocolVersion: uint8ArrayFromString(this.host.protocolVersion)
129
- }
130
- })
131
-
132
- await this.registrar.handle(this.identifyProtocolStr, (data) => {
133
- void this._handleIdentify(data).catch(err => {
134
- this.log.error(err)
135
- })
136
- }, {
137
- maxInboundStreams: this.maxInboundStreams,
138
- maxOutboundStreams: this.maxOutboundStreams,
139
- runOnTransientConnection: this.runOnTransientConnection
140
- })
141
- await this.registrar.handle(this.identifyPushProtocolStr, (data) => {
142
- void this._handlePush(data).catch(err => {
143
- this.log.error(err)
144
- })
145
- }, {
146
- maxInboundStreams: this.maxPushIncomingStreams,
147
- maxOutboundStreams: this.maxPushOutgoingStreams,
148
- runOnTransientConnection: this.runOnTransientConnection
149
- })
150
-
151
- this.started = true
152
- }
153
-
154
- async stop (): Promise<void> {
155
- await this.registrar.unhandle(this.identifyProtocolStr)
156
- await this.registrar.unhandle(this.identifyPushProtocolStr)
157
-
158
- this.started = false
159
- }
160
-
161
- /**
162
- * Send an Identify Push update to the list of connections
163
- */
164
- async pushToConnections (connections: Connection[]): Promise<void> {
165
- const listenAddresses = this.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code))
166
- const peerRecord = new PeerRecord({
167
- peerId: this.peerId,
168
- multiaddrs: listenAddresses
169
- })
170
- const signedPeerRecord = await RecordEnvelope.seal(peerRecord, this.peerId)
171
- const supportedProtocols = this.registrar.getProtocols()
172
- const peer = await this.peerStore.get(this.peerId)
173
- const agentVersion = uint8ArrayToString(peer.metadata.get('AgentVersion') ?? uint8ArrayFromString(this.host.agentVersion))
174
- const protocolVersion = uint8ArrayToString(peer.metadata.get('ProtocolVersion') ?? uint8ArrayFromString(this.host.protocolVersion))
175
-
176
- const pushes = connections.map(async connection => {
177
- let stream: Stream | undefined
178
- const signal = AbortSignal.timeout(this.timeout)
179
-
180
- setMaxListeners(Infinity, signal)
181
-
182
- try {
183
- stream = await connection.newStream(this.identifyPushProtocolStr, {
184
- signal,
185
- runOnTransientConnection: this.runOnTransientConnection
186
- })
187
-
188
- const pb = pbStream(stream, {
189
- maxDataLength: this.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
190
- }).pb(IdentifyMessage)
191
-
192
- await pb.write({
193
- listenAddrs: listenAddresses.map(ma => ma.bytes),
194
- signedPeerRecord: signedPeerRecord.marshal(),
195
- protocols: supportedProtocols,
196
- agentVersion,
197
- protocolVersion
198
- }, {
199
- signal
200
- })
201
-
202
- await stream.close({
203
- signal
204
- })
205
- } catch (err: any) {
206
- // Just log errors
207
- this.log.error('could not push identify update to peer', err)
208
- stream?.abort(err)
209
- }
210
- })
211
-
212
- await Promise.all(pushes)
213
- }
214
-
215
- /**
216
- * Calls `push` on all peer connections
217
- */
218
- async push (): Promise<void> {
219
- // Do not try to push if we are not running
220
- if (!this.isStarted()) {
221
- return
222
- }
223
-
224
- const connections: Connection[] = []
225
-
226
- await Promise.all(
227
- this.connectionManager.getConnections().map(async conn => {
228
- try {
229
- const peer = await this.peerStore.get(conn.remotePeer)
230
-
231
- if (!peer.protocols.includes(this.identifyPushProtocolStr)) {
232
- return
233
- }
234
-
235
- connections.push(conn)
236
- } catch (err: any) {
237
- if (err.code !== ERR_NOT_FOUND) {
238
- throw err
239
- }
240
- }
241
- })
242
- )
243
-
244
- await this.pushToConnections(connections)
245
34
  }
246
35
 
247
36
  async _identify (connection: Connection, options: AbortOptions = {}): Promise<IdentifyMessage> {
@@ -258,13 +47,13 @@ export class Identify implements Startable, IdentifyInterface {
258
47
  }
259
48
 
260
49
  try {
261
- stream = await connection.newStream(this.identifyProtocolStr, {
50
+ stream = await connection.newStream(this.protocol, {
262
51
  ...options,
263
52
  runOnTransientConnection: this.runOnTransientConnection
264
53
  })
265
54
 
266
55
  const pb = pbStream(stream, {
267
- maxDataLength: this.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
56
+ maxDataLength: this.maxMessageSize
268
57
  }).pb(IdentifyMessage)
269
58
 
270
59
  const message = await pb.read(options)
@@ -313,14 +102,14 @@ export class Identify implements Startable, IdentifyInterface {
313
102
  this.addressManager.addObservedAddr(cleanObservedAddr)
314
103
  }
315
104
 
316
- return this.#consumeIdentifyMessage(connection, message)
105
+ return consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message)
317
106
  }
318
107
 
319
108
  /**
320
109
  * Sends the `Identify` response with the Signed Peer Record
321
110
  * to the requesting peer over the given `connection`
322
111
  */
323
- async _handleIdentify (data: IncomingStreamData): Promise<void> {
112
+ async handleProtocol (data: IncomingStreamData): Promise<void> {
324
113
  const { connection, stream } = data
325
114
 
326
115
  const signal = AbortSignal.timeout(this.timeout)
@@ -371,181 +160,4 @@ export class Identify implements Startable, IdentifyInterface {
371
160
  stream.abort(err)
372
161
  }
373
162
  }
374
-
375
- /**
376
- * Reads the Identify Push message from the given `connection`
377
- */
378
- async _handlePush (data: IncomingStreamData): Promise<void> {
379
- const { connection, stream } = data
380
-
381
- try {
382
- if (this.peerId.equals(connection.remotePeer)) {
383
- throw new Error('received push from ourselves?')
384
- }
385
-
386
- const options = {
387
- signal: AbortSignal.timeout(this.timeout)
388
- }
389
-
390
- const pb = pbStream(stream, {
391
- maxDataLength: this.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
392
- }).pb(IdentifyMessage)
393
-
394
- const message = await pb.read(options)
395
- await stream.close(options)
396
-
397
- await this.#consumeIdentifyMessage(connection, message)
398
- } catch (err: any) {
399
- this.log.error('received invalid message', err)
400
- stream.abort(err)
401
- return
402
- }
403
-
404
- this.log('handled push from %p', connection.remotePeer)
405
- }
406
-
407
- async #consumeIdentifyMessage (connection: Connection, message: IdentifyMessage): Promise<IdentifyResult> {
408
- this.log('received identify from %p', connection.remotePeer)
409
-
410
- if (message == null) {
411
- throw new CodeError('message was null or undefined', 'ERR_INVALID_MESSAGE')
412
- }
413
-
414
- const peer: PeerData = {}
415
-
416
- if (message.listenAddrs.length > 0) {
417
- peer.addresses = message.listenAddrs.map(buf => ({
418
- isCertified: false,
419
- multiaddr: multiaddr(buf)
420
- }))
421
- }
422
-
423
- if (message.protocols.length > 0) {
424
- peer.protocols = message.protocols
425
- }
426
-
427
- if (message.publicKey != null) {
428
- peer.publicKey = message.publicKey
429
-
430
- const peerId = await peerIdFromKeys(message.publicKey)
431
-
432
- if (!peerId.equals(connection.remotePeer)) {
433
- throw new CodeError('public key did not match remote PeerId', 'ERR_INVALID_PUBLIC_KEY')
434
- }
435
- }
436
-
437
- let output: SignedPeerRecord | undefined
438
-
439
- // if the peer record has been sent, prefer the addresses in the record as they are signed by the remote peer
440
- if (message.signedPeerRecord != null) {
441
- this.log('received signedPeerRecord from %p', connection.remotePeer)
442
-
443
- let peerRecordEnvelope = message.signedPeerRecord
444
- const envelope = await RecordEnvelope.openAndCertify(peerRecordEnvelope, PeerRecord.DOMAIN)
445
- let peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
446
-
447
- // Verify peerId
448
- if (!peerRecord.peerId.equals(envelope.peerId)) {
449
- throw new CodeError('signing key does not match PeerId in the PeerRecord', 'ERR_INVALID_SIGNING_KEY')
450
- }
451
-
452
- // Make sure remote peer is the one sending the record
453
- if (!connection.remotePeer.equals(peerRecord.peerId)) {
454
- throw new CodeError('signing key does not match remote PeerId', 'ERR_INVALID_PEER_RECORD_KEY')
455
- }
456
-
457
- let existingPeer: Peer | undefined
458
-
459
- try {
460
- existingPeer = await this.peerStore.get(peerRecord.peerId)
461
- } catch (err: any) {
462
- if (err.code !== 'ERR_NOT_FOUND') {
463
- throw err
464
- }
465
- }
466
-
467
- if (existingPeer != null) {
468
- // don't lose any existing metadata
469
- peer.metadata = existingPeer.metadata
470
-
471
- // if we have previously received a signed record for this peer, compare it to the incoming one
472
- if (existingPeer.peerRecordEnvelope != null) {
473
- const storedEnvelope = await RecordEnvelope.createFromProtobuf(existingPeer.peerRecordEnvelope)
474
- const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload)
475
-
476
- // ensure seq is greater than, or equal to, the last received
477
- if (storedRecord.seqNumber >= peerRecord.seqNumber) {
478
- this.log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber)
479
- peerRecord = storedRecord
480
- peerRecordEnvelope = existingPeer.peerRecordEnvelope
481
- }
482
- }
483
- }
484
-
485
- // store the signed record for next time
486
- peer.peerRecordEnvelope = peerRecordEnvelope
487
-
488
- // override the stored addresses with the signed multiaddrs
489
- peer.addresses = peerRecord.multiaddrs.map(multiaddr => ({
490
- isCertified: true,
491
- multiaddr
492
- }))
493
-
494
- output = {
495
- seq: peerRecord.seqNumber,
496
- addresses: peerRecord.multiaddrs
497
- }
498
- } else {
499
- this.log('%p did not send a signed peer record', connection.remotePeer)
500
- }
501
-
502
- this.log('patching %p with', connection.remotePeer, peer)
503
- await this.peerStore.patch(connection.remotePeer, peer)
504
-
505
- if (message.agentVersion != null || message.protocolVersion != null) {
506
- const metadata: Record<string, Uint8Array> = {}
507
-
508
- if (message.agentVersion != null) {
509
- metadata.AgentVersion = uint8ArrayFromString(message.agentVersion)
510
- }
511
-
512
- if (message.protocolVersion != null) {
513
- metadata.ProtocolVersion = uint8ArrayFromString(message.protocolVersion)
514
- }
515
-
516
- this.log('merging %p metadata', connection.remotePeer, metadata)
517
- await this.peerStore.merge(connection.remotePeer, {
518
- metadata
519
- })
520
- }
521
-
522
- const result: IdentifyResult = {
523
- peerId: connection.remotePeer,
524
- protocolVersion: message.protocolVersion,
525
- agentVersion: message.agentVersion,
526
- publicKey: message.publicKey,
527
- listenAddrs: message.listenAddrs.map(buf => multiaddr(buf)),
528
- observedAddr: message.observedAddr == null ? undefined : multiaddr(message.observedAddr),
529
- protocols: message.protocols,
530
- signedPeerRecord: output,
531
- connection
532
- }
533
-
534
- this.events.safeDispatchEvent('peer:identify', { detail: result })
535
-
536
- return result
537
- }
538
- }
539
-
540
- /**
541
- * Takes the `addr` and converts it to a Multiaddr if possible
542
- */
543
- function getCleanMultiaddr (addr: Uint8Array | string | null | undefined): Multiaddr | undefined {
544
- if (addr != null && addr.length > 0) {
545
- try {
546
- return multiaddr(addr)
547
- } catch {
548
-
549
- }
550
- }
551
163
  }