Node cannot dial to another using peer ID in a network connected via a relay. #2815
-
I am learning from the libp2p examples and have been experimenting on my own. The relay server can discover both nodes, but Node 1 cannot directly dial Node 2 using its peer ID, even though I have configured DHT as well. Here is the code for the relay server: /* eslint-disable no-console */
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { circuitRelayServer } from '@libp2p/circuit-relay-v2'
import { privateKeyFromRaw, generateKeyPair } from '@libp2p/crypto/keys'
import { identify } from '@libp2p/identify'
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
import { webSockets } from '@libp2p/websockets'
import * as filters from '@libp2p/websockets/filters'
import { protocols } from '@multiformats/multiaddr'
import { createLibp2p } from 'libp2p'
// const privateKey = await generateKeyPair('Ed25519')
// console.log(privateKey.raw)
const privateKeyRaw = Uint8Array.from([
3, 98, 126, 31, 53, 38, 77, 83, 95, 52, 208,
245, 12, 231, 179, 29, 77, 119, 64, 225, 28, 76,
152, 60, 22, 170, 169, 92, 240, 114, 50, 34, 97,
34, 166, 6, 69, 146, 135, 77, 74, 250, 62, 215,
106, 6, 45, 2, 118, 162, 136, 195, 108, 174, 61,
180, 216, 136, 89, 9, 101, 139, 157, 193
])
const server = await createLibp2p({
privateKey: privateKeyFromRaw(privateKeyRaw),
addresses: {
listen: ['/ip4/127.0.0.1/tcp/54321/ws']
},
transports: [
webSockets({
filter: filters.all
})
],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
services: {
dht: kadDHT({
protocol: '/ipfs/lan/kad/1.0.0',
peerInfoMapper: removePublicAddressesMapper,
clientMode: false
}),
identify: identify(),
relay: circuitRelayServer({
// disable max reservations limit for demo purposes. in production you
// should leave this set to the default of 15 to prevent abuse of your
// node by network peers
reservations: {
maxReservations: Infinity
}
})
}
})
server.addEventListener('peer:discovery', (evt) => {
console.log('discovery', evt.detail)
})
console.info('The relay node is running and listening on the following multiaddrs:')
console.info(server.getMultiaddrs().map((ma) => ma.toString()).join('\n'))
console.info('')
console.log(server.services.dht.isStarted()) Here is the code for Node 1: import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { bootstrap } from '@libp2p/bootstrap'
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
import { generateKeyPair, privateKeyFromRaw } from '@libp2p/crypto/keys'
import { identify, identifyPush } from '@libp2p/identify'
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
import { ping } from '@libp2p/ping'
import { webRTC } from '@libp2p/webrtc'
import { webSockets } from '@libp2p/websockets'
import * as filters from '@libp2p/websockets/filters'
import { protocols } from '@multiformats/multiaddr'
import { createLibp2p } from 'libp2p'
// const privateKey = await generateKeyPair('Ed25519')
// console.log(privateKey.raw)
const privateKeyRaw = Uint8Array.from([
193, 47, 231, 144, 7, 129, 84, 20, 140, 231,
61, 69, 132, 95, 229, 213, 117, 243, 170, 134,
53, 107, 201, 227, 231, 86, 245, 138, 253, 246,
233, 46, 139, 233, 131, 150, 161, 171, 243, 137,
84, 240, 69, 183, 161, 43, 61, 29, 107, 242,
173, 213, 11, 185, 85, 190, 173, 171, 76, 174,
208, 184, 101, 146
])
const node1 = await createLibp2p({
privateKey: privateKeyFromRaw(privateKeyRaw),
addresses: {
listen: ['/webrtc']
},
transports: [
webSockets({
filter: filters.all
}),
webRTC(),
circuitRelayTransport({
discoverRelays: 1
})
],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
connectionGater: {
denyDialMultiaddr: () => {
// by default we refuse to dial local addresses from the browser since they
// are usually sent by remote peers broadcasting undialable multiaddrs but
// here we are explicitly connecting to a local node so do not deny dialing
// any discovered address
return false
}
},
services: {
dht: kadDHT({
protocol: '/ipfs/lan/kad/1.0.0',
peerInfoMapper: removePublicAddressesMapper
}),
identify: identify(),
identifyPush: identifyPush(),
ping: ping()
},
peerDiscovery: [
bootstrap({
list: [
'/ip4/127.0.0.1/tcp/54321/ws/p2p/12D3KooWGMYMmN1RGUYjWaSV6P3XtnBjwnosnJGNMnttfVCRnd6g'
]
})
]
})
async function waitFoundAddr () {
return new Promise(resolve => {
const checkAddr = setInterval(() => {
if (node1.getMultiaddrs().length > 0) {
clearInterval(checkAddr)
resolve(true)
}
}, 300)
})
}
await waitFoundAddr()
console.log('node1 addrs:', node1.getMultiaddrs())
console.log('node1 peerId', node1.peerId.toString()) Here is the code for Node 2: import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { bootstrap } from '@libp2p/bootstrap'
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
import { identify, identifyPush } from '@libp2p/identify'
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
import { peerIdFromMultihash, peerIdFromString } from '@libp2p/peer-id'
import { ping } from '@libp2p/ping'
import { webRTC } from '@libp2p/webrtc'
import { webSockets } from '@libp2p/websockets'
import * as filters from '@libp2p/websockets/filters'
import { multiaddr } from '@multiformats/multiaddr'
import { createLibp2p } from 'libp2p'
const node2 = await createLibp2p({
start: true,
addresses: {
listen: ['/webrtc']
},
transports: [
webSockets({
filter: filters.all
}),
webRTC(),
circuitRelayTransport({
discoverRelays: 1
})
],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
connectionGater: {
denyDialMultiaddr: () => {
return false
}
},
services: {
dht: kadDHT({
protocol: '/ipfs/lan/kad/1.0.0',
peerInfoMapper: removePublicAddressesMapper
}),
identify: identify(),
identifyPush: identifyPush(),
ping: ping()
},
peerDiscovery: [
bootstrap({
list: [
'/ip4/127.0.0.1/tcp/54321/ws/p2p/12D3KooWGMYMmN1RGUYjWaSV6P3XtnBjwnosnJGNMnttfVCRnd6g'
]
})
]
})
async function waitFoundAddr () {
return new Promise(resolve => {
const checkAddr = setInterval(() => {
if (node2.getMultiaddrs().length > 0) {
clearInterval(checkAddr)
resolve(true)
}
}, 300)
})
}
await waitFoundAddr()
console.log('node2 peerId', node2.peerId.toString())
const node1PeerIdString =
'12D3KooWKEXMpZ1An7wvoUdckhESPFh2zJWSNFFN7GwkGvPFUZ37'
const node1PeerId = peerIdFromString(node1PeerIdString)
const signal = AbortSignal.timeout(5000)
//--------- error occurs here ----------
const result = await node2.services.ping.ping(node1PeerId, { signal })
console.log(result) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Sorry for not answering this sooner. There was an undocumented optimisation in go-libp2p-dht that wasn't implemented here around searching for DHT client peers which has since been shipped. I have made a few changes to your code to make it work:
Updated code:
{
"type": "module",
"dependencies": {
"@chainsafe/libp2p-noise": "^16.0.0",
"@chainsafe/libp2p-yamux": "^7.0.1",
"@libp2p/circuit-relay-v2": "^3.1.3",
"@libp2p/crypto": "^5.0.7",
"@libp2p/identify": "^3.0.12",
"@libp2p/kad-dht": "^14.1.3",
"@libp2p/ping": "^2.0.12",
"@libp2p/websockets": "^9.0.13",
"libp2p": "^2.3.1"
}
}
/* eslint-disable no-console */
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { circuitRelayServer } from '@libp2p/circuit-relay-v2'
import { privateKeyFromRaw } from '@libp2p/crypto/keys'
import { identify, identifyPush } from '@libp2p/identify'
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
import { webSockets } from '@libp2p/websockets'
import * as filters from '@libp2p/websockets/filters'
import { createLibp2p } from 'libp2p'
// const privateKey = await generateKeyPair('Ed25519')
// console.log(privateKey.raw)
const privateKeyRaw = Uint8Array.from([
3, 98, 126, 31, 53, 38, 77, 83, 95, 52, 208,
245, 12, 231, 179, 29, 77, 119, 64, 225, 28, 76,
152, 60, 22, 170, 169, 92, 240, 114, 50, 34, 97,
34, 166, 6, 69, 146, 135, 77, 74, 250, 62, 215,
106, 6, 45, 2, 118, 162, 136, 195, 108, 174, 61,
180, 216, 136, 89, 9, 101, 139, 157, 193
])
const relay = await createLibp2p({
privateKey: privateKeyFromRaw(privateKeyRaw),
addresses: {
listen: ['/ip4/127.0.0.1/tcp/54321/ws']
},
transports: [
webSockets({
filter: filters.all
})
],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
services: {
dht: kadDHT({
protocol: '/ipfs/lan/kad/1.0.0',
peerInfoMapper: removePublicAddressesMapper,
clientMode: false
}),
identify: identify(),
identifyPush: identifyPush(),
relay: circuitRelayServer({
// disable max reservations limit for demo purposes. in production you
// should leave this set to the default of 15 to prevent abuse of your
// node by network peers
reservations: {
maxReservations: Infinity
}
})
}
})
relay.addEventListener('peer:discovery', (evt) => {
console.log('discovery', evt.detail)
})
console.info('The relay node is running and listening on the following multiaddrs:')
console.info(relay.getMultiaddrs().map((ma) => ma.toString()).join('\n'))
console.info('')
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { bootstrap } from '@libp2p/bootstrap'
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
import { privateKeyFromRaw } from '@libp2p/crypto/keys'
import { identify, identifyPush } from '@libp2p/identify'
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
import { ping } from '@libp2p/ping'
import { webRTC } from '@libp2p/webrtc'
import { webSockets } from '@libp2p/websockets'
import * as filters from '@libp2p/websockets/filters'
import { createLibp2p } from 'libp2p'
// const privateKey = await generateKeyPair('Ed25519')
// console.log(privateKey.raw)
const privateKeyRaw = Uint8Array.from([
193, 47, 231, 144, 7, 129, 84, 20, 140, 231,
61, 69, 132, 95, 229, 213, 117, 243, 170, 134,
53, 107, 201, 227, 231, 86, 245, 138, 253, 246,
233, 46, 139, 233, 131, 150, 161, 171, 243, 137,
84, 240, 69, 183, 161, 43, 61, 29, 107, 242,
173, 213, 11, 185, 85, 190, 173, 171, 76, 174,
208, 184, 101, 146
])
const listener = await createLibp2p({
privateKey: privateKeyFromRaw(privateKeyRaw),
addresses: {
listen: [
'/webrtc',
'/p2p-circuit'
]
},
transports: [
webSockets({
filter: filters.all
}),
webRTC(),
circuitRelayTransport()
],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
connectionGater: {
denyDialMultiaddr: () => {
// by default we refuse to dial local addresses from the browser since they
// are usually sent by remote peers broadcasting undialable multiaddrs but
// here we are explicitly connecting to a local node so do not deny dialing
// any discovered address
return false
}
},
services: {
dht: kadDHT({
protocol: '/ipfs/lan/kad/1.0.0',
peerInfoMapper: removePublicAddressesMapper
}),
identify: identify(),
identifyPush: identifyPush(),
ping: ping()
},
peerDiscovery: [
bootstrap({
list: [
'/ip4/127.0.0.1/tcp/54321/ws/p2p/12D3KooWGMYMmN1RGUYjWaSV6P3XtnBjwnosnJGNMnttfVCRnd6g'
]
})
]
})
async function waitFoundAddr () {
return new Promise(resolve => {
const checkAddr = setInterval(() => {
if (listener.getMultiaddrs().length > 0) {
clearInterval(checkAddr)
resolve(true)
}
}, 300)
})
}
await waitFoundAddr()
console.log('listener addrs:', listener.getMultiaddrs())
console.log('listener peerId', listener.peerId.toString())
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { bootstrap } from '@libp2p/bootstrap'
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
import { identify, identifyPush } from '@libp2p/identify'
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
import { peerIdFromString } from '@libp2p/peer-id'
import { ping } from '@libp2p/ping'
import { webRTC } from '@libp2p/webrtc'
import { webSockets } from '@libp2p/websockets'
import * as filters from '@libp2p/websockets/filters'
import { createLibp2p } from 'libp2p'
const dialer = await createLibp2p({
transports: [
webSockets({
filter: filters.all
}),
webRTC(),
circuitRelayTransport()
],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
connectionGater: {
denyDialMultiaddr: () => {
return false
}
},
services: {
dht: kadDHT({
protocol: '/ipfs/lan/kad/1.0.0',
peerInfoMapper: removePublicAddressesMapper
}),
identify: identify(),
identifyPush: identifyPush(),
ping: ping()
},
peerDiscovery: [
bootstrap({
list: [
'/ip4/127.0.0.1/tcp/54321/ws/p2p/12D3KooWGMYMmN1RGUYjWaSV6P3XtnBjwnosnJGNMnttfVCRnd6g'
]
})
]
})
console.log('dialer peerId', dialer.peerId.toString())
const listenerPeerIdString = '12D3KooWKEXMpZ1An7wvoUdckhESPFh2zJWSNFFN7GwkGvPFUZ37'
const listenerPeerId = peerIdFromString(listenerPeerIdString)
const signal = AbortSignal.timeout(5000)
const result = await dialer.services.ping.ping(listenerPeerId, { signal })
console.log('ping time', result, 'ms') Please can you try again? |
Beta Was this translation helpful? Give feedback.
Sorry for not answering this sooner. There was an undocumented optimisation in go-libp2p-dht that wasn't implemented here around searching for DHT client peers which has since been shipped.
I have made a few changes to your code to make it work:
server
identifyPush
service - this is so whennode1
gets a circuit relay address, it can notify connected peers (e.g. the server) that it's addresses have changednode1
/p2p-circuit
instead of specifyingdiscoverRelays
to circuit relay transportnode2
discoverRelays
as it's not necessary fornode2
to listen on any addressUpdated code:
package.json