To use discv5, you need to generate a local ENR, configure your listening socket, and provide a tokio runtime. The service manages a Kademlia-like routing table and allows you to perform queries like find_node.
Note that discv5 requires a tokio runtime with timing and IO enabled. If you do not provide an explicit Executor via ConfigBuilder, the library will attempt to use the existing tokio runtime; if none is found, the Discv5::new call will panic.
use discv5::{enr, enr::{CombinedKey, Enr, NodeId}, TokioExecutor, Discv5, ConfigBuilder};
use discv5::socket::ListenConfig;
use std::net::{Ipv4Addr, SocketAddr};
// construct a local ENR
let enr_key = CombinedKey::generate_secp256k1();
let enr = enr::Enr::empty(&enr_key).unwrap();
// build the tokio executor
let mut runtime = tokio::runtime::Builder::new_multi_thread()
.thread_name("Discv5-example")
.enable_all()
.build()
.unwrap();
// configuration for the sockets to listen on
let listen_config = ListenConfig::Ipv4 {
ip: Ipv4Addr::UNSPECIFIED,
port: 9000,
};
// default configuration
let config = ConfigBuilder::new(listen_config).build();
// construct the discv5 server
let mut discv5: Discv5 = Discv5::new(enr, enr_key, config).unwrap();
// In order to bootstrap the routing table an external ENR should be added
// This can be done via add_enr. I.e.:
// discv5.add_enr(<ENR>)
// start the discv5 server
runtime.block_on(discv5.start());
// run a find_node query
runtime.block_on(async {
let found_nodes = discv5.find_node(NodeId::random()).await.unwrap();
println!("Found nodes: {:?}", found_nodes);
});