2019-11-07 12:11:50 +01:00
|
|
|
'use strict'
|
|
|
|
/* eslint-env mocha */
|
|
|
|
|
2020-10-15 15:31:33 +01:00
|
|
|
const { expect } = require('aegir/utils/chai')
|
2019-11-07 12:11:50 +01:00
|
|
|
const sinon = require('sinon')
|
|
|
|
|
2020-04-18 17:06:56 +02:00
|
|
|
const { EventEmitter } = require('events')
|
2019-11-07 12:11:50 +01:00
|
|
|
const PeerId = require('peer-id')
|
|
|
|
const duplexPair = require('it-pair/duplex')
|
|
|
|
const multiaddr = require('multiaddr')
|
2020-02-05 17:35:27 +01:00
|
|
|
const pWaitFor = require('p-wait-for')
|
2020-08-24 11:58:02 +01:00
|
|
|
const unit8ArrayToString = require('uint8arrays/to-string')
|
2019-11-07 12:11:50 +01:00
|
|
|
|
|
|
|
const { codes: Errors } = require('../../src/errors')
|
2020-12-10 14:48:14 +01:00
|
|
|
const IdentifyService = require('../../src/identify')
|
|
|
|
const multicodecs = IdentifyService.multicodecs
|
2019-11-07 12:11:50 +01:00
|
|
|
const Peers = require('../fixtures/peers')
|
|
|
|
const Libp2p = require('../../src')
|
2020-07-15 15:47:45 +02:00
|
|
|
const Envelope = require('../../src/record/envelope')
|
2020-06-29 12:10:58 +02:00
|
|
|
const PeerStore = require('../../src/peer-store')
|
2019-11-07 12:11:50 +01:00
|
|
|
const baseOptions = require('../utils/base-options.browser')
|
2020-09-24 12:49:48 +02:00
|
|
|
const { updateSelfPeerRecord } = require('../../src/record/utils')
|
2020-08-04 18:39:05 +02:00
|
|
|
const pkg = require('../../package.json')
|
2021-01-27 13:55:26 +00:00
|
|
|
const AddressManager = require('../../src/address-manager')
|
2019-11-07 12:11:50 +01:00
|
|
|
|
|
|
|
const { MULTIADDRS_WEBSOCKETS } = require('../fixtures/browser')
|
|
|
|
const remoteAddr = MULTIADDRS_WEBSOCKETS[0]
|
2020-06-20 19:32:39 +02:00
|
|
|
const listenMaddrs = [multiaddr('/ip4/127.0.0.1/tcp/15002/ws')]
|
|
|
|
|
2019-11-07 12:11:50 +01:00
|
|
|
describe('Identify', () => {
|
2021-01-27 13:55:26 +00:00
|
|
|
let localPeer, localPeerStore, localAddressManager
|
|
|
|
let remotePeer, remotePeerStore, remoteAddressManager
|
2020-10-27 13:50:14 +00:00
|
|
|
const protocols = [multicodecs.IDENTIFY, multicodecs.IDENTIFY_PUSH]
|
2019-11-07 12:11:50 +01:00
|
|
|
|
|
|
|
before(async () => {
|
|
|
|
[localPeer, remotePeer] = (await Promise.all([
|
|
|
|
PeerId.createFromJSON(Peers[0]),
|
|
|
|
PeerId.createFromJSON(Peers[1])
|
2020-04-14 14:05:30 +02:00
|
|
|
]))
|
2020-10-27 13:50:14 +00:00
|
|
|
|
|
|
|
localPeerStore = new PeerStore({ peerId: localPeer })
|
|
|
|
localPeerStore.protoBook.set(localPeer, protocols)
|
|
|
|
|
|
|
|
remotePeerStore = new PeerStore({ peerId: remotePeer })
|
|
|
|
remotePeerStore.protoBook.set(remotePeer, protocols)
|
2021-01-27 13:55:26 +00:00
|
|
|
|
|
|
|
localAddressManager = new AddressManager(localPeer)
|
|
|
|
remoteAddressManager = new AddressManager(remotePeer)
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
sinon.restore()
|
|
|
|
})
|
|
|
|
|
2020-07-15 15:47:45 +02:00
|
|
|
it('should be able to identify another peer', async () => {
|
2020-06-20 19:32:39 +02:00
|
|
|
const localIdentify = new IdentifyService({
|
|
|
|
libp2p: {
|
|
|
|
peerId: localPeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: localPeerStore,
|
2020-11-20 15:14:01 +01:00
|
|
|
multiaddrs: listenMaddrs,
|
2020-12-10 14:48:14 +01:00
|
|
|
isStarted: () => true,
|
|
|
|
_options: { host: {} }
|
2020-10-27 13:50:14 +00:00
|
|
|
}
|
2020-06-20 19:32:39 +02:00
|
|
|
})
|
|
|
|
const remoteIdentify = new IdentifyService({
|
|
|
|
libp2p: {
|
|
|
|
peerId: remotePeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: remotePeerStore,
|
2020-11-20 15:14:01 +01:00
|
|
|
multiaddrs: listenMaddrs,
|
2020-12-10 14:48:14 +01:00
|
|
|
isStarted: () => true,
|
|
|
|
_options: { host: {} }
|
2020-10-27 13:50:14 +00:00
|
|
|
}
|
2020-06-20 19:32:39 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
const observedAddr = multiaddr('/ip4/127.0.0.1/tcp/1234')
|
2020-07-15 15:47:45 +02:00
|
|
|
const localConnectionMock = { newStream: () => {}, remotePeer }
|
2020-06-20 19:32:39 +02:00
|
|
|
const remoteConnectionMock = { remoteAddr: observedAddr }
|
|
|
|
|
|
|
|
const [local, remote] = duplexPair()
|
2020-07-15 15:47:45 +02:00
|
|
|
sinon.stub(localConnectionMock, 'newStream').returns({ stream: local, protocol: multicodecs.IDENTIFY })
|
2020-06-20 19:32:39 +02:00
|
|
|
|
2020-07-15 14:34:51 +02:00
|
|
|
sinon.spy(localIdentify.peerStore.addressBook, 'consumePeerRecord')
|
2020-06-20 19:32:39 +02:00
|
|
|
sinon.spy(localIdentify.peerStore.protoBook, 'set')
|
|
|
|
|
2020-09-23 18:45:01 +02:00
|
|
|
// Transport Manager creates signed peer record
|
2020-09-24 12:49:48 +02:00
|
|
|
await updateSelfPeerRecord(remoteIdentify._libp2p)
|
2020-09-23 18:45:01 +02:00
|
|
|
|
2020-06-20 19:32:39 +02:00
|
|
|
// Run identify
|
|
|
|
await Promise.all([
|
|
|
|
localIdentify.identify(localConnectionMock),
|
|
|
|
remoteIdentify.handleMessage({
|
|
|
|
connection: remoteConnectionMock,
|
|
|
|
stream: remote,
|
2020-07-15 15:47:45 +02:00
|
|
|
protocol: multicodecs.IDENTIFY
|
2020-06-20 19:32:39 +02:00
|
|
|
})
|
|
|
|
])
|
|
|
|
|
2020-07-15 14:34:51 +02:00
|
|
|
expect(localIdentify.peerStore.addressBook.consumePeerRecord.callCount).to.equal(1)
|
2020-06-20 19:32:39 +02:00
|
|
|
expect(localIdentify.peerStore.protoBook.set.callCount).to.equal(1)
|
|
|
|
|
|
|
|
// Validate the remote peer gets updated in the peer store
|
2020-07-15 14:34:51 +02:00
|
|
|
const addresses = localIdentify.peerStore.addressBook.get(remotePeer)
|
|
|
|
expect(addresses).to.exist()
|
|
|
|
expect(addresses).have.lengthOf(listenMaddrs.length)
|
|
|
|
expect(addresses.map((a) => a.multiaddr)[0].equals(listenMaddrs[0]))
|
|
|
|
expect(addresses.map((a) => a.isCertified)[0]).to.eql(true)
|
2020-06-20 19:32:39 +02:00
|
|
|
})
|
|
|
|
|
2020-07-15 15:47:45 +02:00
|
|
|
// LEGACY
|
|
|
|
it('should be able to identify another peer with no certified peer records support', async () => {
|
2019-11-07 12:11:50 +01:00
|
|
|
const localIdentify = new IdentifyService({
|
2020-04-18 23:26:46 +02:00
|
|
|
libp2p: {
|
|
|
|
peerId: localPeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
2021-01-27 13:55:26 +00:00
|
|
|
addressManager: localAddressManager,
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: localPeerStore,
|
2020-11-20 15:14:01 +01:00
|
|
|
multiaddrs: listenMaddrs,
|
2020-12-10 14:48:14 +01:00
|
|
|
isStarted: () => true,
|
|
|
|
_options: { host: {} }
|
2020-10-27 13:50:14 +00:00
|
|
|
}
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
2020-06-20 19:32:39 +02:00
|
|
|
|
2019-11-07 12:11:50 +01:00
|
|
|
const remoteIdentify = new IdentifyService({
|
2020-04-18 23:26:46 +02:00
|
|
|
libp2p: {
|
|
|
|
peerId: remotePeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
2021-01-27 13:55:26 +00:00
|
|
|
addressManager: remoteAddressManager,
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: remotePeerStore,
|
2020-11-20 15:14:01 +01:00
|
|
|
multiaddrs: listenMaddrs,
|
2020-12-10 14:48:14 +01:00
|
|
|
isStarted: () => true,
|
|
|
|
_options: { host: {} }
|
2020-10-27 13:50:14 +00:00
|
|
|
}
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
const observedAddr = multiaddr('/ip4/127.0.0.1/tcp/1234')
|
2020-04-14 14:05:30 +02:00
|
|
|
const localConnectionMock = { newStream: () => {}, remotePeer }
|
2019-11-07 12:11:50 +01:00
|
|
|
const remoteConnectionMock = { remoteAddr: observedAddr }
|
|
|
|
|
|
|
|
const [local, remote] = duplexPair()
|
|
|
|
sinon.stub(localConnectionMock, 'newStream').returns({ stream: local, protocol: multicodecs.IDENTIFY })
|
2020-07-15 15:47:45 +02:00
|
|
|
sinon.stub(Envelope, 'openAndCertify').throws()
|
2019-11-07 12:11:50 +01:00
|
|
|
|
2020-07-15 14:34:51 +02:00
|
|
|
sinon.spy(localIdentify.peerStore.addressBook, 'set')
|
2020-04-18 17:06:56 +02:00
|
|
|
sinon.spy(localIdentify.peerStore.protoBook, 'set')
|
2020-08-04 18:39:05 +02:00
|
|
|
sinon.spy(localIdentify.peerStore.metadataBook, 'set')
|
2019-11-07 12:11:50 +01:00
|
|
|
|
|
|
|
// Run identify
|
|
|
|
await Promise.all([
|
2019-12-03 20:14:15 +01:00
|
|
|
localIdentify.identify(localConnectionMock),
|
2019-11-07 12:11:50 +01:00
|
|
|
remoteIdentify.handleMessage({
|
|
|
|
connection: remoteConnectionMock,
|
|
|
|
stream: remote,
|
|
|
|
protocol: multicodecs.IDENTIFY
|
|
|
|
})
|
|
|
|
])
|
|
|
|
|
2020-07-15 14:34:51 +02:00
|
|
|
expect(localIdentify.peerStore.addressBook.set.callCount).to.equal(1)
|
2020-04-18 17:06:56 +02:00
|
|
|
expect(localIdentify.peerStore.protoBook.set.callCount).to.equal(1)
|
2020-08-04 18:39:05 +02:00
|
|
|
|
|
|
|
const metadataArgs = localIdentify.peerStore.metadataBook.set.firstCall.args
|
|
|
|
expect(metadataArgs[0].id.bytes).to.equal(remotePeer.bytes)
|
|
|
|
expect(metadataArgs[1]).to.equal('AgentVersion')
|
2020-08-24 11:58:02 +01:00
|
|
|
expect(unit8ArrayToString(metadataArgs[2])).to.equal(`js-libp2p/${pkg.version}`)
|
2020-08-04 18:39:05 +02:00
|
|
|
|
2019-11-07 12:11:50 +01:00
|
|
|
// Validate the remote peer gets updated in the peer store
|
2020-07-15 14:34:51 +02:00
|
|
|
const call = localIdentify.peerStore.addressBook.set.firstCall
|
|
|
|
expect(call.args[0].id.bytes).to.equal(remotePeer.bytes)
|
|
|
|
expect(call.args[1]).to.exist()
|
|
|
|
expect(call.args[1]).have.lengthOf(listenMaddrs.length)
|
|
|
|
expect(call.args[1][0].equals(listenMaddrs[0]))
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should throw if identified peer is the wrong peer', async () => {
|
|
|
|
const localIdentify = new IdentifyService({
|
2020-04-18 23:26:46 +02:00
|
|
|
libp2p: {
|
|
|
|
peerId: localPeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: localPeerStore,
|
2020-12-10 14:48:14 +01:00
|
|
|
multiaddrs: [],
|
|
|
|
_options: { host: {} }
|
2020-10-27 13:50:14 +00:00
|
|
|
}
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
const remoteIdentify = new IdentifyService({
|
2020-04-18 23:26:46 +02:00
|
|
|
libp2p: {
|
|
|
|
peerId: remotePeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: remotePeerStore,
|
2020-12-10 14:48:14 +01:00
|
|
|
multiaddrs: [],
|
|
|
|
_options: { host: {} }
|
2020-10-27 13:50:14 +00:00
|
|
|
}
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
const observedAddr = multiaddr('/ip4/127.0.0.1/tcp/1234')
|
2020-04-14 14:05:30 +02:00
|
|
|
const localConnectionMock = { newStream: () => {}, remotePeer: localPeer }
|
2019-11-07 12:11:50 +01:00
|
|
|
const remoteConnectionMock = { remoteAddr: observedAddr }
|
|
|
|
|
|
|
|
const [local, remote] = duplexPair()
|
|
|
|
sinon.stub(localConnectionMock, 'newStream').returns({ stream: local, protocol: multicodecs.IDENTIFY })
|
|
|
|
|
|
|
|
// Run identify
|
2019-11-29 16:41:08 +01:00
|
|
|
const identifyPromise = Promise.all([
|
2020-04-14 14:05:30 +02:00
|
|
|
localIdentify.identify(localConnectionMock, localPeer),
|
2019-11-29 16:41:08 +01:00
|
|
|
remoteIdentify.handleMessage({
|
|
|
|
connection: remoteConnectionMock,
|
|
|
|
stream: remote,
|
|
|
|
protocol: multicodecs.IDENTIFY
|
|
|
|
})
|
|
|
|
])
|
|
|
|
|
|
|
|
await expect(identifyPromise)
|
|
|
|
.to.eventually.be.rejected()
|
|
|
|
.and.to.have.property('code', Errors.ERR_INVALID_PEER)
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
|
2020-11-20 15:14:01 +01:00
|
|
|
it('should store host data and protocol version into metadataBook', () => {
|
|
|
|
const agentVersion = 'js-project/1.0.0'
|
|
|
|
const peerStore = new PeerStore({ peerId: localPeer })
|
|
|
|
|
|
|
|
sinon.spy(peerStore.metadataBook, 'set')
|
|
|
|
|
|
|
|
new IdentifyService({ // eslint-disable-line no-new
|
|
|
|
libp2p: {
|
|
|
|
peerId: localPeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
|
|
|
peerStore,
|
|
|
|
multiaddrs: listenMaddrs,
|
|
|
|
_options: {
|
|
|
|
host: {
|
|
|
|
agentVersion
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
protocols
|
|
|
|
})
|
|
|
|
|
|
|
|
expect(peerStore.metadataBook.set.callCount).to.eql(2)
|
|
|
|
|
|
|
|
const storedAgentVersion = peerStore.metadataBook.getValue(localPeer, 'AgentVersion')
|
|
|
|
const storedProtocolVersion = peerStore.metadataBook.getValue(localPeer, 'ProtocolVersion')
|
|
|
|
|
|
|
|
expect(agentVersion).to.eql(unit8ArrayToString(storedAgentVersion))
|
|
|
|
expect(storedProtocolVersion).to.exist()
|
|
|
|
})
|
|
|
|
|
2019-11-07 12:11:50 +01:00
|
|
|
describe('push', () => {
|
2020-07-15 15:47:45 +02:00
|
|
|
it('should be able to push identify updates to another peer', async () => {
|
2020-10-27 13:50:14 +00:00
|
|
|
const storedProtocols = [multicodecs.IDENTIFY, multicodecs.IDENTIFY_PUSH, '/echo/1.0.0']
|
2020-04-18 17:06:56 +02:00
|
|
|
const connectionManager = new EventEmitter()
|
2020-07-15 15:47:45 +02:00
|
|
|
connectionManager.getConnection = () => { }
|
2020-04-18 17:06:56 +02:00
|
|
|
|
2020-10-27 13:50:14 +00:00
|
|
|
const localPeerStore = new PeerStore({ peerId: localPeer })
|
|
|
|
localPeerStore.protoBook.set(localPeer, storedProtocols)
|
|
|
|
|
2019-11-07 12:11:50 +01:00
|
|
|
const localIdentify = new IdentifyService({
|
2020-04-18 23:26:46 +02:00
|
|
|
libp2p: {
|
|
|
|
peerId: localPeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: localPeerStore,
|
2020-11-20 15:14:01 +01:00
|
|
|
multiaddrs: listenMaddrs,
|
2020-12-10 14:48:14 +01:00
|
|
|
isStarted: () => true,
|
|
|
|
_options: { host: {} }
|
2020-10-27 13:50:14 +00:00
|
|
|
}
|
2020-06-20 19:32:39 +02:00
|
|
|
})
|
2020-10-27 13:50:14 +00:00
|
|
|
|
|
|
|
const remotePeerStore = new PeerStore({ peerId: remotePeer })
|
|
|
|
remotePeerStore.protoBook.set(remotePeer, storedProtocols)
|
|
|
|
|
2020-06-20 19:32:39 +02:00
|
|
|
const remoteIdentify = new IdentifyService({
|
|
|
|
libp2p: {
|
|
|
|
peerId: remotePeer,
|
|
|
|
connectionManager,
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: remotePeerStore,
|
2020-11-20 15:14:01 +01:00
|
|
|
multiaddrs: [],
|
2020-12-10 14:48:14 +01:00
|
|
|
isStarted: () => true,
|
|
|
|
_options: { host: {} }
|
2020-06-20 19:32:39 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Setup peer protocols and multiaddrs
|
2020-10-27 13:50:14 +00:00
|
|
|
const localProtocols = new Set(storedProtocols)
|
2020-07-15 15:47:45 +02:00
|
|
|
const localConnectionMock = { newStream: () => { } }
|
2020-06-20 19:32:39 +02:00
|
|
|
const remoteConnectionMock = { remotePeer: localPeer }
|
|
|
|
|
|
|
|
const [local, remote] = duplexPair()
|
2020-07-15 15:47:45 +02:00
|
|
|
sinon.stub(localConnectionMock, 'newStream').returns({ stream: local, protocol: multicodecs.IDENTIFY_PUSH })
|
2020-06-20 19:32:39 +02:00
|
|
|
|
2020-06-29 12:10:58 +02:00
|
|
|
sinon.spy(remoteIdentify.peerStore.addressBook, 'consumePeerRecord')
|
2020-06-20 19:32:39 +02:00
|
|
|
sinon.spy(remoteIdentify.peerStore.protoBook, 'set')
|
|
|
|
|
2020-09-23 18:45:01 +02:00
|
|
|
// Transport Manager creates signed peer record
|
2020-09-24 12:49:48 +02:00
|
|
|
await updateSelfPeerRecord(localIdentify._libp2p)
|
|
|
|
await updateSelfPeerRecord(remoteIdentify._libp2p)
|
2020-09-23 18:45:01 +02:00
|
|
|
|
2020-06-20 19:32:39 +02:00
|
|
|
// Run identify
|
|
|
|
await Promise.all([
|
|
|
|
localIdentify.push([localConnectionMock]),
|
|
|
|
remoteIdentify.handleMessage({
|
|
|
|
connection: remoteConnectionMock,
|
|
|
|
stream: remote,
|
2020-07-15 15:47:45 +02:00
|
|
|
protocol: multicodecs.IDENTIFY_PUSH
|
2020-06-20 19:32:39 +02:00
|
|
|
})
|
|
|
|
])
|
|
|
|
|
2020-09-23 18:45:01 +02:00
|
|
|
expect(remoteIdentify.peerStore.addressBook.consumePeerRecord.callCount).to.equal(2)
|
2020-06-20 19:32:39 +02:00
|
|
|
expect(remoteIdentify.peerStore.protoBook.set.callCount).to.equal(1)
|
2020-06-29 12:10:58 +02:00
|
|
|
|
|
|
|
const addresses = localIdentify.peerStore.addressBook.get(localPeer)
|
|
|
|
expect(addresses).to.exist()
|
|
|
|
expect(addresses).have.lengthOf(listenMaddrs.length)
|
|
|
|
expect(addresses.map((a) => a.multiaddr)).to.eql(listenMaddrs)
|
|
|
|
|
2020-06-20 19:32:39 +02:00
|
|
|
const [peerId2, protocols] = remoteIdentify.peerStore.protoBook.set.firstCall.args
|
|
|
|
expect(peerId2.bytes).to.eql(localPeer.bytes)
|
|
|
|
expect(protocols).to.eql(Array.from(localProtocols))
|
|
|
|
})
|
|
|
|
|
2020-07-15 15:47:45 +02:00
|
|
|
// LEGACY
|
|
|
|
it('should be able to push identify updates to another peer with no certified peer records support', async () => {
|
2020-10-27 13:50:14 +00:00
|
|
|
const storedProtocols = [multicodecs.IDENTIFY, multicodecs.IDENTIFY_PUSH, '/echo/1.0.0']
|
2020-06-20 19:32:39 +02:00
|
|
|
const connectionManager = new EventEmitter()
|
|
|
|
connectionManager.getConnection = () => { }
|
|
|
|
|
2020-10-27 13:50:14 +00:00
|
|
|
const localPeerStore = new PeerStore({ peerId: localPeer })
|
|
|
|
localPeerStore.protoBook.set(localPeer, storedProtocols)
|
|
|
|
|
2020-06-20 19:32:39 +02:00
|
|
|
const localIdentify = new IdentifyService({
|
|
|
|
libp2p: {
|
|
|
|
peerId: localPeer,
|
|
|
|
connectionManager: new EventEmitter(),
|
2020-10-27 13:50:14 +00:00
|
|
|
peerStore: localPeerStore,
|
2020-11-20 15:14:01 +01:00
|
|
|
multiaddrs: listenMaddrs,
|
2020-12-10 14:48:14 +01:00
|
|
|
isStarted: () => true,
|
|
|
|
_options: { host: {} }
|
2020-10-27 13:50:14 +00:00
|
|
|
}
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
2020-10-27 13:50:14 +00:00
|
|
|
|
|
|
|
const remotePeerStore = new PeerStore({ peerId: remotePeer })
|
|
|
|
remotePeerStore.protoBook.set(remotePeer, storedProtocols)
|
|
|
|
|
2019-11-07 12:11:50 +01:00
|
|
|
const remoteIdentify = new IdentifyService({
|
2020-04-18 23:26:46 +02:00
|
|
|
libp2p: {
|
|
|
|
peerId: remotePeer,
|
|
|
|
connectionManager,
|
2020-07-17 14:00:59 +02:00
|
|
|
peerStore: new PeerStore({ peerId: remotePeer }),
|
2020-11-20 15:14:01 +01:00
|
|
|
multiaddrs: [],
|
2020-10-27 13:50:14 +00:00
|
|
|
_options: { host: {} },
|
|
|
|
isStarted: () => true
|
2019-11-07 12:11:50 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Setup peer protocols and multiaddrs
|
2020-10-27 13:50:14 +00:00
|
|
|
const localProtocols = new Set(storedProtocols)
|
2020-07-15 15:47:45 +02:00
|
|
|
const localConnectionMock = { newStream: () => {} }
|
2020-04-14 14:05:30 +02:00
|
|
|
const remoteConnectionMock = { remotePeer: localPeer }
|
2019-11-07 12:11:50 +01:00
|
|
|
|
|
|
|
const [local, remote] = duplexPair()
|
|
|
|
sinon.stub(localConnectionMock, 'newStream').returns({ stream: local, protocol: multicodecs.IDENTIFY_PUSH })
|
2020-07-15 15:47:45 +02:00
|
|
|
sinon.stub(Envelope, 'openAndCertify').throws()
|
2019-11-07 12:11:50 +01:00
|
|
|
|
2020-07-15 14:34:51 +02:00
|
|
|
sinon.spy(remoteIdentify.peerStore.addressBook, 'set')
|
2020-04-18 17:06:56 +02:00
|
|
|
sinon.spy(remoteIdentify.peerStore.protoBook, 'set')
|
2019-11-07 12:11:50 +01:00
|
|
|
|
|
|
|
// Run identify
|
|
|
|
await Promise.all([
|
|
|
|
localIdentify.push([localConnectionMock]),
|
|
|
|
remoteIdentify.handleMessage({
|
|
|
|
connection: remoteConnectionMock,
|
|
|
|
stream: remote,
|
|
|
|
protocol: multicodecs.IDENTIFY_PUSH
|
|
|
|
})
|
|
|
|
])
|
|
|
|
|
2020-07-15 14:34:51 +02:00
|
|
|
expect(remoteIdentify.peerStore.addressBook.set.callCount).to.equal(1)
|
2020-04-18 17:06:56 +02:00
|
|
|
expect(remoteIdentify.peerStore.protoBook.set.callCount).to.equal(1)
|
2020-06-29 12:10:58 +02:00
|
|
|
|
2020-07-15 14:34:51 +02:00
|
|
|
const [peerId, multiaddrs] = remoteIdentify.peerStore.addressBook.set.firstCall.args
|
|
|
|
expect(peerId.bytes).to.eql(localPeer.bytes)
|
|
|
|
expect(multiaddrs).to.eql(listenMaddrs)
|
2020-06-29 12:10:58 +02:00
|
|
|
|
2020-04-18 17:06:56 +02:00
|
|
|
const [peerId2, protocols] = remoteIdentify.peerStore.protoBook.set.firstCall.args
|
2020-04-14 14:05:30 +02:00
|
|
|
expect(peerId2.bytes).to.eql(localPeer.bytes)
|
2020-04-09 16:07:18 +02:00
|
|
|
expect(protocols).to.eql(Array.from(localProtocols))
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('libp2p.dialer.identifyService', () => {
|
2020-04-14 14:05:30 +02:00
|
|
|
let peerId
|
2019-11-07 12:11:50 +01:00
|
|
|
let libp2p
|
|
|
|
let remoteLibp2p
|
|
|
|
|
|
|
|
before(async () => {
|
2020-04-14 14:05:30 +02:00
|
|
|
peerId = await PeerId.createFromJSON(Peers[0])
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
afterEach(async () => {
|
|
|
|
sinon.restore()
|
|
|
|
libp2p && await libp2p.stop()
|
|
|
|
libp2p = null
|
|
|
|
})
|
|
|
|
|
|
|
|
after(async () => {
|
|
|
|
remoteLibp2p && await remoteLibp2p.stop()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should run identify automatically after connecting', async () => {
|
|
|
|
libp2p = new Libp2p({
|
|
|
|
...baseOptions,
|
2020-04-14 14:05:30 +02:00
|
|
|
peerId
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
|
2020-06-20 19:32:39 +02:00
|
|
|
await libp2p.start()
|
|
|
|
|
2019-12-03 10:28:52 +01:00
|
|
|
sinon.spy(libp2p.identifyService, 'identify')
|
2020-06-29 12:10:58 +02:00
|
|
|
const peerStoreSpyConsumeRecord = sinon.spy(libp2p.peerStore.addressBook, 'consumePeerRecord')
|
2020-04-09 16:07:18 +02:00
|
|
|
const peerStoreSpyAdd = sinon.spy(libp2p.peerStore.addressBook, 'add')
|
2019-11-07 12:11:50 +01:00
|
|
|
|
2019-12-15 17:33:16 +01:00
|
|
|
const connection = await libp2p.dialer.connectToPeer(remoteAddr)
|
2019-11-07 12:11:50 +01:00
|
|
|
expect(connection).to.exist()
|
2020-02-05 17:35:27 +01:00
|
|
|
|
|
|
|
// Wait for peer store to be updated
|
2020-09-23 18:45:01 +02:00
|
|
|
// Dialer._createDialTarget (add), Identify (consume)
|
|
|
|
await pWaitFor(() => peerStoreSpyConsumeRecord.callCount === 1 && peerStoreSpyAdd.callCount === 1)
|
2019-12-03 10:28:52 +01:00
|
|
|
expect(libp2p.identifyService.identify.callCount).to.equal(1)
|
2019-11-07 12:11:50 +01:00
|
|
|
|
2020-02-05 17:35:27 +01:00
|
|
|
// The connection should have no open streams
|
2020-10-06 15:37:01 +02:00
|
|
|
await pWaitFor(() => connection.streams.length === 0)
|
2019-11-07 12:11:50 +01:00
|
|
|
await connection.close()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should push protocol updates to an already connected peer', async () => {
|
|
|
|
libp2p = new Libp2p({
|
|
|
|
...baseOptions,
|
2020-04-14 14:05:30 +02:00
|
|
|
peerId
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
|
2020-06-20 19:32:39 +02:00
|
|
|
await libp2p.start()
|
|
|
|
|
2019-12-03 10:28:52 +01:00
|
|
|
sinon.spy(libp2p.identifyService, 'identify')
|
|
|
|
sinon.spy(libp2p.identifyService, 'push')
|
2019-11-07 12:11:50 +01:00
|
|
|
|
2019-12-15 17:33:16 +01:00
|
|
|
const connection = await libp2p.dialer.connectToPeer(remoteAddr)
|
2019-11-07 12:11:50 +01:00
|
|
|
expect(connection).to.exist()
|
|
|
|
|
|
|
|
// Wait for identify to finish
|
2019-12-03 10:28:52 +01:00
|
|
|
await libp2p.identifyService.identify.firstCall.returnValue
|
2019-11-29 16:41:08 +01:00
|
|
|
sinon.stub(libp2p, 'isStarted').returns(true)
|
2019-11-07 12:11:50 +01:00
|
|
|
|
|
|
|
libp2p.handle('/echo/2.0.0', () => {})
|
|
|
|
libp2p.unhandle('/echo/2.0.0')
|
|
|
|
|
|
|
|
// Verify the remote peer is notified of both changes
|
2019-12-03 10:28:52 +01:00
|
|
|
expect(libp2p.identifyService.push.callCount).to.equal(2)
|
|
|
|
for (const call of libp2p.identifyService.push.getCalls()) {
|
2019-11-07 12:11:50 +01:00
|
|
|
const [connections] = call.args
|
|
|
|
expect(connections.length).to.equal(1)
|
|
|
|
expect(connections[0].remotePeer.toB58String()).to.equal(remoteAddr.getPeerId())
|
|
|
|
const results = await call.returnValue
|
|
|
|
expect(results.length).to.equal(1)
|
|
|
|
}
|
2020-02-05 17:35:27 +01:00
|
|
|
|
|
|
|
// Verify the streams close
|
|
|
|
await pWaitFor(() => connection.streams.length === 0)
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
2020-11-20 15:14:01 +01:00
|
|
|
|
|
|
|
it('should store host data and protocol version into metadataBook', () => {
|
|
|
|
const agentVersion = 'js-project/1.0.0'
|
|
|
|
|
|
|
|
libp2p = new Libp2p({
|
|
|
|
...baseOptions,
|
|
|
|
peerId,
|
|
|
|
host: {
|
|
|
|
agentVersion
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const storedAgentVersion = libp2p.peerStore.metadataBook.getValue(localPeer, 'AgentVersion')
|
|
|
|
const storedProtocolVersion = libp2p.peerStore.metadataBook.getValue(localPeer, 'ProtocolVersion')
|
|
|
|
|
|
|
|
expect(agentVersion).to.eql(unit8ArrayToString(storedAgentVersion))
|
|
|
|
expect(storedProtocolVersion).to.exist()
|
|
|
|
})
|
2020-09-24 11:12:02 +02:00
|
|
|
|
|
|
|
it('should push multiaddr updates to an already connected peer', async () => {
|
|
|
|
libp2p = new Libp2p({
|
|
|
|
...baseOptions,
|
|
|
|
peerId
|
|
|
|
})
|
|
|
|
|
|
|
|
await libp2p.start()
|
|
|
|
|
|
|
|
sinon.spy(libp2p.identifyService, 'identify')
|
|
|
|
sinon.spy(libp2p.identifyService, 'push')
|
|
|
|
|
|
|
|
const connection = await libp2p.dialer.connectToPeer(remoteAddr)
|
|
|
|
expect(connection).to.exist()
|
|
|
|
|
|
|
|
// Wait for identify to finish
|
|
|
|
await libp2p.identifyService.identify.firstCall.returnValue
|
|
|
|
sinon.stub(libp2p, 'isStarted').returns(true)
|
|
|
|
|
|
|
|
libp2p.peerStore.addressBook.add(libp2p.peerId, [multiaddr('/ip4/180.0.0.1/tcp/15001/ws')])
|
|
|
|
|
|
|
|
// Verify the remote peer is notified of change
|
|
|
|
expect(libp2p.identifyService.push.callCount).to.equal(1)
|
|
|
|
for (const call of libp2p.identifyService.push.getCalls()) {
|
|
|
|
const [connections] = call.args
|
|
|
|
expect(connections.length).to.equal(1)
|
|
|
|
expect(connections[0].remotePeer.toB58String()).to.equal(remoteAddr.getPeerId())
|
|
|
|
const results = await call.returnValue
|
|
|
|
expect(results.length).to.equal(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the streams close
|
|
|
|
await pWaitFor(() => connection.streams.length === 0)
|
|
|
|
})
|
2019-11-07 12:11:50 +01:00
|
|
|
})
|
|
|
|
})
|