mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-03-28 05:11:04 +00:00
feat: cerified addressbook
This commit is contained in:
parent
b0a36ccbc8
commit
8f2e69048f
@ -9,10 +9,12 @@ const multiaddr = require('multiaddr')
|
|||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
const Book = require('./book')
|
const Book = require('./book')
|
||||||
|
const PeerRecord = require('../record/peer-record')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
codes: { ERR_INVALID_PARAMETERS }
|
codes: { ERR_INVALID_PARAMETERS }
|
||||||
} = require('../errors')
|
} = require('../errors')
|
||||||
|
const Envelope = require('../record/envelope')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The AddressBook is responsible for keeping the known multiaddrs
|
* The AddressBook is responsible for keeping the known multiaddrs
|
||||||
@ -23,8 +25,23 @@ class AddressBook extends Book {
|
|||||||
* Address object
|
* Address object
|
||||||
* @typedef {Object} Address
|
* @typedef {Object} Address
|
||||||
* @property {Multiaddr} multiaddr peer multiaddr.
|
* @property {Multiaddr} multiaddr peer multiaddr.
|
||||||
|
* @property {boolean} isCertified obtained from a signed peer record.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CertifiedRecord object
|
||||||
|
* @typedef {Object} CertifiedRecord
|
||||||
|
* @property {Buffer} raw raw envelope.
|
||||||
|
* @property {number} seqNumber seq counter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry object for the addressBook
|
||||||
|
* @typedef {Object} Entry
|
||||||
|
* @property {Array<Address>} addresses peer Addresses.
|
||||||
|
* @property {CertifiedRecord} record certified peer record.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {PeerStore} peerStore
|
* @param {PeerStore} peerStore
|
||||||
@ -39,16 +56,95 @@ class AddressBook extends Book {
|
|||||||
peerStore,
|
peerStore,
|
||||||
eventName: 'change:multiaddrs',
|
eventName: 'change:multiaddrs',
|
||||||
eventProperty: 'multiaddrs',
|
eventProperty: 'multiaddrs',
|
||||||
eventTransformer: (data) => data.map((address) => address.multiaddr)
|
eventTransformer: (data) => {
|
||||||
|
if (!data.addresses) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return data.addresses.map((address) => address.multiaddr)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map known peers to their known Addresses.
|
* Map known peers to their known Address Entries.
|
||||||
* @type {Map<string, Array<Address>>}
|
* @type {Map<string, Array<Entry>>}
|
||||||
*/
|
*/
|
||||||
this.data = new Map()
|
this.data = new Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ConsumePeerRecord adds addresses from a signed peer.PeerRecord contained in a record envelope.
|
||||||
|
* This will return a boolean that indicates if the record was successfully processed and integrated
|
||||||
|
* into the AddressBook.
|
||||||
|
* @param {Envelope} envelope
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
consumePeerRecord (envelope) {
|
||||||
|
let peerRecord
|
||||||
|
try {
|
||||||
|
peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
|
||||||
|
} catch (err) {
|
||||||
|
log.error('invalid peer record received')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify peerId
|
||||||
|
if (peerRecord.peerId.toB58String() !== envelope.peerId.toB58String()) {
|
||||||
|
log('signing key does not match PeerId in the PeerRecord')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const peerId = peerRecord.peerId
|
||||||
|
const id = peerId.toB58String()
|
||||||
|
const entry = this.data.get(id) || {}
|
||||||
|
const storedRecord = entry.record
|
||||||
|
|
||||||
|
// ensure seq is greater than, or equal to, the last received
|
||||||
|
if (storedRecord &&
|
||||||
|
storedRecord.seqNumber >= peerRecord.seqNumber) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the record has multiaddrs
|
||||||
|
if (!peerRecord.multiaddrs || !peerRecord.multiaddrs.length) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const addresses = this._toAddresses(peerRecord.multiaddrs, true)
|
||||||
|
|
||||||
|
// TODO: new record with different addresses from stored record
|
||||||
|
// - Remove the older ones?
|
||||||
|
// - Change to uncertified?
|
||||||
|
|
||||||
|
// TODO: events
|
||||||
|
// Should a multiaddr only modified to certified trigger an event?
|
||||||
|
// - Needed for persistent peer store
|
||||||
|
this._setData(peerId, {
|
||||||
|
addresses,
|
||||||
|
record: {
|
||||||
|
raw: envelope.marshal(),
|
||||||
|
seqNumber: peerRecord.seqNumber
|
||||||
|
}
|
||||||
|
})
|
||||||
|
log(`stored provided peer record for ${id}`)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an Envelope containing a PeerRecord for the given peer.
|
||||||
|
* @param {PeerId} peerId
|
||||||
|
* @return {Promise<Envelope>}
|
||||||
|
*/
|
||||||
|
getPeerRecord (peerId) {
|
||||||
|
const entry = this.data.get(peerId.toB58String())
|
||||||
|
|
||||||
|
if (!entry || !entry.record || !entry.record.raw) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return Envelope.createFromProtobuf(entry.record.raw)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set known multiaddrs of a provided peer.
|
* Set known multiaddrs of a provided peer.
|
||||||
* @override
|
* @override
|
||||||
@ -64,7 +160,8 @@ class AddressBook extends Book {
|
|||||||
|
|
||||||
const addresses = this._toAddresses(multiaddrs)
|
const addresses = this._toAddresses(multiaddrs)
|
||||||
const id = peerId.toB58String()
|
const id = peerId.toB58String()
|
||||||
const rec = this.data.get(id)
|
const entry = this.data.get(id) || {}
|
||||||
|
const rec = entry.addresses
|
||||||
|
|
||||||
// Not replace multiaddrs
|
// Not replace multiaddrs
|
||||||
if (!addresses.length) {
|
if (!addresses.length) {
|
||||||
@ -83,7 +180,10 @@ class AddressBook extends Book {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._setData(peerId, addresses)
|
this._setData(peerId, {
|
||||||
|
addresses,
|
||||||
|
record: entry.record
|
||||||
|
})
|
||||||
log(`stored provided multiaddrs for ${id}`)
|
log(`stored provided multiaddrs for ${id}`)
|
||||||
|
|
||||||
// Notify the existance of a new peer
|
// Notify the existance of a new peer
|
||||||
@ -109,7 +209,9 @@ class AddressBook extends Book {
|
|||||||
|
|
||||||
const addresses = this._toAddresses(multiaddrs)
|
const addresses = this._toAddresses(multiaddrs)
|
||||||
const id = peerId.toB58String()
|
const id = peerId.toB58String()
|
||||||
const rec = this.data.get(id)
|
|
||||||
|
const entry = this.data.get(id) || {}
|
||||||
|
const rec = entry.addresses
|
||||||
|
|
||||||
// Add recorded uniquely to the new array (Union)
|
// Add recorded uniquely to the new array (Union)
|
||||||
rec && rec.forEach((mi) => {
|
rec && rec.forEach((mi) => {
|
||||||
@ -125,7 +227,10 @@ class AddressBook extends Book {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
this._setData(peerId, addresses)
|
this._setData(peerId, {
|
||||||
|
addresses,
|
||||||
|
record: entry.record
|
||||||
|
})
|
||||||
|
|
||||||
log(`added provided multiaddrs for ${id}`)
|
log(`added provided multiaddrs for ${id}`)
|
||||||
|
|
||||||
@ -137,13 +242,31 @@ class AddressBook extends Book {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the known data of a provided peer.
|
||||||
|
* @override
|
||||||
|
* @param {PeerId} peerId
|
||||||
|
* @returns {Array<data>}
|
||||||
|
*/
|
||||||
|
get (peerId) {
|
||||||
|
// TODO: should we return Entry instead??
|
||||||
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
|
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
|
||||||
|
}
|
||||||
|
|
||||||
|
const entry = this.data.get(peerId.toB58String())
|
||||||
|
|
||||||
|
return entry && entry.addresses ? [...entry.addresses] : undefined
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms received multiaddrs into Address.
|
* Transforms received multiaddrs into Address.
|
||||||
* @private
|
* @private
|
||||||
* @param {Array<Multiaddr>} multiaddrs
|
* @param {Array<Multiaddr>} multiaddrs
|
||||||
|
* @param {boolean} [isCertified]
|
||||||
* @returns {Array<Address>}
|
* @returns {Array<Address>}
|
||||||
*/
|
*/
|
||||||
_toAddresses (multiaddrs) {
|
_toAddresses (multiaddrs, isCertified = false) {
|
||||||
if (!multiaddrs) {
|
if (!multiaddrs) {
|
||||||
log.error('multiaddrs must be provided to store data')
|
log.error('multiaddrs must be provided to store data')
|
||||||
throw errcode(new Error('multiaddrs must be provided'), ERR_INVALID_PARAMETERS)
|
throw errcode(new Error('multiaddrs must be provided'), ERR_INVALID_PARAMETERS)
|
||||||
@ -158,7 +281,8 @@ class AddressBook extends Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addresses.push({
|
addresses.push({
|
||||||
multiaddr: addr
|
multiaddr: addr,
|
||||||
|
isCertified
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -177,13 +301,13 @@ class AddressBook extends Book {
|
|||||||
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
|
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
|
||||||
}
|
}
|
||||||
|
|
||||||
const record = this.data.get(peerId.toB58String())
|
const entry = this.data.get(peerId.toB58String())
|
||||||
|
|
||||||
if (!record) {
|
if (!entry || !entry.addresses) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
return record.map((address) => {
|
return entry.addresses.map((address) => {
|
||||||
const multiaddr = address.multiaddr
|
const multiaddr = address.multiaddr
|
||||||
|
|
||||||
const idString = multiaddr.getPeerId()
|
const idString = multiaddr.getPeerId()
|
||||||
|
@ -296,9 +296,11 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
|
|
||||||
this.addressBook._setData(
|
this.addressBook._setData(
|
||||||
peerId,
|
peerId,
|
||||||
decoded.addrs.map((address) => ({
|
{
|
||||||
multiaddr: multiaddr(address.multiaddr)
|
addresses: decoded.addrs.map((address) => ({
|
||||||
})),
|
multiaddr: multiaddr(address.multiaddr)
|
||||||
|
}))
|
||||||
|
},
|
||||||
{ emit: false })
|
{ emit: false })
|
||||||
break
|
break
|
||||||
case 'keys':
|
case 'keys':
|
||||||
|
@ -4,11 +4,26 @@ const protons = require('protons')
|
|||||||
|
|
||||||
const message = `
|
const message = `
|
||||||
message Addresses {
|
message Addresses {
|
||||||
|
// Address represents a single multiaddr.
|
||||||
message Address {
|
message Address {
|
||||||
required bytes multiaddr = 1;
|
required bytes multiaddr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CertifiedRecord contains a serialized signed PeerRecord used to
|
||||||
|
// populate the signedAddrs list.
|
||||||
|
message CertifiedRecord {
|
||||||
|
// The Seq counter from the signed PeerRecord envelope
|
||||||
|
uint64 seq = 1;
|
||||||
|
|
||||||
|
// The serialized bytes of the SignedEnvelope containing the PeerRecord.
|
||||||
|
bytes raw = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The known multiaddrs.
|
||||||
repeated Address addrs = 1;
|
repeated Address addrs = 1;
|
||||||
|
|
||||||
|
// The most recently received signed PeerRecord.
|
||||||
|
CertifiedRecord certified_record = 2;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -112,11 +112,6 @@ const formatSignaturePayload = (domain, payloadType, payload) => {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unmarshal a serialized Envelope protobuf message.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @return {Envelope}
|
|
||||||
*/
|
|
||||||
const unmarshalEnvelope = async (data) => {
|
const unmarshalEnvelope = async (data) => {
|
||||||
const envelopeData = Protobuf.decode(data)
|
const envelopeData = Protobuf.decode(data)
|
||||||
const peerId = await PeerId.createFromPubKey(envelopeData.public_key)
|
const peerId = await PeerId.createFromPubKey(envelopeData.public_key)
|
||||||
@ -129,6 +124,13 @@ const unmarshalEnvelope = async (data) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmarshal a serialized Envelope protobuf message.
|
||||||
|
* @param {Buffer} data
|
||||||
|
* @return {Promise<Envelope>}
|
||||||
|
*/
|
||||||
|
Envelope.createFromProtobuf = unmarshalEnvelope
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seal marshals the given Record, places the marshaled bytes inside an Envelope
|
* Seal marshals the given Record, places the marshaled bytes inside an Envelope
|
||||||
* and signs it with the given peerId's private key.
|
* and signs it with the given peerId's private key.
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
|
/* eslint max-nested-callbacks: ["error", 6] */
|
||||||
|
|
||||||
const chai = require('chai')
|
const chai = require('chai')
|
||||||
chai.use(require('dirty-chai'))
|
chai.use(require('dirty-chai'))
|
||||||
const { expect } = chai
|
const { expect } = chai
|
||||||
|
|
||||||
const pDefer = require('p-defer')
|
const { Buffer } = require('buffer')
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
const arrayEquals = require('libp2p-utils/src/array-equals')
|
const arrayEquals = require('libp2p-utils/src/array-equals')
|
||||||
|
const PeerId = require('peer-id')
|
||||||
|
const pDefer = require('p-defer')
|
||||||
|
|
||||||
const PeerStore = require('../../src/peer-store')
|
const PeerStore = require('../../src/peer-store')
|
||||||
|
const Envelope = require('../../src/record/envelope')
|
||||||
|
const PeerRecord = require('../../src/record/peer-record')
|
||||||
|
|
||||||
const peerUtils = require('../utils/creators/peer')
|
const peerUtils = require('../utils/creators/peer')
|
||||||
const {
|
const {
|
||||||
@ -396,4 +401,237 @@ describe('addressBook', () => {
|
|||||||
return defer.promise
|
return defer.promise
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('certified records', () => {
|
||||||
|
let peerStore, ab
|
||||||
|
|
||||||
|
describe('consumes successfully a valid peer record and stores its data', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
peerStore = new PeerStore()
|
||||||
|
ab = peerStore.addressBook
|
||||||
|
})
|
||||||
|
|
||||||
|
it('no previous data in AddressBook', async () => {
|
||||||
|
const multiaddrs = [addr1, addr2]
|
||||||
|
const peerRecord = new PeerRecord({
|
||||||
|
peerId,
|
||||||
|
multiaddrs
|
||||||
|
})
|
||||||
|
const envelope = await Envelope.seal(peerRecord, peerId)
|
||||||
|
|
||||||
|
// consume peer record
|
||||||
|
const consumed = ab.consumePeerRecord(envelope)
|
||||||
|
expect(consumed).to.eql(true)
|
||||||
|
|
||||||
|
// Validate stored envelope
|
||||||
|
const storedEnvelope = await ab.getPeerRecord(peerId)
|
||||||
|
expect(envelope.isEqual(storedEnvelope)).to.eql(true)
|
||||||
|
|
||||||
|
// Validate AddressBook addresses
|
||||||
|
const addrs = ab.get(peerId)
|
||||||
|
expect(addrs).to.exist()
|
||||||
|
expect(addrs).to.have.lengthOf(multiaddrs.length)
|
||||||
|
addrs.forEach((addr, index) => {
|
||||||
|
expect(addr.isCertified).to.eql(true)
|
||||||
|
expect(multiaddrs[index].equals(addr.multiaddr)).to.eql(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits change:multiaddrs event when adding multiaddrs', async () => {
|
||||||
|
const defer = pDefer()
|
||||||
|
const multiaddrs = [addr1, addr2]
|
||||||
|
const peerRecord = new PeerRecord({
|
||||||
|
peerId,
|
||||||
|
multiaddrs
|
||||||
|
})
|
||||||
|
const envelope = await Envelope.seal(peerRecord, peerId)
|
||||||
|
|
||||||
|
peerStore.once('change:multiaddrs', ({ peerId, multiaddrs }) => {
|
||||||
|
expect(peerId).to.exist()
|
||||||
|
expect(multiaddrs).to.eql(multiaddrs)
|
||||||
|
defer.resolve()
|
||||||
|
})
|
||||||
|
|
||||||
|
// consume peer record
|
||||||
|
const consumed = ab.consumePeerRecord(envelope)
|
||||||
|
expect(consumed).to.eql(true)
|
||||||
|
|
||||||
|
return defer.promise
|
||||||
|
})
|
||||||
|
|
||||||
|
it('with same data currently in AddressBook (not certified)', async () => {
|
||||||
|
const multiaddrs = [addr1, addr2]
|
||||||
|
|
||||||
|
// Set addressBook data
|
||||||
|
ab.set(peerId, multiaddrs)
|
||||||
|
|
||||||
|
// Validate data exists, but not certified
|
||||||
|
let addrs = ab.get(peerId)
|
||||||
|
expect(addrs).to.exist()
|
||||||
|
expect(addrs).to.have.lengthOf(multiaddrs.length)
|
||||||
|
|
||||||
|
addrs.forEach((addr, index) => {
|
||||||
|
expect(addr.isCertified).to.eql(false)
|
||||||
|
expect(multiaddrs[index].equals(addr.multiaddr)).to.eql(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create peer record
|
||||||
|
const peerRecord = new PeerRecord({
|
||||||
|
peerId,
|
||||||
|
multiaddrs
|
||||||
|
})
|
||||||
|
const envelope = await Envelope.seal(peerRecord, peerId)
|
||||||
|
|
||||||
|
// consume peer record
|
||||||
|
const consumed = ab.consumePeerRecord(envelope)
|
||||||
|
expect(consumed).to.eql(true)
|
||||||
|
|
||||||
|
// Validate data exists and certified
|
||||||
|
addrs = ab.get(peerId)
|
||||||
|
expect(addrs).to.exist()
|
||||||
|
expect(addrs).to.have.lengthOf(multiaddrs.length)
|
||||||
|
addrs.forEach((addr, index) => {
|
||||||
|
expect(addr.isCertified).to.eql(true)
|
||||||
|
expect(multiaddrs[index].equals(addr.multiaddr)).to.eql(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('with previous partial data in AddressBook (not certified)', async () => {
|
||||||
|
const multiaddrs = [addr1, addr2]
|
||||||
|
|
||||||
|
// Set addressBook data
|
||||||
|
ab.set(peerId, [addr1])
|
||||||
|
|
||||||
|
// Validate data exists, but not certified
|
||||||
|
let addrs = ab.get(peerId)
|
||||||
|
expect(addrs).to.exist()
|
||||||
|
expect(addrs).to.have.lengthOf(1)
|
||||||
|
expect(addrs[0].isCertified).to.eql(false)
|
||||||
|
expect(addrs[0].multiaddr.equals(addr1)).to.eql(true)
|
||||||
|
|
||||||
|
// Create peer record
|
||||||
|
const peerRecord = new PeerRecord({
|
||||||
|
peerId,
|
||||||
|
multiaddrs
|
||||||
|
})
|
||||||
|
const envelope = await Envelope.seal(peerRecord, peerId)
|
||||||
|
|
||||||
|
// consume peer record
|
||||||
|
const consumed = ab.consumePeerRecord(envelope)
|
||||||
|
expect(consumed).to.eql(true)
|
||||||
|
|
||||||
|
// Validate data exists and certified
|
||||||
|
addrs = ab.get(peerId)
|
||||||
|
expect(addrs).to.exist()
|
||||||
|
expect(addrs).to.have.lengthOf(multiaddrs.length)
|
||||||
|
addrs.forEach((addr, index) => {
|
||||||
|
expect(addr.isCertified).to.eql(true)
|
||||||
|
expect(multiaddrs[index].equals(addr.multiaddr)).to.eql(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('with previous different data in AddressBook (not certified)', async () => {
|
||||||
|
const multiaddrsUncertified = [addr3]
|
||||||
|
const multiaddrsCertified = [addr1, addr2]
|
||||||
|
|
||||||
|
// Set addressBook data
|
||||||
|
ab.set(peerId, multiaddrsUncertified)
|
||||||
|
|
||||||
|
// Validate data exists, but not certified
|
||||||
|
let addrs = ab.get(peerId)
|
||||||
|
expect(addrs).to.exist()
|
||||||
|
expect(addrs).to.have.lengthOf(multiaddrsUncertified.length)
|
||||||
|
addrs.forEach((addr, index) => {
|
||||||
|
expect(addr.isCertified).to.eql(false)
|
||||||
|
expect(multiaddrsUncertified[index].equals(addr.multiaddr)).to.eql(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create peer record
|
||||||
|
const peerRecord = new PeerRecord({
|
||||||
|
peerId,
|
||||||
|
multiaddrs: multiaddrsCertified
|
||||||
|
})
|
||||||
|
const envelope = await Envelope.seal(peerRecord, peerId)
|
||||||
|
|
||||||
|
// consume peer record
|
||||||
|
const consumed = ab.consumePeerRecord(envelope)
|
||||||
|
expect(consumed).to.eql(true)
|
||||||
|
|
||||||
|
// Validate data exists and certified
|
||||||
|
addrs = ab.get(peerId)
|
||||||
|
expect(addrs).to.exist()
|
||||||
|
expect(addrs).to.have.lengthOf(multiaddrsCertified.length)
|
||||||
|
addrs.forEach((addr, index) => {
|
||||||
|
expect(addr.isCertified).to.eql(true)
|
||||||
|
expect(multiaddrsCertified[index].equals(addr.multiaddr)).to.eql(true)
|
||||||
|
})
|
||||||
|
// TODO: should it has the older one?
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fails to consume invalid peer records', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
peerStore = new PeerStore()
|
||||||
|
ab = peerStore.addressBook
|
||||||
|
})
|
||||||
|
|
||||||
|
it('invalid peer record', () => {
|
||||||
|
const invalidEnvelope = {
|
||||||
|
payload: Buffer.from('invalid-peerRecord')
|
||||||
|
}
|
||||||
|
|
||||||
|
const consumed = ab.consumePeerRecord(invalidEnvelope)
|
||||||
|
expect(consumed).to.eql(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('peer that created the envelope is not the same as the peer record', async () => {
|
||||||
|
const multiaddrs = [addr1, addr2]
|
||||||
|
|
||||||
|
// Create peer record
|
||||||
|
const peerId2 = await PeerId.create()
|
||||||
|
const peerRecord = new PeerRecord({
|
||||||
|
peerId: peerId2,
|
||||||
|
multiaddrs
|
||||||
|
})
|
||||||
|
const envelope = await Envelope.seal(peerRecord, peerId)
|
||||||
|
|
||||||
|
const consumed = ab.consumePeerRecord(envelope)
|
||||||
|
expect(consumed).to.eql(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not store an outdated record', async () => {
|
||||||
|
const multiaddrs = [addr1, addr2]
|
||||||
|
const peerRecord1 = new PeerRecord({
|
||||||
|
peerId,
|
||||||
|
multiaddrs,
|
||||||
|
seqNumber: Date.now()
|
||||||
|
})
|
||||||
|
const peerRecord2 = new PeerRecord({
|
||||||
|
peerId,
|
||||||
|
multiaddrs,
|
||||||
|
seqNumber: Date.now() - 1
|
||||||
|
})
|
||||||
|
const envelope1 = await Envelope.seal(peerRecord1, peerId)
|
||||||
|
const envelope2 = await Envelope.seal(peerRecord2, peerId)
|
||||||
|
|
||||||
|
// Consume envelope1 (bigger seqNumber)
|
||||||
|
let consumed = ab.consumePeerRecord(envelope1)
|
||||||
|
expect(consumed).to.eql(true)
|
||||||
|
|
||||||
|
consumed = ab.consumePeerRecord(envelope2)
|
||||||
|
expect(consumed).to.eql(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('empty multiaddrs', async () => {
|
||||||
|
const peerRecord = new PeerRecord({
|
||||||
|
peerId,
|
||||||
|
multiaddrs: []
|
||||||
|
})
|
||||||
|
const envelope = await Envelope.seal(peerRecord, peerId)
|
||||||
|
|
||||||
|
const consumed = ab.consumePeerRecord(envelope)
|
||||||
|
expect(consumed).to.eql(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -210,6 +210,8 @@ describe('Persisted PeerStore', () => {
|
|||||||
throw new Error('Datastore should be empty')
|
throw new Error('Datastore should be empty')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// TODO: certified?
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('setup with content not stored per change (threshold 2)', () => {
|
describe('setup with content not stored per change (threshold 2)', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user