From f33f9ccd2cd1c1f801d2b28bbaa1f2aca35a3177 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 2 Jun 2021 13:05:22 +0100 Subject: [PATCH 1/6] chore: update to new multiformats Replaces the `cids`, `multihashes` and `multibase` modules with the new multiformats module. BREAKING CHANGE: uses the CID class from the new multiformats module and pubsub.getMsgId became async --- package.json | 6 ++---- src/content-routing/types.d.ts | 2 +- src/pubsub/index.js | 2 +- src/pubsub/utils.js | 5 ++--- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 473e3df4b..a96acef94 100644 --- a/package.json +++ b/package.json @@ -71,9 +71,8 @@ "it-pushable": "^1.4.2", "libp2p-crypto": "^0.19.0", "libp2p-tcp": "^0.15.3", - "multiaddr": "^9.0.1", - "multibase": "^4.0.2", - "multihashes": "^4.0.2", + "multiaddr": "multiformats/js-multiaddr#chore/update-to-new-multiformats", + "multiformats": "^9.0.2", "p-defer": "^3.0.0", "p-limit": "^3.1.0", "p-wait-for": "^3.2.0", @@ -86,7 +85,6 @@ "devDependencies": { "@types/debug": "^4.1.5", "aegir": "^33.0.0", - "cids": "^1.1.6", "events": "^3.3.0", "it-handshake": "^2.0.0", "rimraf": "^3.0.2", diff --git a/src/content-routing/types.d.ts b/src/content-routing/types.d.ts index c8f1b57d8..519587a6d 100644 --- a/src/content-routing/types.d.ts +++ b/src/content-routing/types.d.ts @@ -1,6 +1,6 @@ import PeerId from 'peer-id' import { Multiaddr } from 'multiaddr' -import CID from 'cids' +import { CID } from 'multiformats/cid' export interface ContentRoutingFactory { new (options?: any): ContentRouting; diff --git a/src/pubsub/index.js b/src/pubsub/index.js index 1697c99aa..06a595449 100644 --- a/src/pubsub/index.js +++ b/src/pubsub/index.js @@ -476,7 +476,7 @@ class PubsubBaseProtocol extends EventEmitter { * Child class can override this. * * @param {InMessage} msg - the message object - * @returns {Uint8Array} message id as bytes + * @returns {Promise | Uint8Array} message id as bytes */ getMsgId (msg) { const signaturePolicy = this.globalSignaturePolicy diff --git a/src/pubsub/utils.js b/src/pubsub/utils.js index 0cf71dfb2..b624a90ee 100644 --- a/src/pubsub/utils.js +++ b/src/pubsub/utils.js @@ -5,7 +5,7 @@ const randomBytes = require('libp2p-crypto/src/random-bytes') const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayFromString = require('uint8arrays/from-string') const PeerId = require('peer-id') -const multihash = require('multihashes') +const { sha256 } = require('multiformats/hashes/sha2') /** * @typedef {import('./message/rpc').RPC.IMessage} IMessage @@ -43,10 +43,9 @@ const msgId = (from, seqno) => { * Generate a message id, based on message `data`. * * @param {Uint8Array} data - * @returns {Uint8Array} * @private */ -const noSignMsgId = (data) => multihash.encode(data, 'sha2-256') +const noSignMsgId = (data) => sha256.encode(data) /** * Check if any member of the first set is also a member From e694935eaade076edde32f2c87c130b50fd09370 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 3 Jun 2021 19:09:35 +0100 Subject: [PATCH 2/6] chore: update peer-id branch --- package.json | 2 +- src/pubsub/message/rpc.d.ts | 35 ++++- src/pubsub/message/rpc.js | 166 +++++++++++++++-------- src/pubsub/message/sign.js | 10 +- src/pubsub/message/topic-descriptor.d.ts | 21 ++- src/pubsub/message/topic-descriptor.js | 97 ++++++++++--- test/pubsub/sign.spec.js | 22 ++- 7 files changed, 261 insertions(+), 92 deletions(-) diff --git a/package.json b/package.json index a96acef94..fb8c54d8a 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "p-defer": "^3.0.0", "p-limit": "^3.1.0", "p-wait-for": "^3.2.0", - "peer-id": "^0.14.2", + "peer-id": "libp2p/js-peer-id#chore/update-to-new-multiformats", "protobufjs": "^6.10.2", "sinon": "^10.0.0", "streaming-iterables": "^5.0.4", diff --git a/src/pubsub/message/rpc.d.ts b/src/pubsub/message/rpc.d.ts index 5836c6695..957cc9076 100644 --- a/src/pubsub/message/rpc.d.ts +++ b/src/pubsub/message/rpc.d.ts @@ -86,10 +86,16 @@ export namespace RPC { constructor(p?: RPC.ISubOpts); /** SubOpts subscribe. */ - public subscribe: boolean; + public subscribe?: (boolean|null); /** SubOpts topicID. */ - public topicID: string; + public topicID?: (string|null); + + /** SubOpts _subscribe. */ + public _subscribe?: "subscribe"; + + /** SubOpts _topicID. */ + public _topicID?: "topicID"; /** * Encodes the specified SubOpts message. Does not implicitly {@link RPC.SubOpts.verify|verify} messages. @@ -163,22 +169,37 @@ export namespace RPC { constructor(p?: RPC.IMessage); /** Message from. */ - public from: Uint8Array; + public from?: (Uint8Array|null); /** Message data. */ - public data: Uint8Array; + public data?: (Uint8Array|null); /** Message seqno. */ - public seqno: Uint8Array; + public seqno?: (Uint8Array|null); /** Message topicIDs. */ public topicIDs: string[]; /** Message signature. */ - public signature: Uint8Array; + public signature?: (Uint8Array|null); /** Message key. */ - public key: Uint8Array; + public key?: (Uint8Array|null); + + /** Message _from. */ + public _from?: "from"; + + /** Message _data. */ + public _data?: "data"; + + /** Message _seqno. */ + public _seqno?: "seqno"; + + /** Message _signature. */ + public _signature?: "signature"; + + /** Message _key. */ + public _key?: "key"; /** * Encodes the specified Message message. Does not implicitly {@link RPC.Message.verify|verify} messages. diff --git a/src/pubsub/message/rpc.js b/src/pubsub/message/rpc.js index d27ed718a..e46d601aa 100644 --- a/src/pubsub/message/rpc.js +++ b/src/pubsub/message/rpc.js @@ -216,19 +216,44 @@ $root.RPC = (function() { /** * SubOpts subscribe. - * @member {boolean} subscribe + * @member {boolean|null|undefined} subscribe * @memberof RPC.SubOpts * @instance */ - SubOpts.prototype.subscribe = false; + SubOpts.prototype.subscribe = null; /** * SubOpts topicID. - * @member {string} topicID + * @member {string|null|undefined} topicID * @memberof RPC.SubOpts * @instance */ - SubOpts.prototype.topicID = ""; + SubOpts.prototype.topicID = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * SubOpts _subscribe. + * @member {"subscribe"|undefined} _subscribe + * @memberof RPC.SubOpts + * @instance + */ + Object.defineProperty(SubOpts.prototype, "_subscribe", { + get: $util.oneOfGetter($oneOfFields = ["subscribe"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * SubOpts _topicID. + * @member {"topicID"|undefined} _topicID + * @memberof RPC.SubOpts + * @instance + */ + Object.defineProperty(SubOpts.prototype, "_topicID", { + get: $util.oneOfGetter($oneOfFields = ["topicID"]), + set: $util.oneOfSetter($oneOfFields) + }); /** * Encodes the specified SubOpts message. Does not implicitly {@link RPC.SubOpts.verify|verify} messages. @@ -315,15 +340,15 @@ $root.RPC = (function() { if (!o) o = {}; var d = {}; - if (o.defaults) { - d.subscribe = false; - d.topicID = ""; - } if (m.subscribe != null && m.hasOwnProperty("subscribe")) { d.subscribe = m.subscribe; + if (o.oneofs) + d._subscribe = "subscribe"; } if (m.topicID != null && m.hasOwnProperty("topicID")) { d.topicID = m.topicID; + if (o.oneofs) + d._topicID = "topicID"; } return d; }; @@ -374,27 +399,27 @@ $root.RPC = (function() { /** * Message from. - * @member {Uint8Array} from + * @member {Uint8Array|null|undefined} from * @memberof RPC.Message * @instance */ - Message.prototype.from = $util.newBuffer([]); + Message.prototype.from = null; /** * Message data. - * @member {Uint8Array} data + * @member {Uint8Array|null|undefined} data * @memberof RPC.Message * @instance */ - Message.prototype.data = $util.newBuffer([]); + Message.prototype.data = null; /** * Message seqno. - * @member {Uint8Array} seqno + * @member {Uint8Array|null|undefined} seqno * @memberof RPC.Message * @instance */ - Message.prototype.seqno = $util.newBuffer([]); + Message.prototype.seqno = null; /** * Message topicIDs. @@ -406,19 +431,77 @@ $root.RPC = (function() { /** * Message signature. - * @member {Uint8Array} signature + * @member {Uint8Array|null|undefined} signature * @memberof RPC.Message * @instance */ - Message.prototype.signature = $util.newBuffer([]); + Message.prototype.signature = null; /** * Message key. - * @member {Uint8Array} key + * @member {Uint8Array|null|undefined} key + * @memberof RPC.Message + * @instance + */ + Message.prototype.key = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * Message _from. + * @member {"from"|undefined} _from + * @memberof RPC.Message + * @instance + */ + Object.defineProperty(Message.prototype, "_from", { + get: $util.oneOfGetter($oneOfFields = ["from"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Message _data. + * @member {"data"|undefined} _data + * @memberof RPC.Message + * @instance + */ + Object.defineProperty(Message.prototype, "_data", { + get: $util.oneOfGetter($oneOfFields = ["data"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Message _seqno. + * @member {"seqno"|undefined} _seqno + * @memberof RPC.Message + * @instance + */ + Object.defineProperty(Message.prototype, "_seqno", { + get: $util.oneOfGetter($oneOfFields = ["seqno"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Message _signature. + * @member {"signature"|undefined} _signature * @memberof RPC.Message * @instance */ - Message.prototype.key = $util.newBuffer([]); + Object.defineProperty(Message.prototype, "_signature", { + get: $util.oneOfGetter($oneOfFields = ["signature"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Message _key. + * @member {"key"|undefined} _key + * @memberof RPC.Message + * @instance + */ + Object.defineProperty(Message.prototype, "_key", { + get: $util.oneOfGetter($oneOfFields = ["key"]), + set: $util.oneOfSetter($oneOfFields) + }); /** * Encodes the specified Message message. Does not implicitly {@link RPC.Message.verify|verify} messages. @@ -564,51 +647,20 @@ $root.RPC = (function() { if (o.arrays || o.defaults) { d.topicIDs = []; } - if (o.defaults) { - if (o.bytes === String) - d.from = ""; - else { - d.from = []; - if (o.bytes !== Array) - d.from = $util.newBuffer(d.from); - } - if (o.bytes === String) - d.data = ""; - else { - d.data = []; - if (o.bytes !== Array) - d.data = $util.newBuffer(d.data); - } - if (o.bytes === String) - d.seqno = ""; - else { - d.seqno = []; - if (o.bytes !== Array) - d.seqno = $util.newBuffer(d.seqno); - } - if (o.bytes === String) - d.signature = ""; - else { - d.signature = []; - if (o.bytes !== Array) - d.signature = $util.newBuffer(d.signature); - } - if (o.bytes === String) - d.key = ""; - else { - d.key = []; - if (o.bytes !== Array) - d.key = $util.newBuffer(d.key); - } - } if (m.from != null && m.hasOwnProperty("from")) { d.from = o.bytes === String ? $util.base64.encode(m.from, 0, m.from.length) : o.bytes === Array ? Array.prototype.slice.call(m.from) : m.from; + if (o.oneofs) + d._from = "from"; } if (m.data != null && m.hasOwnProperty("data")) { d.data = o.bytes === String ? $util.base64.encode(m.data, 0, m.data.length) : o.bytes === Array ? Array.prototype.slice.call(m.data) : m.data; + if (o.oneofs) + d._data = "data"; } if (m.seqno != null && m.hasOwnProperty("seqno")) { d.seqno = o.bytes === String ? $util.base64.encode(m.seqno, 0, m.seqno.length) : o.bytes === Array ? Array.prototype.slice.call(m.seqno) : m.seqno; + if (o.oneofs) + d._seqno = "seqno"; } if (m.topicIDs && m.topicIDs.length) { d.topicIDs = []; @@ -618,9 +670,13 @@ $root.RPC = (function() { } if (m.signature != null && m.hasOwnProperty("signature")) { d.signature = o.bytes === String ? $util.base64.encode(m.signature, 0, m.signature.length) : o.bytes === Array ? Array.prototype.slice.call(m.signature) : m.signature; + if (o.oneofs) + d._signature = "signature"; } if (m.key != null && m.hasOwnProperty("key")) { d.key = o.bytes === String ? $util.base64.encode(m.key, 0, m.key.length) : o.bytes === Array ? Array.prototype.slice.call(m.key) : m.key; + if (o.oneofs) + d._key = "key"; } return d; }; diff --git a/src/pubsub/message/sign.js b/src/pubsub/message/sign.js index 0b4b8f2df..c4dc41a82 100644 --- a/src/pubsub/message/sign.js +++ b/src/pubsub/message/sign.js @@ -2,6 +2,7 @@ const PeerId = require('peer-id') const { RPC } = require('./rpc') +const { CID } = require('multiformats/cid') const uint8ArrayConcat = require('uint8arrays/concat') const uint8ArrayFromString = require('uint8arrays/from-string') const SignPrefix = uint8ArrayFromString('libp2p-pubsub:') @@ -44,13 +45,16 @@ async function verifySignature (message) { throw new Error('Message must contain a signature to be verified') } + if (!message.from) { + throw new Error('Message must contain a from to be verified') + } + // Get message sans the signature const bytes = uint8ArrayConcat([ SignPrefix, RPC.Message.encode({ ...message, - // @ts-ignore message.from needs to exist - from: PeerId.createFromCID(message.from).toBytes(), + from: PeerId.createFromB58String(message.from).toBytes(), signature: undefined, key: undefined }).finish() @@ -76,7 +80,7 @@ async function messagePublicKey (message) { throw new Error('Could not get the public key from the originator id') } - const from = PeerId.createFromCID(message.from) + const from = PeerId.createFromB58String(message.from) if (message.key) { const keyPeerId = await PeerId.createFromPubKey(message.key) diff --git a/src/pubsub/message/topic-descriptor.d.ts b/src/pubsub/message/topic-descriptor.d.ts index 179deba27..b4dc5cf84 100644 --- a/src/pubsub/message/topic-descriptor.d.ts +++ b/src/pubsub/message/topic-descriptor.d.ts @@ -22,7 +22,7 @@ export class TopicDescriptor implements ITopicDescriptor { constructor(p?: ITopicDescriptor); /** TopicDescriptor name. */ - public name: string; + public name?: (string|null); /** TopicDescriptor auth. */ public auth?: (TopicDescriptor.IAuthOpts|null); @@ -30,6 +30,15 @@ export class TopicDescriptor implements ITopicDescriptor { /** TopicDescriptor enc. */ public enc?: (TopicDescriptor.IEncOpts|null); + /** TopicDescriptor _name. */ + public _name?: "name"; + + /** TopicDescriptor _auth. */ + public _auth?: "auth"; + + /** TopicDescriptor _enc. */ + public _enc?: "enc"; + /** * Encodes the specified TopicDescriptor message. Does not implicitly {@link TopicDescriptor.verify|verify} messages. * @param m TopicDescriptor message or plain object to encode @@ -92,11 +101,14 @@ export namespace TopicDescriptor { constructor(p?: TopicDescriptor.IAuthOpts); /** AuthOpts mode. */ - public mode: TopicDescriptor.AuthOpts.AuthMode; + public mode?: (TopicDescriptor.AuthOpts.AuthMode|null); /** AuthOpts keys. */ public keys: Uint8Array[]; + /** AuthOpts _mode. */ + public _mode?: "mode"; + /** * Encodes the specified AuthOpts message. Does not implicitly {@link TopicDescriptor.AuthOpts.verify|verify} messages. * @param m AuthOpts message or plain object to encode @@ -167,11 +179,14 @@ export namespace TopicDescriptor { constructor(p?: TopicDescriptor.IEncOpts); /** EncOpts mode. */ - public mode: TopicDescriptor.EncOpts.EncMode; + public mode?: (TopicDescriptor.EncOpts.EncMode|null); /** EncOpts keyHashes. */ public keyHashes: Uint8Array[]; + /** EncOpts _mode. */ + public _mode?: "mode"; + /** * Encodes the specified EncOpts message. Does not implicitly {@link TopicDescriptor.EncOpts.verify|verify} messages. * @param m EncOpts message or plain object to encode diff --git a/src/pubsub/message/topic-descriptor.js b/src/pubsub/message/topic-descriptor.js index 61c62be62..9758d570a 100644 --- a/src/pubsub/message/topic-descriptor.js +++ b/src/pubsub/message/topic-descriptor.js @@ -37,11 +37,11 @@ $root.TopicDescriptor = (function() { /** * TopicDescriptor name. - * @member {string} name + * @member {string|null|undefined} name * @memberof TopicDescriptor * @instance */ - TopicDescriptor.prototype.name = ""; + TopicDescriptor.prototype.name = null; /** * TopicDescriptor auth. @@ -59,6 +59,42 @@ $root.TopicDescriptor = (function() { */ TopicDescriptor.prototype.enc = null; + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * TopicDescriptor _name. + * @member {"name"|undefined} _name + * @memberof TopicDescriptor + * @instance + */ + Object.defineProperty(TopicDescriptor.prototype, "_name", { + get: $util.oneOfGetter($oneOfFields = ["name"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * TopicDescriptor _auth. + * @member {"auth"|undefined} _auth + * @memberof TopicDescriptor + * @instance + */ + Object.defineProperty(TopicDescriptor.prototype, "_auth", { + get: $util.oneOfGetter($oneOfFields = ["auth"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * TopicDescriptor _enc. + * @member {"enc"|undefined} _enc + * @memberof TopicDescriptor + * @instance + */ + Object.defineProperty(TopicDescriptor.prototype, "_enc", { + get: $util.oneOfGetter($oneOfFields = ["enc"]), + set: $util.oneOfSetter($oneOfFields) + }); + /** * Encodes the specified TopicDescriptor message. Does not implicitly {@link TopicDescriptor.verify|verify} messages. * @function encode @@ -156,19 +192,20 @@ $root.TopicDescriptor = (function() { if (!o) o = {}; var d = {}; - if (o.defaults) { - d.name = ""; - d.auth = null; - d.enc = null; - } if (m.name != null && m.hasOwnProperty("name")) { d.name = m.name; + if (o.oneofs) + d._name = "name"; } if (m.auth != null && m.hasOwnProperty("auth")) { d.auth = $root.TopicDescriptor.AuthOpts.toObject(m.auth, o); + if (o.oneofs) + d._auth = "auth"; } if (m.enc != null && m.hasOwnProperty("enc")) { d.enc = $root.TopicDescriptor.EncOpts.toObject(m.enc, o); + if (o.oneofs) + d._enc = "enc"; } return d; }; @@ -212,11 +249,11 @@ $root.TopicDescriptor = (function() { /** * AuthOpts mode. - * @member {TopicDescriptor.AuthOpts.AuthMode} mode + * @member {TopicDescriptor.AuthOpts.AuthMode|null|undefined} mode * @memberof TopicDescriptor.AuthOpts * @instance */ - AuthOpts.prototype.mode = 0; + AuthOpts.prototype.mode = null; /** * AuthOpts keys. @@ -226,6 +263,20 @@ $root.TopicDescriptor = (function() { */ AuthOpts.prototype.keys = $util.emptyArray; + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * AuthOpts _mode. + * @member {"mode"|undefined} _mode + * @memberof TopicDescriptor.AuthOpts + * @instance + */ + Object.defineProperty(AuthOpts.prototype, "_mode", { + get: $util.oneOfGetter($oneOfFields = ["mode"]), + set: $util.oneOfSetter($oneOfFields) + }); + /** * Encodes the specified AuthOpts message. Does not implicitly {@link TopicDescriptor.AuthOpts.verify|verify} messages. * @function encode @@ -337,11 +388,10 @@ $root.TopicDescriptor = (function() { if (o.arrays || o.defaults) { d.keys = []; } - if (o.defaults) { - d.mode = o.enums === String ? "NONE" : 0; - } if (m.mode != null && m.hasOwnProperty("mode")) { d.mode = o.enums === String ? $root.TopicDescriptor.AuthOpts.AuthMode[m.mode] : m.mode; + if (o.oneofs) + d._mode = "mode"; } if (m.keys && m.keys.length) { d.keys = []; @@ -410,11 +460,11 @@ $root.TopicDescriptor = (function() { /** * EncOpts mode. - * @member {TopicDescriptor.EncOpts.EncMode} mode + * @member {TopicDescriptor.EncOpts.EncMode|null|undefined} mode * @memberof TopicDescriptor.EncOpts * @instance */ - EncOpts.prototype.mode = 0; + EncOpts.prototype.mode = null; /** * EncOpts keyHashes. @@ -424,6 +474,20 @@ $root.TopicDescriptor = (function() { */ EncOpts.prototype.keyHashes = $util.emptyArray; + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * EncOpts _mode. + * @member {"mode"|undefined} _mode + * @memberof TopicDescriptor.EncOpts + * @instance + */ + Object.defineProperty(EncOpts.prototype, "_mode", { + get: $util.oneOfGetter($oneOfFields = ["mode"]), + set: $util.oneOfSetter($oneOfFields) + }); + /** * Encodes the specified EncOpts message. Does not implicitly {@link TopicDescriptor.EncOpts.verify|verify} messages. * @function encode @@ -535,11 +599,10 @@ $root.TopicDescriptor = (function() { if (o.arrays || o.defaults) { d.keyHashes = []; } - if (o.defaults) { - d.mode = o.enums === String ? "NONE" : 0; - } if (m.mode != null && m.hasOwnProperty("mode")) { d.mode = o.enums === String ? $root.TopicDescriptor.EncOpts.EncMode[m.mode] : m.mode; + if (o.oneofs) + d._mode = "mode"; } if (m.keyHashes && m.keyHashes.length) { d.keyHashes = []; diff --git a/test/pubsub/sign.spec.js b/test/pubsub/sign.spec.js index 14726efa0..82da15e61 100644 --- a/test/pubsub/sign.spec.js +++ b/test/pubsub/sign.spec.js @@ -16,6 +16,7 @@ const PeerId = require('peer-id') const { randomSeqno } = require('../../src/pubsub/utils') describe('message signing', () => { + /** @type {PeerId} */ let peerId before(async () => { peerId = await PeerId.create({ @@ -25,7 +26,7 @@ describe('message signing', () => { it('should be able to sign and verify a message', async () => { const message = { - from: peerId.id, + from: peerId.toBytes(), data: uint8ArrayFromString('hello'), seqno: randomSeqno(), topicIDs: ['test-topic'] @@ -41,7 +42,10 @@ describe('message signing', () => { expect(signedMessage.key).to.eql(peerId.pubKey.bytes) // Verify the signature - const verified = await verifySignature(signedMessage) + const verified = await verifySignature({ + ...signedMessage, + from: peerId.toB58String() + }) expect(verified).to.eql(true) }) @@ -49,7 +53,7 @@ describe('message signing', () => { const secPeerId = await PeerId.create({ keyType: 'secp256k1' }) const message = { - from: secPeerId.id, + from: secPeerId.toBytes(), data: uint8ArrayFromString('hello'), seqno: randomSeqno(), topicIDs: ['test-topic'] @@ -65,13 +69,16 @@ describe('message signing', () => { signedMessage.key = undefined // Verify the signature - const verified = await verifySignature(signedMessage) + const verified = await verifySignature({ + ...signedMessage, + from: secPeerId.toB58String() + }) expect(verified).to.eql(true) }) it('should be able to extract the public key from the message', async () => { const message = { - from: peerId.id, + from: peerId.toBytes(), data: uint8ArrayFromString('hello'), seqno: randomSeqno(), topicIDs: ['test-topic'] @@ -87,7 +94,10 @@ describe('message signing', () => { expect(signedMessage.key).to.eql(peerId.pubKey.bytes) // Verify the signature - const verified = await verifySignature(signedMessage) + const verified = await verifySignature({ + ...signedMessage, + from: peerId.toB58String() + }) expect(verified).to.eql(true) }) }) From 66871a96b308cc380770fa2b281bc03e33abeb06 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 3 Jun 2021 19:15:42 +0100 Subject: [PATCH 3/6] chore: remove unused variable --- src/pubsub/message/sign.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pubsub/message/sign.js b/src/pubsub/message/sign.js index c4dc41a82..279012eac 100644 --- a/src/pubsub/message/sign.js +++ b/src/pubsub/message/sign.js @@ -2,7 +2,6 @@ const PeerId = require('peer-id') const { RPC } = require('./rpc') -const { CID } = require('multiformats/cid') const uint8ArrayConcat = require('uint8arrays/concat') const uint8ArrayFromString = require('uint8arrays/from-string') const SignPrefix = uint8ArrayFromString('libp2p-pubsub:') From 6de0304307c5d7df8e6b192741bbfa6448830328 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 4 Jun 2021 18:01:06 +0100 Subject: [PATCH 4/6] chore: pr comments Co-authored-by: Vasco Santos --- src/pubsub/message/sign.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pubsub/message/sign.js b/src/pubsub/message/sign.js index 279012eac..8844aaa1f 100644 --- a/src/pubsub/message/sign.js +++ b/src/pubsub/message/sign.js @@ -45,7 +45,7 @@ async function verifySignature (message) { } if (!message.from) { - throw new Error('Message must contain a from to be verified') + throw new Error('Message must contain a from property to be verified') } // Get message sans the signature From 2579cb5d38db5b6a4857cd6a6f510870b5519492 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 5 Jul 2021 18:33:12 +0100 Subject: [PATCH 5/6] chore: handle strings or uint8arrays --- src/pubsub/utils.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pubsub/utils.js b/src/pubsub/utils.js index b624a90ee..1f775fff0 100644 --- a/src/pubsub/utils.js +++ b/src/pubsub/utils.js @@ -6,6 +6,7 @@ const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayFromString = require('uint8arrays/from-string') const PeerId = require('peer-id') const { sha256 } = require('multiformats/hashes/sha2') +const { CID } = require('multiformats/cid') /** * @typedef {import('./message/rpc').RPC.IMessage} IMessage @@ -26,13 +27,20 @@ const randomSeqno = () => { /** * Generate a message id, based on the `from` and `seqno`. * - * @param {string} from + * @param {Uint8Array|string} from * @param {Uint8Array} seqno * @returns {Uint8Array} * @private */ const msgId = (from, seqno) => { - const fromBytes = PeerId.createFromB58String(from).id + let fromBytes + + if (from instanceof Uint8Array) { + fromBytes = PeerId.createFromBytes(from).id + } else { + fromBytes = PeerId.createFromCID(CID.parse(from)).id + } + const msgId = new Uint8Array(fromBytes.length + seqno.length) msgId.set(fromBytes, 0) msgId.set(seqno, fromBytes.length) From 17523f0dcddda53583fd7027c3298ec9a2def0a1 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 6 Jul 2021 14:03:34 +0100 Subject: [PATCH 6/6] chore: fix tests --- package.json | 4 ++-- src/pubsub/index.js | 2 +- src/pubsub/message/sign.js | 7 ++++--- src/pubsub/utils.js | 3 +-- test/pubsub/message.spec.js | 20 +++++++++++--------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index fb8c54d8a..7fa662495 100644 --- a/package.json +++ b/package.json @@ -71,12 +71,12 @@ "it-pushable": "^1.4.2", "libp2p-crypto": "^0.19.0", "libp2p-tcp": "^0.15.3", - "multiaddr": "multiformats/js-multiaddr#chore/update-to-new-multiformats", + "multiaddr": "^10.0.0", "multiformats": "^9.0.2", "p-defer": "^3.0.0", "p-limit": "^3.1.0", "p-wait-for": "^3.2.0", - "peer-id": "libp2p/js-peer-id#chore/update-to-new-multiformats", + "peer-id": "^0.15.0", "protobufjs": "^6.10.2", "sinon": "^10.0.0", "streaming-iterables": "^5.0.4", diff --git a/src/pubsub/index.js b/src/pubsub/index.js index 06a595449..12a8ea535 100644 --- a/src/pubsub/index.js +++ b/src/pubsub/index.js @@ -618,7 +618,7 @@ class PubsubBaseProtocol extends EventEmitter { case SignaturePolicy.StrictSign: message.from = this.peerId.toB58String() message.seqno = utils.randomSeqno() - return signMessage(this.peerId, utils.normalizeOutRpcMessage(message)) + return signMessage(this.peerId, message) case SignaturePolicy.StrictNoSign: return Promise.resolve(message) default: diff --git a/src/pubsub/message/sign.js b/src/pubsub/message/sign.js index 8844aaa1f..b93b47313 100644 --- a/src/pubsub/message/sign.js +++ b/src/pubsub/message/sign.js @@ -5,6 +5,7 @@ const { RPC } = require('./rpc') const uint8ArrayConcat = require('uint8arrays/concat') const uint8ArrayFromString = require('uint8arrays/from-string') const SignPrefix = uint8ArrayFromString('libp2p-pubsub:') +const { normalizeOutRpcMessage } = require('../utils') /** * @typedef {import('..').InMessage} @@ -14,14 +15,14 @@ const SignPrefix = uint8ArrayFromString('libp2p-pubsub:') * Signs the provided message with the given `peerId` * * @param {PeerId} peerId - * @param {RPC.Message} message - * @returns {Promise} + * @param {InMessage} message + * @returns {Promise} */ async function signMessage (peerId, message) { // Get the message in bytes, and prepend with the pubsub prefix const bytes = uint8ArrayConcat([ SignPrefix, - RPC.Message.encode(message).finish() + RPC.Message.encode(normalizeOutRpcMessage(message)).finish() ]) const signature = await peerId.privKey.sign(bytes) diff --git a/src/pubsub/utils.js b/src/pubsub/utils.js index 1f775fff0..04bc71347 100644 --- a/src/pubsub/utils.js +++ b/src/pubsub/utils.js @@ -6,7 +6,6 @@ const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayFromString = require('uint8arrays/from-string') const PeerId = require('peer-id') const { sha256 } = require('multiformats/hashes/sha2') -const { CID } = require('multiformats/cid') /** * @typedef {import('./message/rpc').RPC.IMessage} IMessage @@ -38,7 +37,7 @@ const msgId = (from, seqno) => { if (from instanceof Uint8Array) { fromBytes = PeerId.createFromBytes(from).id } else { - fromBytes = PeerId.createFromCID(CID.parse(from)).id + fromBytes = PeerId.parse(from).id } const msgId = new Uint8Array(fromBytes.length + seqno.length) diff --git a/test/pubsub/message.spec.js b/test/pubsub/message.spec.js index a1e9f1e62..6b4073754 100644 --- a/test/pubsub/message.spec.js +++ b/test/pubsub/message.spec.js @@ -3,6 +3,7 @@ const { expect } = require('aegir/utils/chai') const sinon = require('sinon') +const uint8arrayFromString = require('uint8arrays/from-string') const PubsubBaseImpl = require('../../src/pubsub') const { SignaturePolicy } = require('../../src/pubsub/signature-policy') @@ -33,13 +34,14 @@ describe('pubsub base messages', () => { it('_buildMessage normalizes and signs messages', async () => { const message = { - receivedFrom: peerId.id, - data: 'hello', + receivedFrom: peerId.toB58String(), + data: uint8arrayFromString('hello'), topicIDs: ['test-topic'] } const signedMessage = await pubsub._buildMessage(message) - expect(pubsub.validate(signedMessage)).to.not.be.rejected() + + await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected() }) it('validate with StrictNoSign will reject a message with from, signature, key, seqno present', async () => { @@ -54,15 +56,15 @@ describe('pubsub base messages', () => { const signedMessage = await pubsub._buildMessage(message) sinon.stub(pubsub, 'globalSignaturePolicy').value(SignaturePolicy.StrictNoSign) - await expect(pubsub.validate(signedMessage)).to.be.rejected() + await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected() delete signedMessage.from - await expect(pubsub.validate(signedMessage)).to.be.rejected() + await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected() delete signedMessage.signature - await expect(pubsub.validate(signedMessage)).to.be.rejected() + await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected() delete signedMessage.key - await expect(pubsub.validate(signedMessage)).to.be.rejected() + await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected() delete signedMessage.seqno - await expect(pubsub.validate(signedMessage)).to.not.be.rejected() + await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected() }) it('validate with StrictNoSign will validate a message without a signature, key, and seqno', async () => { @@ -75,7 +77,7 @@ describe('pubsub base messages', () => { sinon.stub(pubsub, 'globalSignaturePolicy').value(SignaturePolicy.StrictNoSign) const signedMessage = await pubsub._buildMessage(message) - expect(pubsub.validate(signedMessage)).to.not.be.rejected() + await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected() }) it('validate with StrictSign requires a signature', async () => {