@libp2p/pubsub 8.0.14 → 9.0.0-09dd02987

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@libp2p/pubsub",
3
- "version": "8.0.14",
3
+ "version": "9.0.0-09dd02987",
4
4
  "description": "libp2p pubsub base class",
5
5
  "license": "Apache-2.0 OR MIT",
6
- "homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/pubsub#readme",
6
+ "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/pubsub#readme",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/libp2p/js-libp2p.git"
@@ -11,6 +11,10 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/libp2p/js-libp2p/issues"
13
13
  },
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "provenance": true
17
+ },
14
18
  "keywords": [
15
19
  "interface",
16
20
  "libp2p"
@@ -67,7 +71,7 @@
67
71
  "scripts": {
68
72
  "clean": "aegir clean",
69
73
  "lint": "aegir lint",
70
- "dep-check": "aegir dep-check -i protons",
74
+ "dep-check": "aegir dep-check",
71
75
  "build": "aegir build",
72
76
  "generate": "protons test/message/rpc.proto",
73
77
  "test": "aegir test",
@@ -79,30 +83,30 @@
79
83
  "test:electron-main": "aegir test -t electron-main"
80
84
  },
81
85
  "dependencies": {
82
- "@libp2p/crypto": "^2.0.8",
83
- "@libp2p/interface": "^0.1.6",
84
- "@libp2p/interface-internal": "^0.1.9",
85
- "@libp2p/logger": "^3.1.0",
86
- "@libp2p/peer-collections": "^4.0.8",
87
- "@libp2p/peer-id": "^3.0.6",
88
- "abortable-iterator": "^5.0.1",
89
- "it-length-prefixed": "^9.0.1",
86
+ "@libp2p/crypto": "3.0.1-09dd02987",
87
+ "@libp2p/interface": "1.0.1-09dd02987",
88
+ "@libp2p/interface-internal": "1.0.1-09dd02987",
89
+ "@libp2p/peer-collections": "5.0.0-09dd02987",
90
+ "@libp2p/peer-id": "4.0.1-09dd02987",
91
+ "@libp2p/utils": "5.0.2-09dd02987",
92
+ "it-length-prefixed": "^9.0.3",
90
93
  "it-pipe": "^3.0.1",
91
- "it-pushable": "^3.2.0",
92
- "multiformats": "^12.0.1",
93
- "p-queue": "^7.3.4",
94
+ "it-pushable": "^3.2.1",
95
+ "multiformats": "^12.1.3",
96
+ "p-queue": "^7.4.1",
94
97
  "uint8arraylist": "^2.4.3",
95
98
  "uint8arrays": "^4.0.6"
96
99
  },
97
100
  "devDependencies": {
98
- "@libp2p/peer-id-factory": "^3.0.8",
101
+ "@libp2p/logger": "4.0.1-09dd02987",
102
+ "@libp2p/peer-id-factory": "4.0.0-09dd02987",
99
103
  "@types/sinon": "^17.0.0",
100
104
  "aegir": "^41.0.2",
101
105
  "delay": "^6.0.0",
102
106
  "it-pair": "^2.0.6",
103
107
  "p-defer": "^4.0.0",
104
108
  "p-wait-for": "^5.0.2",
105
- "protons": "^7.0.2",
109
+ "protons": "^7.3.0",
106
110
  "protons-runtime": "^5.0.0",
107
111
  "sinon": "^17.0.0"
108
112
  }
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * A set of components to be extended in order to create a pubsub implementation.
5
5
  *
6
6
  * @example
7
+ *
7
8
  * ```javascript
8
9
  * import { PubSubBaseProtocol } from '@libp2p/pubsub'
9
10
  *
@@ -13,10 +14,8 @@
13
14
  * ```
14
15
  */
15
16
 
16
- import { CodeError } from '@libp2p/interface/errors'
17
- import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events'
18
- import { type PubSub, type Message, type StrictNoSign, type StrictSign, type PubSubInit, type PubSubEvents, type PeerStreams, type PubSubRPCMessage, type PubSubRPC, type PubSubRPCSubscription, type SubscriptionChangeData, type PublishResult, type TopicValidatorFn, TopicValidatorResult } from '@libp2p/interface/pubsub'
19
- import { logger } from '@libp2p/logger'
17
+ import { CodeError, TypedEventEmitter, CustomEvent } from '@libp2p/interface'
18
+ import { type PubSub, type Message, type StrictNoSign, type StrictSign, type PubSubInit, type PubSubEvents, type PeerStreams, type PubSubRPCMessage, type PubSubRPC, type PubSubRPCSubscription, type SubscriptionChangeData, type PublishResult, type TopicValidatorFn, TopicValidatorResult, type ComponentLogger, type Logger, type Connection, type PeerId } from '@libp2p/interface'
20
19
  import { PeerMap, PeerSet } from '@libp2p/peer-collections'
21
20
  import { pipe } from 'it-pipe'
22
21
  import Queue from 'p-queue'
@@ -27,16 +26,13 @@ import {
27
26
  verifySignature
28
27
  } from './sign.js'
29
28
  import { toMessage, ensureArray, noSignMsgId, msgId, toRpcMessage, randomSeqno } from './utils.js'
30
- import type { Connection } from '@libp2p/interface/connection'
31
- import type { PeerId } from '@libp2p/interface/peer-id'
32
- import type { IncomingStreamData, Registrar } from '@libp2p/interface-internal/registrar'
29
+ import type { IncomingStreamData, Registrar } from '@libp2p/interface-internal'
33
30
  import type { Uint8ArrayList } from 'uint8arraylist'
34
31
 
35
- const log = logger('libp2p:pubsub')
36
-
37
32
  export interface PubSubComponents {
38
33
  peerId: PeerId
39
34
  registrar: Registrar
35
+ logger: ComponentLogger
40
36
  }
41
37
 
42
38
  /**
@@ -44,6 +40,8 @@ export interface PubSubComponents {
44
40
  * and specifies the API that pubsub routers should have.
45
41
  */
46
42
  export abstract class PubSubBaseProtocol<Events extends Record<string, any> = PubSubEvents> extends TypedEventEmitter<Events> implements PubSub<Events> {
43
+ protected log: Logger
44
+
47
45
  public started: boolean
48
46
  /**
49
47
  * Map of topics to which peers are subscribed to
@@ -98,6 +96,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
98
96
  maxOutboundStreams = 1
99
97
  } = props
100
98
 
99
+ this.log = components.logger.forComponent('libp2p:pubsub')
101
100
  this.components = components
102
101
  this.multicodecs = ensureArray(multicodecs)
103
102
  this.enabled = props.enabled !== false
@@ -128,7 +127,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
128
127
  return
129
128
  }
130
129
 
131
- log('starting')
130
+ this.log('starting')
132
131
 
133
132
  const registrar = this.components.registrar
134
133
  // Incoming streams
@@ -148,7 +147,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
148
147
  }
149
148
  this._registrarTopologyIds = await Promise.all(this.multicodecs.map(async multicodec => registrar.register(multicodec, topology)))
150
149
 
151
- log('started')
150
+ this.log('started')
152
151
  this.started = true
153
152
  }
154
153
 
@@ -173,7 +172,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
173
172
  await registrar.unhandle(multicodec)
174
173
  }))
175
174
 
176
- log('stopping')
175
+ this.log('stopping')
177
176
  for (const peerStreams of this.peers.values()) {
178
177
  peerStreams.close()
179
178
  }
@@ -181,7 +180,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
181
180
  this.peers.clear()
182
181
  this.subscriptions = new Set()
183
182
  this.started = false
184
- log('stopped')
183
+ this.log('stopped')
185
184
  }
186
185
 
187
186
  isStarted (): boolean {
@@ -204,18 +203,18 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
204
203
  const inboundStream = peer.attachInboundStream(stream)
205
204
 
206
205
  this.processMessages(peerId, inboundStream, peer)
207
- .catch(err => { log(err) })
206
+ .catch(err => { this.log(err) })
208
207
  }
209
208
 
210
209
  /**
211
210
  * Registrar notifies an established connection with pubsub protocol
212
211
  */
213
212
  protected _onPeerConnected (peerId: PeerId, conn: Connection): void {
214
- log('connected %p', peerId)
213
+ this.log('connected %p', peerId)
215
214
 
216
215
  // if this connection is already in use for pubsub, ignore it
217
216
  if (conn.streams.find(stream => stream.direction === 'outbound' && stream.protocol != null && this.multicodecs.includes(stream.protocol)) != null) {
218
- log('outbound pubsub streams already present on connection from %p', peerId)
217
+ this.log('outbound pubsub streams already present on connection from %p', peerId)
219
218
  return
220
219
  }
221
220
 
@@ -231,14 +230,14 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
231
230
  const peer = this.addPeer(peerId, stream.protocol)
232
231
  await peer.attachOutboundStream(stream)
233
232
  } catch (err: any) {
234
- log.error(err)
233
+ this.log.error(err)
235
234
  }
236
235
 
237
236
  // Immediately send my own subscriptions to the newly established conn
238
237
  this.send(peerId, { subscriptions: Array.from(this.subscriptions).map(sub => sub.toString()), subscribe: true })
239
238
  })
