diff --git a/src/circuit/auto-relay.js b/src/circuit/auto-relay.js index 85fdd80b09..bc4c25abb4 100644 --- a/src/circuit/auto-relay.js +++ b/src/circuit/auto-relay.js @@ -19,14 +19,13 @@ class AutoRelay { /** * Creates an instance of AutoRelay * @constructor - * @param {object} params - * @param {Libp2p} params.libp2p - * @param {number} params.maxListeners maximum number of relays to listen. + * @param {object} props + * @param {Libp2p} props.libp2p + * @param {number} props.maxListeners maximum number of relays to listen. */ constructor ({ libp2p, maxListeners }) { this._libp2p = libp2p this._peerId = libp2p.peerId - this._registrar = libp2p.registrar this._peerStore = libp2p.peerStore this._connectionManager = libp2p.connectionManager this._transportManager = libp2p.transportManager @@ -46,8 +45,8 @@ class AutoRelay { } /** - * Check if a new peer supports the relay protocol. - * If the protocol is not supported, check if it was supported before and remove listen relay. + * Check if a peer supports the relay protocol. + * If the protocol is not supported, check if it was supported before and remove it as a listen relay. * If the protocol is supported, check if the peer supports **HOP** and add it as a listener if * inside the threshold. * @param {Object} props @@ -80,6 +79,7 @@ class AutoRelay { } await canHop({ connection }) + this._peerStore.metadataBook.set(peerId, hopMetadataKey, uint8ArrayFromString(hopMetadataValue)) await this._addListenRelay(connection, id) } catch (err) { diff --git a/src/transport-manager.js b/src/transport-manager.js index 03fec6a09d..5030c594b5 100644 --- a/src/transport-manager.js +++ b/src/transport-manager.js @@ -134,8 +134,6 @@ class TransportManager { * @param {Array} addrs addresses to attempt to listen on */ async listen (addrs) { - // const addrs = this.libp2p.addressManager.getListenAddrs() - if (!addrs || addrs.length === 0) { log('no addresses were provided for listening, this node is dial only') return diff --git a/test/relay/auto-relay.node.js b/test/relay/auto-relay.node.js index c0c51b4147..6993b8b99a 100644 --- a/test/relay/auto-relay.node.js +++ b/test/relay/auto-relay.node.js @@ -19,6 +19,82 @@ const baseOptions = require('../utils/base-options') const listenAddr = '/ip4/0.0.0.0/tcp/0' describe('auto-relay', () => { + describe('basics', () => { + let libp2p + let relayLibp2p + let autoRelay + + beforeEach(async () => { + const peerIds = await createPeerId({ number: 2 }) + // Create 2 nodes, and turn HOP on for the relay + ;[libp2p, relayLibp2p] = peerIds.map((peerId, index) => { + const opts = baseOptions + + opts.config.relay = { + ...opts.config.relay, + hop: { + enabled: index !== 0 + }, + autoRelay: { + enabled: true, + maxListeners: 1 + } + } + + return new Libp2p({ + ...opts, + addresses: { + listen: [listenAddr] + }, + connectionManager: { + autoDial: false + }, + peerDiscovery: { + autoDial: false + }, + peerId + }) + }) + + autoRelay = libp2p.transportManager._transports.get('Circuit')._autoRelay + + expect(autoRelay.maxListeners).to.eql(1) + }) + + beforeEach(() => { + // Start each node + return Promise.all([libp2p, relayLibp2p].map(libp2p => libp2p.start())) + }) + + afterEach(() => { + // Stop each node + return Promise.all([libp2p, relayLibp2p].map(libp2p => libp2p.stop())) + }) + + it('should ask if node supports hop on protocol change (relay protocol) and add to listen multiaddrs', async () => { + // Spy if a connected peer is being added as listen relay + sinon.spy(autoRelay, '_addListenRelay') + + const originalMultiaddrsLength = relayLibp2p.multiaddrs.length + + // Discover relay + libp2p.peerStore.addressBook.add(relayLibp2p.peerId, relayLibp2p.multiaddrs) + await libp2p.dial(relayLibp2p.peerId) + + // Wait for peer added as listen relay + await pWaitFor(() => autoRelay._addListenRelay.callCount === 1) + expect(autoRelay._listenRelays.size).to.equal(1) + + // Wait for listen multiaddr update + await pWaitFor(() => libp2p.multiaddrs.length === originalMultiaddrsLength + 1) + expect(libp2p.multiaddrs[originalMultiaddrsLength].getPeerId()).to.eql(relayLibp2p.peerId.toB58String()) + + // Peer has relay multicodec + const knownProtocols = libp2p.peerStore.protoBook.get(relayLibp2p.peerId) + expect(knownProtocols).to.include(relayMulticodec) + }) + }) + describe('flows with 1 listener max', () => { let libp2p let relayLibp2p1 @@ -81,8 +157,9 @@ describe('auto-relay', () => { // Discover relay relayLibp2p1.peerStore.addressBook.add(relayLibp2p2.peerId, relayLibp2p2.multiaddrs) - expect(relayLibp2p1.multiaddrs).to.have.lengthOf(2) - expect(relayLibp2p2.multiaddrs).to.have.lengthOf(2) + + const originalMultiaddrs1Length = relayLibp2p1.multiaddrs.length + const originalMultiaddrs2Length = relayLibp2p2.multiaddrs.length await relayLibp2p1.dial(relayLibp2p2.peerId) @@ -92,10 +169,10 @@ describe('auto-relay', () => { // Wait for listen multiaddr update await Promise.all([ - pWaitFor(() => relayLibp2p1.multiaddrs.length === 3), - pWaitFor(() => relayLibp2p2.multiaddrs.length === 3) + pWaitFor(() => relayLibp2p1.multiaddrs.length === originalMultiaddrs1Length + 1), + pWaitFor(() => relayLibp2p2.multiaddrs.length === originalMultiaddrs2Length + 1) ]) - expect(relayLibp2p1.multiaddrs[2].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) + expect(relayLibp2p1.multiaddrs[originalMultiaddrs1Length].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) // Peer has relay multicodec const knownProtocols = relayLibp2p1.peerStore.protoBook.get(relayLibp2p2.peerId) @@ -103,6 +180,9 @@ describe('auto-relay', () => { }) it('should be able to dial a peer from its relayed address previously added', async () => { + const originalMultiaddrs1Length = relayLibp2p1.multiaddrs.length + const originalMultiaddrs2Length = relayLibp2p2.multiaddrs.length + // Discover relay relayLibp2p1.peerStore.addressBook.add(relayLibp2p2.peerId, relayLibp2p2.multiaddrs) @@ -110,10 +190,10 @@ describe('auto-relay', () => { // Wait for listen multiaddr update await Promise.all([ - pWaitFor(() => relayLibp2p1.multiaddrs.length === 3), - pWaitFor(() => relayLibp2p2.multiaddrs.length === 3) + pWaitFor(() => relayLibp2p1.multiaddrs.length === originalMultiaddrs1Length + 1), + pWaitFor(() => relayLibp2p2.multiaddrs.length === originalMultiaddrs2Length + 1) ]) - expect(relayLibp2p1.multiaddrs[2].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) + expect(relayLibp2p1.multiaddrs[originalMultiaddrs1Length].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) // Dial from the other through a relay const relayedMultiaddr2 = multiaddr(`${relayLibp2p1.multiaddrs[0]}/p2p/${relayLibp2p1.peerId.toB58String()}/p2p-circuit`) @@ -123,6 +203,9 @@ describe('auto-relay', () => { }) it('should only add maxListeners relayed addresses', async () => { + const originalMultiaddrs1Length = relayLibp2p1.multiaddrs.length + const originalMultiaddrs2Length = relayLibp2p2.multiaddrs.length + // Spy if a connected peer is being added as listen relay sinon.spy(autoRelay1, '_addListenRelay') sinon.spy(autoRelay1._listenRelays, 'add') @@ -139,10 +222,10 @@ describe('auto-relay', () => { // Wait for listen multiaddr update await Promise.all([ - pWaitFor(() => relayLibp2p1.multiaddrs.length === 3), - pWaitFor(() => relayLibp2p2.multiaddrs.length === 3) + pWaitFor(() => relayLibp2p1.multiaddrs.length === originalMultiaddrs1Length + 1), + pWaitFor(() => relayLibp2p2.multiaddrs.length === originalMultiaddrs2Length + 1) ]) - expect(relayLibp2p1.multiaddrs[2].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) + expect(relayLibp2p1.multiaddrs[originalMultiaddrs1Length].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) // Relay2 has relay multicodec const knownProtocols2 = relayLibp2p1.peerStore.protoBook.get(relayLibp2p2.peerId) @@ -166,24 +249,28 @@ describe('auto-relay', () => { }) it('should not listen on a relayed address if peer disconnects', async () => { + const originalMultiaddrs1Length = relayLibp2p1.multiaddrs.length + // Discover one relay and connect relayLibp2p1.peerStore.addressBook.add(relayLibp2p2.peerId, relayLibp2p2.multiaddrs) await relayLibp2p1.dial(relayLibp2p2.peerId) // Wait for listenning on the relay - await pWaitFor(() => relayLibp2p1.multiaddrs.length === 3) + await pWaitFor(() => relayLibp2p1.multiaddrs.length === originalMultiaddrs1Length + 1) expect(autoRelay1._listenRelays.size).to.equal(1) - expect(relayLibp2p1.multiaddrs[2].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) + expect(relayLibp2p1.multiaddrs[originalMultiaddrs1Length].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) // Disconnect from peer used for relay await relayLibp2p1.hangUp(relayLibp2p2.peerId) // Wait for removed listening on the relay - await pWaitFor(() => relayLibp2p1.multiaddrs.length === 2) + await pWaitFor(() => relayLibp2p1.multiaddrs.length === originalMultiaddrs1Length) expect(autoRelay1._listenRelays.size).to.equal(0) }) it('should try to listen on other relayed addresses if one used relay disconnects', async () => { + const originalMultiaddrs1Length = relayLibp2p1.multiaddrs.length + // Spy if a connected peer is being added as listen relay sinon.spy(autoRelay1, '_addListenRelay') @@ -201,8 +288,8 @@ describe('auto-relay', () => { expect(relayLibp2p1.connectionManager.size).to.eql(2) // Wait for listen multiaddr update - await pWaitFor(() => relayLibp2p1.multiaddrs.length === 3) - expect(relayLibp2p1.multiaddrs[2].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) + await pWaitFor(() => relayLibp2p1.multiaddrs.length === originalMultiaddrs1Length + 1) + expect(relayLibp2p1.multiaddrs[originalMultiaddrs1Length].getPeerId()).to.eql(relayLibp2p2.peerId.toB58String()) // Spy if relay from listen map was removed sinon.spy(autoRelay1._listenRelays, 'delete') @@ -218,8 +305,8 @@ describe('auto-relay', () => { expect(relayLibp2p1.connectionManager.size).to.eql(1) // Wait for listen multiaddr update - await pWaitFor(() => relayLibp2p1.multiaddrs.length === 3) - expect(relayLibp2p1.multiaddrs[2].getPeerId()).to.eql(relayLibp2p3.peerId.toB58String()) + await pWaitFor(() => relayLibp2p1.multiaddrs.length === originalMultiaddrs1Length + 1) + expect(relayLibp2p1.multiaddrs[originalMultiaddrs1Length].getPeerId()).to.eql(relayLibp2p3.peerId.toB58String()) }) }) @@ -300,7 +387,7 @@ describe('auto-relay', () => { expect(autoRelay2._listenRelays.size).to.equal(1) // Relay 1 discovers Relay 2 relayed multiaddr via Relay 3 - const ma2RelayedBy3 = relayLibp2p2.multiaddrs[2] + const ma2RelayedBy3 = relayLibp2p2.multiaddrs[relayLibp2p2.multiaddrs.length - 1] relayLibp2p1.peerStore.addressBook.add(relayLibp2p2.peerId, [ma2RelayedBy3]) await relayLibp2p1.dial(relayLibp2p2.peerId)