From 8f28bea18949c056fe2b47b01ecd1ed6f19aaede Mon Sep 17 00:00:00 2001 From: Artur Yurii Korchynskyi <42449190+akorchyn@users.noreply.github.com> Date: Fri, 8 Dec 2023 20:57:42 +0200 Subject: [PATCH 1/3] sepolia (#88) --- crates/consensus-types/src/network_config.rs | 13 ++ crates/eth2-pallet-init/src/eth_network.rs | 6 +- crates/eth2-pallet-init/src/init_pallet.rs | 1 + crates/lc-relay-config/src/lib.rs | 2 +- eth2substrate-block-relay-rs/src/config.rs | 117 ++++++++++++++++++ .../src/test_utils.rs | 2 + 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 eth2substrate-block-relay-rs/src/config.rs diff --git a/crates/consensus-types/src/network_config.rs b/crates/consensus-types/src/network_config.rs index aedd18f3..bf0d97cc 100644 --- a/crates/consensus-types/src/network_config.rs +++ b/crates/consensus-types/src/network_config.rs @@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize}; pub enum Network { Mainnet, Goerli, + Sepolia, } impl FromStr for Network { @@ -17,6 +18,7 @@ impl FromStr for Network { match input.to_lowercase().as_str() { "mainnet" => Ok(Network::Mainnet), "goerli" => Ok(Network::Goerli), + "sepolia" => Ok(Network::Sepolia), _ => Err(alloc::format!("Unknown network: {input}")), } } @@ -56,6 +58,17 @@ impl NetworkConfig { capella_fork_version: [0x03, 0x00, 0x10, 0x20], capella_fork_epoch: 162304, }, + Network::Sepolia => Self { + genesis_validators_root: [ + 0x91, 0x43, 0xaa, 0x7c, 0x61, 0x5a, 0x7f, 0x71, 0x15, 0xe2, 0xb6, 0xaa, 0xc3, + 0x19, 0xc0, 0x35, 0x29, 0xdf, 0x82, 0x42, 0xae, 0x70, 0x5f, 0xba, 0x9d, 0xf3, + 0x9b, 0x79, 0xc5, 0x9f, 0xa8, 0xb1, + ], + bellatrix_fork_version: [144, 0, 0, 113], + bellatrix_fork_epoch: 100, + capella_fork_version: [144, 0, 0, 114], + capella_fork_epoch: 56832, + }, } } diff --git a/crates/eth2-pallet-init/src/eth_network.rs b/crates/eth2-pallet-init/src/eth_network.rs index f12a1f40..1011a288 100644 --- a/crates/eth2-pallet-init/src/eth_network.rs +++ b/crates/eth2-pallet-init/src/eth_network.rs @@ -10,6 +10,7 @@ use std::{ pub enum EthNetwork { Mainnet, Goerli, + Sepolia } #[derive(Debug, Clone, Deserialize)] @@ -17,7 +18,7 @@ pub struct IncorrectEthNetwork; impl Display for IncorrectEthNetwork { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Unknown Ethereum network. Possible networks: 'Mainnet', 'Goerli'") + write!(f, "Unknown Ethereum network. Possible networks: 'Mainnet', 'Goerli', 'Sepolia'") } } @@ -34,6 +35,7 @@ impl EthNetwork { match self { EthNetwork::Mainnet => "mainnet", EthNetwork::Goerli => "goerli", + EthNetwork::Sepolia => "sepolia" } } @@ -41,6 +43,7 @@ impl EthNetwork { match self { EthNetwork::Mainnet => webb_proposals::TypedChainId::Evm(1), EthNetwork::Goerli => webb_proposals::TypedChainId::Evm(5), + EthNetwork::Sepolia => webb_proposals::TypedChainId::Evm(11155111) } } } @@ -52,6 +55,7 @@ impl FromStr for EthNetwork { match s.to_lowercase().as_str() { "mainnet" => Ok(EthNetwork::Mainnet), "goerli" => Ok(EthNetwork::Goerli), + "sepolia" => Ok(EthNetwork::Sepolia), _ => Err(IncorrectEthNetwork), } } diff --git a/crates/eth2-pallet-init/src/init_pallet.rs b/crates/eth2-pallet-init/src/init_pallet.rs index cc59fffd..511f8cdf 100644 --- a/crates/eth2-pallet-init/src/init_pallet.rs +++ b/crates/eth2-pallet-init/src/init_pallet.rs @@ -41,6 +41,7 @@ pub fn get_typed_chain_id(config: &Config) -> TypedChainId { match config.ethereum_network { crate::eth_network::EthNetwork::Mainnet => TypedChainId::Evm(1), crate::eth_network::EthNetwork::Goerli => TypedChainId::Evm(5), + crate::eth_network::EthNetwork::Sepolia => TypedChainId::Evm(11155111), } } diff --git a/crates/lc-relay-config/src/lib.rs b/crates/lc-relay-config/src/lib.rs index 380488c3..27194b26 100644 --- a/crates/lc-relay-config/src/lib.rs +++ b/crates/lc-relay-config/src/lib.rs @@ -22,7 +22,7 @@ pub struct RelayConfig { // Path to the file with a secret key for signer account pub path_to_signer_secret_key: String, - // The Ethereum network name (Mainnet, Goerli) + // The Ethereum network name (Mainnet, Goerli, Sepolia) pub ethereum_network: EthNetwork, // Period of submission light client updates. Once in N epochs. diff --git a/eth2substrate-block-relay-rs/src/config.rs b/eth2substrate-block-relay-rs/src/config.rs new file mode 100644 index 00000000..af2a21b5 --- /dev/null +++ b/eth2substrate-block-relay-rs/src/config.rs @@ -0,0 +1,117 @@ +use dotenvy::dotenv; +use eth2_pallet_init::eth_network::EthNetwork; +use eth_rpc_client::beacon_rpc_client::BeaconRPCVersion; +use reqwest::Url; +use serde::{Deserialize, Serialize}; +use std::{io::Read, path::PathBuf}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Config { + // endpoint to a full node of Eth2 Beacon chain with Light Client API + pub beacon_endpoint: String, + + // endpoint for the Ethereum full node, which supports Eth1 RPC API + pub eth1_endpoint: String, + + // the max number of headers submitted in one batch to eth client + pub headers_batch_size: u32, + + // endpoint for a full node on the Substrate chain + pub substrate_endpoint: String, + + // Path to the file with a secret key for signer account + pub path_to_signer_secret_key: String, + + // The Ethereum network name (Mainnet, Goerli, Sepolia) + pub ethereum_network: EthNetwork, + + // Period of submission light client updates. Once in N epochs. + pub interval_between_light_client_updates_submission_in_epochs: u64, + + // maximum gap in slots between submitting light client update + pub max_blocks_for_finalization: u64, + + // Port for Prometheus + pub prometheus_metrics_port: Option, + + // Path to dir for output submitted light client updates and execution blocks + pub output_dir: Option, + + // Path to the json file with beacon state in the next attested slot + // for case of short relay run + pub path_to_attested_state: Option, + + // Include next sync committee to the Light Client Update in short relay run + pub include_next_sync_committee_to_light_client: bool, + + // Timeout for ETH RPC requests in seconds + pub eth_requests_timeout_seconds: u64, + + // Timeout for ETH RPC get status requests in seconds + pub state_requests_timeout_seconds: u64, + + // Timeout for Substrate RPC requests in seconds + pub substrate_requests_timeout_seconds: u64, + + // Sleep time in seconds when ETH client is synchronized with ETH network + pub sleep_time_on_sync_secs: u64, + + // Sleep time in seconds after blocks/light_client_update submission to client + pub sleep_time_after_submission_secs: u64, + + /// Max number of stored blocks in the storage of the eth2 client contract. + /// Events that happen past this threshold cannot be verified by the client. + /// It is used on initialization of the Eth2 client. + pub hashes_gc_threshold: Option, + + // Beacon rpc version (V1_1, V1_2) + pub beacon_rpc_version: BeaconRPCVersion, + + pub get_light_client_update_by_epoch: Option, +} + +impl Config { + pub fn load_from_toml(path: PathBuf) -> Self { + let mut config = std::fs::File::open(path).expect("Error on parsing path to config"); + let mut content = String::new(); + config.read_to_string(&mut content).expect("Error on reading config"); + let mut config: Config = toml::from_str(content.as_str()).expect("Error on config parsing"); + dotenv().ok(); + let api_key_string = std::env::var("ETH1_INFURA_API_KEY").unwrap(); + config.eth1_endpoint = config.eth1_endpoint.replace("ETH1_INFURA_API_KEY", &api_key_string); + + Self::check_urls(&config); + config + } + + fn check_urls(&self) { + // check `beacon_endpoint` + Url::parse(&self.beacon_endpoint).expect("Error on beacon endpoint URL parsing"); + + // check `eth1_endpoint` + Url::parse(&self.eth1_endpoint).expect("Error on ETH1 endpoint URL parsing"); + + // check `substrate_endpoint` + Url::parse(&self.substrate_endpoint).expect("Error on Substrate endpoint URL parsing"); + } +} + +impl From for eth2_pallet_init::config::Config { + fn from(val: Config) -> Self { + eth2_pallet_init::config::Config { + beacon_endpoint: val.beacon_endpoint, + eth1_endpoint: val.eth1_endpoint, + substrate_endpoint: val.substrate_endpoint, + path_to_signer_secret_key: val.path_to_signer_secret_key, + ethereum_network: val.ethereum_network, + output_dir: val.output_dir, + eth_requests_timeout_seconds: Some(val.eth_requests_timeout_seconds), + validate_updates: None, + verify_bls_signature: None, + hashes_gc_threshold: val.hashes_gc_threshold, + trusted_signer_account_id: None, + init_block_root: None, + beacon_rpc_version: val.beacon_rpc_version, + } + } +} diff --git a/eth2substrate-block-relay-rs/src/test_utils.rs b/eth2substrate-block-relay-rs/src/test_utils.rs index 75efa738..03907733 100644 --- a/eth2substrate-block-relay-rs/src/test_utils.rs +++ b/eth2substrate-block-relay-rs/src/test_utils.rs @@ -24,6 +24,7 @@ pub fn get_typed_chain_id(config: &ConfigForTests) -> TypedChainId { match config.network_name { EthNetwork::Mainnet => TypedChainId::Evm(1), EthNetwork::Goerli => TypedChainId::Evm(5), + EthNetwork::Sepolia => TypedChainId::Evm(11155111), } } @@ -83,6 +84,7 @@ pub async fn init_pallet_from_files( let typed_chain_id = match config_for_test.network_name.clone() { EthNetwork::Mainnet => TypedChainId::Evm(1), EthNetwork::Goerli => TypedChainId::Evm(5), + EthNetwork::Sepolia => TypedChainId::Evm(11155111), }; eth_client_pallet From e8f84967b1dff733f8d3e48bf444c8b5d5beef94 Mon Sep 17 00:00:00 2001 From: Artur Yurii Korchynskyi <42449190+akorchyn@users.noreply.github.com> Date: Fri, 8 Dec 2023 20:58:14 +0200 Subject: [PATCH 2/3] Secret file usage (#87) --- Cargo.toml | 36 ++++++++++++++++++++++++------------ flake.nix | 1 + gadget/src/lib.rs | 17 +++++++++++++---- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 240b6c2a..f872737f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,12 +15,12 @@ members = [ "gadget/cli", "node", "runtime", - "primitives" + "primitives", ] [patch] [patch.crates-io] -arbitrary = { git = "https://github.com/michaelsproul/arbitrary", rev="a572fd8743012a4f1ada5ee5968b1b3619c427ba" } +arbitrary = { git = "https://github.com/michaelsproul/arbitrary", rev = "a572fd8743012a4f1ada5ee5968b1b3619c427ba" } [workspace.dependencies] ethereum-types = { version = "0.14.1", default-features = false } @@ -32,7 +32,7 @@ serde_json = { version = "1.0.74", default-features = false } serde = { version = "1.0", features = ["derive"], default-features = false } reqwest = { version = "0.11", features = ["blocking", "json"] } clap = { version = "4.0.9", features = ["derive"] } -tokio = { version = "1.1", features = ["macros", "rt", "time"] } +tokio = { version = "1.1", features = ["macros", "rt", "time", "signal"] } env_logger = "0.9.0" futures = { version = "0.3.21", default-features = false } async-std = { version = "1.12.0", default-features = false } @@ -59,15 +59,21 @@ rand = { version = "0.7.3", default-features = false } rand_chacha = { version = "0.3.1", default-features = false } backoff = { version = "0.4.0", features = ["tokio"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = [ + "derive", +] } rlp = { version = "0.5.0", default-features = false } rlp-derive = { version = "0.1.0", default-features = false } derive_more = { version = "^0.99.2" } -tiny-keccak = { version = "2.0", features = ["keccak"], default-features = false } +tiny-keccak = { version = "2.0", features = [ + "keccak", +], default-features = false } ring = { version = "0.16.19", default-features = false } sha2 = { version = "0.10.2", default-features = false } -zeroize = { version = "1.4.2", features = ["zeroize_derive"], default-features = false } +zeroize = { version = "1.4.2", features = [ + "zeroize_derive", +], default-features = false } subxt = "0.29.0" webb-relayer-utils = { git = "https://github.com/webb-tools/relayer.git" } @@ -75,12 +81,16 @@ webb-relayer-types = { git = "https://github.com/webb-tools/relayer.git" } webb = { version = "0.7.3", default-features = false, features = [ "evm-runtime", "substrate-runtime", -]} -webb-proposals = { git = "https://github.com/webb-tools/webb-rs.git", rev="a960eaf", default-features = false, features = ["scale", "evm"] } +] } +webb-proposals = { git = "https://github.com/webb-tools/webb-rs.git", rev = "a960eaf", default-features = false, features = [ + "scale", + "evm", + "serde", +] } -milagro_bls = { git = "https://github.com/Snowfork/milagro_bls", default-features = false, rev="a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" } -types = { git = "https://github.com/webb-tools/lighthouse.git", rev="ef72e752eaf45f4b7eb64dd8dbb0fe088f955df8" } -merkle_proof = { git = "https://github.com/webb-tools/lighthouse.git", rev="ef72e752eaf45f4b7eb64dd8dbb0fe088f955df8" } +milagro_bls = { git = "https://github.com/Snowfork/milagro_bls", default-features = false, rev = "a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" } +types = { git = "https://github.com/webb-tools/lighthouse.git", rev = "ef72e752eaf45f4b7eb64dd8dbb0fe088f955df8" } +merkle_proof = { git = "https://github.com/webb-tools/lighthouse.git", rev = "ef72e752eaf45f4b7eb64dd8dbb0fe088f955df8" } tree_hash = { version = "0.5.0", features = ["arbitrary"] } ethereum_hashing = { version = "1.0.0-beta.2" } ethereum_ssz = { version = "0.5.0", features = ["arbitrary"] } @@ -123,7 +133,9 @@ pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } pallet-grandpa = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } pallet-indices = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } -pallet-session = { version = "4.0.0-dev", features = ["historical"], default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } +pallet-session = { version = "4.0.0-dev", features = [ + "historical", +], default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } pallet-staking-reward-curve = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } pallet-sudo = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } pallet-timestamp = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v1.0.0" } diff --git a/flake.nix b/flake.nix index e4660452..24293fe9 100644 --- a/flake.nix +++ b/flake.nix @@ -33,6 +33,7 @@ pkgs.clang pkgs.libclang.lib pkgs.rustPlatform.bindgenHook + pkgs.openssl # Mold Linker for faster builds (only on Linux) (lib.optionals pkgs.stdenv.isLinux pkgs.mold) (lib.optionals pkgs.stdenv.isDarwin pkgs.darwin.apple_sdk.frameworks.Security) diff --git a/gadget/src/lib.rs b/gadget/src/lib.rs index fc7b900a..0ed0200a 100644 --- a/gadget/src/lib.rs +++ b/gadget/src/lib.rs @@ -6,6 +6,7 @@ use eth2_to_substrate_relay::eth2substrate_relay::Eth2SubstrateRelay; use lc_relay_config::RelayConfig; use lc_relayer_context::LightClientRelayerContext; use std::{path::PathBuf, sync::Arc}; +use subxt::ext::sp_core::Pair; use tokio::signal::unix; use webb_proposals::TypedChainId; pub mod errors; @@ -33,10 +34,18 @@ pub async fn ignite_lc_relayer(ctx: LightClientRelayerContext) -> anyhow::Result }, }; let api_client = Arc::new(api_client); - let mut eth_pallet = EthClientPallet::new( - api_client, - ctx.lc_relay_config.ethereum_network.as_typed_chain_id(), - ); + let pair = std::fs::read_to_string(&ctx.lc_init_config.path_to_signer_secret_key) + .expect("failed to read secret key"); + let pair = subxt::ext::sp_core::sr25519::Pair::from_string(&pair, None); + let network = ctx.lc_relay_config.ethereum_network.as_typed_chain_id(); + let mut eth_pallet = if let Ok(pair) = pair { + tracing::info!(target: "relay", "=== Initializing client with signer ==="); + EthClientPallet::new_with_pair(api_client, pair, network) + } else { + tracing::info!(target: "relay", "=== Initializing client without signer. Alice used as default ==="); + EthClientPallet::new(api_client, network) + }; + let mut relay = Eth2SubstrateRelay::init(&ctx.lc_relay_config, Box::new(eth_pallet.clone())).await; tracing::info!(target: "relay", "=== Initializing relay ==="); From 1565ab2b3f615d3ad2ae919b37e17f9aec6a8438 Mon Sep 17 00:00:00 2001 From: Artur Yurii Korchynskyi <42449190+akorchyn@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:38:00 +0200 Subject: [PATCH 3/3] wrong root (#89) --- crates/consensus-types/src/network_config.rs | 6 +++--- crates/eth2-pallet-init/src/eth_network.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/consensus-types/src/network_config.rs b/crates/consensus-types/src/network_config.rs index bf0d97cc..f12f71e0 100644 --- a/crates/consensus-types/src/network_config.rs +++ b/crates/consensus-types/src/network_config.rs @@ -60,9 +60,9 @@ impl NetworkConfig { }, Network::Sepolia => Self { genesis_validators_root: [ - 0x91, 0x43, 0xaa, 0x7c, 0x61, 0x5a, 0x7f, 0x71, 0x15, 0xe2, 0xb6, 0xaa, 0xc3, - 0x19, 0xc0, 0x35, 0x29, 0xdf, 0x82, 0x42, 0xae, 0x70, 0x5f, 0xba, 0x9d, 0xf3, - 0x9b, 0x79, 0xc5, 0x9f, 0xa8, 0xb1, + 0xd8, 0xea, 0x17, 0x1f, 0x3c, 0x94, 0xae, 0xa2, 0x1e, 0xbc, 0x42, 0xa1, 0xed, + 0x61, 0x05, 0x2a, 0xcf, 0x3f, 0x92, 0x09, 0xc0, 0x0e, 0x4e, 0xfb, 0xaa, 0xdd, + 0xac, 0x09, 0xed, 0x9b, 0x80, 0x78, ], bellatrix_fork_version: [144, 0, 0, 113], bellatrix_fork_epoch: 100, diff --git a/crates/eth2-pallet-init/src/eth_network.rs b/crates/eth2-pallet-init/src/eth_network.rs index 1011a288..2ae14b2d 100644 --- a/crates/eth2-pallet-init/src/eth_network.rs +++ b/crates/eth2-pallet-init/src/eth_network.rs @@ -10,7 +10,7 @@ use std::{ pub enum EthNetwork { Mainnet, Goerli, - Sepolia + Sepolia, } #[derive(Debug, Clone, Deserialize)] @@ -35,7 +35,7 @@ impl EthNetwork { match self { EthNetwork::Mainnet => "mainnet", EthNetwork::Goerli => "goerli", - EthNetwork::Sepolia => "sepolia" + EthNetwork::Sepolia => "sepolia", } } @@ -43,7 +43,7 @@ impl EthNetwork { match self { EthNetwork::Mainnet => webb_proposals::TypedChainId::Evm(1), EthNetwork::Goerli => webb_proposals::TypedChainId::Evm(5), - EthNetwork::Sepolia => webb_proposals::TypedChainId::Evm(11155111) + EthNetwork::Sepolia => webb_proposals::TypedChainId::Evm(11155111), } } }