When contacting a peer it unleash a UnroutablePeer
event.
This are the steps that i follow:
- start first peer
- second node has the first as boot address
- start second peer
What happens is that in the first node this is what happens:
[INFO]peer id: 12D3KooWCPyxtinDT6yBBk9TEuaH1YFER6kfKAh1VEN9DHQSqzyc
adding local node into DHT result: false
listen on result: true
is connected to a peer: false
Dialed "/ip4/10.0.0.11/tcp/8000"
Searching for the closest peers to PeerId("12D3KooWBeXS6GZEDMwjf9prXq8RFHAQ6JQqwL6LTCwpeR89Epxw")
Query finished with no closest peers.
External addr /ip4/10.0.0.11/tcp/8000
External addr /ip4/10.0.0.11/tcp/8000
Listening on /ip4/127.0.0.1/tcp/8000
Listening on /ip4/10.0.0.11/tcp/8000
Other event: UnroutablePeer {
peer: PeerId(
"12D3KooWARTkYv6S4J3NGBt1ZGdZs46bSCPHfLSPtKP1Ct1gqMem",
),
}
Other event: InboundRequest {
request: FindNode {
num_closer_peers: 0,
},
}
Other event: InboundRequest {
request: FindNode {
num_closer_peers: 0,
},
}
Other event: UnroutablePeer {
peer: PeerId(
"12D3KooWARTkYv6S4J3NGBt1ZGdZs46bSCPHfLSPtKP1Ct1gqMem",
),
}
Other event: InboundRequest {
request: FindNode {
num_closer_peers: 0,
},
}
This is my implementation:
use crate::utils;
use async_std::future;
use async_std::task::{self, block_on};
use futures::StreamExt;
use libp2p::kad::record::store::MemoryStore;
use libp2p::kad::{
GetClosestPeersError, Kademlia, KademliaBucketInserts, KademliaConfig, KademliaEvent,
QueryResult,
};
use libp2p::swarm::AddressScore;
use libp2p::{
development_transport, identity,
swarm::{Swarm, SwarmEvent},
Multiaddr, PeerId,
};
use std::task::{Context, Poll};
use std::{error::Error, str::FromStr, time::Duration};
async fn run_async(peer_mod: String, port: String) -> Result<(), Box<dyn Error>> {
env_logger::init();
// loading boot peer id
let boot_key = utils::load_keypair("./keypairs/boot.bin".to_string());
let boot_peer_id = boot_key.public().to_peer_id();
// Create a random key for ourselves.
let local_key = if peer_mod.eq(&format!("boot")) {
utils::load_keypair("./keypairs/boot.bin".to_string())
} else if peer_mod.eq(&format!("w-boot")) {
let local_key = utils::generate_keypair();
utils::store_keypair(&local_key, "./keypairs/boot.bin".to_string());
local_key
} else {
utils::generate_keypair()
};
let local_peer_id = PeerId::from(local_key.public());
println!("[INFO]peer id:\t{}", local_peer_id.to_string());
utils::log_local(format!("[INFO]peer id:\t{}", local_peer_id.to_string()));
// Set up a an encrypted DNS-enabled TCP Transport over the Mplex protocol
let transport = development_transport(local_key).await?;
// Create a swarm to manage peers and events.
let mut swarm = {
// Create a Kademlia behaviour.
let mut cfg = KademliaConfig::default();
cfg.set_query_timeout(Duration::from_secs(5 * 60))
.set_kbucket_inserts(KademliaBucketInserts::OnConnected)
.set_connection_idle_timeout(Duration::from_secs(5 * 60))
.set_provider_publication_interval(Some(Duration::from_secs(60)));
let store = MemoryStore::new(local_peer_id);
let mut behaviour = Kademlia::with_config(local_peer_id, store, cfg);
let bootaddr = Multiaddr::from_str(
"/ip4/10.0.0.11/tcp/8000/p2p/12D3KooWCPyxtinDT6yBBk9TEuaH1YFER6kfKAh1VEN9DHQSqzyc",
)?;
behaviour.add_address(
&PeerId::from_str(&boot_peer_id.to_string())?,
bootaddr.clone(),
);
println!("adding local node into DHT result: {:?}", behaviour.bootstrap().is_ok());
Swarm::new(transport, behaviour, local_peer_id)
};
// CHANGE THIS PORT
let addr = format!("/ip4/{}/tcp/{}", "0.0.0.0", port);
let addr = addr.parse::<Multiaddr>().unwrap();
let result = swarm.listen_on(addr).is_ok();
println!("listen on result: {:?}", result);
println!(
"is connected to a peer: {:?}",
swarm.is_connected(&boot_peer_id)
);
// Reach out to another node if specified
let addr = Multiaddr::from_str("/ip4/10.0.0.11/tcp/8000").unwrap();
swarm.dial(addr.clone()).unwrap();
//dial_addr(&mut swarm, addr)?;
println!("Dialed {:?}", addr);
// Order Kademlia to search for a peer.
let to_search: PeerId = identity::Keypair::generate_ed25519().public().into();
println!("Searching for the closest peers to {:?}", to_search);
swarm.behaviour_mut().get_closest_peers(to_search);
// get all peers
for bucket in swarm.behaviour_mut().kbuckets() {
println!("the bucket has :{} peers", bucket.num_entries());
for peer in bucket.iter() {
println!("{:?}", peer.node.key);
}
}
let addr = Multiaddr::from_str(&format!("/ip4/10.0.0.11/tcp/{}", port)).unwrap();
let score = AddressScore::Infinite;
let _result = swarm.add_external_address(addr, score);
let mut listening = false;
let future_poll = future::poll_fn(move |cx: &mut Context<'_>| -> Poll<()> {
loop {
match swarm.poll_next_unpin(cx) {
Poll::Ready(Some(event)) => {
match event {
SwarmEvent::Behaviour(event) => match event {
KademliaEvent::RoutingUpdated {
peer,
is_new_peer,
addresses,
bucket_range: _,
old_peer: _,
} => {
println!("===\nRouting Table has been updated");
if is_new_peer {
println!("#new peer: {}#", peer);
} else {
println!("#old peer: {}#", peer);
}
for addr in addresses.iter() {
println!("\t\t{}", addr)
}
}
KademliaEvent::OutboundQueryCompleted {
result: QueryResult::GetClosestPeers(result),
..
} => {
match result {
Ok(ok) => {
if !ok.peers.is_empty() {
println!("Query finished with closest peers: {:#?}", ok.peers)
} else {
// The example is considered failed as there
// should always be at least 1 reachable peer.
println!("Query finished with no closest peers.")
}
}
Err(GetClosestPeersError::Timeout { peers, .. }) => {
if !peers.is_empty() {
println!("Query timed out with closest peers: {:#?}", peers)
} else {
// The example is considered failed as there
// should always be at least 1 reachable peer.
println!("Query timed out with no closest peers.");
}
}
}
}
_=> println!("Other event: {:#?}", event)
//KademliaEvent::InboundRequest { request } => todo!(),
//KademliaEvent::OutboundQueryCompleted { id, result, stats } => todo!(),
//KademliaEvent::UnroutablePeer { peer } => todo!(),
//KademliaEvent::RoutablePeer { peer, address } => todo!(),
//KademliaEvent::PendingRoutablePeer { peer, address } => todo!(),
},
_ => (),
}
}
Poll::Ready(None) => return Poll::Ready(()),
Poll::Pending => {
if !listening {
for addr in Swarm::external_addresses(&swarm) {
println!("External addr {}", addr.addr);
}
for addr in Swarm::listeners(&swarm) {
println!("Listening on {}", addr);
listening = true;
}
}
return Poll::Pending;
}
}
}
});
future_poll.await;
Ok(())
}
pub fn run(peer_mod: String, port: String) {
block_on(run_async(peer_mod, port)).unwrap();
}
What should i do?