240
239
  .catch(err => {
241
- log.error(err)
240
+ this.log.error(err)
242
241
  })
243
242
  }
244
243
 
@@ -248,7 +247,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
248
247
  protected _onPeerDisconnected (peerId: PeerId, conn?: Connection): void {
249
248
  const idB58Str = peerId.toString()
250
249
 
251
- log('connection ended', idB58Str)
250
+ this.log('connection ended', idB58Str)
252
251
  this._removePeer(peerId)
253
252
  }
254
253
 
@@ -264,9 +263,9 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
264
263
  }
265
264
 
266
265
  // else create a new peer streams
267
- log('new peer %p', peerId)
266
+ this.log('new peer %p', peerId)
268
267
 
269
- const peerStreams: PeerStreams = new PeerStreamsImpl({
268
+ const peerStreams: PeerStreams = new PeerStreamsImpl(this.components, {
270
269
  id: peerId,
271
270
  protocol
272
271
  })
@@ -292,7 +291,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
292
291
  peerStreams.close()
293
292
 
294
293
  // delete peer streams
295
- log('delete peer %p', peerId)
294
+ this.log('delete peer %p', peerId)
296
295
  this.peers.delete(peerId)
297
296
 
298
297
  // remove peer from topics map
@@ -319,7 +318,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
319
318
 
320
319
  for (const msg of (rpcMsg.messages ?? [])) {
321
320
  if (msg.from == null || msg.data == null || msg.topic == null) {
322
- log('message from %p was missing from, data or topic fields, dropping', peerId)
321
+ this.log('message from %p was missing from, data or topic fields, dropping', peerId)
323
322
  continue
324
323
  }
325
324
 
@@ -344,7 +343,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
344
343
  })),
