@libp2p/pubsub 1.2.4 → 1.2.5
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.
- package/dist/src/errors.d.ts +4 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +4 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +22 -21
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +89 -67
- package/dist/src/index.js.map +1 -1
- package/dist/src/message/sign.d.ts.map +1 -1
- package/dist/src/message/sign.js +6 -8
- package/dist/src/message/sign.js.map +1 -1
- package/dist/src/peer-streams.d.ts +5 -5
- package/dist/src/peer-streams.d.ts.map +1 -1
- package/dist/src/peer-streams.js +1 -0
- package/dist/src/peer-streams.js.map +1 -1
- package/dist/src/utils.d.ts +6 -5
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +36 -28
- package/dist/src/utils.js.map +1 -1
- package/package.json +3 -2
- package/src/errors.ts +4 -0
- package/src/index.ts +110 -79
- package/src/message/sign.ts +6 -9
- package/src/peer-streams.ts +6 -4
- package/src/utils.ts +39 -29
package/src/index.ts
CHANGED
@@ -5,9 +5,8 @@ import { pipe } from 'it-pipe'
|
|
5
5
|
import Queue from 'p-queue'
|
6
6
|
import { Topology } from '@libp2p/topology'
|
7
7
|
import { codes } from './errors.js'
|
8
|
-
import {
|
9
|
-
import {
|
10
|
-
import * as utils from './utils.js'
|
8
|
+
import { PeerStreams as PeerStreamsImpl } from './peer-streams.js'
|
9
|
+
import { toRpcMessage, toMessage, ensureArray, randomSeqno, noSignMsgId, msgId } from './utils.js'
|
11
10
|
import {
|
12
11
|
signMessage,
|
13
12
|
verifySignature
|
@@ -15,9 +14,14 @@ import {
|
|
15
14
|
import type { PeerId } from '@libp2p/interfaces/peer-id'
|
16
15
|
import type { Registrar, IncomingStreamData } from '@libp2p/interfaces/registrar'
|
17
16
|
import type { Connection } from '@libp2p/interfaces/connection'
|
18
|
-
import type
|
19
|
-
import type { PubSub, Message, StrictNoSign, StrictSign, PubsubOptions, PubsubEvents } from '@libp2p/interfaces/pubsub'
|
17
|
+
import type { PubSub, Message, StrictNoSign, StrictSign, PubSubOptions, PubSubEvents, RPCMessage, RPC, PeerStreams, RPCSubscription } from '@libp2p/interfaces/pubsub'
|
20
18
|
import type { Logger } from '@libp2p/logger'
|
19
|
+
import { base58btc } from 'multiformats/bases/base58'
|
20
|
+
import { peerMap } from '@libp2p/peer-map'
|
21
|
+
import type { PeerMap } from '@libp2p/peer-map'
|
22
|
+
import { peerIdFromString } from '@libp2p/peer-id'
|
23
|
+
import type { IRPC } from './message/rpc.js'
|
24
|
+
import { RPC as RPCProto } from './message/rpc.js'
|
21
25
|
|
22
26
|
export interface TopicValidator { (topic: string, message: Message): Promise<void> }
|
23
27
|
|
@@ -25,7 +29,7 @@ export interface TopicValidator { (topic: string, message: Message): Promise<voi
|
|
25
29
|
* PubsubBaseProtocol handles the peers and connections logic for pubsub routers
|
26
30
|
* and specifies the API that pubsub routers should have.
|
27
31
|
*/
|
28
|
-
export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap &
|
32
|
+
export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap & PubSubEvents> implements PubSub<EventMap & PubSubEvents> {
|
29
33
|
public peerId: PeerId
|
30
34
|
public started: boolean
|
31
35
|
/**
|
@@ -39,11 +43,11 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
39
43
|
/**
|
40
44
|
* Map of peer streams
|
41
45
|
*/
|
42
|
-
public peers:
|
46
|
+
public peers: PeerMap<PeerStreams>
|
43
47
|
/**
|
44
48
|
* The signature policy to follow by default
|
45
49
|
*/
|
46
|
-
public globalSignaturePolicy: StrictNoSign | StrictSign
|
50
|
+
public globalSignaturePolicy: typeof StrictNoSign | typeof StrictSign
|
47
51
|
/**
|
48
52
|
* If router can relay received messages, even if not subscribed
|
49
53
|
*/
|
@@ -61,20 +65,21 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
61
65
|
public topicValidators: Map<string, TopicValidator>
|
62
66
|
public queue: Queue
|
63
67
|
public registrar: Registrar
|
68
|
+
public multicodecs: string[]
|
64
69
|
|
65
70
|
protected log: Logger
|
66
|
-
protected multicodecs: string[]
|
67
71
|
protected _libp2p: any
|
68
72
|
private _registrarHandlerId: string | undefined
|
69
73
|
private _registrarTopologyId: string | undefined
|
70
74
|
|
71
|
-
constructor (props:
|
75
|
+
constructor (props: PubSubOptions) {
|
72
76
|
super()
|
73
77
|
|
74
78
|
const {
|
75
79
|
debugName = 'libp2p:pubsub',
|
76
80
|
multicodecs = [],
|
77
|
-
|
81
|
+
peerId,
|
82
|
+
registrar,
|
78
83
|
globalSignaturePolicy = 'StrictSign',
|
79
84
|
canRelayMessage = false,
|
80
85
|
emitSelf = false,
|
@@ -82,14 +87,13 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
82
87
|
} = props
|
83
88
|
|
84
89
|
this.log = logger(debugName)
|
85
|
-
this.multicodecs =
|
86
|
-
this.
|
87
|
-
this.
|
88
|
-
this.peerId = libp2p.peerId
|
90
|
+
this.multicodecs = ensureArray(multicodecs)
|
91
|
+
this.registrar = registrar
|
92
|
+
this.peerId = peerId
|
89
93
|
this.started = false
|
90
94
|
this.topics = new Map()
|
91
95
|
this.subscriptions = new Set()
|
92
|
-
this.peers =
|
96
|
+
this.peers = peerMap<PeerStreams>()
|
93
97
|
this.globalSignaturePolicy = globalSignaturePolicy === 'StrictNoSign' ? 'StrictNoSign' : 'StrictSign'
|
94
98
|
this.canRelayMessage = canRelayMessage
|
95
99
|
this.emitSelf = emitSelf
|
@@ -148,9 +152,11 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
148
152
|
}
|
149
153
|
|
150
154
|
this.log('stopping')
|
151
|
-
|
155
|
+
for (const peerStreams of this.peers.values()) {
|
156
|
+
peerStreams.close()
|
157
|
+
}
|
152
158
|
|
153
|
-
this.peers
|
159
|
+
this.peers.clear()
|
154
160
|
this.subscriptions = new Set()
|
155
161
|
this.started = false
|
156
162
|
this.log('stopped')
|
@@ -166,11 +172,10 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
166
172
|
protected _onIncomingStream (evt: CustomEvent<IncomingStreamData>) {
|
167
173
|
const { protocol, stream, connection } = evt.detail
|
168
174
|
const peerId = connection.remotePeer
|
169
|
-
const idB58Str = peerId.toString()
|
170
175
|
const peer = this._addPeer(peerId, protocol)
|
171
176
|
const inboundStream = peer.attachInboundStream(stream)
|
172
177
|
|
173
|
-
this._processMessages(
|
178
|
+
this._processMessages(peerId, inboundStream, peer)
|
174
179
|
.catch(err => this.log(err))
|
175
180
|
}
|
176
181
|
|
@@ -178,8 +183,7 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
178
183
|
* Registrar notifies an established connection with pubsub protocol
|
179
184
|
*/
|
180
185
|
protected async _onPeerConnected (peerId: PeerId, conn: Connection) {
|
181
|
-
|
182
|
-
this.log('connected', idB58Str)
|
186
|
+
this.log('connected %p', peerId)
|
183
187
|
|
184
188
|
try {
|
185
189
|
const { stream, protocol } = await conn.newStream(this.multicodecs)
|
@@ -190,7 +194,7 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
190
194
|
}
|
191
195
|
|
192
196
|
// Immediately send my own subscriptions to the newly established conn
|
193
|
-
this._sendSubscriptions(
|
197
|
+
this._sendSubscriptions(peerId, Array.from(this.subscriptions), true)
|
194
198
|
}
|
195
199
|
|
196
200
|
/**
|
@@ -206,9 +210,8 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
206
210
|
/**
|
207
211
|
* Notifies the router that a peer has been connected
|
208
212
|
*/
|
209
|
-
protected _addPeer (peerId: PeerId, protocol: string) {
|
210
|
-
const
|
211
|
-
const existing = this.peers.get(id)
|
213
|
+
protected _addPeer (peerId: PeerId, protocol: string): PeerStreams {
|
214
|
+
const existing = this.peers.get(peerId)
|
212
215
|
|
213
216
|
// If peer streams already exists, do nothing
|
214
217
|
if (existing != null) {
|
@@ -216,14 +219,14 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
216
219
|
}
|
217
220
|
|
218
221
|
// else create a new peer streams
|
219
|
-
this.log('new peer',
|
222
|
+
this.log('new peer %p', peerId)
|
220
223
|
|
221
|
-
const peerStreams = new
|
224
|
+
const peerStreams: PeerStreams = new PeerStreamsImpl({
|
222
225
|
id: peerId,
|
223
226
|
protocol
|
224
227
|
})
|
225
228
|
|
226
|
-
this.peers.set(
|
229
|
+
this.peers.set(peerId, peerStreams)
|
227
230
|
peerStreams.addEventListener('close', () => this._removePeer(peerId), {
|
228
231
|
once: true
|
229
232
|
})
|
@@ -236,7 +239,7 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
236
239
|
*/
|
237
240
|
protected _removePeer (peerId: PeerId) {
|
238
241
|
const id = peerId.toString()
|
239
|
-
const peerStreams = this.peers.get(
|
242
|
+
const peerStreams = this.peers.get(peerId)
|
240
243
|
if (peerStreams == null) {
|
241
244
|
return
|
242
245
|
}
|
@@ -245,8 +248,8 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
245
248
|
peerStreams.close()
|
246
249
|
|
247
250
|
// delete peer streams
|
248
|
-
this.log('delete peer',
|
249
|
-
this.peers.delete(
|
251
|
+
this.log('delete peer %p', peerId)
|
252
|
+
this.peers.delete(peerId)
|
250
253
|
|
251
254
|
// remove peer from topics map
|
252
255
|
for (const peers of this.topics.values()) {
|
@@ -261,20 +264,32 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
261
264
|
/**
|
262
265
|
* Responsible for processing each RPC message received by other peers.
|
263
266
|
*/
|
264
|
-
async _processMessages (
|
267
|
+
async _processMessages (peerId: PeerId, stream: AsyncIterable<Uint8Array>, peerStreams: PeerStreams) {
|
265
268
|
try {
|
266
269
|
await pipe(
|
267
270
|
stream,
|
268
271
|
async (source) => {
|
269
272
|
for await (const data of source) {
|
270
|
-
const
|
271
|
-
const rpcMsg = this._decodeRpc(rpcBytes)
|
273
|
+
const rpcMsg = this._decodeRpc(data)
|
272
274
|
|
273
275
|
// Since _processRpc may be overridden entirely in unsafe ways,
|
274
276
|
// the simplest/safest option here is to wrap in a function and capture all errors
|
275
277
|
// to prevent a top-level unhandled exception
|
276
278
|
// This processing of rpc messages should happen without awaiting full validation/execution of prior messages
|
277
|
-
this.
|
279
|
+
this.processRpc(peerId, peerStreams, {
|
280
|
+
subscriptions: (rpcMsg.subscriptions).map(sub => ({
|
281
|
+
subscribe: Boolean(sub.subscribe),
|
282
|
+
topicID: sub.topicID ?? ''
|
283
|
+
})),
|
284
|
+
msgs: (rpcMsg.msgs ?? []).map(msg => ({
|
285
|
+
from: msg.from ?? peerId.multihash.bytes,
|
286
|
+
data: msg.data ?? new Uint8Array(0),
|
287
|
+
topicIDs: msg.topicIDs ?? [],
|
288
|
+
seqno: msg.seqno ?? undefined,
|
289
|
+
signature: msg.signature ?? undefined,
|
290
|
+
key: msg.key ?? undefined
|
291
|
+
}))
|
292
|
+
})
|
278
293
|
.catch(err => this.log(err))
|
279
294
|
}
|
280
295
|
}
|
@@ -287,23 +302,23 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
287
302
|
/**
|
288
303
|
* Handles an rpc request from a peer
|
289
304
|
*/
|
290
|
-
async
|
291
|
-
this.log('rpc from',
|
305
|
+
async processRpc (from: PeerId, peerStreams: PeerStreams, rpc: RPC) {
|
306
|
+
this.log('rpc from %p', from)
|
292
307
|
const subs = rpc.subscriptions
|
293
308
|
const msgs = rpc.msgs
|
294
309
|
|
295
310
|
if (subs.length > 0) {
|
296
311
|
// update peer subscriptions
|
297
312
|
subs.forEach((subOpt) => {
|
298
|
-
this._processRpcSubOpt(
|
313
|
+
this._processRpcSubOpt(from, subOpt)
|
299
314
|
})
|
300
315
|
this.dispatchEvent(new CustomEvent('pubsub:subscription-change', {
|
301
316
|
detail: { peerId: peerStreams.id, subscriptions: subs }
|
302
317
|
}))
|
303
318
|
}
|
304
319
|
|
305
|
-
if (!this._acceptFrom(
|
306
|
-
this.log('received message from unacceptable peer %
|
320
|
+
if (!this._acceptFrom(from)) {
|
321
|
+
this.log('received message from unacceptable peer %p', from)
|
307
322
|
return false
|
308
323
|
}
|
309
324
|
|
@@ -318,9 +333,12 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
318
333
|
}
|
319
334
|
|
320
335
|
try {
|
321
|
-
const msg =
|
336
|
+
const msg = toMessage({
|
337
|
+
...message,
|
338
|
+
from: from.multihash.bytes
|
339
|
+
})
|
322
340
|
|
323
|
-
await this.
|
341
|
+
await this._processMessage(msg)
|
324
342
|
} catch (err: any) {
|
325
343
|
this.log.error(err)
|
326
344
|
}
|
@@ -333,7 +351,7 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
333
351
|
/**
|
334
352
|
* Handles a subscription change from a peer
|
335
353
|
*/
|
336
|
-
_processRpcSubOpt (id:
|
354
|
+
_processRpcSubOpt (id: PeerId, subOpt: RPCSubscription) {
|
337
355
|
const t = subOpt.topicID
|
338
356
|
|
339
357
|
if (t == null) {
|
@@ -346,20 +364,20 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
346
364
|
this.topics.set(t, topicSet)
|
347
365
|
}
|
348
366
|
|
349
|
-
if (subOpt.subscribe
|
367
|
+
if (subOpt.subscribe) {
|
350
368
|
// subscribe peer to new topic
|
351
|
-
topicSet.add(id)
|
369
|
+
topicSet.add(id.toString())
|
352
370
|
} else {
|
353
371
|
// unsubscribe from existing topic
|
354
|
-
topicSet.delete(id)
|
372
|
+
topicSet.delete(id.toString())
|
355
373
|
}
|
356
374
|
}
|
357
375
|
|
358
376
|
/**
|
359
377
|
* Handles an message from a peer
|
360
378
|
*/
|
361
|
-
async
|
362
|
-
if (
|
379
|
+
async _processMessage (msg: Message) {
|
380
|
+
if (this.peerId.equals(msg.from) && !this.emitSelf) {
|
363
381
|
return
|
364
382
|
}
|
365
383
|
|
@@ -372,15 +390,15 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
372
390
|
}
|
373
391
|
|
374
392
|
// Emit to self
|
375
|
-
this.
|
393
|
+
this.emitMessage(msg)
|
376
394
|
|
377
|
-
return await this._publish(
|
395
|
+
return await this._publish(toRpcMessage(msg))
|
378
396
|
}
|
379
397
|
|
380
398
|
/**
|
381
399
|
* Emit a message from a peer
|
382
400
|
*/
|
383
|
-
|
401
|
+
emitMessage (message: Message) {
|
384
402
|
message.topicIDs.forEach((topic) => {
|
385
403
|
if (this.subscriptions.has(topic)) {
|
386
404
|
this.dispatchEvent(new CustomEvent(topic, {
|
@@ -398,10 +416,13 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
398
416
|
const signaturePolicy = this.globalSignaturePolicy
|
399
417
|
switch (signaturePolicy) {
|
400
418
|
case 'StrictSign':
|
401
|
-
|
402
|
-
|
419
|
+
if (msg.seqno == null) {
|
420
|
+
throw errcode(new Error('Need seqno when signature policy is StrictSign but it was missing'), codes.ERR_MISSING_SEQNO)
|
421
|
+
}
|
422
|
+
|
423
|
+
return msgId(msg.from, msg.seqno)
|
403
424
|
case 'StrictNoSign':
|
404
|
-
return
|
425
|
+
return noSignMsgId(msg.data)
|
405
426
|
default:
|
406
427
|
throw errcode(new Error('Cannot get message id: unhandled signature policy'), codes.ERR_UNHANDLED_SIGNATURE_POLICY)
|
407
428
|
}
|
@@ -411,7 +432,7 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
411
432
|
* Whether to accept a message from a peer
|
412
433
|
* Override to create a graylist
|
413
434
|
*/
|
414
|
-
_acceptFrom (id:
|
435
|
+
_acceptFrom (id: PeerId) {
|
415
436
|
return true
|
416
437
|
}
|
417
438
|
|
@@ -420,7 +441,7 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
420
441
|
* This can be override to use a custom router protobuf.
|
421
442
|
*/
|
422
443
|
_decodeRpc (bytes: Uint8Array) {
|
423
|
-
return
|
444
|
+
return RPCProto.decode(bytes)
|
424
445
|
}
|
425
446
|
|
426
447
|
/**
|
@@ -428,27 +449,29 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
428
449
|
* This can be override to use a custom router protobuf.
|
429
450
|
*/
|
430
451
|
_encodeRpc (rpc: IRPC) {
|
431
|
-
return
|
452
|
+
return RPCProto.encode(rpc).finish()
|
432
453
|
}
|
433
454
|
|
434
455
|
/**
|
435
456
|
* Send an rpc object to a peer
|
436
457
|
*/
|
437
|
-
_sendRpc (
|
438
|
-
const peerStreams = this.peers.get(
|
439
|
-
|
440
|
-
|
458
|
+
_sendRpc (peer: PeerId, rpc: IRPC) {
|
459
|
+
const peerStreams = this.peers.get(peer)
|
460
|
+
|
461
|
+
if (peerStreams == null || !peerStreams.isWritable) {
|
462
|
+
const msg = `Cannot send RPC to ${peer.toString(base58btc)} as there is no open stream to it available`
|
441
463
|
|
442
464
|
this.log.error(msg)
|
443
465
|
return
|
444
466
|
}
|
467
|
+
|
445
468
|
peerStreams.write(this._encodeRpc(rpc))
|
446
469
|
}
|
447
470
|
|
448
471
|
/**
|
449
472
|
* Send subscriptions to a peer
|
450
473
|
*/
|
451
|
-
_sendSubscriptions (id:
|
474
|
+
_sendSubscriptions (id: PeerId, topics: string[], subscribe: boolean) {
|
452
475
|
return this._sendRpc(id, {
|
453
476
|
subscriptions: topics.map(t => ({ topicID: t, subscribe: subscribe }))
|
454
477
|
})
|
@@ -462,9 +485,6 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
462
485
|
const signaturePolicy = this.globalSignaturePolicy
|
463
486
|
switch (signaturePolicy) {
|
464
487
|
case 'StrictNoSign':
|
465
|
-
if (message.from != null) {
|
466
|
-
throw errcode(new Error('StrictNoSigning: from should not be present'), codes.ERR_UNEXPECTED_FROM)
|
467
|
-
}
|
468
488
|
if (message.signature != null) {
|
469
489
|
throw errcode(new Error('StrictNoSigning: signature should not be present'), codes.ERR_UNEXPECTED_SIGNATURE)
|
470
490
|
}
|
@@ -502,12 +522,11 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
502
522
|
* Normalizes the message and signs it, if signing is enabled.
|
503
523
|
* Should be used by the routers to create the message to send.
|
504
524
|
*/
|
505
|
-
protected async
|
525
|
+
protected async _maybeSignMessage (message: Message) {
|
506
526
|
const signaturePolicy = this.globalSignaturePolicy
|
507
527
|
switch (signaturePolicy) {
|
508
528
|
case 'StrictSign':
|
509
|
-
message.
|
510
|
-
message.seqno = utils.randomSeqno()
|
529
|
+
message.seqno = randomSeqno()
|
511
530
|
return await signMessage(this.peerId, message)
|
512
531
|
case 'StrictNoSign':
|
513
532
|
return await Promise.resolve(message)
|
@@ -536,7 +555,7 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
536
555
|
return []
|
537
556
|
}
|
538
557
|
|
539
|
-
return Array.from(peersInTopic)
|
558
|
+
return Array.from(peersInTopic).map(str => peerIdFromString(str))
|
540
559
|
}
|
541
560
|
|
542
561
|
/**
|
@@ -549,29 +568,27 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
549
568
|
|
550
569
|
this.log('publish', topic, message)
|
551
570
|
|
552
|
-
const from = this.peerId.toString()
|
553
571
|
const msgObject = {
|
554
|
-
|
572
|
+
from: this.peerId,
|
555
573
|
data: message,
|
556
574
|
topicIDs: [topic]
|
557
575
|
}
|
558
576
|
|
559
577
|
// ensure that the message follows the signature policy
|
560
|
-
const
|
561
|
-
const msg = utils.normalizeInRpcMessage(outMsg)
|
578
|
+
const msg = await this._maybeSignMessage(msgObject)
|
562
579
|
|
563
580
|
// Emit to self if I'm interested and emitSelf enabled
|
564
|
-
this.emitSelf && this.
|
581
|
+
this.emitSelf && this.emitMessage(msg)
|
565
582
|
|
566
583
|
// send to all the other peers
|
567
|
-
await this._publish(msg)
|
584
|
+
await this._publish(toRpcMessage(msg))
|
568
585
|
}
|
569
586
|
|
570
587
|
/**
|
571
588
|
* Overriding the implementation of publish should handle the appropriate algorithms for the publish/subscriber implementation.
|
572
589
|
* For example, a Floodsub implementation might simply publish each message to each topic for every peer
|
573
590
|
*/
|
574
|
-
abstract _publish (message:
|
591
|
+
abstract _publish (message: RPCMessage): Promise<void>
|
575
592
|
|
576
593
|
/**
|
577
594
|
* Subscribes to a given topic.
|
@@ -583,7 +600,10 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
583
600
|
|
584
601
|
if (!this.subscriptions.has(topic)) {
|
585
602
|
this.subscriptions.add(topic)
|
586
|
-
|
603
|
+
|
604
|
+
for (const peerId of this.peers.keys()) {
|
605
|
+
this._sendSubscriptions(peerId, [topic], true)
|
606
|
+
}
|
587
607
|
}
|
588
608
|
}
|
589
609
|
|
@@ -597,7 +617,10 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
597
617
|
|
598
618
|
if (this.subscriptions.has(topic) && this.listenerCount(topic) === 0) {
|
599
619
|
this.subscriptions.delete(topic)
|
600
|
-
|
620
|
+
|
621
|
+
for (const peerId of this.peers.keys()) {
|
622
|
+
this._sendSubscriptions(peerId, [topic], false)
|
623
|
+
}
|
601
624
|
}
|
602
625
|
}
|
603
626
|
|
@@ -611,4 +634,12 @@ export abstract class PubsubBaseProtocol<EventMap> extends EventEmitter<EventMap
|
|
611
634
|
|
612
635
|
return Array.from(this.subscriptions)
|
613
636
|
}
|
637
|
+
|
638
|
+
getPeers () {
|
639
|
+
if (!this.started) {
|
640
|
+
throw new Error('Pubsub is not started')
|
641
|
+
}
|
642
|
+
|
643
|
+
return Array.from(this.peers.keys())
|
644
|
+
}
|
614
645
|
}
|
package/src/message/sign.ts
CHANGED
@@ -2,10 +2,9 @@ import * as PeerIdFactory from '@libp2p/peer-id-factory'
|
|
2
2
|
import { RPC } from './rpc.js'
|
3
3
|
import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
|
4
4
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
5
|
-
import {
|
5
|
+
import { toRpcMessage } from '../utils.js'
|
6
6
|
import type { PeerId } from '@libp2p/interfaces/peer-id'
|
7
7
|
import { keys } from '@libp2p/crypto'
|
8
|
-
import { peerIdFromBytes } from '@libp2p/peer-id'
|
9
8
|
import type { Message } from '@libp2p/interfaces/pubsub'
|
10
9
|
|
11
10
|
export const SignPrefix = uint8ArrayFromString('libp2p-pubsub:')
|
@@ -17,7 +16,7 @@ export async function signMessage (peerId: PeerId, message: Message) {
|
|
17
16
|
// Get the message in bytes, and prepend with the pubsub prefix
|
18
17
|
const bytes = uint8ArrayConcat([
|
19
18
|
SignPrefix,
|
20
|
-
RPC.Message.encode(
|
19
|
+
RPC.Message.encode(toRpcMessage(message)).finish()
|
21
20
|
])
|
22
21
|
|
23
22
|
if (peerId.privateKey == null) {
|
@@ -56,7 +55,7 @@ export async function verifySignature (message: Message) {
|
|
56
55
|
const bytes = uint8ArrayConcat([
|
57
56
|
SignPrefix,
|
58
57
|
RPC.Message.encode({
|
59
|
-
...message,
|
58
|
+
...toRpcMessage(message),
|
60
59
|
signature: undefined,
|
61
60
|
key: undefined
|
62
61
|
}).finish()
|
@@ -80,21 +79,19 @@ export async function messagePublicKey (message: Message) {
|
|
80
79
|
throw new Error('Could not get the public key from the originator id')
|
81
80
|
}
|
82
81
|
|
83
|
-
const from = peerIdFromBytes(message.from)
|
84
|
-
|
85
82
|
if (message.key != null) {
|
86
83
|
const keyPeerId = await PeerIdFactory.createFromPubKey(keys.unmarshalPublicKey(message.key))
|
87
84
|
|
88
85
|
// the key belongs to the sender, return the key
|
89
|
-
if (!keyPeerId.equals(from)) {
|
86
|
+
if (!keyPeerId.equals(message.from)) {
|
90
87
|
throw new Error('Public Key does not match the originator')
|
91
88
|
}
|
92
89
|
|
93
90
|
if (keyPeerId.publicKey != null) {
|
94
91
|
return keyPeerId.publicKey
|
95
92
|
}
|
96
|
-
} else if (from.publicKey != null) {
|
97
|
-
return from.publicKey
|
93
|
+
} else if (message.from.publicKey != null) {
|
94
|
+
return message.from.publicKey
|
98
95
|
}
|
99
96
|
|
100
97
|
// We couldn't validate pubkey is from the originator, error
|
package/src/peer-streams.ts
CHANGED
@@ -25,19 +25,19 @@ export class PeerStreams extends EventEmitter<PeerStreamEvents> {
|
|
25
25
|
/**
|
26
26
|
* Write stream - it's preferable to use the write method
|
27
27
|
*/
|
28
|
-
public outboundStream
|
28
|
+
public outboundStream?: Pushable<Uint8Array>
|
29
29
|
/**
|
30
30
|
* Read stream
|
31
31
|
*/
|
32
|
-
public inboundStream
|
32
|
+
public inboundStream?: AsyncIterable<Uint8Array>
|
33
33
|
/**
|
34
34
|
* The raw outbound stream, as retrieved from conn.newStream
|
35
35
|
*/
|
36
|
-
private _rawOutboundStream
|
36
|
+
private _rawOutboundStream?: Stream
|
37
37
|
/**
|
38
38
|
* The raw inbound stream, as retrieved from the callback from libp2p.handle
|
39
39
|
*/
|
40
|
-
private _rawInboundStream
|
40
|
+
private _rawInboundStream?: Stream
|
41
41
|
/**
|
42
42
|
* An AbortController for controlled shutdown of the inbound stream
|
43
43
|
*/
|
@@ -142,6 +142,8 @@ export class PeerStreams extends EventEmitter<PeerStreamEvents> {
|
|
142
142
|
if (_prevStream == null) {
|
143
143
|
this.dispatchEvent(new CustomEvent('stream:outbound'))
|
144
144
|
}
|
145
|
+
|
146
|
+
return this.outboundStream
|
145
147
|
}
|
146
148
|
|
147
149
|
/**
|