Expand description
An implementation of Discovery V5.
Overview
Discovery v5 is a protocol designed for encrypted peer discovery and topic advertisement. Each peer/node on the network is identified via it’s ENR (Ethereum Name Record), which is essentially a signed key-value store containing the node’s public key and optionally IP address and port.
Discv5 employs a kademlia-like routing table to store and manage discovered peers and topics. The protocol allows for external IP discovery in NAT environments through regular PING/PONG’s with discovered nodes. Nodes return the external IP address that they have received and a simple majority is chosen as our external IP address. If an external IP address is updated, this is produced as an event to notify the swarm (if one is used for this behaviour).
For a simple CLI discovery service see discv5-cli
This protocol is split into four main sections/layers:
- Socket - The
socket
module is responsible for opening the underlying UDP socket. It creates individual tasks for sending/encoding and receiving/decoding packets from the UDP socket. - Handler - The protocol’s communication is encrypted with
AES_GCM
. All node communication undergoes a handshake, which results in aSession
.Session
’s are established when needed and get dropped after a timeout. This section manages the creation and maintenance of sessions between nodes and the encryption/decryption of packets from the socket. It is realised by thehandler::Handler
struct and it runs in its own task. - Service - This section contains the protocol-level logic. In particular it manages the
routing table of known ENR’s, topic registration/advertisement and performs various queries
such as peer discovery. This section is realised by the
Service
struct. This also runs in it’s own thread. - Application - This section is the user-facing API which can start/stop the underlying tasks, initiate queries and obtain metrics about the underlying server.
Event Stream
The Discv5
struct provides access to an event-stream which allows the user to listen to
Discv5Event
that get generated from the underlying server. The stream can be obtained
from the Discv5::event_stream()
function.
Runtimes
Discv5 requires a tokio runtime with timing and io enabled. An explicit runtime can be given
via the configuration. See the Discv5ConfigBuilder
for further details. Such a runtime
must implement the Executor
trait.
If an explicit runtime is not provided via the configuration parameters, it is assumed that
a tokio runtime is present when creating the Discv5
struct. The struct will use the
existing runtime for spawning the underlying server tasks. If a runtime is not present, the
creation of the Discv5
struct will panic.
Usage
A simple example of creating this service is as follows:
use discv5::{enr, enr::{CombinedKey, NodeId}, TokioExecutor, Discv5, Discv5ConfigBuilder};
use std::net::SocketAddr;
// listening address and port
let listen_addr = "0.0.0.0:9000".parse::<SocketAddr>().unwrap();
// construct a local ENR
let enr_key = CombinedKey::generate_secp256k1();
let enr = enr::EnrBuilder::new("v4").build(&enr_key).unwrap();
// build the tokio executor
let mut runtime = tokio::runtime::Builder::new_multi_thread()
.thread_name("Discv5-example")
.enable_all()
.build()
.unwrap();
// default configuration
let config = Discv5ConfigBuilder::new().build();
// construct the discv5 server
let mut 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(listen_addr));
// run a find_node query
runtime.block_on(async {
let found_nodes = discv5.find_node(NodeId::random()).await.unwrap();
println!("Found nodes: {:?}", found_nodes);
});
Re-exports
pub use kbucket::ConnectionDirection;
pub use permit_ban::PermitBanList;
pub use service::TalkRequest;
pub use enr;
Modules
Session and packet handling for the Discv5 Discovery service.
Implementation of a Kademlia routing table as used by a single peer participating in a Kademlia DHT.
This module defines the raw UDP message packets for Discovery v5.1.
The Discovery v5 protocol. See lib.rs
for further details.
Structs
The main Discv5 Service struct. This provides the user-level API for performing queries and interacting with the underlying service.
Configuration parameters that define the performance of the discovery network.
A Key
is a cryptographic hash, identifying both the nodes participating in
the Kademlia DHT, as well as records stored in the DHT.
Manages rate limiting of requests per peer, with differentiated rates per protocol.
User-friendly builder of a RateLimiter
. The user can specify three kinds of rate limits but
must at least set the total quota. The three types are:
Enums
The connection state of a node.
A general error that is used throughout the Discv5 library.
Events that can be produced by the Discv5
event stream.
! A set of configuration parameters to tune the discovery protocol.
Sets the socket type to be established and also determines the type of ENRs that we will store
in our routing table.
We store ENR’s that have a get_contractable_addr()
based on the IpMode
set.