345
344
  messages
346
345
  })
347
- .catch(err => { log(err) })
346
+ .catch(err => { this.log(err) })
348
347
  }
349
348
  }
350
349
  )
@@ -358,16 +357,16 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
358
357
  */
359
358
  async processRpc (from: PeerId, peerStreams: PeerStreams, rpc: PubSubRPC): Promise<boolean> {
360
359
  if (!this.acceptFrom(from)) {
361
- log('received message from unacceptable peer %p', from)
360
+ this.log('received message from unacceptable peer %p', from)
362
361
  return false
363
362
  }
364
363
 
365
- log('rpc from %p', from)
364
+ this.log('rpc from %p', from)
366
365
 
367
366
  const { subscriptions, messages } = rpc
368
367
 
369
368
  if (subscriptions != null && subscriptions.length > 0) {
370
- log('subscription update from %p', from)
369
+ this.log('subscription update from %p', from)
371
370
 
372
371
  // update peer subscriptions
373
372
  subscriptions.forEach((subOpt) => {
@@ -386,11 +385,11 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
386
385
  }
387
386
 
388
387
  if (messages != null && messages.length > 0) {
389
- log('messages from %p', from)
388
+ this.log('messages from %p', from)
390
389
 
391
390
  this.queue.addAll(messages.map(message => async () => {
392
391
  if (message.topic == null || (!this.subscriptions.has(message.topic) && !this.canRelayMessage)) {
393
- log('received message we didn\'t subscribe to. Dropping.')
392
+ this.log('received message we didn\'t subscribe to. Dropping.')
394
393
  return false
395
394
  }
396
395
 
@@ -399,10 +398,10 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
399
398
 
400
399
  await this.processMessage(from, msg)
401
400
  } catch (err: any) {
402
- log.error(err)
401
+ this.log.error(err)
403
402
  }
404
403
  }))
405
- .catch(err => { log(err) })
404
+ .catch(err => { this.log(err) })
406
405
  }
407
406
 
408
407
  return true
@@ -445,7 +444,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
445
444
  try {
446
445
  await this.validate(from, msg)
447
446
  } catch (err: any) {
448
- log('Message is invalid, dropping it. %O', err)
447
+ this.log('Message is invalid, dropping it. %O', err)
449
448
  return
450
449
  }
451
450
 
@@ -535,13 +534,13 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
535
534
  const peerStreams = this.peers.get(peer)
536
535
 
537
536
  if (peerStreams == null) {
538
- log.error('Cannot send RPC to %p as there are no streams to it available', peer)
537
+ this.log.error('Cannot send RPC to %p as there are no streams to it available', peer)
539
538
 
540
539
  return
541
540
  }
542
541
 
543
542
  if (!peerStreams.isWritable) {
544
- log.error('Cannot send RPC to %p as there is no outbound stream to it available', peer)
543
+ this.log.error('Cannot send RPC to %p as there is no outbound stream to it available', peer)
545
544
 
546
545
  return
547
546
  }
@@ -664,7 +663,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
664
663
  sequenceNumber: randomSeqno()
665
664
  }
666
665
 
667
- log('publish topic: %s from: %p data: %m', topic, message.from, message.data)
666
+ this.log('publish topic: %s from: %p data: %m', topic, message.from, message.data)
668
667
 
669
668
  const rpcMessage = await this.buildMessage(message)
670
669
  let emittedToSelf = false
@@ -706,7 +705,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
706
705
  throw new Error('Pubsub has not started')
707
706
  }
