Skip to content

Commit

Permalink
chore: integrate new peer-store with code using adapters for other mo…
Browse files Browse the repository at this point in the history
…dules
  • Loading branch information
vasco-santos committed Mar 31, 2020
1 parent 72dea96 commit 63583ab
Show file tree
Hide file tree
Showing 20 changed files with 477 additions and 514 deletions.
36 changes: 23 additions & 13 deletions src/dialer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const errCode = require('err-code')
const TimeoutController = require('timeout-abort-controller')
const anySignal = require('any-signal')
const PeerId = require('peer-id')
const PeerInfo = require('peer-info')
const debug = require('debug')
const log = debug('libp2p:dialer')
log.error = debug('libp2p:dialer:error')
Expand Down Expand Up @@ -62,13 +61,13 @@ class Dialer {
* The dial to the first address that is successfully able to upgrade a connection
* will be used.
*
* @param {PeerInfo|Multiaddr} peer The peer to dial
* @param {PeerId|Multiaddr} peerId The peer to dial
* @param {object} [options]
* @param {AbortSignal} [options.signal] An AbortController signal
* @returns {Promise<Connection>}
*/
async connectToPeer (peer, options = {}) {
const dialTarget = this._createDialTarget(peer)
async connectToPeer (peerId, options = {}) {
const dialTarget = this._createDialTarget(peerId)
if (dialTarget.addrs.length === 0) {
throw errCode(new Error('The dial request has no addresses'), codes.ERR_NO_VALID_ADDRESSES)
}
Expand Down Expand Up @@ -100,7 +99,7 @@ class Dialer {
* Creates a DialTarget. The DialTarget is used to create and track
* the DialRequest to a given peer.
* @private
* @param {PeerInfo|Multiaddr} peer A PeerId or Multiaddr
* @param {PeerId|Multiaddr} peer A PeerId or Multiaddr
* @returns {DialTarget}
*/
_createDialTarget (peer) {
Expand All @@ -111,7 +110,10 @@ class Dialer {
addrs: [dialable]
}
}
const addrs = this.peerStore.multiaddrsForPeer(dialable)

dialable.multiaddrs && this.peerStore.addressBook.set(dialable.id, Array.from(dialable.multiaddrs), { replace: false })
const addrs = this.peerStore.addressBook.getMultiaddrsForPeer(dialable.id)

return {
id: dialable.id.toB58String(),
addrs
Expand Down Expand Up @@ -179,21 +181,27 @@ class Dialer {
this.tokens.push(token)
}

/**
* PeerInfo object
* @typedef {Object} peerInfo
* @property {Multiaddr} multiaddr peer multiaddr.
* @property {PeerId} id peer id.
*/

/**
* Converts the given `peer` into a `PeerInfo` or `Multiaddr`.
* @static
* @param {PeerInfo|PeerId|Multiaddr|string} peer
* @returns {PeerInfo|Multiaddr}
* @param {PeerId|Multiaddr|string} peer
* @returns {peerInfo|Multiaddr}
*/
static getDialable (peer) {
if (PeerInfo.isPeerInfo(peer)) return peer
if (typeof peer === 'string') {
peer = multiaddr(peer)
}

let addr
let addrs
if (multiaddr.isMultiaddr(peer)) {
addr = peer
addrs = new Set([peer]) // TODO: after peer-info removal, a Set should not be needed
try {
peer = PeerId.createFromCID(peer.getPeerId())
} catch (err) {
Expand All @@ -202,10 +210,12 @@ class Dialer {
}

if (PeerId.isPeerId(peer)) {
peer = new PeerInfo(peer)
peer = {
id: peer,
multiaddrs: addrs
}
}

addr && peer.multiaddrs.add(addr)
return peer
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/get-peer-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function getPeerInfo (peer, peerStore) {

addr && peer.multiaddrs.add(addr)

return peerStore ? peerStore.put(peer) : peer
return peerStore ? peerStore.put(peer, { replace: false }) : peer
}

/**
Expand Down
55 changes: 8 additions & 47 deletions src/identify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const lp = require('it-length-prefixed')
const pipe = require('it-pipe')
const { collect, take, consume } = require('streaming-iterables')

const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const multiaddr = require('multiaddr')
const { toBuffer } = require('it-buffer')
Expand All @@ -27,39 +26,6 @@ const errCode = require('err-code')
const { codes } = require('../errors')

class IdentifyService {
/**
* Replaces the multiaddrs on the given `peerInfo`,
* with the provided `multiaddrs`
* @param {PeerInfo} peerInfo
* @param {Array<Multiaddr>|Array<Buffer>} multiaddrs
*/
static updatePeerAddresses (peerInfo, multiaddrs) {
if (multiaddrs && multiaddrs.length > 0) {
peerInfo.multiaddrs.clear()
multiaddrs.forEach(ma => {
try {
peerInfo.multiaddrs.add(ma)
} catch (err) {
log.error('could not add multiaddr', err)
}
})
}
}

/**
* Replaces the protocols on the given `peerInfo`,
* with the provided `protocols`
* @static
* @param {PeerInfo} peerInfo
* @param {Array<string>} protocols
*/
static updatePeerProtocols (peerInfo, protocols) {
if (protocols && protocols.length > 0) {
peerInfo.protocols.clear()
protocols.forEach(proto => peerInfo.protocols.add(proto))
}
}

/**
* Takes the `addr` and converts it to a Multiaddr if possible
* @param {Buffer|String} addr
Expand Down Expand Up @@ -181,19 +147,18 @@ class IdentifyService {
} = message

const id = await PeerId.createFromPubKey(publicKey)
const peerInfo = new PeerInfo(id)

if (connection.remotePeer.toB58String() !== id.toB58String()) {
throw errCode(new Error('identified peer does not match the expected peer'), codes.ERR_INVALID_PEER)
}

// Get the observedAddr if there is one
observedAddr = IdentifyService.getCleanMultiaddr(observedAddr)

// Copy the listenAddrs and protocols
IdentifyService.updatePeerAddresses(peerInfo, listenAddrs)
IdentifyService.updatePeerProtocols(peerInfo, protocols)
// Update peers data in PeerStore
this.registrar.peerStore.addressBook.set(id, listenAddrs.map((addr) => multiaddr(addr)))
this.registrar.peerStore.protoBook.set(id, protocols)

this.registrar.peerStore.replace(peerInfo)
// TODO: Track our observed address so that we can score it
log('received observed address of %s', observedAddr)
}
Expand Down Expand Up @@ -273,20 +238,16 @@ class IdentifyService {
return log.error('received invalid message', err)
}

// Update the listen addresses
const peerInfo = new PeerInfo(connection.remotePeer)

// Update peers data in PeerStore
const id = connection.remotePeer
try {
IdentifyService.updatePeerAddresses(peerInfo, message.listenAddrs)
this.registrar.peerStore.addressBook.set(id, message.listenAddrs.map((addr) => multiaddr(addr)))
} catch (err) {
return log.error('received invalid listen addrs', err)
}

// Update the protocols
IdentifyService.updatePeerProtocols(peerInfo, message.protocols)

// Update the peer in the PeerStore
this.registrar.peerStore.replace(peerInfo)
this.registrar.peerStore.protoBook.set(id, message.protocols)
}
}

Expand Down
13 changes: 10 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class Libp2p extends EventEmitter {
localPeer: this.peerInfo.id,
metrics: this.metrics,
onConnection: (connection) => {
const peerInfo = this.peerStore.put(new PeerInfo(connection.remotePeer), { silent: true })
const peerInfo = new PeerInfo(connection.remotePeer)
this.registrar.onConnect(peerInfo, connection)
this.connectionManager.onConnect(connection)
this.emit('peer:connect', peerInfo)
Expand Down Expand Up @@ -289,7 +289,11 @@ class Libp2p extends EventEmitter {
const dialable = Dialer.getDialable(peer)
let connection
if (PeerInfo.isPeerInfo(dialable)) {
this.peerStore.put(dialable, { silent: true })
// TODO Inconsistency from: getDialable adds a set, while regular peerInfo uses a Multiaddr set
// This should be handled on `peer-info` removal
const multiaddrs = dialable.multiaddrs.toArray ? dialable.multiaddrs.toArray() : Array.from(dialable.multiaddrs)
this.peerStore.addressBook.set(dialable.id, multiaddrs, { replace: false })

connection = this.registrar.getConnection(dialable)
}

Expand Down Expand Up @@ -430,7 +434,10 @@ class Libp2p extends EventEmitter {
log.error(new Error(codes.ERR_DISCOVERED_SELF))
return
}
this.peerStore.put(peerInfo)

// TODO: once we deprecate peer-info, we should only set if we have data
this.peerStore.addressBook.set(peerInfo.id, peerInfo.multiaddrs.toArray(), { replace: false })
this.peerStore.protoBook.set(peerInfo.id, Array.from(peerInfo.protocols), { replace: false })
}

/**
Expand Down
58 changes: 45 additions & 13 deletions src/peer-store/address-book.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ log.error = debug('libp2p:peer-store:address-book:error')

const multiaddr = require('multiaddr')
const PeerId = require('peer-id')
const PeerInfo = require('peer-info')

const Book = require('./book')

Expand Down Expand Up @@ -52,15 +53,17 @@ class AddressBook extends Book {
* @param {PeerId} peerId
* @param {Array<Multiaddr>|Multiaddr} addresses
* @param {Object} [options]
* @param {boolean} [options.replace = true] wether addresses received replace stored ones or a unique union is performed.
* @param {boolean} [options.replace = true] whether addresses received replace stored ones or a unique union is performed.
* @returns {Array<multiaddrInfo>}
*/
set (peerId, addresses, { replace = true } = {}) {
if (!PeerId.isPeerId(peerId)) {
log.error('peerId must be an instance of peer-id to store data')
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
}

if (!addresses) {
log.error('addresses must be provided to store data')
throw errcode(new Error('addresses must be provided'), ERR_INVALID_PARAMETERS)
}

Expand All @@ -72,6 +75,7 @@ class AddressBook extends Book {
const multiaddrInfos = []
addresses.forEach((addr) => {
if (!multiaddr.isMultiaddr(addr)) {
log.error(`multiaddr ${addr} must be an instance of multiaddr`)
throw errcode(new Error(`multiaddr ${addr} must be an instance of multiaddr`), ERR_INVALID_PARAMETERS)
}

Expand All @@ -88,7 +92,7 @@ class AddressBook extends Book {
}

/**
* Replace known addresses to a provided peer.
* Replace known addresses of a provided peer.
* If the peer is not known, it is set with the given addresses.
* @param {PeerId} peerId
* @param {Array<multiaddrInfo>} multiaddrInfos
Expand All @@ -98,22 +102,39 @@ class AddressBook extends Book {
const id = peerId.toString()
const rec = this.data.get(id)

// Already know the peer
// Not replace multiaddrs
if (!multiaddrInfos.length) {
return rec ? [...rec] : []
}

// Already knows the peer
if (rec && rec.length === multiaddrInfos.length) {
const intersection = rec.filter((mi) => multiaddrInfos.some((newMi) => mi.multiaddr === newMi.multiaddr))

// New addresses equal the old ones?
// Are new addresses equal to the old ones?
// If yes, no changes needed!
if (intersection.length === rec.length) {
log(`the addresses provided to store are equal to the already stored for ${id}`)
return [...multiaddrInfos]
}
}

this.data.set(id, multiaddrInfos)
log(`stored provided multiaddrs for ${id}`)

// TODO: Remove peerInfo and its usage on peer-info deprecate
const peerInfo = new PeerInfo(peerId)
multiaddrInfos.forEach((mi) => peerInfo.multiaddrs.add(mi.multiaddr))

// Notify the existance of a new peer
if (!rec) {
// this._ps.emit('peer', peerId)
this._ps.emit('peer', peerInfo)
}

this._ps.emit('peer', peerId)
this._ps.emit('change:multiaddrs', {
peerId,
peerInfo,
multiaddrs: multiaddrInfos.map((mi) => mi.multiaddr)
})

Expand All @@ -129,31 +150,40 @@ class AddressBook extends Book {
*/
_add (peerId, multiaddrInfos) {
const id = peerId.toString()
const rec = this.data.get(id) || []
const rec = this.data.get(id)

// Add recorded uniquely to the new array
rec.forEach((mi) => {
// Add recorded uniquely to the new array (Union)
rec && rec.forEach((mi) => {
if (!multiaddrInfos.find(r => r.multiaddr === mi.multiaddr)) {
multiaddrInfos.push(mi)
}
})

// If the recorded length is equal to the new after the uniquely union
// If the recorded length is equal to the new after the unique union
// The content is the same, no need to update.
if (rec.length === multiaddrInfos.length) {
if (rec && rec.length === multiaddrInfos.length) {
log(`the addresses provided to store are already stored for ${id}`)
return [...multiaddrInfos]
}

this.data.set(id, multiaddrInfos)

log(`added provided multiaddrs for ${id}`)

// TODO: Remove peerInfo and its usage on peer-info deprecate
const peerInfo = new PeerInfo(peerId)
multiaddrInfos.forEach((mi) => peerInfo.multiaddrs.add(mi.multiaddr))

this._ps.emit('change:multiaddrs', {
peerId,
peerInfo,
multiaddrs: multiaddrInfos.map((mi) => mi.multiaddr)
})

// Notify the existance of a new peer
// TODO: do we need this?
if (!rec) {
this._ps.emit('peer', peerId)
// this._ps.emit('peer', peerId)
this._ps.emit('peer', peerInfo)
}

return [...multiaddrInfos]
Expand All @@ -179,7 +209,9 @@ class AddressBook extends Book {
return record.map((multiaddrInfo) => {
const addr = multiaddrInfo.multiaddr

if (addr.getPeerId()) return addr
const idString = addr.getPeerId()
if (idString && idString === peerId.toB58String()) return addr

return addr.encapsulate(`/p2p/${peerId.toB58String()}`)
})
}
Expand Down
Loading

0 comments on commit 63583ab

Please sign in to comment.