• Stars
    star
    142
  • Rank 250,264 (Top 6 %)
  • Language
    Rust
  • License
    Apache License 2.0
  • Created about 4 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Rust implementation of Discovery v5

discv5

Build Status Doc Status Crates Status

Documentation at docs.rs

Overview

This is a rust implementation of the Discovery v5 peer discovery protocol.

Discovery v5 is a protocol designed for encrypted peer discovery (and topic advertisement tba). Each peer/node on the network is identified via it's ENR (Ethereum Node 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

Usage

A simple example of creating this service is as follows:

   use discv5::{enr, enr::{CombinedKey, NodeId}, TokioExecutor, Discv5, Discv5ConfigBuilder};
   use discv5::socket::ListenConfig;
   use std::net::SocketAddr;

   // 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();

   // configuration for the sockets to listen on
   let listen_config = ListenConfig::Ipv4 {
       ip: Ipv4Addr::UNSPECIFIED,
       port: 9000,
   };

   // default configuration
   let config = Discv5ConfigBuilder::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);
   });

Addresses in ENRs

This protocol will drop messages (i.e not respond to requests) from peers that advertise non-contactable address in their ENR (e.g 127.0.0.1 when connecting to non-local nodes). This section explains the rationale behind this design decision.

An ENR is a signed record which is primarily used in this protocol for identifying and connecting to peers. ENRs have OPTIONAL ip and port fields.

If a node does not know its contactable address (i.e if it is behind a NAT), it should leave these fields empty. This is done for the following reasons:

  1. When we receive an ENR we must decide whether to add it to our local routing table and advertise it to other peers. If a node has put some non-contactable address in the ENR (e.g 127.0.0.1 when connecting to non-local nodes) we cannot use this ENR to contact the node and we therefore do not wish to advertise it to other nodes. Putting a non-contactable address is therefore functionally equivalent to leaving the fields empty.
  2. For every new inbound connection, we do not wish to check that the address given to us in an ENR is contactable. We do not want the scenario, where any peer can give us any address and force us to attempt a connection to arbitrary addresses (to check their validity) as it consumes unnecessary bandwidth and we want to avoid DOS attacks where malicious users spam many nodes attempting them all to send messages to a victim IP.

How this protocol handles advertised IPs in ENRs

To handle the above two cases this protocol filters out and only advertises contactable ENRs. It doesn't make sense for a discovery protocol to advertise non-contactable peers.

This is done in the following way:

  1. If a connecting node provides an ENR without specifying an address (this should be the default case for most nodes behind a NAT, or ones that have just started) we consider this valid. Typically this will occur when a node has yet to determine its external IP address via PONG responses and has not updated its ENR to a contactable address. In this case, we respond to all requests this peer asks for but we do not store or add its ENR to our routing table.
  2. If a peer connects to us with an ENR that specifies an IP address that matches the src address we received the packet from, we consider this peer valid and attempt to add it to our local routing table and therefore may advertise its ENR to others.
  3. If a peer connects to us with an ENR that specifies an IP address that does not match the src socket it connects to us on (e.g 127.0.0.1, or potentially some internal subnet IP that is unreachable from our current network) we consider this peer malicious/faulty and drop all packets. This way we can efficiently drop peers that may try to get us to send messages to arbitrary remote IPs, and we can be sure that all ENRs in our routing table are contactable (at least by our local node at some point in time).

More Repositories

1

lighthouse

Ethereum consensus client in Rust
Rust
2,745
star
2

solidity-security-blog

Comprehensive list of known attack vectors and common anti-patterns
1,321
star
3

beacon-fuzz

Differential Fuzzer for Ethereum 2.0
Rust
154
star
4

lighthouse-metrics

A docker-compose with Grafana + Prometheus for monitoring Lighthouse
Dockerfile
138
star
5

public-audits

Collection of public security reviews
115
star
6

blockprint

Block fingerprinting for the beacon chain, for client diversity metrics
Python
85
star
7

superstruct

Rust library for versioned data types
Rust
64
star
8

