From 31f00f0e51de99f12cc8e5e1510d41510e48cc0c Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Wed, 8 May 2019 21:52:26 +0100 Subject: [PATCH 1/3] refactor: default to base32 encoding for v1 CIDs This switches the default encoding for v1 CIDs from base58btc to base32. See https://github.com/ipfs/js-ipfs/issues/1995 for details. BREAKING CHANGE: The default string encoding for v1 CIDs has changed from base58btc to base32. License: MIT Signed-off-by: Alan Shaw --- src/index.js | 8 ++++---- test/index.spec.js | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/index.js b/src/index.js index cf53eb3..1545642 100644 --- a/src/index.js +++ b/src/index.js @@ -59,7 +59,7 @@ class CID { * new CID() * new CID() */ - constructor (version, codec, multihash, multibaseName = 'base58btc') { + constructor (version, codec, multihash, multibaseName) { if (module.exports.isCID(version)) { // version is an exising CID instance const cid = version @@ -95,13 +95,13 @@ class CID { if (Buffer.isBuffer(version)) { const firstByte = version.slice(0, 1) const v = parseInt(firstByte.toString('hex'), 16) - if (v === 0 || v === 1) { + if (v === 1) { // version is a CID buffer const cid = version this.version = v this.codec = multicodec.getCodec(cid.slice(1)) this.multihash = multicodec.rmPrefix(cid.slice(1)) - this.multibaseName = (v === 0) ? 'base58btc' : multibaseName + this.multibaseName = 'base32' } else { // version is a raw multihash buffer, so v0 this.version = 0 @@ -133,7 +133,7 @@ class CID { /** * @type {string} */ - this.multibaseName = multibaseName + this.multibaseName = multibaseName || (version === 0 ? 'base58btc' : 'base32') CID.validateCID(this) } diff --git a/test/index.spec.js b/test/index.spec.js index 5544493..c9b03b0 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -32,6 +32,7 @@ describe('CID', () => { expect(cid).to.have.property('codec', 'dag-pb') expect(cid).to.have.property('version', 0) expect(cid).to.have.property('multihash').that.eql(multihash.fromB58String(mhStr)) + expect(cid).to.have.property('multibaseName', 'base58btc') expect(cid.toBaseEncodedString()).to.be.eql(mhStr) }) @@ -46,6 +47,7 @@ describe('CID', () => { expect(cid).to.have.property('codec', 'dag-pb') expect(cid).to.have.property('version', 0) expect(cid).to.have.property('multihash').that.eql(mh) + expect(cid).to.have.property('multibaseName', 'base58btc') expect(cid.toBaseEncodedString()).to.eql(mhStr) done() @@ -58,6 +60,7 @@ describe('CID', () => { expect(cid).to.have.property('codec', 'dag-pb') expect(cid).to.have.property('version', 0) expect(cid).to.have.property('multihash') + expect(cid).to.have.property('multibaseName', 'base58btc') }) it('throws on invalid BS58Str multihash ', () => { @@ -108,12 +111,13 @@ describe('CID', () => { expect(cid).to.have.property('codec', 'dag-pb') expect(cid).to.have.property('version', 1) expect(cid).to.have.property('multihash') + expect(cid).to.have.property('multibaseName', 'base58btc') expect(cid.toBaseEncodedString()).to.be.eql(cidStr) }) it('handles CID (no multibase)', () => { - const cidStr = 'zdj7Wd8AMwqnhJGQCbFxBVodGSBG84TM7Hs1rcJuQMwTyfEDS' + const cidStr = 'bafybeidskjjd4zmr7oh6ku6wp72vvbxyibcli2r6if3ocdcy7jjjusvl2u' const cidBuf = Buffer.from('017012207252523e6591fb8fe553d67ff55a86f84044b46a3e4176e10c58fa529a4aabd5', 'hex') const cid = new CID(cidBuf) @@ -121,6 +125,7 @@ describe('CID', () => { expect(cid).to.have.property('codec', 'dag-pb') expect(cid).to.have.property('version', 1) expect(cid).to.have.property('multihash') + expect(cid).to.have.property('multibaseName', 'base32') expect(cid.toBaseEncodedString()).to.be.eql(cidStr) }) @@ -131,6 +136,7 @@ describe('CID', () => { expect(cid).to.have.property('codec', 'dag-cbor') expect(cid).to.have.property('version', 1) expect(cid).to.have.property('multihash') + expect(cid).to.have.property('multibaseName', 'base32') }) it('can roundtrip through cid.toBaseEncodedString()', () => { @@ -140,6 +146,7 @@ describe('CID', () => { expect(cid1).to.have.property('codec').that.eql(cid2.codec) expect(cid1).to.have.property('version').that.eql(cid2.version) expect(cid1).to.have.property('multihash').that.eql(cid2.multihash) + expect(cid1).to.have.property('multibaseName').that.eql(cid2.multibaseName) }) it('handles multibyte varint encoded codec codes', () => { @@ -151,9 +158,11 @@ describe('CID', () => { expect(cid1).to.have.property('codec', 'eth-block') expect(cid1).to.have.property('version', 1) expect(cid1).to.have.property('multihash').that.eql(mh) + expect(cid1).to.have.property('multibaseName', 'base32') expect(cid2).to.have.property('codec', 'eth-block') expect(cid2).to.have.property('version', 1) expect(cid2).to.have.property('multihash').that.eql(mh) + expect(cid2).to.have.property('multibaseName', 'base32') }) it('.prefix', () => { @@ -199,9 +208,9 @@ describe('CID', () => { it('returns a string in the base provided', () => { const b58v1Str = 'zdj7Wd8AMwqnhJGQCbFxBVodGSBG84TM7Hs1rcJuQMwTyfEDS' - const b32v1Str = 'bafybeidskjjd4zmr7oh6ku6wp72vvbxyibcli2r6if3ocdcy7jjjusvl2u' + const b64urlv1Str = 'uAXASIHJSUj5lkfuP5VPWf_VahvhARLRqPkF24QxY-lKaSqvV' const cid = new CID(b58v1Str) - expect(cid.toString('base32')).to.equal(b32v1Str) + expect(cid.toString('base64url')).to.equal(b64urlv1Str) }) }) From 6d1b7bf297e579335f1ab9c56f656b72096c1a85 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 9 May 2019 11:31:29 +0100 Subject: [PATCH 2/3] docs: add docs on multibaseName value for v1 CIDs License: MIT Signed-off-by: Alan Shaw --- README.md | 9 +++++++-- src/index.js | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dd4a8e8..e038068 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ instance. Returns true if valid, false if not valid. `multihash` must be a `Buffer` instance of a valid [multihash](https://github.com/multiformats/multihash). -`multibaseName` optional string. Must be a valid [multibase](https://github.com/multiformats/multibase/blob/master/multibase.csv) name. Default is `base58btc`. +`multibaseName` optional string. Must be a valid [multibase](https://github.com/multiformats/multibase/blob/master/multibase.csv) name. Default is `base58btc` for v0 CIDs or `base32` for v1 CIDs. ### new CID(baseEncodedString) @@ -169,7 +169,12 @@ Returns the CID encoded in version 1. #### cid.toBaseEncodedString(base=this.multibaseName) -Returns a base encodec string of the CID. Defaults to the base encoding in `this.multibaseName` +Returns a base encoded string of the CID. Defaults to the base encoding in `this.multibaseName`. + +The value of `this.multibaseName` depends on how the instance was constructed: + +1. If the CID was constructed from an object that already had a multibase (a string or an existing CID) then it retains that base. +2. If the CID was constructed from an object that _did not_ have a multibase (a buffer, or by passing only version + codec + multihash to the constructor), then `multibaseName` will be `base58btc` for a v0 CID or `base32` for a v1 CID. #### cid.toString(base=this.multibaseName) diff --git a/src/index.js b/src/index.js index 1545642..57c7bcb 100644 --- a/src/index.js +++ b/src/index.js @@ -46,7 +46,7 @@ class CID { * -> construct CID by parts * ``` * - * @param {string|Buffer} version + * @param {string|Buffer|CID} version * @param {string} [codec] * @param {Buffer} [multihash] * @param {string} [multibaseName] From 93cbd8582e866abc622e5d5137f97953e8594ee5 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Thu, 9 May 2019 13:09:08 +0100 Subject: [PATCH 3/3] docs: update usage docs for base32 encoded CIDv1 --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e038068..76d1244 100644 --- a/README.md +++ b/README.md @@ -59,13 +59,13 @@ You can create an instance from a CID string or CID Buffer ```js const CID = require('cids') -const cid = new CID('zdj7WkRPAX9o9nb9zPbXzwG7JEs78uyhwbUs8JSUayB98DWWY') +const cid = new CID('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu') cid.version // 1 cid.codec // 'dag-pb' -cid.multibaseName // 'base58btc' +cid.multibaseName // 'base32' cid.toString() -// 'zdj7WkRPAX9o9nb9zPbXzwG7JEs78uyhwbUs8JSUayB98DWWY' +// 'bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu' ``` or by specifying the [cid version](https://github.com/multiformats/cid#versions), [multicodec name](https://github.com/multiformats/multicodec/blob/master/table.csv) and [multihash](https://github.com/multiformats/multihash): @@ -74,28 +74,28 @@ or by specifying the [cid version](https://github.com/multiformats/cid#versions) const CID = require('cids') const multihashing = require('multihashing-async') -multihashing(Buffer.from('OMG!'), 'sha2-256', (err, hash) => { - const cid = new CID(1, 'dag-pb', hash) - console.log(cid.toString()) - // zdj7WkRPAX9o9nb9zPbXzwG7JEs78uyhwbUs8JSUayB98DWWY -}) +const hash = await multihashing(Buffer.from('OMG!'), 'sha2-256') +const cid = new CID(1, 'dag-pb', hash) +console.log(cid.toString()) +// bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu ``` -The string form of CIDs currently defaults to `base58btc` flavour. (This is [soon to change to `base32`](https://github.com/ipfs/ipfs/issues/337). When creating a new instance you can optionally specify the default multibase to use when calling `toBaseEncodedString()` or `toString()` +The string form of v1 CIDs defaults to `base32` encoding (v0 CIDs are always `base58btc` encoded). When creating a new instance you can optionally specify the default multibase to use when calling `toBaseEncodedString()` or `toString()` ```js -const cid = new CID(1, 'raw', hash, 'base32') +const cid = new CID(1, 'raw', hash, 'base64') console.log(cid.toString()) -// bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu +// mAXASIN69ets85WVE0ipva5M5b2mAqAZ8LME08PeAG2MxCSuV ``` If you construct an instance from a valid CID string, the base you provided will be preserved as the default. ```js -const cid = new CID('bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy') +// e.g. a base64url encoded CID +const cid = new CID('uAXASIHJSUj5lkfuP5VPWf_VahvhARLRqPkF24QxY-lKaSqvV') cid.toString() -// bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy +// uAXASIHJSUj5lkfuP5VPWf_VahvhARLRqPkF24QxY-lKaSqvV ```