708
707
 
709
- log('subscribe to topic: %s', topic)
708
+ this.log('subscribe to topic: %s', topic)
710
709
 
711
710
  if (!this.subscriptions.has(topic)) {
712
711
  this.subscriptions.add(topic)
@@ -729,7 +728,7 @@ export abstract class PubSubBaseProtocol<Events extends Record<string, any> = Pu
729
728
 
730
729
  const wasSubscribed = this.subscriptions.has(topic)
731
730
 
732
- log('unsubscribe from %s - am subscribed %s', topic, wasSubscribed)
731
+ this.log('unsubscribe from %s - am subscribed %s', topic, wasSubscribed)
733
732
 
734
733
  if (wasSubscribed) {
735
734
  this.subscriptions.delete(topic)
@@ -1,22 +1,21 @@
1
- import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events'
2
- import { logger } from '@libp2p/logger'
3
- import { abortableSource } from 'abortable-iterator'
1
+ import { TypedEventEmitter, CustomEvent } from '@libp2p/interface'
2
+ import { closeSource } from '@libp2p/utils/close-source'
4
3
  import * as lp from 'it-length-prefixed'
5
4
  import { pipe } from 'it-pipe'
6
5
  import { pushable } from 'it-pushable'
7
6
  import { Uint8ArrayList } from 'uint8arraylist'
8
- import type { Stream } from '@libp2p/interface/connection'
9
- import type { PeerId } from '@libp2p/interface/peer-id'
10
- import type { PeerStreamEvents } from '@libp2p/interface/pubsub'
7
+ import type { ComponentLogger, Logger, Stream, PeerId, PeerStreamEvents } from '@libp2p/interface'
11
8
  import type { Pushable } from 'it-pushable'
12
9
 
13
- const log = logger('libp2p-pubsub:peer-streams')
14
-
15
10
  export interface PeerStreamsInit {
16
11
  id: PeerId
17
12
  protocol: string
18
13
  }
19
14
 
15
+ export interface PeerStreamsComponents {
16
+ logger: ComponentLogger
17
+ }
18
+
20
19
  /**
21
20
  * Thin wrapper around a peer's inbound / outbound pubsub streams
22
21
  */
@@ -44,10 +43,12 @@ export class PeerStreams extends TypedEventEmitter<PeerStreamEvents> {
44
43
  */
45
44
  private readonly _inboundAbortController: AbortController
46
45
  private closed: boolean
46
+ private readonly log: Logger
47
47
 
48
- constructor (init: PeerStreamsInit) {
48
+ constructor (components: PeerStreamsComponents, init: PeerStreamsInit) {
49
49
  super()
50
50
 
51
+ this.log = components.logger.forComponent('libp2p-pubsub:peer-streams')
51
52
  this.id = init.id
52
53
  this.protocol = init.protocol
53
54
 
@@ -86,18 +87,22 @@ export class PeerStreams extends TypedEventEmitter<PeerStreamEvents> {
86
87
  * Attach a raw inbound stream and setup a read stream
87
88
  */
88
89
  attachInboundStream (stream: Stream): AsyncIterable<Uint8ArrayList> {
90
+ const abortListener = (): void => {
91
+ closeSource(stream.source, this.log)
92
+ }
93
+
94
+ this._inboundAbortController.signal.addEventListener('abort', abortListener, {
95
+ once: true
96
+ })
97
+
89
98
  // Create and attach a new inbound stream
90
99
  // The inbound stream is:
91
100
  // - abortable, set to only return on abort, rather than throw
92
101
  // - transformed with length-prefix transform
93
102
  this._rawInboundStream = stream
94
- this.inboundStream = abortableSource(
95
- pipe(
96
- this._rawInboundStream,
97
- (source) => lp.decode(source)
98
- ),
99
- this._inboundAbortController.signal,
100
- { returnOnAbort: true }
103
+ this.inboundStream = pipe(
104
+ this._rawInboundStream,
105
+ (source) => lp.decode(source)
101
106
  )
102
107
 
103
108
  this.dispatchEvent(new CustomEvent('stream:inbound'))
@@ -117,13 +122,12 @@ export class PeerStreams extends TypedEventEmitter<PeerStreamEvents> {
117
122
 
118
123
  this._rawOutboundStream = stream
119
124
  this.outboundStream = pushable<Uint8ArrayList>({
120
- objectMode: true,
121
125
  onEnd: (shouldEmit) => {
122
126
  // close writable side of the stream
123
127
  if (this._rawOutboundStream != null) { // eslint-disable-line @typescript-eslint/prefer-optional-chain
124
128
  this._rawOutboundStream.closeWrite()
125
129
  .catch(err => {
126
- log('error closing outbound stream', err)
130
+ this.log('error closing outbound stream', err)
127
131
  })
128
132
  }
129
133
 
@@ -140,7 +144,7 @@ export class PeerStreams extends TypedEventEmitter<PeerStreamEvents> {
140
144
  (source) => lp.encode(source),
141
145
  this._rawOutboundStream
142
146
  ).catch((err: Error) => {
143
- log.error(err)
147
+ this.log.error(err)
144
148
  })
145
149
 
146
150
  // Only emit if the connection is new
package/src/sign.ts CHANGED
@@ -3,8 +3,7 @@ import { peerIdFromKeys } from '@libp2p/peer-id'
3
3
  import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
4
4
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
5
5
  import { toRpcMessage } from './utils.js'
6
- import type { PeerId } from '@libp2p/interface/peer-id'
7
- import type { PubSubRPCMessage, SignedMessage } from '@libp2p/interface/pubsub'
6
+ import type { PeerId, PubSubRPCMessage, SignedMessage } from '@libp2p/interface'
8
7
 
9
8
  export const SignPrefix = uint8ArrayFromString('libp2p-pubsub:')
10
9
 
package/src/utils.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { randomBytes } from '@libp2p/crypto'
2
- import { CodeError } from '@libp2p/interface/errors'
2
+ import { CodeError } from '@libp2p/interface'
3
3
  import { peerIdFromBytes, peerIdFromKeys } from '@libp2p/peer-id'
4
4
  import { sha256 } from 'multiformats/hashes/sha2'
5
5
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
6
  import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
7
7
  import { codes } from './errors.js'
8
- import type { Message, PubSubRPCMessage } from '@libp2p/interface/pubsub'
8
+ import type { Message, PubSubRPCMessage } from '@libp2p/interface'
9
9
 
10
10
  /**
11
11
  * Generate a random sequence number