Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: add certified peer records to persisted peer store
  • Loading branch information
vasco-santos committed Jul 15, 2020
commit e4645eab3f3aaa94a090675e7360a0ffa4d2a085
43 changes: 20 additions & 23 deletions src/identify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

/**
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -293,21 +286,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)
}
Expand All @@ -320,10 +316,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 {
Expand All @@ -332,10 +330,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')
}
Expand Down
58 changes: 33 additions & 25 deletions src/peer-store/address-book.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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: {
Expand All @@ -130,19 +124,34 @@ class AddressBook extends Book {
return true
}

/**
* Get a peer raw envelope.
* @param {PeerId} peerId
* @return {Buffer}
*/
getRawEnvelope (peerId) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a convenience method for getRawSelfEnvelope?
We are using this providing own peerId in the identify protocol, and I am also using it now in rendezvous

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the need here? We should already have easy access to libp2p, libp2p.peerStore.addressBook.getRawEnvelope(libp2p.peerId), I'm not seeing what we'd gain from this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not needed, but could potentially help. I did not have access to the self peerId in the rendezvous server (in the previous PR state), and I needed to change everything to provide libp2p because of that. But yeah, it was mostly a question, we don't need it, it could just help in some cases

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)
}

/**
Expand Down Expand Up @@ -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!
Expand Down Expand Up @@ -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)
}
})

Expand Down Expand Up @@ -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)
}
Expand Down
19 changes: 13 additions & 6 deletions src/peer-store/persistent/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions test/dialing/direct.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ describe('Dialing (direct, WebSockets)', () => {
const connection = await libp2p.dial(remoteAddr)
expect(connection).to.exist()

sinon.spy(libp2p.peerStore.addressBook, 'set')
sinon.spy(libp2p.peerStore.addressBook, 'consumePeerRecord')
sinon.spy(libp2p.peerStore.protoBook, 'set')

// Wait for onConnection to be called
Expand All @@ -372,7 +372,8 @@ describe('Dialing (direct, WebSockets)', () => {
expect(libp2p.identifyService.identify.callCount).to.equal(1)
await libp2p.identifyService.identify.firstCall.returnValue

expect(libp2p.peerStore.addressBook.set.callCount).to.equal(1)
// Self + New peer
expect(libp2p.peerStore.addressBook.consumePeerRecord.callCount).to.equal(2)
expect(libp2p.peerStore.protoBook.set.callCount).to.equal(1)
})

Expand Down
Loading