chore: add certified peer records to persisted peer store

This commit is contained in:
Vasco Santos
2020-06-29 12:10:58 +02:00
committed by Jacob Heun
parent 8f2e69048f
commit 74d414c21f
7 changed files with 299 additions and 123 deletions

View File

@ -82,9 +82,6 @@ class IdentifyService {
this._protocols = protocols
this.handleMessage = this.handleMessage.bind(this)
// TODO: this should be stored in the certified AddressBook in follow up PR
this._selfRecord = undefined
}
/**
@ -184,22 +181,18 @@ class IdentifyService {
// Get the observedAddr if there is one
observedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
let addresses
try {
const envelope = await Envelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN)
const peerRecord = await PeerRecord.createFromProtobuf(envelope.payload)
addresses = peerRecord.multiaddrs
if (this.peerStore.addressBook.consumePeerRecord(envelope)) {
return
}
} catch (err) {
log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
// Try Legacy
addresses = listenAddrs
}
// Update peers data in PeerStore
try {
this.peerStore.addressBook.set(id, addresses.map((addr) => multiaddr(addr)))
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => multiaddr(addr)))
} catch (err) {
log.error('received invalid addrs', err)
}
@ -294,21 +287,24 @@ class IdentifyService {
const id = connection.remotePeer
let addresses
try {
const envelope = await Envelope.openAndCertify(message.signedPeerRecord, PeerRecord.DOMAIN)
const peerRecord = await PeerRecord.createFromProtobuf(envelope.payload)
addresses = peerRecord.multiaddrs
if (this.peerStore.addressBook.consumePeerRecord(envelope)) {
return
}
} catch (err) {
<<<<<<< HEAD
log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
// Try Legacy
addresses = message.listenAddrs
=======
log('received invalid envelope, discard it and fallback to listenAddrs is available')
>>>>>>> chore: add certified peer records to persisted peer store
}
// Update peers data in PeerStore
try {
this.peerStore.addressBook.set(id, addresses.map((addr) => multiaddr(addr)))
this.peerStore.addressBook.set(id, message.listenAddrs.map((addr) => multiaddr(addr)))
} catch (err) {
log.error('received invalid addrs', err)
}
@ -321,10 +317,12 @@ class IdentifyService {
* Get self signed peer record raw envelope.
* @return {Buffer}
*/
async _getSelfPeerRecord () {
async _getSelfPeerRecord() {
const selfSignedPeerRecord = this.peerStore.addressBook.getRawEnvelope(this.peerId)
// TODO: support invalidation when dynamic multiaddrs are supported
if (this._selfRecord) {
return this._selfRecord
if (selfSignedPeerRecord) {
return selfSignedPeerRecord
}
try {
@ -333,10 +331,9 @@ class IdentifyService {
multiaddrs: this._libp2p.multiaddrs
})
const envelope = await Envelope.seal(peerRecord, this.peerId)
this.peerStore.addressBook.consumePeerRecord(envelope)
this._selfRecord = envelope.marshal()
return this._selfRecord
return this.peerStore.addressBook.getRawEnvelope(this.peerId)
} catch (err) {
log.error('failed to get self peer record')
}

View File

@ -72,8 +72,8 @@ class AddressBook extends Book {
}
/**
* 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
* ConsumePeerRecord adds addresses from a signed peer record contained in a record envelope.
* This will return a boolean that indicates if the record was successfully processed and added
* into the AddressBook.
* @param {Envelope} envelope
* @return {boolean}
@ -93,31 +93,25 @@ class AddressBook extends Book {
return false
}
// ensure the record has multiaddrs
if (!peerRecord.multiaddrs || !peerRecord.multiaddrs.length) {
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) {
if (storedRecord && storedRecord.seqNumber >= peerRecord.seqNumber) {
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
// Replace unsigned addresses by the new ones from the record
// TODO: Once we have ttls for the addresses, we should merge these in.
this._setData(peerId, {
addresses,
record: {
@ -130,19 +124,34 @@ class AddressBook extends Book {
return true
}
/**
* Get a peer raw envelope.
* @param {PeerId} peerId
* @return {Buffer}
*/
getRawEnvelope (peerId) {
const entry = this.data.get(peerId.toB58String())
if (!entry || !entry.record || !entry.record.raw) {
return undefined
}
return entry.record.raw
}
/**
* 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())
const raw = this.getRawEnvelope(peerId)
if (!entry || !entry.record || !entry.record.raw) {
return
if (!raw) {
return undefined
}
return Envelope.createFromProtobuf(entry.record.raw)
return Envelope.createFromProtobuf(raw)
}
/**
@ -170,7 +179,7 @@ class AddressBook extends Book {
// Already knows the peer
if (rec && rec.length === addresses.length) {
const intersection = rec.filter((mi) => addresses.some((newMi) => mi.multiaddr.equals(newMi.multiaddr)))
const intersection = rec.filter((addr) => addresses.some((newAddr) => addr.multiaddr.equals(newAddr.multiaddr)))
// Are new addresses equal to the old ones?
// If yes, no changes needed!
@ -214,9 +223,9 @@ class AddressBook extends Book {
const rec = entry.addresses
// Add recorded uniquely to the new array (Union)
rec && rec.forEach((mi) => {
if (!addresses.find(r => r.multiaddr.equals(mi.multiaddr))) {
addresses.push(mi)
rec && rec.forEach((addr) => {
if (!addresses.find(r => r.multiaddr.equals(addr.multiaddr))) {
addresses.push(addr)
}
})
@ -249,7 +258,6 @@ class AddressBook extends Book {
* @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)
}

View File

@ -177,21 +177,24 @@ class PersistentPeerStore extends PeerStore {
const b32key = peerId.toString()
const key = new Key(`${NAMESPACE_ADDRESS}${b32key}`)
const addresses = this.addressBook.get(peerId)
const entry = this.addressBook.data.get(peerId.toB58String())
try {
// Deleted from the book
if (!addresses) {
if (!entry) {
batch.delete(key)
return
}
const encodedData = Addresses.encode({
addrs: addresses.map((address) => ({
addrs: entry.addresses.map((address) => ({
multiaddr: address.multiaddr.buffer
}))
})),
certified_record: entry.record ? {
seq: entry.record.seqNumber,
raw: entry.record.raw
} : undefined
})
batch.put(key, encodedData)
} catch (err) {
log.error(err)
@ -299,7 +302,11 @@ class PersistentPeerStore extends PeerStore {
{
addresses: decoded.addrs.map((address) => ({
multiaddr: multiaddr(address.multiaddr)
}))
})),
record: decoded.certified_record ? {
raw: decoded.certified_record.raw,
seqNumber: decoded.certified_record.seq
} : undefined
},
{ emit: false })
break