Skip to content

Commit bec05ed

Browse files
authored
fix: handle dialing /p2p/Qmfoo-style addresses (#3064)
Dialing `/p2p/Qmfoo` address should load addresses from the peer store and/or query the routing.
1 parent f04e182 commit bec05ed

File tree

4 files changed

+67
-11
lines changed

4 files changed

+67
-11
lines changed

packages/libp2p/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
"@libp2p/utils": "^6.6.0",
104104
"@multiformats/dns": "^1.0.6",
105105
"@multiformats/multiaddr": "^12.3.5",
106-
"@multiformats/multiaddr-matcher": "^1.6.0",
106+
"@multiformats/multiaddr-matcher": "^1.7.0",
107107
"any-signal": "^4.1.1",
108108
"datastore-core": "^10.0.2",
109109
"interface-datastore": "^8.3.1",

packages/libp2p/src/connection-manager/dial-queue.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,9 @@ export class DialQueue {
385385
}
386386
}
387387

388-
// if we still don't have any addresses for this peer, try a lookup
389-
// using the peer routing
388+
// if we still don't have any addresses for this peer, or the only
389+
// addresses we have are without any routing information (e.g.
390+
// `/p2p/Qmfoo`), try a lookup using the peer routing
390391
if (addrs.length === 0) {
391392
this.log('looking up multiaddrs for %p in the peer routing', peerId)
392393

packages/libp2p/src/get-peer.ts

+14-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { InvalidMultiaddrError, InvalidParametersError, isPeerId } from '@libp2p/interface'
22
import { peerIdFromString } from '@libp2p/peer-id'
33
import { isMultiaddr } from '@multiformats/multiaddr'
4+
import { PEER_ID } from '@multiformats/multiaddr-matcher'
45
import type { PeerId } from '@libp2p/interface'
56
import type { Multiaddr } from '@multiformats/multiaddr'
67

@@ -10,25 +11,24 @@ export interface PeerAddress {
1011
}
1112

1213
/**
13-
* Extracts a PeerId and/or multiaddr from the passed PeerId or Multiaddr or an array of Multiaddrs
14+
* Extracts a PeerId and/or multiaddr from the passed PeerId or Multiaddr or an
15+
* array of Multiaddrs
1416
*/
1517
export function getPeerAddress (peer: PeerId | Multiaddr | Multiaddr[]): PeerAddress {
1618
if (isPeerId(peer)) {
1719
return { peerId: peer, multiaddrs: [] }
1820
}
1921

20-
if (!Array.isArray(peer)) {
21-
peer = [peer]
22-
}
22+
let multiaddrs = Array.isArray(peer) ? peer : [peer]
2323

2424
let peerId: PeerId | undefined
2525

26-
if (peer.length > 0) {
27-
const peerIdStr = peer[0].getPeerId()
26+
if (multiaddrs.length > 0) {
27+
const peerIdStr = multiaddrs[0].getPeerId()
2828
peerId = peerIdStr == null ? undefined : peerIdFromString(peerIdStr)
2929

3030
// ensure PeerId is either not set or is consistent
31-
peer.forEach(ma => {
31+
multiaddrs.forEach(ma => {
3232
if (!isMultiaddr(ma)) {
3333
throw new InvalidMultiaddrError('Invalid multiaddr')
3434
}
@@ -49,8 +49,14 @@ export function getPeerAddress (peer: PeerId | Multiaddr | Multiaddr[]): PeerAdd
4949
})
5050
}
5151

52+
// ignore any `/p2p/Qmfoo`-style addresses as we will include the peer id in
53+
// the returned value of this function
54+
multiaddrs = multiaddrs.filter(ma => {
55+
return !PEER_ID.exactMatch(ma)
56+
})
57+
5258
return {
5359
peerId,
54-
multiaddrs: peer
60+
multiaddrs
5561
}
5662
}

packages/libp2p/test/connection-manager/dial-queue.spec.ts

+49
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,33 @@ describe('dial queue', () => {
8282
await expect(deferredConn.promise).to.eventually.be.undefined()
8383
})
8484

85+
it('should load addresses from the peer store when dialing a multiaddr that only contains a peer id', async () => {
86+
const peerId = peerIdFromPrivateKey(await generateKeyPair('Ed25519'))
87+
const connection = stubInterface<Connection>()
88+
const foundAddress = multiaddr('/ip4/127.0.0.1/tcp/4001')
89+
const ma = multiaddr(`/p2p/${peerId}`)
90+
91+
components.peerStore.get.withArgs(peerId).resolves({
92+
id: peerId,
93+
addresses: [{
94+
multiaddr: foundAddress,
95+
isCertified: false
96+
}],
97+
protocols: [],
98+
metadata: new Map(),
99+
tags: new Map()
100+
})
101+
102+
components.transportManager.dialTransportForMultiaddr.returns(stubInterface<Transport>())
103+
components.transportManager.dial.withArgs(foundAddress.encapsulate(`/p2p/${peerId}`)).resolves(connection)
104+
105+
dialer = new DialQueue(components)
106+
107+
await expect(dialer.dial(ma)).to.eventually.equal(connection)
108+
109+
expect(components.peerRouting.findPeer).to.have.property('called', false)
110+
})
111+
85112
it('should load addresses from the peer routing when peer id is not in the peer store', async () => {
86113
const peerId = peerIdFromPrivateKey(await generateKeyPair('Ed25519'))
87114
const connection = stubInterface<Connection>()
@@ -103,6 +130,28 @@ describe('dial queue', () => {
103130
await expect(dialer.dial(peerId)).to.eventually.equal(connection)
104131
})
105132

133+
it('should load addresses from the peer routing when dialing a multiaddr that only contains a peer id', async () => {
134+
const peerId = peerIdFromPrivateKey(await generateKeyPair('Ed25519'))
135+
const connection = stubInterface<Connection>()
136+
const foundAddress = multiaddr('/ip4/127.0.0.1/tcp/4001')
137+
const ma = multiaddr(`/p2p/${peerId}`)
138+
139+
components.peerStore.get.withArgs(peerId).rejects(new NotFoundError('Not found'))
140+
components.peerRouting.findPeer.withArgs(peerId).resolves({
141+
id: peerId,
142+
multiaddrs: [
143+
foundAddress
144+
]
145+
})
146+
147+
components.transportManager.dialTransportForMultiaddr.returns(stubInterface<Transport>())
148+
components.transportManager.dial.withArgs(foundAddress.encapsulate(`/p2p/${peerId}`)).resolves(connection)
149+
150+
dialer = new DialQueue(components)
151+
152+
await expect(dialer.dial(ma)).to.eventually.equal(connection)
153+
})
154+
106155
it('should load addresses from the peer routing when none are present in the peer store', async () => {
107156
const peerId = peerIdFromPrivateKey(await generateKeyPair('Ed25519'))
108157
const connection = stubInterface<Connection>()

0 commit comments

Comments
 (0)