diff --git a/eth2near/Cargo.lock b/eth2near/Cargo.lock index dcf3a56d..8f571524 100644 --- a/eth2near/Cargo.lock +++ b/eth2near/Cargo.lock @@ -1433,6 +1433,7 @@ dependencies = [ "dotenv", "env_logger", "eth-types", + "eth2-utility", "ethereum-types", "ethereum_hashing", "ethereum_ssz", diff --git a/eth2near/eth2near-block-relay-rs/src/eth2near_relay.rs b/eth2near/eth2near-block-relay-rs/src/eth2near_relay.rs index a3c303cc..86849838 100644 --- a/eth2near/eth2near-block-relay-rs/src/eth2near_relay.rs +++ b/eth2near/eth2near-block-relay-rs/src/eth2near_relay.rs @@ -8,7 +8,7 @@ use crate::prometheus_metrics::{ use bitvec::macros::internal::funty::Fundamental; use contract_wrapper::eth_client_contract_trait::EthClientContractTrait; use contract_wrapper::near_rpc_client::NearRPCClient; -use eth2_utility::consensus::{EPOCHS_PER_SYNC_COMMITTEE_PERIOD, SLOTS_PER_EPOCH}; +use eth2_utility::consensus::{EPOCHS_PER_SYNC_COMMITTEE_PERIOD, Network, NetworkConfig, SLOTS_PER_EPOCH}; use eth_rpc_client::beacon_rpc_client::BeaconRPCClient; use eth_rpc_client::eth1_rpc_client::Eth1RPCClient; use eth_rpc_client::hand_made_finality_light_client_update::HandMadeFinalityLightClientUpdate; @@ -24,6 +24,7 @@ use std::thread; use std::thread::sleep; use std::time::Duration; use std::vec::Vec; +use std::str::FromStr; use eth2_utility::types::ClientMode; use types::Slot; @@ -119,11 +120,13 @@ impl Eth2NearRelay { ) -> Self { info!(target: "relay", "=== Relay initialization === "); + let network_config = NetworkConfig::new(&Network::from_str(config.ethereum_network.as_str()).unwrap()); let beacon_rpc_client = BeaconRPCClient::new( &config.beacon_endpoint, config.eth_requests_timeout_seconds, config.state_requests_timeout_seconds, Some(config.beacon_rpc_version.clone()), + network_config ); let next_light_client_update = Self::get_light_client_update_from_file(config, &beacon_rpc_client) @@ -463,7 +466,7 @@ impl Eth2NearRelay { fn send_light_client_updates( &mut self, last_finalized_slot_on_near: u64, - last_finalized_slot_on_eth: u64, + last_finalized_slot_on_eth: u64 ) { info!(target: "relay", "= Sending light client update ="); diff --git a/eth2near/eth2near-block-relay-rs/src/main.rs b/eth2near/eth2near-block-relay-rs/src/main.rs index 6b7ac550..df7192c3 100644 --- a/eth2near/eth2near-block-relay-rs/src/main.rs +++ b/eth2near/eth2near-block-relay-rs/src/main.rs @@ -103,7 +103,7 @@ fn main() -> Result<(), Box> { let mut eth2near_relay = Eth2NearRelay::init( &config, - get_eth_client_contract(&config) + get_eth_client_contract(&config), ); eth2near_relay.run(None); diff --git a/eth2near/eth_rpc_client/Cargo.toml b/eth2near/eth_rpc_client/Cargo.toml index d223d302..400405ac 100644 --- a/eth2near/eth_rpc_client/Cargo.toml +++ b/eth2near/eth_rpc_client/Cargo.toml @@ -17,6 +17,7 @@ serde = { version = "1.0", features = ["derive"] } ethereum-types = { version = "0.14.1", features = ["rlp", "serialize"], default-features = false } reqwest = { version = "0.11", features = ["blocking"] } eth-types = { path = "../../contracts/near/eth-types/" } +eth2-utility = { path = "../../contracts/near/eth2-utility/" } contract_wrapper = { path = "../contract_wrapper" } clap = { version = "3.1.6", features = ["derive"] } tokio = { version = "1.1", features = ["macros", "rt", "time"] } diff --git a/eth2near/eth_rpc_client/src/beacon_block_body_merkle_tree.rs b/eth2near/eth_rpc_client/src/beacon_block_body_merkle_tree.rs index 89c84361..94dfca51 100644 --- a/eth2near/eth_rpc_client/src/beacon_block_body_merkle_tree.rs +++ b/eth2near/eth_rpc_client/src/beacon_block_body_merkle_tree.rs @@ -1,3 +1,5 @@ +use eth2_utility::consensus::NetworkConfig; +use eth_types::eth2::Epoch; use ethereum_types::H256; use merkle_proof::MerkleTree; use tree_hash::TreeHash; @@ -56,11 +58,15 @@ impl BeaconBlockBodyMerkleTree { pub struct ExecutionPayloadMerkleTree(pub MerkleTree); impl ExecutionPayloadMerkleTree { - pub const TREE_NUM_LEAVES: usize = 15; - pub const TREE_DEPTH: usize = 4; + pub fn get_tree_depth(network_config: &NetworkConfig, epoch: Epoch) -> usize { + let proof_size = network_config.compute_proof_size(epoch); + proof_size.l2_execution_payload_proof_size + } - pub fn new(execution_payload: &ExecutionPayload) -> Self { - let leaves: [H256; Self::TREE_NUM_LEAVES] = [ + pub fn new(execution_payload: &ExecutionPayload, + network_config: &NetworkConfig, + epoch: Epoch) -> Self { + let mut leaves: Vec = vec![ execution_payload.parent_hash().tree_hash_root(), execution_payload.fee_recipient().tree_hash_root(), execution_payload.state_root().tree_hash_root(), @@ -82,7 +88,18 @@ impl ExecutionPayloadMerkleTree { }, ]; - Self(MerkleTree::create(&leaves, Self::TREE_DEPTH)) + let tree_depth = Self::get_tree_depth(network_config, epoch); + if tree_depth > 4 { + if let Ok(blob_gas_used) = execution_payload.blob_gas_used() { + leaves.push(blob_gas_used.tree_hash_root()); + } + + if let Ok(excess_blob_gas) = execution_payload.excess_blob_gas() { + leaves.push(excess_blob_gas.tree_hash_root()); + } + } + + Self(MerkleTree::create(&leaves, tree_depth)) } } diff --git a/eth2near/eth_rpc_client/src/beacon_rpc_client.rs b/eth2near/eth_rpc_client/src/beacon_rpc_client.rs index 92f75a17..c7d0b900 100644 --- a/eth2near/eth_rpc_client/src/beacon_rpc_client.rs +++ b/eth2near/eth_rpc_client/src/beacon_rpc_client.rs @@ -14,6 +14,7 @@ use eth_types::eth2::SyncAggregate; use eth_types::eth2::SyncCommittee; use eth_types::eth2::SyncCommitteeUpdate; use eth_types::H256; +use eth2_utility::consensus::NetworkConfig; use log::trace; use reqwest::blocking::Client; use serde::Deserialize; @@ -81,6 +82,7 @@ pub struct BeaconRPCClient { client: Client, client_state_request: Client, routes: BeaconRPCRoutes, + network_config: NetworkConfig, } impl BeaconRPCClient { @@ -93,6 +95,7 @@ impl BeaconRPCClient { timeout_seconds: u64, timeout_state_seconds: u64, version: Option, + network_config: NetworkConfig, ) -> Self { Self { endpoint_url: endpoint_url.to_string(), @@ -105,9 +108,14 @@ impl BeaconRPCClient { .build() .expect("Error on building blocking client for state request."), routes: BeaconRPCRoutes::new(version.unwrap_or(BeaconRPCVersion::V1_1)), + network_config, } } + pub fn get_network_config(&self) -> &NetworkConfig { + &self.network_config + } + /// Returns `BeaconBlockBody` struct for the given `block_id`. /// /// # Arguments @@ -501,6 +509,19 @@ impl BeaconRPCClient { _ => serde_json::to_string(&v["data"][0]["finalized_header"])?, }; + let slot = match self.routes.version { + BeaconRPCVersion::V1_5 => { + let mut res = serde_json::to_value(&v[0]["data"]["attested_header"]["beacon"]["slot"])?; + if res == "null" { + res = serde_json::to_value(&v["data"][0]["attested_header"]["beacon"]["slot"])?; + } + res + } + _ => serde_json::to_value(&v["data"][0]["attested_header"]["slot"])?, + }.as_u64().ok_or(FailOnGettingJson {response: "Error on extraction slot number".to_string()})?; + + let epoch = eth2_utility::consensus::compute_epoch_at_slot(slot); + let finalized_header: BeaconBlockHeader = serde_json::from_str(&finalized_header_json_str)?; let mut finalized_branch_json_str = @@ -516,7 +537,8 @@ impl BeaconRPCClient { let finalized_block_body = self.get_beacon_block_body_for_block_id(&format!("{}", finalized_block_slot))?; let finalized_block_eth1data_proof = - ExecutionBlockProof::construct_from_beacon_block_body(&finalized_block_body)?; + ExecutionBlockProof::construct_from_beacon_block_body(&finalized_block_body, + &self.network_config, epoch)?; Ok(FinalizedHeaderUpdate { header_update: HeaderUpdate { diff --git a/eth2near/eth_rpc_client/src/execution_block_proof.rs b/eth2near/eth_rpc_client/src/execution_block_proof.rs index 2dfc9893..db63d3e3 100644 --- a/eth2near/eth_rpc_client/src/execution_block_proof.rs +++ b/eth2near/eth_rpc_client/src/execution_block_proof.rs @@ -5,6 +5,8 @@ use ethereum_types::H256; use std::error::Error; use std::fmt; use std::fmt::Display; +use eth2_utility::consensus::NetworkConfig; +use eth_types::eth2::Epoch; use types::{BeaconBlockBody, ExecutionPayload, MainnetEthSpec}; /// `ExecutionBlockProof` contains a `block_hash` (execution block) and @@ -17,29 +19,23 @@ use types::{BeaconBlockBody, ExecutionPayload, MainnetEthSpec}; /// The proof starts from the leaf. pub struct ExecutionBlockProof { block_hash: H256, - proof: [H256; Self::PROOF_SIZE], + proof: Vec, } impl ExecutionBlockProof { - pub const L1_BEACON_BLOCK_BODY_TREE_EXECUTION_PAYLOAD_INDEX: usize = 9; - pub const L2_EXECUTION_PAYLOAD_TREE_EXECUTION_BLOCK_INDEX: usize = 12; - - pub const L1_BEACON_BLOCK_BODY_PROOF_SIZE: usize = - BeaconBlockBodyMerkleTree::BEACON_BLOCK_BODY_TREE_DEPTH; - pub const L2_EXECUTION_PAYLOAD_PROOF_SIZE: usize = ExecutionPayloadMerkleTree::TREE_DEPTH; - pub const PROOF_SIZE: usize = - Self::L1_BEACON_BLOCK_BODY_PROOF_SIZE + Self::L2_EXECUTION_PAYLOAD_PROOF_SIZE; - - pub fn construct_from_raw_data(block_hash: &H256, proof: &[H256; Self::PROOF_SIZE]) -> Self { + pub fn construct_from_raw_data(block_hash: &H256, proof: Vec) -> Self { Self { block_hash: *block_hash, - proof: *proof, + proof, } } pub fn construct_from_beacon_block_body( beacon_block_body: &BeaconBlockBody, + network_config: &NetworkConfig, + epoch: Epoch ) -> Result> { + let proof_size = network_config.compute_proof_size(epoch); let beacon_block_merkle_tree = &BeaconBlockBodyMerkleTree::new(beacon_block_body); let execution_payload_merkle_tree = &ExecutionPayloadMerkleTree::new( @@ -47,21 +43,23 @@ impl ExecutionBlockProof { .execution_payload() .map_err(|_| MissExecutionPayload)? .into(), + network_config, + epoch ); let l1_execution_payload_proof = beacon_block_merkle_tree .0 .generate_proof( - Self::L1_BEACON_BLOCK_BODY_TREE_EXECUTION_PAYLOAD_INDEX, - Self::L1_BEACON_BLOCK_BODY_PROOF_SIZE, + proof_size.l1_beacon_block_body_tree_execution_payload_index, + proof_size.l1_beacon_block_body_proof_size, ) .map_err(|err| MerkleTreeError(err))? .1; let mut block_proof = execution_payload_merkle_tree .0 .generate_proof( - Self::L2_EXECUTION_PAYLOAD_TREE_EXECUTION_BLOCK_INDEX, - Self::L2_EXECUTION_PAYLOAD_PROOF_SIZE, + proof_size.l2_execution_payload_tree_execution_block_index, + proof_size.l2_execution_payload_proof_size, ) .map_err(|err| MerkleTreeError(err))? .1; @@ -77,8 +75,8 @@ impl ExecutionBlockProof { }) } - pub fn get_proof(&self) -> [H256; Self::PROOF_SIZE] { - self.proof + pub fn get_proof(&self) -> Vec { + self.proof.clone() } pub fn get_execution_block_hash(&self) -> H256 { @@ -88,22 +86,26 @@ impl ExecutionBlockProof { pub fn verify_proof_for_hash( &self, beacon_block_body_hash: &H256, + network_config: &NetworkConfig, + epoch: Epoch ) -> Result { - let l2_proof: &[H256] = &self.proof[0..Self::L2_EXECUTION_PAYLOAD_PROOF_SIZE]; + let proof_size = network_config.compute_proof_size(epoch); + + let l2_proof: &[H256] = &self.proof[0..proof_size.l2_execution_payload_proof_size]; let l1_proof: &[H256] = - &self.proof[Self::L2_EXECUTION_PAYLOAD_PROOF_SIZE..Self::PROOF_SIZE]; + &self.proof[proof_size.l2_execution_payload_proof_size..proof_size.execution_proof_size]; let execution_payload_hash = Self::merkle_root_from_branch( self.block_hash, l2_proof, - Self::L2_EXECUTION_PAYLOAD_PROOF_SIZE, - Self::L2_EXECUTION_PAYLOAD_TREE_EXECUTION_BLOCK_INDEX, + proof_size.l2_execution_payload_proof_size, + proof_size.l2_execution_payload_tree_execution_block_index, )?; Ok(merkle_proof::verify_merkle_proof( execution_payload_hash, l1_proof, BeaconBlockBodyMerkleTree::BEACON_BLOCK_BODY_TREE_DEPTH, - Self::L1_BEACON_BLOCK_BODY_TREE_EXECUTION_PAYLOAD_INDEX, + proof_size.l1_beacon_block_body_tree_execution_payload_index, *beacon_block_body_hash, )) } diff --git a/eth2near/eth_rpc_client/src/hand_made_finality_light_client_update.rs b/eth2near/eth_rpc_client/src/hand_made_finality_light_client_update.rs index f42073ac..cd4143a6 100644 --- a/eth2near/eth_rpc_client/src/hand_made_finality_light_client_update.rs +++ b/eth2near/eth_rpc_client/src/hand_made_finality_light_client_update.rs @@ -14,8 +14,9 @@ use log::trace; use serde_json::Value; use ssz::Encode; use std::error::Error; +use eth2_utility::consensus::NetworkConfig; use tree_hash::TreeHash; -use types::{BeaconBlockBody, BeaconBlockHeader, BeaconState, MainnetEthSpec}; +use types::{BeaconBlockBody, BeaconBlockHeader, BeaconState, Epoch, MainnetEthSpec}; pub struct HandMadeFinalityLightClientUpdate {} @@ -162,6 +163,7 @@ impl HandMadeFinalityLightClientUpdate { beacon_state: BeaconState, include_next_sync_committee: bool, ) -> Result> { + let epoch = eth2_utility::consensus::compute_epoch_at_slot(attested_slot); let signature_beacon_body = beacon_rpc_client.get_beacon_block_body_for_block_id(&format!("{}", signature_slot))?; let sync_aggregate = signature_beacon_body @@ -192,6 +194,8 @@ impl HandMadeFinalityLightClientUpdate { &finality_header, &beacon_state, &finalized_block_body, + beacon_rpc_client.get_network_config(), + epoch.into() )?, sync_committee_update: if include_next_sync_committee { Some(Self::get_next_sync_committee(&beacon_state)?) @@ -301,10 +305,12 @@ impl HandMadeFinalityLightClientUpdate { finality_header: &BeaconBlockHeader, beacon_state: &BeaconState, finalized_block_body: &BeaconBlockBody, + network_config: &NetworkConfig, + epoch: Epoch ) -> Result> { let finality_branch = Self::get_finality_branch(beacon_state)?; let finalized_block_eth1data_proof = - ExecutionBlockProof::construct_from_beacon_block_body(finalized_block_body)?; + ExecutionBlockProof::construct_from_beacon_block_body(finalized_block_body, network_config, epoch.into())?; Ok(FinalizedHeaderUpdate { header_update: HeaderUpdate {