eleel

Execution layer multiplexer
Rust
50
star
9

enr

Ethereum Node Record
Rust
50
star
10

siren

User interface for Lighthouse
TypeScript
44
star
11

lighthouse-docker

A docker-compose environment for running the Lighthouse Eth2 client
Shell
33
star
12

milagro_bls

BLS12-381 cryptography using Apache Milagro
Rust
26
star
13

cbc-casper-js

JS implementation of Vlad Zamfir's CBC Casper TFG
JavaScript
24
star
14

positions-vacant

Vacant Positions at Sigma Prime
23
star
15

presentations

Collection of presentations given by Sigma Prime
17
star
16

ecies-parity

JavaScript Elliptic Curve Integrated Encryption Scheme (ECIES) Library - Based off Parity's implementation
JavaScript
17
star
17

tree_hash

SSZ-compatible tree hash implementation optimised for speed and security
Rust
16
star
18

opcode-purity

A document describing purity detection in EVM opcode
15
star
19

metastruct

Abstractions for iterating and mapping over struct fields
Rust
14
star
20

milhouse

Persistent binary merkle tree
Rust
13
star
21

ethereum_hashing

Hashing primitives used in Ethereum
Rust
11
star
22

ethereum_ssz

SimpleSerialize (SSZ) implementation optimised for speed and security
Rust
10
star
23

rust-bls-remote-signer

Remote Signer API for BLS12-381
9
star
24

ethereum_serde_utils

Serialization and deserialization utilities for JSON representations of Ethereum types
Rust
8
star
25

gossipsub-testground

Testground plans for gossipsub
Rust
7
star
26

serde_array_query

Serde deserialization format for HTTP query string arrays
Rust
5
star
27

serialization_sandbox

Sandbox for testing different serialization mechanisms
Python
5
star
28

serenity-benches

Results from benchmarking Serenity state processing with Lighthouse.
3
star
29

verified-consensus

Formalisation of Ethereum consensus in Isabelle/HOL
Isabelle
3
star
30

shuffling_sandbox

A sandbox for testing shuffling functions
Python
3
star
31

eth-npg

National Portrait Gallery generates ethereum network profiles for testing
Rust
3
star
32

lighthouse-tg-bot

A Telegram bot for pushing notifications about Lighthouse validator performance
Python
3
star
33

beacon-fuzz-corpora

Corpora for the beacon-fuzz repository (Differential fuzzer for Ethereum 2.0)
3
star
34

unsafe-eth2-deposit-contract

An UNSAFE deposit contract for testing Lighthouse. DO NOT USE.
Python
3
star
35

eth2.0-resources

A collection of informal resources generated during the development of sigp/lightouse
Python
3
star
36

E2E

Ethereum 2 Ethereum - Encrypted Ethereum Messaging Dapp
JavaScript
2
star
37

sha2_fixed_64

Optimised SHA256 for 64 byte messages
Rust
2
star
38

havven-audit

Security review of the Havven contracts (not including token-sale contracts)
Python
2
star
39

ethereum-pubkey-collector

Collects Ethereum public keys from signed transactions on the chain.
JavaScript
2
star
40

audit-horizon-state-token-sale

Public audit of the Horizon State token sale smart contracts
JavaScript
1
star
41

crate_template

Rust crate template for SigP code published on crates.io
1
star
42

lighthouse-merge-f2f

Resources used during the October 2021 merge interop
Shell
1
star
43

lighthouse-kintsugi

Tracks the progress of Lighthouse on the Kintsugi interop effort
Shell
1
star
44

ssz_types

List, vector and bitfield types for SSZ
Rust
1
star
45

polkafuzz

Fuzzing Framework for Polkadot
Rust
1
star
46

lighthouse-pm

Lighthouse Project Management
1
star
47

reduced_tree_fork_choice

LMD GHOST fork choice implementation, conceptualized by Nate Rush
Rust
1
star
48

aave-public-tests

Public testing artifacts for Aave reviews
Solidity
1
star