Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,51 @@ leanEthereum Consensus Client written in Rust using Grandine's libraries.
Run in debug mode via terminal (with XMSS signing):
```
RUST_LOG=info ./target/release/lean_client \
--genesis ../lean-quickstart/local-devnet/genesis/config.yaml \
--validator-registry-path ../lean-quickstart/local-devnet/genesis/validators.yaml \
--hash-sig-key-dir ../lean-quickstart/local-devnet/genesis/hash-sig-keys \
--genesis ../../lean-quickstart/local-devnet/genesis/config.yaml \
--validator-registry-path ../../lean-quickstart/local-devnet/genesis/validators.yaml \
--hash-sig-key-dir ../../lean-quickstart/local-devnet/genesis/hash-sig-keys \
--node-id qlean_0 \
--node-key ../lean-quickstart/local-devnet/genesis/qlean_0.key \
--node-key ../../lean-quickstart/local-devnet/genesis/qlean_0.key \
--port 9003 \
--disable-discovery \
--bootnodes "/ip4/127.0.0.1/udp/9001/quic-v1/p2p/16Uiu2HAkvi2sxT75Bpq1c7yV2FjnSQJJ432d6jeshbmfdJss1i6f" \
--bootnodes "/ip4/127.0.0.1/udp/9002/quic-v1/p2p/16Uiu2HAmPQhkD6Zg5Co2ee8ShshkiY4tDePKFARPpCS2oKSLj1E1" \
--bootnodes "/ip4/127.0.0.1/udp/9004/quic-v1/p2p/16Uiu2HAm7TYVs6qvDKnrovd9m4vvRikc4HPXm1WyLumKSe5fHxBv"
```
4. Leave client running for a few minutes and observe warnings, errors, check if blocks are being justified and finalized (don't need debug mode for this last one)

## Testing discovery

1. Build the client:
```bash
cd lean_client/
cargo build --release
```

2. Start the bootnode

Run in the terminal:
```
RUST_LOG=info ./target/release/lean_client \
--port 9000 \
--discovery-port 9100
```

3. Start the other nodes

Run in the terminal:
```
RUST_LOG=info ./target/release/lean_client \
--port 9001 \
--discovery-port 9101 \
--bootnodes "<bootnode-enr>"
```

```
RUST_LOG=info ./target/release/lean_client \
--port 9002 \
--discovery-port 9102 \
--bootnodes "<bootnode-enr>"
```

After a minute all the nodes should be synced up and see each other
4 changes: 4 additions & 0 deletions lean_client/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion lean_client/networking/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ snap = {workspace = true}
sha2 = { workspace = true }
anyhow = { workspace = true }
async-trait = "0.1"
discv5 = "0.10.2"
enr = { version = "0.13", features = ["k256"] }
k256 = "0.13"
futures = "0.3"
libp2p-identity = { version = "0.2", features = ["secp256k1"] }
libp2p-mplex = "0.39"
Expand All @@ -26,7 +29,11 @@ yamux = "0.12"
ssz = { workspace = true }
serde = { workspace = true }
serde_yaml = { workspace = true }
discv5 = "0.10.2"
hex = "0.4.3"
tiny-keccak = "2.0.2"
derive_more = "2.1.1"

[dev-dependencies]
hex = "0.4"
num-bigint = "0.4"
num-traits = "0.2"
86 changes: 82 additions & 4 deletions lean_client/networking/src/bootnodes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use std::sync::Arc;

use discv5::enr::CombinedKey;
use enr::Enr;
use libp2p::Multiaddr;
use tracing::warn;

use crate::discovery::{DiscoveryService, parse_enr};

pub trait BootnodeSource: Send + Sync {
fn to_multiaddrs(&self) -> Vec<Multiaddr>;
Expand All @@ -24,17 +29,90 @@ impl BootnodeSource for Arc<[Multiaddr]> {
}
}

#[derive(Debug, Clone)]
pub enum Bootnode {
Multiaddr(Multiaddr),
Enr(Enr<CombinedKey>),
}

impl Bootnode {
pub fn parse(s: &str) -> Option<Self> {
if s.starts_with("enr:") {
match parse_enr(s) {
Ok(enr) => Some(Bootnode::Enr(enr)),
Err(e) => {
warn!(bootnode = s, error = ?e, "Failed to parse ENR bootnode");
None
}
}
} else {
match s.parse::<Multiaddr>() {
Ok(addr) => Some(Bootnode::Multiaddr(addr)),
Err(e) => {
warn!(bootnode = s, error = ?e, "Failed to parse Multiaddr bootnode");
None
}
}
}
}

pub fn to_multiaddr(&self) -> Option<Multiaddr> {
match self {
Bootnode::Multiaddr(addr) => Some(addr.clone()),
Bootnode::Enr(enr) => DiscoveryService::enr_to_multiaddr(enr),
}
}

pub fn as_enr(&self) -> Option<&Enr<CombinedKey>> {
match self {
Bootnode::Enr(enr) => Some(enr),
Bootnode::Multiaddr(_) => None,
}
}
}

#[derive(Debug, Clone, Default)]
pub struct StaticBootnodes(Vec<Multiaddr>);
pub struct StaticBootnodes {
multiaddrs: Vec<Multiaddr>,
enrs: Vec<Enr<CombinedKey>>,
}

impl StaticBootnodes {
pub fn new<T: Into<Vec<Multiaddr>>>(addrs: T) -> Self {
StaticBootnodes(addrs.into())
pub fn new(bootnodes: Vec<Bootnode>) -> Self {
let mut multiaddrs = Vec::new();
let mut enrs = Vec::new();

for bootnode in bootnodes {
match bootnode {
Bootnode::Multiaddr(addr) => multiaddrs.push(addr),
Bootnode::Enr(enr) => {
// Convert ENR to multiaddr for libp2p connection
if let Some(addr) = DiscoveryService::enr_to_multiaddr(&enr) {
multiaddrs.push(addr);
}
enrs.push(enr);
}
}
}

StaticBootnodes { multiaddrs, enrs }
}

pub fn parse(bootnode_strs: &[String]) -> Self {
let bootnodes: Vec<Bootnode> = bootnode_strs
.iter()
.filter_map(|s| Bootnode::parse(s))
.collect();
Self::new(bootnodes)
}

pub fn enrs(&self) -> &[Enr<CombinedKey>] {
&self.enrs
}
}

impl BootnodeSource for StaticBootnodes {
fn to_multiaddrs(&self) -> Vec<Multiaddr> {
self.0.clone()
self.multiaddrs.clone()
}
}
40 changes: 40 additions & 0 deletions lean_client/networking/src/discovery/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::net::IpAddr;

use discv5::enr::CombinedKey;
use enr::Enr;

#[derive(Debug, Clone)]
pub struct DiscoveryConfig {
pub enabled: bool,
pub udp_port: u16,
pub libp2p_port: u16,
pub listen_address: IpAddr,
pub bootnodes: Vec<Enr<CombinedKey>>,
}

impl DiscoveryConfig {
pub fn new(listen_address: IpAddr, udp_port: u16, libp2p_port: u16) -> Self {
Self {
enabled: true,
udp_port,
libp2p_port,
listen_address,
bootnodes: Vec::new(),
}
}

pub fn with_bootnodes(mut self, bootnodes: Vec<Enr<CombinedKey>>) -> Self {
self.bootnodes = bootnodes;
self
}

pub fn disabled() -> Self {
Self {
enabled: false,
udp_port: 0,
libp2p_port: 0,
listen_address: IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED),
bootnodes: Vec::new(),
}
}
}
Loading
Loading