Skip to content

Commit 06ee535

Browse files
authored
fix: replace node buffers with uint8arrays (#67)
BREAKING CHANGES: - All deps of this module use Uint8Arrays instead of Buffers - value and validity fields of IPNSEntries are now Uint8Arrays instead of Strings as they are `bytes` in the protobuf definition
1 parent 2ae9525 commit 06ee535

File tree

5 files changed

+80
-49
lines changed

5 files changed

+80
-49
lines changed

.aegir.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict'
2+
3+
module.exports = {
4+
webpack: {
5+
node: {
6+
// needed by the ipfs-repo-migrations module
7+
path: true,
8+
9+
// needed by the abstract-leveldown module
10+
Buffer: true
11+
}
12+
}
13+
}

README.md

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# IPNS
1+
# IPNS <!-- omit in toc -->
22

33
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://protocol.ai)
44
[![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/)
@@ -12,20 +12,30 @@
1212
1313
This module contains all the necessary code for creating, understanding and validating IPNS records.
1414

15-
## Lead Maintainer
15+
## Lead Maintainer <!-- omit in toc -->
1616

1717
[Vasco Santos](https://github.com/vasco-santos).
1818

19-
## Table of Contents
19+
## Table of Contents <!-- omit in toc -->
2020

21-
- [Install](#install)
2221
- [Usage](#usage)
23-
- [Create Record](#create-record)
24-
- [Validate Record](#validate-record)
25-
- [Embed public key to record](#embed-public-key-to-record)
26-
- [Extract public key from record](#extract-public-key-from-record)
27-
- [Datastore key](#datastore-key)
22+
- [Create record](#create-record)
23+
- [Validate record](#validate-record)
24+
- [Embed public key to record](#embed-public-key-to-record)
25+
- [Extract public key from record](#extract-public-key-from-record)
26+
- [Datastore key](#datastore-key)
27+
- [Marshal data with proto buffer](#marshal-data-with-proto-buffer)
28+
- [Unmarshal data from proto buffer](#unmarshal-data-from-proto-buffer)
29+
- [Validator](#validator)
2830
- [API](#api)
31+
- [Create record](#create-record-1)
32+
- [Validate record](#validate-record-1)
33+
- [Datastore key](#datastore-key-1)
34+
- [Marshal data with proto buffer](#marshal-data-with-proto-buffer-1)
35+
- [Unmarshal data from proto buffer](#unmarshal-data-from-proto-buffer-1)
36+
- [Embed public key to record](#embed-public-key-to-record-1)
37+
- [Extract public key from record](#extract-public-key-from-record-1)
38+
- [Namespace](#namespace)
2939
- [Contribute](#contribute)
3040
- [License](#license)
3141

@@ -136,13 +146,13 @@ Create an IPNS record for being stored in a protocol buffer.
136146
- `lifetime` (string): lifetime of the record (in milliseconds).
137147

138148
Returns a `Promise` that resolves to an object with the entry's properties eg:
139-
149+
140150
```js
141151
{
142-
value: '/ipfs/QmWEekX7EZLUd9VXRNMRXW3LXe4F6x7mB8oPxY5XLptrBq',
143-
signature: Buffer,
152+
value: Uint8Array,
153+
signature: Uint8Array,
144154
validityType: 0,
145-
validity: '2018-06-27T14:49:14.074000000Z',
155+
validity: Uint8Array,
146156
sequence: 2
147157
}
148158
```
@@ -189,7 +199,7 @@ const data = ipns.unmarshal(storedData)
189199

190200
Returns the entry data structure after being serialized.
191201

192-
- `storedData` (Buffer): ipns entry record serialized.
202+
- `storedData` (Uint8Array): ipns entry record serialized.
193203

194204
#### Embed public key to record
195205

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,26 @@
3333
},
3434
"homepage": "https://github.com/ipfs/js-ipns#readme",
3535
"dependencies": {
36-
"buffer": "^5.6.0",
3736
"debug": "^4.1.1",
3837
"err-code": "^2.0.0",
39-
"interface-datastore": "^1.0.2",
40-
"libp2p-crypto": "^0.17.1",
38+
"interface-datastore": "^2.0.0",
39+
"libp2p-crypto": "^0.18.0",
4140
"multibase": "^3.0.0",
4241
"multihashes": "^3.0.1",
43-
"peer-id": "^0.13.6",
44-
"protons": "^1.0.1",
45-
"timestamp-nano": "^1.0.0"
42+
"peer-id": "^0.14.0",
43+
"protons": "^2.0.0",
44+
"timestamp-nano": "^1.0.0",
45+
"uint8arrays": "^1.1.0"
4646
},
4747
"devDependencies": {
48-
"aegir": "^23.0.0",
48+
"aegir": "^25.1.0",
4949
"chai": "^4.2.0",
5050
"chai-bytes": "~0.1.2",
5151
"chai-string": "^1.5.0",
5252
"dirty-chai": "^2.0.1",
5353
"ipfs": "^0.49.0",
5454
"ipfs-http-client": "^46.0.0",
55-
"ipfsd-ctl": "^4.0.1"
55+
"ipfsd-ctl": "^6.0.0"
5656
},
5757
"contributors": [
5858
"Vasco Santos <[email protected]>",

src/index.js

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ const crypto = require('libp2p-crypto')
66
const PeerId = require('peer-id')
77
const multihash = require('multihashes')
88
const errCode = require('err-code')
9-
const { Buffer } = require('buffer')
109
const multibase = require('multibase')
10+
const uint8ArrayFromString = require('uint8arrays/from-string')
11+
const uint8ArrayToString = require('uint8arrays/to-string')
12+
const uint8ArrayConcat = require('uint8arrays/concat')
1113

1214
const debug = require('debug')
1315
const log = debug('jsipns')
@@ -25,7 +27,7 @@ const namespace = '/ipns/'
2527
* IPNS entry
2628
* @typedef {Object} IpnsEntry
2729
* @property {string} value - value to be stored in the record
28-
* @property {Buffer} signature - signature of the record
30+
* @property {Uint8Array} signature - signature of the record
2931
* @property {number} validityType - Type of validation being used
3032
* @property {string} validity - expiration datetime for the record in RFC3339 format
3133
* @property {number} sequence - number representing the version of the record
@@ -67,10 +69,10 @@ const _create = async (privateKey, value, seq, isoValidity, validityType) => {
6769
const signature = await sign(privateKey, value, validityType, isoValidity)
6870

6971
const entry = {
70-
value: value,
72+
value: uint8ArrayFromString(value),
7173
signature: signature,
7274
validityType: validityType,
73-
validity: isoValidity,
75+
validity: uint8ArrayFromString(isoValidity),
7476
sequence: seq
7577
}
7678

@@ -106,7 +108,7 @@ const validate = async (publicKey, entry) => {
106108
let validityDate
107109

108110
try {
109-
validityDate = parseRFC3339(validity.toString())
111+
validityDate = parseRFC3339(uint8ArrayToString(validity))
110112
} catch (e) {
111113
log.error('unrecognized validity format (not an rfc3339 format)')
112114
throw errCode(new Error('unrecognized validity format (not an rfc3339 format)'), ERRORS.ERR_UNRECOGNIZED_FORMAT)
@@ -214,7 +216,7 @@ const rawStdEncoding = (key) => multibase.encode('base32', key).toString().slice
214216
* Get key for storing the record locally.
215217
* Format: /ipns/${base32(<HASH>)}
216218
*
217-
* @param {Buffer} key peer identifier object.
219+
* @param {Uint8Array} key peer identifier object.
218220
* @returns {string}
219221
*/
220222
const getLocalKey = (key) => new Key(`/ipns/${rawStdEncoding(key)}`)
@@ -223,18 +225,18 @@ const getLocalKey = (key) => new Key(`/ipns/${rawStdEncoding(key)}`)
223225
* Get key for sharing the record in the routing mechanism.
224226
* Format: ${base32(/ipns/<HASH>)}, ${base32(/pk/<HASH>)}
225227
*
226-
* @param {Buffer} pid peer identifier represented by the multihash of the public key as Buffer.
228+
* @param {Uint8Array} pid peer identifier represented by the multihash of the public key as Uint8Array.
227229
* @returns {Object} containing the `nameKey` and the `ipnsKey`.
228230
*/
229231
const getIdKeys = (pid) => {
230-
const pkBuffer = Buffer.from('/pk/')
231-
const ipnsBuffer = Buffer.from('/ipns/')
232+
const pkBuffer = uint8ArrayFromString('/pk/')
233+
const ipnsBuffer = uint8ArrayFromString('/ipns/')
232234

233235
return {
234-
routingPubKey: new Key(Buffer.concat([pkBuffer, pid]), false), // Added on https://github.com/ipfs/js-ipns/pull/8#issue-213857876 (pkKey will be deprecated in a future release)
235-
pkKey: new Key(rawStdEncoding(Buffer.concat([pkBuffer, pid]))),
236-
routingKey: new Key(Buffer.concat([ipnsBuffer, pid]), false), // Added on https://github.com/ipfs/js-ipns/pull/6#issue-213631461 (ipnsKey will be deprecated in a future release)
237-
ipnsKey: new Key(rawStdEncoding(Buffer.concat([ipnsBuffer, pid])))
236+
routingPubKey: new Key(uint8ArrayConcat([pkBuffer, pid]), false), // Added on https://github.com/ipfs/js-ipns/pull/8#issue-213857876 (pkKey will be deprecated in a future release)
237+
pkKey: new Key(rawStdEncoding(uint8ArrayConcat([pkBuffer, pid]))),
238+
routingKey: new Key(uint8ArrayConcat([ipnsBuffer, pid]), false), // Added on https://github.com/ipfs/js-ipns/pull/6#issue-213631461 (ipnsKey will be deprecated in a future release)
239+
ipnsKey: new Key(rawStdEncoding(uint8ArrayConcat([ipnsBuffer, pid])))
238240
}
239241
}
240242

@@ -263,11 +265,17 @@ const getValidityType = (validityType) => {
263265

264266
// Utility for creating the record data for being signed
265267
const ipnsEntryDataForSig = (value, validityType, validity) => {
266-
const valueBuffer = Buffer.from(value)
267-
const validityTypeBuffer = Buffer.from(getValidityType(validityType))
268-
const validityBuffer = Buffer.from(validity)
268+
if (!(value instanceof Uint8Array)) {
269+
value = uint8ArrayFromString(value)
270+
}
271+
272+
if (!(validity instanceof Uint8Array)) {
273+
validity = uint8ArrayFromString(validity)
274+
}
275+
276+
const validityTypeBuffer = uint8ArrayFromString(getValidityType(validityType))
269277

270-
return Buffer.concat([valueBuffer, validityBuffer, validityTypeBuffer])
278+
return uint8ArrayConcat([value, validity, validityTypeBuffer])
271279
}
272280

273281
// Utility for extracting the public key from a peer-id

test/index.spec.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ const chai = require('chai')
55
const dirtyChai = require('dirty-chai')
66
const chaiBytes = require('chai-bytes')
77
const chaiString = require('chai-string')
8-
const { Buffer } = require('buffer')
98
const expect = chai.expect
109
chai.use(dirtyChai)
1110
chai.use(chaiBytes)
1211
chai.use(chaiString)
1312
const { toB58String } = require('multihashes')
13+
const uint8ArrayFromString = require('uint8arrays/from-string')
1414

1515
const ipfs = require('ipfs')
1616
const ipfsHttpClient = require('ipfs-http-client')
@@ -56,7 +56,7 @@ describe('ipns', function () {
5656

5757
const entry = await ipns.create(rsa, cid, sequence, validity)
5858
expect(entry).to.deep.include({
59-
value: cid,
59+
value: uint8ArrayFromString(cid),
6060
sequence: sequence
6161
})
6262
expect(entry).to.have.a.property('validity')
@@ -73,7 +73,7 @@ describe('ipns', function () {
7373

7474
await ipns.validate(rsa.public, entry)
7575
expect(entry).to.have.a.property('validity')
76-
expect(entry.validity).to.equal('2033-05-18T03:33:20.000000000Z')
76+
expect(entry.validity).to.equalBytes(uint8ArrayFromString('2033-05-18T03:33:20.000000000Z'))
7777
})
7878

7979
it('should create an ipns record and validate it correctly', async () => {
@@ -129,8 +129,8 @@ describe('ipns', function () {
129129
const marshalledData = ipns.marshal(entryDataCreated)
130130
const unmarshalledData = ipns.unmarshal(marshalledData)
131131

132-
expect(entryDataCreated.value).to.equal(unmarshalledData.value.toString())
133-
expect(entryDataCreated.validity).to.equal(unmarshalledData.validity.toString())
132+
expect(entryDataCreated.value).to.equalBytes(unmarshalledData.value)
133+
expect(entryDataCreated.validity).to.equalBytes(unmarshalledData.validity)
134134
expect(entryDataCreated.validityType).to.equal(unmarshalledData.validityType)
135135
expect(entryDataCreated.signature).to.equalBytes(unmarshalledData.signature)
136136
expect(entryDataCreated.sequence).to.equal(unmarshalledData.sequence)
@@ -166,7 +166,7 @@ describe('ipns', function () {
166166

167167
keys.forEach(key => {
168168
const { routingKey } = ipns.getIdKeys(fromB58String(key))
169-
const id = toB58String(routingKey.toBuffer().slice(ipns.namespaceLength))
169+
const id = toB58String(routingKey.uint8Array().subarray(ipns.namespaceLength))
170170

171171
expect(id).to.equal(key)
172172
})
@@ -206,7 +206,7 @@ describe('ipns', function () {
206206
const entry = await ipns.create(rsa, cid, sequence, validity)
207207

208208
const marshalledData = ipns.marshal(entry)
209-
const key = Buffer.from(`/ipns/${ipfsId.id}`)
209+
const key = uint8ArrayFromString(`/ipns/${ipfsId.id}`)
210210

211211
try {
212212
await ipns.validator.validate(marshalledData, key)
@@ -235,7 +235,7 @@ describe('ipns', function () {
235235
await ipns.embedPublicKey(rsa.public, entry)
236236

237237
const marshalledData = ipns.marshal(entry)
238-
const key = Buffer.from(`/ipns/${ipfsId.id}`)
238+
const key = uint8ArrayFromString(`/ipns/${ipfsId.id}`)
239239

240240
const valid = await ipns.validator.validate(marshalledData, key)
241241
expect(valid).to.equal(true)
@@ -249,9 +249,9 @@ describe('ipns', function () {
249249
await ipns.embedPublicKey(rsa.public, entry)
250250

251251
// corrupt the record by changing the value to random bytes
252-
entry.value = crypto.randomBytes(46).toString()
252+
entry.value = crypto.randomBytes(46)
253253
const marshalledData = ipns.marshal(entry)
254-
const key = Buffer.from(`/ipns/${ipfsId.id}`)
254+
const key = uint8ArrayFromString(`/ipns/${ipfsId.id}`)
255255

256256
try {
257257
await ipns.validator.validate(marshalledData, key)

0 commit comments

Comments
 (0)