@libp2p/pubsub 0.0.0 → 0.2.0

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 (76) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +35 -0
  3. package/dist/src/errors.d.ts +39 -0
  4. package/dist/src/errors.d.ts.map +1 -0
  5. package/dist/src/errors.js +41 -0
  6. package/dist/src/errors.js.map +1 -0
  7. package/dist/src/index.d.ts +180 -0
  8. package/dist/src/index.d.ts.map +1 -0
  9. package/dist/src/index.js +467 -0
  10. package/dist/src/index.js.map +1 -0
  11. package/dist/src/message/rpc.d.ts +258 -0
  12. package/dist/src/message/rpc.js +699 -0
  13. package/dist/src/message/sign.d.ts +17 -0
  14. package/dist/src/message/sign.d.ts.map +1 -0
  15. package/dist/src/message/sign.js +84 -0
  16. package/dist/src/message/sign.js.map +1 -0
  17. package/dist/src/message/topic-descriptor.d.ts +254 -0
  18. package/dist/src/message/topic-descriptor.js +647 -0
  19. package/dist/src/peer-streams.d.ts +67 -0
  20. package/dist/src/peer-streams.d.ts.map +1 -0
  21. package/dist/src/peer-streams.js +112 -0
  22. package/dist/src/peer-streams.js.map +1 -0
  23. package/dist/src/utils.d.ts +29 -0
  24. package/dist/src/utils.d.ts.map +1 -0
  25. package/dist/src/utils.js +80 -0
  26. package/dist/src/utils.js.map +1 -0
  27. package/dist/test/emit-self.spec.d.ts +2 -0
  28. package/dist/test/emit-self.spec.d.ts.map +1 -0
  29. package/dist/test/emit-self.spec.js +63 -0
  30. package/dist/test/emit-self.spec.js.map +1 -0
  31. package/dist/test/instance.spec.d.ts +2 -0
  32. package/dist/test/instance.spec.d.ts.map +1 -0
  33. package/dist/test/instance.spec.js +50 -0
  34. package/dist/test/instance.spec.js.map +1 -0
  35. package/dist/test/lifesycle.spec.d.ts +2 -0
  36. package/dist/test/lifesycle.spec.d.ts.map +1 -0
  37. package/dist/test/lifesycle.spec.js +192 -0
  38. package/dist/test/lifesycle.spec.js.map +1 -0
  39. package/dist/test/message.spec.d.ts +2 -0
  40. package/dist/test/message.spec.d.ts.map +1 -0
  41. package/dist/test/message.spec.js +83 -0
  42. package/dist/test/message.spec.js.map +1 -0
  43. package/dist/test/pubsub.spec.d.ts +2 -0
  44. package/dist/test/pubsub.spec.d.ts.map +1 -0
  45. package/dist/test/pubsub.spec.js +310 -0
  46. package/dist/test/pubsub.spec.js.map +1 -0
  47. package/dist/test/sign.spec.d.ts +2 -0
  48. package/dist/test/sign.spec.d.ts.map +1 -0
  49. package/dist/test/sign.spec.js +93 -0
  50. package/dist/test/sign.spec.js.map +1 -0
  51. package/dist/test/topic-validators.spec.d.ts +2 -0
  52. package/dist/test/topic-validators.spec.d.ts.map +1 -0
  53. package/dist/test/topic-validators.spec.js +86 -0
  54. package/dist/test/topic-validators.spec.js.map +1 -0
  55. package/dist/test/utils/index.d.ts +22 -0
  56. package/dist/test/utils/index.d.ts.map +1 -0
  57. package/dist/test/utils/index.js +86 -0
  58. package/dist/test/utils/index.js.map +1 -0
  59. package/dist/test/utils.spec.d.ts +2 -0
  60. package/dist/test/utils.spec.d.ts.map +1 -0
  61. package/dist/test/utils.spec.js +53 -0
  62. package/dist/test/utils.spec.js.map +1 -0
  63. package/dist/tsconfig.tsbuildinfo +1 -0
  64. package/package.json +109 -4
  65. package/src/README.md +251 -0
  66. package/src/errors.ts +45 -0
  67. package/src/index.ts +610 -0
  68. package/src/message/rpc.d.ts +258 -0
  69. package/src/message/rpc.js +699 -0
  70. package/src/message/rpc.proto +20 -0
  71. package/src/message/sign.ts +101 -0
  72. package/src/message/topic-descriptor.d.ts +254 -0
  73. package/src/message/topic-descriptor.js +647 -0
  74. package/src/message/topic-descriptor.proto +30 -0
  75. package/src/peer-streams.ts +169 -0
  76. package/src/utils.ts +93 -0
