Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ssv_network_config for configurable networks #121

Merged
merged 5 commits into from
Feb 5, 2025
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
13 changes: 12 additions & 1 deletion Cargo.lock

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

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"anchor/client",
"anchor/common/bls_lagrange",
"anchor/common/qbft",
"anchor/common/ssv_network_config",
"anchor/common/ssv_types",
"anchor/common/version",
"anchor/database",
Expand Down Expand Up @@ -36,6 +37,7 @@ processor = { path = "anchor/processor" }
qbft = { path = "anchor/common/qbft" }
qbft_manager = { path = "anchor/qbft_manager" }
signature_collector = { path = "anchor/signature_collector" }
ssv_network_config = { path = "anchor/common/ssv_network_config" }
ssv_types = { path = "anchor/common/ssv_types" }

beacon_node_fallback = { git = "https://github.com/sigp/lighthouse", rev = "1a77f7a0" }
Expand Down Expand Up @@ -81,6 +83,7 @@ derive_more = { version = "1.0.0", features = ["full"] }
dirs = "6.0.0"
discv5 = "0.9.0"
either = "1.13.0"
enr = "0.13.0"
ethereum_ssz = "0.7"
ethereum_ssz_derive = "0.7.0"
futures = "0.3.30"
Expand All @@ -94,6 +97,7 @@ rand = "0.8.5"
reqwest = "0.12.12"
rusqlite = "0.28.0"
serde = { version = "1.0.208", features = ["derive"] }
serde_yaml = "0.9"
sha2 = "0.10.8"
strum = { version = "0.26.3", features = ["derive"] }
tokio = { version = "1.39.2", features = [
Expand Down
2 changes: 1 addition & 1 deletion anchor/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ dirs = { workspace = true }
eth = { workspace = true }
eth2 = { workspace = true }
eth2_config = { workspace = true }
eth2_network_config = { workspace = true }
ethereum_hashing = "0.7.0"
fdlimit = "0.3"
http_api = { workspace = true }
Expand All @@ -33,6 +32,7 @@ serde = { workspace = true }
signature_collector = { workspace = true }
slashing_protection = { workspace = true }
slot_clock = { workspace = true }
ssv_network_config = { workspace = true }
ssv_types = { workspace = true }
strum = { workspace = true }
task_executor = { workspace = true }
Expand Down
36 changes: 22 additions & 14 deletions anchor/client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// use clap_utils::{flags::DISABLE_MALLOC_TUNING_FLAG, parse_optional, parse_required};

use crate::cli::Anchor;
use eth2_network_config::Eth2NetworkConfig;
use network::{ListenAddr, ListenAddress};
use sensitive_url::SensitiveUrl;
use ssv_network_config::SsvNetworkConfig;
use std::fs;
use std::net::IpAddr;
use std::path::PathBuf;
use tracing::warn;
use tracing::{error, warn};

pub const DEFAULT_BEACON_NODE: &str = "http://localhost:5052/";
pub const DEFAULT_EXECUTION_NODE: &str = "http://localhost:8545/";
Expand All @@ -25,8 +25,8 @@ pub const CUSTOM_TESTNET_DIR: &str = "custom";
pub struct Config {
/// The data directory, which stores all validator databases
pub data_dir: PathBuf,
/// The Eth2 Network to use
pub eth2_network: Eth2NetworkConfig,
/// The SSV Network to use
pub ssv_network: SsvNetworkConfig,
/// The http endpoints of the beacon node APIs.
///
/// Should be similar to `["http://localhost:8080"]`
Expand Down Expand Up @@ -58,13 +58,14 @@ pub struct Config {
impl Config {
/// Build a new configuration from defaults.
///
/// eth2_network: We pass this because it would be expensive to uselessly get a default eagerly.
fn new(eth2_network: Eth2NetworkConfig) -> Self {
/// ssv_network: We pass this because it would be expensive to uselessly get a default eagerly.
fn new(ssv_network: SsvNetworkConfig) -> Self {
let data_dir = dirs::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join(DEFAULT_ROOT_DIR)
.join(
eth2_network
ssv_network
.eth2_network
.config
.config_name
.as_deref()
Expand All @@ -82,7 +83,7 @@ impl Config {

Self {
data_dir,
eth2_network,
ssv_network,
beacon_nodes,
proposer_nodes: vec![],
execution_nodes,
Expand All @@ -101,11 +102,10 @@ impl Config {
/// Returns a `Default` implementation of `Self` with some parameters modified by the supplied
/// `cli_args`.
pub fn from_cli(cli_args: &Anchor) -> Result<Config, String> {
let eth2_network = if let Some(_testnet_dir) = &cli_args.testnet_dir {
// todo
return Err("testnet dir not yet supported".into());
let eth2_network = if let Some(testnet_dir) = &cli_args.testnet_dir {
SsvNetworkConfig::load(testnet_dir.clone())
} else {
Eth2NetworkConfig::constant(&cli_args.network)
SsvNetworkConfig::constant(&cli_args.network)
.and_then(|net| net.ok_or_else(|| format!("Unknown network {}", cli_args.network)))
}?;

Expand Down Expand Up @@ -144,7 +144,8 @@ pub fn from_cli(cli_args: &Anchor) -> Result<Config, String> {
for addr in cli_args.boot_nodes_enr.clone() {
match addr.parse() {
Ok(enr) => config.network.boot_nodes_enr.push(enr),
Err(_) => {
Err(err) => {
error!(enr = addr, err, "Failed to parse boot node ENR, skipping");
// parsing as ENR failed, try as Multiaddr
// let multi: Multiaddr = addr
// .parse()
Expand All @@ -159,6 +160,13 @@ pub fn from_cli(cli_args: &Anchor) -> Result<Config, String> {
}
}
}
if cli_args.boot_nodes_enr.is_empty() {
config.network.boot_nodes_enr = config
.ssv_network
.ssv_boot_nodes
.clone()
.unwrap_or_default();
}

config.beacon_nodes_tls_certs = cli_args.beacon_nodes_tls_certs.clone();
config.execution_nodes_tls_certs = cli_args.execution_nodes_tls_certs.clone();
Expand Down Expand Up @@ -395,7 +403,7 @@ mod tests {
// Ensures the default config does not panic.
fn default_config() {
Config::new(
Eth2NetworkConfig::constant(DEFAULT_HARDCODED_NETWORK)
SsvNetworkConfig::constant(DEFAULT_HARDCODED_NETWORK)
.unwrap()
.unwrap(),
);
Expand Down
8 changes: 2 additions & 6 deletions anchor/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl Client {
"Starting the Anchor client"
);

let spec = Arc::new(config.eth2_network.chain_spec::<E>()?);
let spec = Arc::new(config.ssv_network.eth2_network.chain_spec::<E>()?);

let key = read_or_generate_private_key(&config.data_dir.join("key.pem"))?;
let err = |e| format!("Unable to derive public key: {e:?}");
Expand Down Expand Up @@ -319,11 +319,7 @@ impl Client {
.full
.to_string(),
beacon_url: "".to_string(), // this one is not actually needed :)
network: match spec.config_name.as_deref() {
Some("mainnet") => eth::Network::Mainnet,
Some("holesky") => eth::Network::Holesky,
_ => return Err(format!("Unsupported network {:?}", spec.config_name)),
},
network: config.ssv_network,
historic_finished_notify: Some(historic_finished_tx),
},
)
Expand Down
11 changes: 11 additions & 0 deletions anchor/common/ssv_network_config/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "ssv_network_config"
version = "0.1.0"
authors = ["Sigma Prime <contact@sigmaprime.io"]
edition = { workspace = true }

[dependencies]
alloy = { workspace = true }
enr = { workspace = true }
eth2_network_config = { workspace = true }
serde_yaml = { workspace = true }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SSV Labs
- enr:-Ja4QKFD3u5tZob7xukp-JKX9QJMFqqI68cItsE4tBbhsOyDR0M_1UUjb35hbrqvTP3bnXO_LnKh-jNLTeaUqN4xiduGAZKaP_sagmlkgnY0gmlwhDb0fh6Jc2VjcDI1NmsxoQMw_H2anuiqP9NmEaZwbUfdvPFog7PvcKmoVByDa576SINzc3YBg3RjcIITioN1ZHCCD6I
- enr:-Li4QFIQzamdvTxGJhvcXG_DFmCeyggSffDnllY5DiU47pd_K_1MRnSaJimWtfKJ-MD46jUX9TwgW5Jqe0t4pH41RYWGAYuFnlyth2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhCLdu_SJc2VjcDI1NmsxoQN4v-N9zFYwEqzGPBBX37q24QPFvAVUtokIo1fblIsmTIN0Y3CCE4uDdWRwgg-j
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
181612
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SSV Labs
- enr:-Ja4QAbDe5XANqJUDyJU1GmtS01qqMwDYx9JNZgymjBb55fMaha80E2HznRYoUGy6NFVSvs1u1cFqSM0MgJI-h1QKLeGAZKaTo7LgmlkgnY0gmlwhDQrfraJc2VjcDI1NmsxoQNEj0Pgq9-VxfeX83LPDOUPyWiTVzdI-DnfMdO1n468u4Nzc3YBg3RjcIITioN1ZHCCD6I
- enr:-Li4QHEPYASj5ZY3BXXKXAoWcoIw0ChgUlTtfOSxgNlYxlmpEWUR_K6Nr04VXsMpWSQxWWM4QHDyypnl92DQNpWkMS-GAYiWUvo8h2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhCzmKVSJc2VjcDI1NmsxoQOW29na1pUAQw4jF3g0zsPgJG89ViHJOOkHFFklnC2UyIN0Y3CCE4qDdWRwgg-i
# 0NEinfra bootnode
- enr:-Li4QDwrOuhEq5gBJBzFUPkezoYiy56SXZUwkSD7bxYo8RAhPnHyS0de0nOQrzl-cL47RY9Jg8k6Y_MgaUd9a5baYXeGAYnfZE76h2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhDaTS0mJc2VjcDI1NmsxoQMZzUHaN3eClRgF9NAqRNc-ilGpJDDJxdenfo4j-zWKKYN0Y3CCE4iDdWRwgg-g
# Eridian
- enr:-Li4QIzHQ2H82twhvsu8EePZ6CA1gl0_B0WWsKaT07245TkHUqXay-MXEgObJB7BxMFl8TylFxfnKNxQyGTXh-2nAlOGAYuraxUEh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBKCzUSJc2VjcDI1NmsxoQNKskkQ6-mBdBWr_ORJfyHai5uD0vL6Fuw90X0sPwmRsoN0Y3CCE4iDdWRwgg-g
# CryptoManufaktur
- enr:-Li4QH7FwJcL8gJj0zHAITXqghMkG-A5bfWh2-3Q7vosy9D1BS8HZk-1ITuhK_rfzG3v_UtBDI6uNJZWpdcWfrQFCxKGAYnQ1DRCh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLb3g2Jc2VjcDI1NmsxoQKeSDcZWSaY9FC723E9yYX1Li18bswhLNlxBZdLfgOKp4N0Y3CCE4mDdWRwgg-h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0xDD9BC35aE942eF0cFa76930954a156B3fF30a4E1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
17507487
104 changes: 104 additions & 0 deletions anchor/common/ssv_network_config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use alloy::primitives::Address;
use enr::{CombinedKey, Enr};
use eth2_network_config::Eth2NetworkConfig;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::str::FromStr;

macro_rules! include_str_for_net {
($network:ident, $file:literal) => {
include_str!(concat!(
"../built_in_network_configs/",
stringify!($network),
"/",
$file
))
};
}

macro_rules! get_hardcoded {
($network:ident) => {
(
include_str_for_net!($network, "ssv_boot_enr.yaml"),
include_str_for_net!($network, "ssv_contract_address.txt"),
include_str_for_net!($network, "ssv_contract_block.txt"),
)
};
}

#[derive(Clone, Debug)]
pub struct SsvNetworkConfig {
pub eth2_network: Eth2NetworkConfig,
pub ssv_boot_nodes: Option<Vec<Enr<CombinedKey>>>,
pub ssv_contract: Address,
pub ssv_contract_block: u64,
}

impl SsvNetworkConfig {
pub fn constant(name: &str) -> Result<Option<Self>, String> {
let (enr_yaml, address, block) = match name {
"mainnet" => get_hardcoded!(mainnet),
"holesky" => get_hardcoded!(holesky),
_ => return Ok(None),
};
let Some(eth2_network) = Eth2NetworkConfig::constant(name)? else {
return Ok(None);
};
Ok(Some(Self {
eth2_network,
ssv_boot_nodes: Some(
serde_yaml::from_str(enr_yaml).map_err(|_| "Unable to parse built-in yaml!")?,
),
ssv_contract: address
.parse()
.map_err(|_| "Unable to parse built-in address!")?,
ssv_contract_block: block
.parse()
.map_err(|_| "Unable to parse built-in block!")?,
}))
}

pub fn load(base_dir: PathBuf) -> Result<Self, String> {
let ssv_boot_nodes_path = base_dir.join("ssv_boot_enr.yaml");
let ssv_boot_nodes = ssv_boot_nodes_path
.exists()
.then(|| {
File::open(&ssv_boot_nodes_path)
.map_err(|e| format!("Unable to read {ssv_boot_nodes_path:?}: {e}"))
.and_then(|f| {
serde_yaml::from_reader(f)
.map_err(|e| format!("Unable to parse {ssv_boot_nodes_path:?}: {e}"))
})
})
.transpose()?;

Ok(Self {
ssv_boot_nodes,
ssv_contract: read(&base_dir.join("ssv_contract_address.txt"))?,
ssv_contract_block: read(&base_dir.join("ssv_contract_block.txt"))?,
eth2_network: Eth2NetworkConfig::load(base_dir)?,
})
}
}

fn read<T: FromStr>(file: &Path) -> Result<T, String> {
std::fs::read_to_string(file)
.map_err(|e| format!("Unable to read {file:?}: {e}"))?
.parse()
.map_err(|_| format!("Unable to parse {file:?}"))
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_holesky() {
SsvNetworkConfig::constant("holesky").unwrap().unwrap();
}

#[test]
fn test_mainnet() {
SsvNetworkConfig::constant("mainnet").unwrap().unwrap();
}
}
1 change: 1 addition & 0 deletions anchor/eth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ openssl = { workspace = true }
rand = "0.8.5"
reqwest = { workspace = true }
serde = { workspace = true }
ssv_network_config = { workspace = true }
ssv_types = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
Expand Down
5 changes: 3 additions & 2 deletions anchor/eth/execution.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use base64::prelude::*;
use database::NetworkDatabase;
use eth::{Config, Network, SsvEventSyncer};
use eth::{Config, SsvEventSyncer};
use openssl::rsa::Rsa;
use ssv_network_config::SsvNetworkConfig;
use std::path::Path;
use std::sync::Arc;
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
Expand All @@ -27,7 +28,7 @@ async fn main() {
http_url: String::from(rpc_endpoint),
ws_url: String::from(ws_endpoint),
beacon_url: String::from(beacon_endpoint),
network: Network::Mainnet,
network: SsvNetworkConfig::constant("mainnet").unwrap().unwrap(),
historic_finished_notify: None,
};

Expand Down
2 changes: 1 addition & 1 deletion anchor/eth/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use sync::{Config, Network, SsvEventSyncer};
pub use sync::{Config, SsvEventSyncer};
mod error;
mod event_parser;
mod event_processor;
Expand Down
Loading