Skip to content
This repository was archived by the owner on Jul 21, 2023. It is now read-only.

Commit 10177ae

Browse files
authored
feat: new record definition (#8)
BREAKING CHANGE: having the libp2p-record protobuf definition compliant with go-libp2p-record. Author and signature were removed.
1 parent cbdc360 commit 10177ae

File tree

6 files changed

+12
-229
lines changed

6 files changed

+12
-229
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@
4141
"chai": "^4.1.2",
4242
"dirty-chai": "^2.0.1",
4343
"libp2p-crypto": "~0.10.3",
44+
"peer-id": "~0.11.0",
4445
"pre-commit": "^1.2.2"
4546
},
4647
"dependencies": {
4748
"async": "^2.5.0",
4849
"buffer-split": "^1.0.0",
4950
"left-pad": "^1.1.3",
50-
"multihashes": "~0.4.9",
51+
"multihashes": "~0.4.14",
5152
"multihashing-async": "~0.4.6",
52-
"peer-id": "~0.10.0",
5353
"protons": "^1.0.0"
5454
},
5555
"contributors": [

src/record.js

Lines changed: 3 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const protons = require('protons')
44
const assert = require('assert')
5-
const PeerId = require('peer-id')
65

76
const pb = protons(require('./record.proto')).Record
87
const utils = require('./utils')
@@ -11,10 +10,9 @@ class Record {
1110
/**
1211
* @param {Buffer} [key]
1312
* @param {Buffer} [value]
14-
* @param {PeerId} [author]
1513
* @param {Date} [recvtime]
1614
*/
17-
constructor (key, value, author, recvtime) {
15+
constructor (key, value, recvtime) {
1816
if (key) {
1917
assert(Buffer.isBuffer(key), 'key must be a Buffer')
2018
}
@@ -25,22 +23,7 @@ class Record {
2523

2624
this.key = key
2725
this.value = value
28-
this.author = author
2926
this.timeReceived = recvtime
30-
this.signature = null
31-
}
32-
33-
/**
34-
* Returns the blob protected by the record signature.
35-
*
36-
* @returns {Buffer}
37-
*/
38-
blobForSignature () {
39-
return Buffer.concat([
40-
Buffer.from(this.key),
41-
this.value,
42-
this.author.id
43-
])
4427
}
4528

4629
/**
@@ -59,36 +42,9 @@ class Record {
5942
return {
6043
key: this.key,
6144
value: this.value,
62-
author: this.author.id,
63-
signature: this.signature,
6445
timeReceived: this.timeReceived && utils.toRFC3339(this.timeReceived)
6546
}
6647
}
67-
/**
68-
* @param {PrivateKey} privKey
69-
* @param {function(Error, Buffer)} callback
70-
* @returns {undefined}
71-
*/
72-
serializeSigned (privKey, callback) {
73-
const blob = this.blobForSignature()
74-
75-
privKey.sign(blob, (err, signature) => {
76-
if (err) {
77-
return callback(err)
78-
}
79-
80-
this.signature = signature
81-
82-
let rec
83-
try {
84-
rec = this.serialize()
85-
} catch (err) {
86-
return callback(err)
87-
}
88-
89-
callback(null, rec)
90-
})
91-
}
9248

9349
/**
9450
* Decode a protobuf encoded record.
@@ -102,8 +58,7 @@ class Record {
10258
}
10359

10460
/**
105-
* Create a record from the raw object returnde from the
106-
* protobuf library.
61+
* Create a record from the raw object returned from the protobuf library.
10762
*
10863
* @param {Object} obj
10964
* @returns {Record}
@@ -114,41 +69,12 @@ class Record {
11469
recvtime = utils.parseRFC3339(obj.timeReceived)
11570
}
11671

117-
let author
118-
if (obj.author) {
119-
author = new PeerId(obj.author)
120-
}
121-
12272
const rec = new Record(
123-
obj.key, obj.value, author, recvtime
73+
obj.key, obj.value, recvtime
12474
)
12575

126-
rec.signature = obj.signature
127-
12876
return rec
12977
}
130-
/**
131-
* Verify the signature of a record against the given public key.
132-
*
133-
* @param {PublicKey} pubKey
134-
* @param {function(Error)} callback
135-
* @returns {undefined}
136-
*/
137-
verifySignature (pubKey, callback) {
138-
const blob = this.blobForSignature()
139-
140-
pubKey.verify(blob, this.signature, (err, good) => {
141-
if (err) {
142-
return callback(err)
143-
}
144-
145-
if (!good) {
146-
return callback(new Error('Invalid record signature'))
147-
}
148-
149-
callback()
150-
})
151-
}
15278
}
15379

15480
module.exports = Record

src/record.proto.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@ module.exports = `// Record represents a dht record that contains a value
33
// for a key value pair
44
message Record {
55
// The key that references this record
6-
// adjusted for j
7-
optional bytes key = 1;
6+
bytes key = 1;
87
98
// The actual value this record is storing
10-
optional bytes value = 2;
9+
bytes value = 2;
1110
11+
// Note: These fields were removed from the Record message
1212
// hash of the authors public key
13-
// converted to bytes for JavaScript
14-
optional bytes author = 3;
15-
13+
// optional bytes author = 3;
1614
// A PKI signature for the key+value+author
17-
optional bytes signature = 4;
15+
// optional bytes signature = 4;
1816
1917
// Time the record was received, set by receiver
2018
optional string timeReceived = 5;

src/validator.js

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,32 +29,7 @@ const verifyRecord = (validators, record, callback) => {
2929
validator.func(key, record.value, callback)
3030
}
3131

32-
/**
33-
* Check if a given key was signed.
34-
*
35-
* @param {Object} validators
36-
* @param {Buffer} key
37-
* @returns {boolean}
38-
*/
39-
const isSigned = (validators, key) => {
40-
const parts = bsplit(key, Buffer.from('/'))
41-
42-
if (parts.length < 3) {
43-
// No validator available
44-
return false
45-
}
46-
47-
const validator = validators[parts[1].toString()]
48-
49-
if (!validator) {
50-
throw new Error('Invalid record keytype')
51-
}
52-
53-
return validator.sign
54-
}
55-
5632
module.exports = {
5733
verifyRecord: verifyRecord,
58-
isSigned: isSigned,
5934
validators: require('./validators')
6035
}

test/record.spec.js

Lines changed: 2 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44
const chai = require('chai')
55
chai.use(require('dirty-chai'))
66
const expect = chai.expect
7-
const crypto = require('libp2p-crypto')
8-
const waterfall = require('async/waterfall')
9-
const parallel = require('async/parallel')
10-
const PeerId = require('peer-id')
117

128
const libp2pRecord = require('../src')
139
const Record = libp2pRecord.Record
@@ -17,114 +13,30 @@ const fixture = require('./fixtures/go-record.js')
1713
const date = new Date(Date.UTC(2012, 1, 25, 10, 10, 10, 10))
1814

1915
describe('record', () => {
20-
let key
21-
let otherKey
22-
let id
23-
24-
before((done) => {
25-
waterfall([
26-
(cb) => parallel([
27-
(cb) => crypto.keys.generateKeyPair('rsa', 1024, cb),
28-
(cb) => crypto.keys.generateKeyPair('rsa', 1024, cb)
29-
], cb),
30-
(keys, cb) => {
31-
otherKey = keys[0]
32-
key = keys[1]
33-
34-
PeerId.createFromPrivKey(key.bytes, cb)
35-
},
36-
(_id, cb) => {
37-
id = _id
38-
39-
cb()
40-
}
41-
], done)
42-
})
43-
4416
it('new', () => {
4517
const rec = new Record(
4618
Buffer.from('hello'),
47-
Buffer.from('world'),
48-
id
19+
Buffer.from('world')
4920
)
5021

5122
expect(rec).to.have.property('key').eql(Buffer.from('hello'))
5223
expect(rec).to.have.property('value').eql(Buffer.from('world'))
53-
expect(rec).to.have.property('author').eql(id)
5424
})
5525

5626
it('serialize & deserialize', () => {
57-
const rec = new Record(Buffer.from('hello'), Buffer.from('world'), id, date)
27+
const rec = new Record(Buffer.from('hello'), Buffer.from('world'), date)
5828
const dec = Record.deserialize(rec.serialize())
5929

6030
expect(dec).to.have.property('key').eql(Buffer.from('hello'))
6131
expect(dec).to.have.property('value').eql(Buffer.from('world'))
62-
expect(dec).to.have.property('author')
63-
expect(dec.author.id.equals(id.id)).to.be.eql(true)
6432
expect(dec.timeReceived).to.be.eql(date)
6533
})
6634

67-
it('serializeSigned', (done) => {
68-
const rec = new Record(Buffer.from('hello2'), Buffer.from('world2'), id, date)
69-
rec.serializeSigned(key, (err, enc) => {
70-
expect(err).to.not.exist()
71-
72-
const dec = Record.deserialize(enc)
73-
expect(dec).to.have.property('key').eql(Buffer.from('hello2'))
74-
expect(dec).to.have.property('value').eql(Buffer.from('world2'))
75-
expect(dec).to.have.property('author')
76-
expect(dec.author.id.equals(id.id)).to.be.eql(true)
77-
expect(dec.timeReceived).to.be.eql(date)
78-
79-
const blob = rec.blobForSignature()
80-
81-
key.sign(blob, (err, signature) => {
82-
expect(err).to.not.exist()
83-
84-
expect(dec.signature).to.be.eql(signature)
85-
done()
86-
})
87-
})
88-
})
89-
90-
describe('verifySignature', () => {
91-
it('valid', (done) => {
92-
const rec = new Record(Buffer.from('hello'), Buffer.from('world'), id)
93-
94-
rec.serializeSigned(key, (err, enc) => {
95-
expect(err).to.not.exist()
96-
97-
rec.verifySignature(key.public, done)
98-
})
99-
})
100-
101-
it('invalid', (done) => {
102-
const rec = new Record(Buffer.from('hello'), Buffer.from('world'), id)
103-
rec.serializeSigned(key, (err, enc) => {
104-
expect(err).to.not.exist()
105-
106-
rec.verifySignature(otherKey.public, (err) => {
107-
expect(err).to.match(/Invalid record signature/)
108-
done()
109-
})
110-
})
111-
})
112-
})
113-
11435
describe('go interop', () => {
11536
it('no signature', () => {
11637
const dec = Record.deserialize(fixture.serialized)
11738
expect(dec).to.have.property('key').eql(Buffer.from('hello'))
11839
expect(dec).to.have.property('value').eql(Buffer.from('world'))
119-
expect(dec).to.have.property('author')
120-
})
121-
122-
it('with signature', () => {
123-
const dec = Record.deserialize(fixture.serializedSigned)
124-
expect(dec).to.have.property('key').eql(Buffer.from('hello'))
125-
expect(dec).to.have.property('value').eql(Buffer.from('world'))
126-
expect(dec).to.have.property('author')
127-
expect(dec).to.have.property('signature')
12840
})
12941
})
13042
})

test/validator.spec.js

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -81,34 +81,6 @@ describe('validator', () => {
8181
})
8282
})
8383

84-
describe('isSigned', () => {
85-
it('returns false for missing validator', () => {
86-
const validators = {}
87-
88-
expect(validator.isSigned(validators, Buffer.from('/hello')))
89-
.to.eql(false)
90-
})
91-
92-
it('throws on unkown validator', () => {
93-
const validators = {}
94-
95-
expect(() => validator.isSigned(validators, Buffer.from('/hello/world')))
96-
.to.throw(/Invalid record keytype/)
97-
})
98-
99-
it('returns the value from the matching validator', () => {
100-
const validators = {
101-
hello: {sign: true},
102-
world: {sign: false}
103-
}
104-
105-
expect(validator.isSigned(validators, Buffer.from('/hello/world')))
106-
.to.eql(true)
107-
108-
expect(validator.isSigned(validators, '/world/hello')).to.eql(false)
109-
})
110-
})
111-
11284
describe('validators', () => {
11385
it('exports pk', () => {
11486
expect(validator.validators).to.have.keys(['pk'])

0 commit comments

Comments
 (0)