@@ -0,0 +1,83 @@
1
+ /* eslint-env mocha */
2
+ import { expect } from 'aegir/utils/chai.js';
3
+ import sinon from 'sinon';
4
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
5
+ import { PubsubBaseProtocol } from '../src/index.js';
6
+ import { createPeerId, mockRegistrar } from './utils/index.js';
7
+ class PubsubProtocol extends PubsubBaseProtocol {
8
+ async _publish(message) {
9
+ throw new Error('Method not implemented');
10
+ }
11
+ async buildMessage(message) {
12
+ return await this._buildMessage(message);
13
+ }
14
+ }
15
+ describe('pubsub base messages', () => {
16
+ let peerId;
17
+ let pubsub;
18
+ before(async () => {
19
+ peerId = await createPeerId();
20
+ pubsub = new PubsubProtocol({
21
+ debugName: 'pubsub',
22
+ multicodecs: ['/pubsub/1.0.0'],
23
+ libp2p: {
24
+ peerId: peerId,
25
+ registrar: mockRegistrar
26
+ }
27
+ });
28
+ });
29
+ afterEach(() => {
30
+ sinon.restore();
31
+ });
32
+ it('_buildMessage normalizes and signs messages', async () => {
33
+ const message = {
34
+ from: peerId.multihash.bytes,
35
+ receivedFrom: peerId.toString(),
36
+ data: uint8ArrayFromString('hello'),
37
+ topicIDs: ['test-topic']
38
+ };
39
+ const signedMessage = await pubsub.buildMessage(message);
40
+ await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected();
41
+ });
42
+ it('validate with StrictNoSign will reject a message with from, signature, key, seqno present', async () => {
43
+ const message = {
44
+ from: peerId.multihash.bytes,
45
+ receivedFrom: peerId.toString(),
46
+ data: uint8ArrayFromString('hello'),
47
+ topicIDs: ['test-topic']
48
+ };
49
+ sinon.stub(pubsub, 'globalSignaturePolicy').value('StrictSign');
50
+ const signedMessage = await pubsub.buildMessage(message);
51
+ sinon.stub(pubsub, 'globalSignaturePolicy').value('StrictNoSign');
52
+ await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected();
53
+ delete signedMessage.from;
54
+ await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected();
55
+ delete signedMessage.signature;
56
+ await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected();
57
+ delete signedMessage.key;
58
+ await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected();
59
+ delete signedMessage.seqno;
60
+ await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected();
61
+ });
62
+ it('validate with StrictNoSign will validate a message without a signature, key, and seqno', async () => {
63
+ const message = {
64
+ from: peerId.multihash.bytes,
65
+ receivedFrom: peerId.toString(),
66
+ data: uint8ArrayFromString('hello'),
67
+ topicIDs: ['test-topic']
68
+ };
69
+ sinon.stub(pubsub, 'globalSignaturePolicy').value('StrictNoSign');
70
+ const signedMessage = await pubsub.buildMessage(message);
71
+ await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected();
72
+ });
73
+ it('validate with StrictSign requires a signature', async () => {
74
+ const message = {
75
+ from: peerId.multihash.bytes,
76
+ receivedFrom: peerId.toString(),
77
+ data: uint8ArrayFromString('hello'),
78
+ topicIDs: ['test-topic']
79
+ };
80
+ await expect(pubsub.validate(message)).to.be.rejectedWith(Error, 'Signing required and no signature was present');
81
+ });
82
+ });
83
+ //# sourceMappingURL=message.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.spec.js","sourceRoot":"","sources":["../../test/message.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pubsub.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubsub.spec.d.ts","sourceRoot":"","sources":["../../test/pubsub.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,310 @@
1
+ /* eslint max-nested-callbacks: ["error", 6] */
2
+ import { expect } from 'aegir/utils/chai.js';
3
+ import sinon from 'sinon';
4
+ import pWaitFor from 'p-wait-for';
5
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
6
+ import { PeerStreams } from '../src/peer-streams.js';
7
+ import { createPeerId, createMockRegistrar, ConnectionPair, mockRegistrar, PubsubImplementation } from './utils/index.js';
8
+ const protocol = '/pubsub/1.0.0';
9
+ const topic = 'test-topic';
10
+ const message = uint8ArrayFromString('hello');
11
+ describe('pubsub base implementation', () => {
12
+ describe('publish', () => {
13
+ let pubsub;
14
+ beforeEach(async () => {
15
+ const peerId = await createPeerId();
16
+ pubsub = new PubsubImplementation({
17
+ libp2p: {
18
+ peerId: peerId,
19
+ registrar: mockRegistrar
20
+ },
21
+ multicodecs: [protocol]
22
+ });
23
+ });
24
+ afterEach(() => pubsub.stop());
25
+ it('calls _publish for router to forward messages', async () => {
26
+ sinon.spy(pubsub, '_publish');
27
+ await pubsub.start();
28
+ await pubsub.publish(topic, message);
29
+ // @ts-expect-error .callCount is a added by sinon
30
+ expect(pubsub._publish.callCount).to.eql(1);
31
+ });
32
+ it('should sign messages on publish', async () => {
33
+ sinon.spy(pubsub, '_publish');
34
+ await pubsub.start();
35
+ await pubsub.publish(topic, message);
36
+ // Get the first message sent to _publish, and validate it
37
+ // @ts-expect-error .getCall is a added by sinon
38
+ const signedMessage = pubsub._publish.getCall(0).lastArg;
39
+ await expect(pubsub.validate(signedMessage)).to.eventually.be.undefined();
40
+ });
41
+ });
42
+ describe('subscribe', () => {
43
+ describe('basics', () => {
44
+ let pubsub;
45
+ beforeEach(async () => {
46
+ const peerId = await createPeerId();
47
+ pubsub = new PubsubImplementation({
48
+ multicodecs: [protocol],
49
+ libp2p: {
50
+ peerId: peerId,
51
+ registrar: mockRegistrar
52
+ }
53
+ });
54
+ await pubsub.start();
55
+ });
56
+ afterEach(() => pubsub.stop());
57
+ it('should add subscription', () => {
58
+ pubsub.subscribe(topic);
59
+ expect(pubsub.subscriptions.size).to.eql(1);
60
+ expect(pubsub.subscriptions.has(topic)).to.be.true();
61
+ });
62
+ });
63
+ describe('two nodes', () => {
64
+ let pubsubA, pubsubB;
65
+ let peerIdA, peerIdB;
66
+ const registrarRecordA = new Map();
67
+ const registrarRecordB = new Map();
68
+ beforeEach(async () => {
69
+ peerIdA = await createPeerId();
70
+ peerIdB = await createPeerId();
71
+ pubsubA = new PubsubImplementation({
72
+ multicodecs: [protocol],
73
+ libp2p: {
74
+ peerId: peerIdA,
75
+ registrar: createMockRegistrar(registrarRecordA)
76
+ }
77
+ });
78
+ pubsubB = new PubsubImplementation({
79
+ multicodecs: [protocol],
80
+ libp2p: {
81
+ peerId: peerIdB,
82
+ registrar: createMockRegistrar(registrarRecordB)
83
+ }
84
+ });
85
+ });
86
+ // start pubsub and connect nodes
87
+ beforeEach(async () => {
88
+ pubsubA.start();
89
+ pubsubB.start();
90
+ const onConnectA = registrarRecordA.get(protocol).onConnect;
91
+ const handlerB = registrarRecordB.get(protocol).handler;
92
+ // Notice peers of connection
93
+ const [c0, c1] = ConnectionPair();
94
+ await onConnectA(peerIdB, c0);
95
+ await handlerB({
96
+ protocol,
97
+ stream: c1.stream,
98
+ connection: {
99
+ remotePeer: peerIdA
100
+ }
101
+ });
102
+ });
103
+ afterEach(() => {
104
+ pubsubA.stop();
105
+ pubsubB.stop();
106
+ });
107
+ it('should send subscribe message to connected peers', async () => {
108
+ sinon.spy(pubsubA, '_sendSubscriptions');
109
+ sinon.spy(pubsubB, '_processRpcSubOpt');
110
+ pubsubA.subscribe(topic);
111
+ // Should send subscriptions to a peer
112
+ // @ts-expect-error .callCount is a added by sinon
113
+ expect(pubsubA._sendSubscriptions.callCount).to.eql(1);
114
+ // Other peer should receive subscription message
115
+ await pWaitFor(() => {
116
+ const subscribers = pubsubB.getSubscribers(topic);
117
+ return subscribers.length === 1;
118
+ });
119
+ // @ts-expect-error .callCount is a added by sinon
120
+ expect(pubsubB._processRpcSubOpt.callCount).to.eql(1);
121
+ });
122
+ });
123
+ });
124
+ describe('unsubscribe', () => {
125
+ describe('basics', () => {
126
+ let pubsub;
127
+ beforeEach(async () => {
128
+ const peerId = await createPeerId();
129
+ pubsub = new PubsubImplementation({
130
+ multicodecs: [protocol],
131
+ libp2p: {
132
+ peerId: peerId,
133
+ registrar: mockRegistrar
134
+ }
135
+ });
136
+ await pubsub.start();
137
+ });
138
+ afterEach(() => pubsub.stop());
139
+ it('should remove all subscriptions for a topic', () => {
140
+ pubsub.subscribe(topic);
141
+ pubsub.subscribe(topic);
142
+ expect(pubsub.subscriptions.size).to.eql(1);
143
+ pubsub.unsubscribe(topic);
144
+ expect(pubsub.subscriptions.size).to.eql(0);
145
+ });
146
+ });
147
+ describe('two nodes', () => {
148
+ let pubsubA, pubsubB;
149
+ let peerIdA, peerIdB;
150
+ const registrarRecordA = new Map();
151
+ const registrarRecordB = new Map();
152
+ beforeEach(async () => {
153
+ peerIdA = await createPeerId();
154
+ peerIdB = await createPeerId();
155
+ pubsubA = new PubsubImplementation({
156
+ multicodecs: [protocol],
157
+ libp2p: {
158
+ peerId: peerIdA,
159
+ registrar: createMockRegistrar(registrarRecordA)
160
+ }
161
+ });
162
+ pubsubB = new PubsubImplementation({
163
+ multicodecs: [protocol],
164
+ libp2p: {
165
+ peerId: peerIdB,
166
+ registrar: createMockRegistrar(registrarRecordB)
167
+ }
168
+ });
169
+ });
170
+ // start pubsub and connect nodes
171
+ beforeEach(async () => {
172
+ pubsubA.start();
173
+ pubsubB.start();
174
+ const onConnectA = registrarRecordA.get(protocol).onConnect;
175
+ const handlerB = registrarRecordB.get(protocol).handler;
176
+ // Notice peers of connection
177
+ const [c0, c1] = ConnectionPair();
178
+ await onConnectA(peerIdB, c0);
179
+ await handlerB({
180
+ protocol,
181
+ stream: c1.stream,
182
+ connection: {
183
+ remotePeer: peerIdA
184
+ }
185
+ });
186
+ });
187
+ afterEach(() => {
188
+ pubsubA.stop();
189
+ pubsubB.stop();
190
+ });
191
+ it('should send unsubscribe message to connected peers', async () => {
192
+ sinon.spy(pubsubA, '_sendSubscriptions');
193
+ sinon.spy(pubsubB, '_processRpcSubOpt');
194
+ pubsubA.subscribe(topic);
195
+ // Should send subscriptions to a peer
196
+ // @ts-expect-error .callCount is a property added by sinon
197
+ expect(pubsubA._sendSubscriptions.callCount).to.eql(1);
198
+ // Other peer should receive subscription message
199
+ await pWaitFor(() => {
200
+ const subscribers = pubsubB.getSubscribers(topic);
201
+ return subscribers.length === 1;
202
+ });
203
+ // @ts-expect-error .callCount is a property added by sinon
204
+ expect(pubsubB._processRpcSubOpt.callCount).to.eql(1);
205
+ // Unsubscribe
206
+ pubsubA.unsubscribe(topic);
207
+ // Should send subscriptions to a peer
208
+ // @ts-expect-error .callCount is a property added by sinon
209
+ expect(pubsubA._sendSubscriptions.callCount).to.eql(2);
210
+ // Other peer should receive subscription message
211
+ await pWaitFor(() => {
212
+ const subscribers = pubsubB.getSubscribers(topic);
213
+ return subscribers.length === 0;
214
+ });
215
+ // @ts-expect-error .callCount is a property added by sinon
216
+ expect(pubsubB._processRpcSubOpt.callCount).to.eql(2);
217
+ });
218
+ it('should not send unsubscribe message to connected peers if not subscribed', () => {
219
+ sinon.spy(pubsubA, '_sendSubscriptions');
220
+ sinon.spy(pubsubB, '_processRpcSubOpt');
221
+ // Unsubscribe
222
+ pubsubA.unsubscribe(topic);
223
+ // Should send subscriptions to a peer
224
+ // @ts-expect-error .callCount is a property added by sinon
225
+ expect(pubsubA._sendSubscriptions.callCount).to.eql(0);
226
+ });
227
+ });
228
+ });
229
+ describe('getTopics', () => {
230
+ let peerId;
231
+ let pubsub;
232
+ beforeEach(async () => {
233
+ peerId = await createPeerId();
234
+ pubsub = new PubsubImplementation({
235
+ multicodecs: [protocol],
236
+ libp2p: {
237
+ peerId: peerId,
238
+ registrar: mockRegistrar
239
+ }
240
+ });
241
+ await pubsub.start();
242
+ });
243
+ afterEach(() => pubsub.stop());
244
+ it('returns the subscribed topics', () => {
245
+ let subsTopics = pubsub.getTopics();
246
+ expect(subsTopics).to.have.lengthOf(0);
247
+ pubsub.subscribe(topic);
248
+ subsTopics = pubsub.getTopics();
249
+ expect(subsTopics).to.have.lengthOf(1);
250
+ expect(subsTopics[0]).to.eql(topic);
251
+ });
252
+ });
253
+ describe('getSubscribers', () => {
254
+ let peerId;
255
+ let pubsub;
256
+ beforeEach(async () => {
257
+ peerId = await createPeerId();
258
+ pubsub = new PubsubImplementation({
259
+ multicodecs: [protocol],
260
+ libp2p: {
261
+ peerId: peerId,
262
+ registrar: mockRegistrar
263
+ }
264
+ });
265
+ });
266
+ afterEach(() => pubsub.stop());
267
+ it('should fail if pubsub is not started', () => {
268
+ const topic = 'topic-test';
269
+ try {
270
+ pubsub.getSubscribers(topic);
271
+ }
272
+ catch (err) {
273
+ expect(err).to.exist();
274
+ expect(err.code).to.eql('ERR_NOT_STARTED_YET');
275
+ return;
276
+ }
277
+ throw new Error('should fail if pubsub is not started');
278
+ });
279
+ it('should fail if no topic is provided', async () => {
280
+ // start pubsub
281
+ await pubsub.start();
282
+ try {
283
+ // @ts-expect-error invalid params
284
+ pubsub.getSubscribers();
285
+ }
286
+ catch (err) {
287
+ expect(err).to.exist();
288
+ expect(err.code).to.eql('ERR_NOT_VALID_TOPIC');
289
+ return;
290
+ }
291
+ throw new Error('should fail if no topic is provided');
292
+ });
293
+ it('should get peer subscribed to one topic', async () => {
294
+ const topic = 'topic-test';
295
+ // start pubsub
296
+ await pubsub.start();
297
+ let peersSubscribed = pubsub.getSubscribers(topic);
298
+ expect(peersSubscribed).to.be.empty();
299
+ // Set mock peer subscribed
300
+ const peer = new PeerStreams({ id: peerId, protocol: 'a-protocol' });
301
+ const id = peer.id.toString();
302
+ pubsub.topics.set(topic, new Set([id]));
303
+ pubsub.peers.set(id, peer);
304
+ peersSubscribed = pubsub.getSubscribers(topic);
305
+ expect(peersSubscribed).to.not.be.empty();
306
+ expect(peersSubscribed[0]).to.eql(id);
307
+ });
308
+ });
309
+ });
310
+ //# sourceMappingURL=pubsub.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubsub.spec.js","sourceRoot":"","sources":["../../test/pubsub.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sign.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign.spec.d.ts","sourceRoot":"","sources":["../../test/sign.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,93 @@
1
+ import { expect } from 'aegir/utils/chai.js';
2
+ import { concat as uint8ArrayConcat } from 'uint8arrays/concat';
3
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
4
+ import { RPC } from '../src/message/rpc.js';
5
+ import { signMessage, SignPrefix, verifySignature } from '../src/message/sign.js';
6
+ import * as PeerIdFactory from '@libp2p/peer-id-factory';
7
+ import { randomSeqno } from '../src/utils.js';
8
+ import { keys } from '@libp2p/crypto';
9
+ describe('message signing', () => {
10
+ let peerId;
11
+ before(async () => {
12
+ peerId = await PeerIdFactory.createRSAPeerId({
13
+ bits: 1024
14
+ });
15
+ });
16
+ it('should be able to sign and verify a message', async () => {
17
+ const message = {
18
+ from: peerId.toBytes(),
19
+ receivedFrom: peerId.toString(),
20
+ data: uint8ArrayFromString('hello'),
21
+ seqno: randomSeqno(),
22
+ topicIDs: ['test-topic']
23
+ };
24
+ const bytesToSign = uint8ArrayConcat([SignPrefix, RPC.Message.encode(message).finish()]);
25
+ if (peerId.privateKey == null) {
26
+ throw new Error('No private key found on PeerId');
27
+ }
28
+ const privateKey = await keys.unmarshalPrivateKey(peerId.privateKey);
29
+ const expectedSignature = await privateKey.sign(bytesToSign);
30
+ const signedMessage = await signMessage(peerId, message);
31
+ // Check the signature and public key
32
+ expect(signedMessage.signature).to.eql(expectedSignature);
33
+ expect(signedMessage.key).to.eql(peerId.publicKey);
34
+ // Verify the signature
35
+ const verified = await verifySignature({
36
+ ...signedMessage,
37
+ from: peerId.toBytes()
38
+ });
39
+ expect(verified).to.eql(true);
40
+ });
41
+ it('should be able to extract the public key from an inlined key', async () => {
42
+ const secPeerId = await PeerIdFactory.createSecp256k1PeerId();
43
+ const message = {
44
+ from: secPeerId.toBytes(),
45
+ receivedFrom: secPeerId.toString(),
46
+ data: uint8ArrayFromString('hello'),
47
+ seqno: randomSeqno(),
48
+ topicIDs: ['test-topic']
49
+ };
50
+ const bytesToSign = uint8ArrayConcat([SignPrefix, RPC.Message.encode(message).finish()]);
51
+ if (secPeerId.privateKey == null) {
52
+ throw new Error('No private key found on PeerId');
53
+ }
54
+ const privateKey = await keys.unmarshalPrivateKey(secPeerId.privateKey);
55
+ const expectedSignature = await privateKey.sign(bytesToSign);
56
+ const signedMessage = await signMessage(secPeerId, message);
57
+ // Check the signature and public key
58
+ expect(signedMessage.signature).to.eql(expectedSignature);
59
+ signedMessage.key = undefined;
60
+ // Verify the signature
61
+ const verified = await verifySignature({
62
+ ...signedMessage,
63
+ from: secPeerId.toBytes()
64
+ });
65
+ expect(verified).to.eql(true);
66
+ });
67
+ it('should be able to extract the public key from the message', async () => {
68
+ const message = {
69
+ from: peerId.toBytes(),
70
+ receivedFrom: peerId.toString(),
71
+ data: uint8ArrayFromString('hello'),
72
+ seqno: randomSeqno(),
73
+ topicIDs: ['test-topic']
74
+ };
75
+ const bytesToSign = uint8ArrayConcat([SignPrefix, RPC.Message.encode(message).finish()]);
76
+ if (peerId.privateKey == null) {
77
+ throw new Error('No private key found on PeerId');
78
+ }
79
+ const privateKey = await keys.unmarshalPrivateKey(peerId.privateKey);
80
+ const expectedSignature = await privateKey.sign(bytesToSign);
81
+ const signedMessage = await signMessage(peerId, message);
82
+ // Check the signature and public key
83
+ expect(signedMessage.signature).to.equalBytes(expectedSignature);
84
+ expect(signedMessage.key).to.equalBytes(peerId.publicKey);
85
+ // Verify the signature
86
+ const verified = await verifySignature({
87
+ ...signedMessage,
88
+ from: peerId.toBytes()
89
+ });
90
+ expect(verified).to.eql(true);
91
+ });
92
+ });
93
+ //# sourceMappingURL=sign.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign.spec.js","sourceRoot":"","sources":["../../test/sign.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=topic-validators.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topic-validators.spec.d.ts","sourceRoot":"","sources":["../../test/topic-validators.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,86 @@
1
+ import { expect } from 'aegir/utils/chai.js';
2
+ import sinon from 'sinon';
3
+ import pWaitFor from 'p-wait-for';
4
+ import errCode from 'err-code';
5
+ import * as PeerIdFactory from '@libp2p/peer-id-factory';
6
+ import { equals as uint8ArrayEquals } from 'uint8arrays/equals';
7
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
8
+ import { PeerStreams } from '../src/peer-streams.js';
9
+ import { createPeerId, mockRegistrar, PubsubImplementation } from './utils/index.js';
10
+ const protocol = '/pubsub/1.0.0';
11
+ describe('topic validators', () => {
12
+ let pubsub;
13
+ beforeEach(async () => {
14
+ const peerId = await createPeerId();
15
+ pubsub = new PubsubImplementation({
16
+ libp2p: {
17
+ peerId: peerId,
18
+ registrar: mockRegistrar
19
+ },
20
+ multicodecs: [protocol],
21
+ globalSignaturePolicy: 'StrictNoSign'
22
+ });
23
+ await pubsub.start();
24
+ });
25
+ afterEach(() => {
26
+ sinon.restore();
27
+ });
28
+ it('should filter messages by topic validator', async () => {
29
+ // use _publish.callCount() to see if a message is valid or not
30
+ sinon.spy(pubsub, '_publish');
31
+ // @ts-expect-error not all fields are implemented in return value
32
+ sinon.stub(pubsub.peers, 'get').returns({});
33
+ const filteredTopic = 't';
34
+ const peer = new PeerStreams({ id: await PeerIdFactory.createEd25519PeerId(), protocol: 'a-protocol' });
35
+ // Set a trivial topic validator
36
+ pubsub.topicValidators.set(filteredTopic, async (topic, message) => {
37
+ if (!uint8ArrayEquals(message.data, uint8ArrayFromString('a message'))) {
38
+ throw errCode(new Error(), 'ERR_TOPIC_VALIDATOR_REJECT');
39
+ }
40
+ });
41
+ // valid case
42
+ const validRpc = {
43
+ subscriptions: [],
44
+ msgs: [{
45
+ data: uint8ArrayFromString('a message'),
46
+ topicIDs: [filteredTopic]
47
+ }],
48
+ toJSON: () => ({})
49
+ };
50
+ // process valid message
51
+ pubsub.subscribe(filteredTopic);
52
+ void pubsub._processRpc(peer.id.toString(), peer, validRpc);
53
+ // @ts-expect-error .callCount is a property added by sinon
54
+ await pWaitFor(() => pubsub._publish.callCount === 1);
55
+ // invalid case
56
+ const invalidRpc = {
57
+ subscriptions: [],
58
+ msgs: [{
59
+ data: uint8ArrayFromString('a different message'),
60
+ topicIDs: [filteredTopic]
61
+ }],
62
+ toJSON: () => ({})
63
+ };
64
+ // process invalid message
65
+ void pubsub._processRpc(peer.id.toString(), peer, invalidRpc);
66
+ // @ts-expect-error .callCount is a property added by sinon
67
+ expect(pubsub._publish.callCount).to.eql(1);
68
+ // remove topic validator
69
+ pubsub.topicValidators.delete(filteredTopic);
70
+ // another invalid case
71
+ const invalidRpc2 = {
72
+ subscriptions: [],
73
+ msgs: [{
74
+ data: uint8ArrayFromString('a different message'),
75
+ topicIDs: [filteredTopic]
76
+ }],
77
+ toJSON: () => ({})
78
+ };
79
+ // process previously invalid message, now is valid
80
+ void pubsub._processRpc(peer.id.toString(), peer, invalidRpc2);
81
+ pubsub.unsubscribe(filteredTopic);
82
+ // @ts-expect-error .callCount is a property added by sinon
83
+ await pWaitFor(() => pubsub._publish.callCount === 2);
84
+ });
85
+ });
86
+ //# sourceMappingURL=topic-validators.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topic-validators.spec.js","sourceRoot":"","sources":["../../test/topic-validators.spec.ts"],"names":[],"mappings":"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"}