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. 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.
For a simple CLI discovery service see discv5-cli
This protocol is split into four main layers:
socket
: 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 withAES_GCM
. All node communication undergoes a handshake, which results in aSession
. These are established when needed and get dropped after a timeout. The creation and maintenance of sessions between nodes and the encryption/decryption of packets from the socket is realised by thehandler::Handler
struct runnning in its own task.service
: Contains the protocol-level logic. Theservice::Service
manages the routing table of known ENR’s, and performs parallel queries for peer discovery. It also runs in it’s own task.Discv5
: The application level. Manages the user-facing API. It starts/stops the underlying tasks, allows initiating 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
Event
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 ConfigBuilder
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, 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);
});
Re-exports§
pub use kbucket::ConnectionDirection;
pub use kbucket::ConnectionState;
pub use kbucket::Key;
pub use packet::DefaultProtocolId;
pub use packet::ProtocolIdentity;
pub use permit_ban::PermitBanList;
pub use service::TalkRequest;
pub use socket::ListenConfig;
pub use socket::RateLimiter;
pub use socket::RateLimiterBuilder;
pub use enr;
Modules§
- handler
- Session and packet handling for the Discv5 Discovery service.
- kbucket
- Implementation of a Kademlia routing table as used by a single peer participating in a Kademlia DHT.
- metrics
- packet
- This module defines the raw UDP message packets for Discovery v5.1.
- permit_
ban - rpc
- service
- The Discovery v5 protocol. See
lib.rs
for further details. - socket
Structs§
- Config
- Configuration parameters that define the performance of the discovery network.
- Config
Builder - Discv5
- The main Discv5 Service struct. This provides the user-level API for performing queries and interacting with the underlying service.
- Tokio
Executor
Enums§
- Error
- A general error that is used throughout the Discv5 library.
- Event
- Events that can be produced by the
Discv5
event stream. - IpMode
- 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 theIpMode
set. - Query
Error - Request
Error - Response
Error