diff --git a/Cargo.lock b/Cargo.lock index b0ec250..235b825 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -695,6 +695,7 @@ dependencies = [ "serde", "serde_json", "ssz-rs", + "superstruct", "thiserror", "tokio", "toml", @@ -975,6 +976,41 @@ dependencies = [ "syn", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "der" version = "0.6.1" @@ -2184,6 +2220,12 @@ dependencies = [ "cxx-build", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.3.0" @@ -4206,6 +4248,20 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "superstruct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f4e1f478a7728f8855d7e620e9a152cf8932c6614f86564c886f9b8141f3201" +dependencies = [ + "darling", + "itertools", + "proc-macro2", + "quote", + "smallvec", + "syn", +] + [[package]] name = "syn" version = "1.0.109" diff --git a/client/src/node.rs b/client/src/node.rs index d2091cb..75c299d 100644 --- a/client/src/node.rs +++ b/client/src/node.rs @@ -109,11 +109,11 @@ impl Node { .map_err(NodeError::ConsensusPayloadError)?; self.payloads - .insert(latest_payload.block_number, latest_payload); + .insert(*latest_payload.block_number(), latest_payload); self.payloads - .insert(finalized_payload.block_number, finalized_payload.clone()); + .insert(*finalized_payload.block_number(), finalized_payload.clone()); self.finalized_payloads - .insert(finalized_payload.block_number, finalized_payload); + .insert(*finalized_payload.block_number(), finalized_payload); let start_slot = self .current_slot @@ -124,7 +124,7 @@ impl Node { .await .map_err(NodeError::ConsensusPayloadError)?; for payload in backfill_payloads { - self.payloads.insert(payload.block_number, payload); + self.payloads.insert(*payload.block_number(), payload); } self.current_slot = Some(latest_header.slot); @@ -188,14 +188,14 @@ impl Node { pub fn get_block_transaction_count_by_hash(&self, hash: &Vec) -> Result { let payload = self.get_payload_by_hash(hash)?; - let transaction_count = payload.1.transactions.len(); + let transaction_count = payload.1.transactions().len(); Ok(transaction_count as u64) } pub fn get_block_transaction_count_by_number(&self, block: BlockTag) -> Result { let payload = self.get_payload(block)?; - let transaction_count = payload.transactions.len(); + let transaction_count = payload.transactions().len(); Ok(transaction_count as u64) } @@ -269,7 +269,7 @@ impl Node { self.check_head_age()?; let payload = self.get_payload(BlockTag::Latest)?; - let base_fee = U256::from_little_endian(&payload.base_fee_per_gas.to_bytes_le()); + let base_fee = U256::from_little_endian(&payload.base_fee_per_gas().to_bytes_le()); let tip = U256::from(10_u64.pow(9)); Ok(base_fee + tip) } @@ -284,7 +284,7 @@ impl Node { self.check_head_age()?; let payload = self.get_payload(BlockTag::Latest)?; - Ok(payload.block_number) + Ok(*payload.block_number()) } pub async fn get_block_by_number( @@ -367,7 +367,7 @@ impl Node { pub fn get_coinbase(&self) -> Result
{ self.check_head_age()?; let payload = self.get_payload(BlockTag::Latest)?; - let coinbase_address = Address::from_slice(&payload.fee_recipient); + let coinbase_address = Address::from_slice(payload.fee_recipient()); Ok(coinbase_address) } @@ -398,7 +398,7 @@ impl Node { let payloads = self .payloads .iter() - .filter(|entry| &entry.1.block_hash.to_vec() == hash) + .filter(|entry| &entry.1.block_hash().to_vec() == hash) .collect::>(); payloads diff --git a/config/src/config.rs b/config/src/config.rs index 990cbf4..99e8faa 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -73,7 +73,9 @@ impl Config { pub fn fork_version(&self, slot: u64) -> Vec { let epoch = slot / 32; - if epoch >= self.forks.bellatrix.epoch { + if epoch >= self.forks.capella.epoch { + self.forks.capella.fork_version.clone() + } else if epoch >= self.forks.bellatrix.epoch { self.forks.bellatrix.fork_version.clone() } else if epoch >= self.forks.altair.epoch { self.forks.altair.fork_version.clone() diff --git a/config/src/networks.rs b/config/src/networks.rs index ebe4f9e..9f2f7f8 100644 --- a/config/src/networks.rs +++ b/config/src/networks.rs @@ -62,6 +62,10 @@ pub fn mainnet() -> BaseConfig { epoch: 144896, fork_version: hex_str_to_bytes("0x02000000").unwrap(), }, + capella: Fork { + epoch: u64::MAX, // TODO: set epoch when known + fork_version: hex_str_to_bytes("0x03000000").unwrap(), + }, }, max_checkpoint_age: 1_209_600, // 14 days } @@ -96,6 +100,10 @@ pub fn goerli() -> BaseConfig { epoch: 112260, fork_version: hex_str_to_bytes("0x02001020").unwrap(), }, + capella: Fork { + epoch: 162304, + fork_version: hex_str_to_bytes("0x03001020").unwrap(), + }, }, max_checkpoint_age: 1_209_600, // 14 days } diff --git a/config/src/types.rs b/config/src/types.rs index 4a15521..aca1d28 100644 --- a/config/src/types.rs +++ b/config/src/types.rs @@ -18,6 +18,7 @@ pub struct Forks { pub genesis: Fork, pub altair: Fork, pub bellatrix: Fork, + pub capella: Fork, } #[derive(Serialize, Deserialize, Debug, Default, Clone)] diff --git a/consensus/Cargo.toml b/consensus/Cargo.toml index 6c5576f..38cb0a3 100644 --- a/consensus/Cargo.toml +++ b/consensus/Cargo.toml @@ -19,6 +19,7 @@ log = "0.4.17" chrono = "0.4.23" thiserror = "1.0.37" reqwest = { version = "0.11.13", features = ["json"] } +superstruct = "0.7.0" common = { path = "../common" } config = { path = "../config" } diff --git a/consensus/src/consensus.rs b/consensus/src/consensus.rs index ea0051e..7a8e45f 100644 --- a/consensus/src/consensus.rs +++ b/consensus/src/consensus.rs @@ -103,7 +103,7 @@ impl ConsensusClient { ) .into()) } else { - Ok(block.body.execution_payload) + Ok(block.body.execution_payload().clone()) } } @@ -115,30 +115,33 @@ impl ConsensusClient { let payloads_fut = (start_slot..end_slot) .rev() .map(|slot| self.rpc.get_block(slot)); + let mut prev_parent_hash: Bytes32 = self .rpc .get_block(end_slot) .await? .body - .execution_payload - .parent_hash; + .execution_payload() + .parent_hash() + .clone(); + let mut payloads: Vec = Vec::new(); for result in join_all(payloads_fut).await { if result.is_err() { continue; } - let payload = result.unwrap().body.execution_payload; - if payload.block_hash != prev_parent_hash { + let payload = result.unwrap().body.execution_payload().clone(); + if payload.block_hash() != &prev_parent_hash { warn!( "error while backfilling blocks: {}", ConsensusError::InvalidHeaderHash( format!("{prev_parent_hash:02X?}"), - format!("{:02X?}", payload.parent_hash), + format!("{:02X?}", payload.parent_hash()), ) ); break; } - prev_parent_hash = payload.parent_hash.clone(); + prev_parent_hash = payload.parent_hash().clone(); payloads.push(payload); } Ok(payloads) diff --git a/consensus/src/types.rs b/consensus/src/types.rs index b341ef2..ea0e4f8 100644 --- a/consensus/src/types.rs +++ b/consensus/src/types.rs @@ -4,6 +4,7 @@ use ssz_rs::prelude::*; use common::types::Bytes32; use common::utils::hex_str_to_bytes; +use superstruct::superstruct; pub type BLSPubKey = Vector; pub type SignatureBytes = Vector; @@ -24,7 +25,15 @@ pub struct BeaconBlock { pub body: BeaconBlockBody, } -#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)] +#[superstruct( + variants(Bellatrix, Capella), + variant_attributes( + derive(serde::Deserialize, Clone, Debug, SimpleSerialize, Default), + serde(deny_unknown_fields) + ) +)] +#[derive(serde::Deserialize, Debug, Clone)] +#[serde(untagged)] pub struct BeaconBlockBody { #[serde(deserialize_with = "signature_deserialize")] randao_reveal: SignatureBytes, @@ -38,9 +47,79 @@ pub struct BeaconBlockBody { voluntary_exits: List, sync_aggregate: SyncAggregate, pub execution_payload: ExecutionPayload, + #[superstruct(only(Capella))] + bls_to_execution_changes: List, } -#[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)] +impl ssz_rs::Merkleized for BeaconBlockBody { + fn hash_tree_root(&mut self) -> Result { + match self { + BeaconBlockBody::Bellatrix(body) => body.hash_tree_root(), + BeaconBlockBody::Capella(body) => body.hash_tree_root(), + } + } +} + +impl ssz_rs::Sized for BeaconBlockBody { + fn is_variable_size() -> bool { + true + } + + fn size_hint() -> usize { + 0 + } +} + +impl ssz_rs::Serialize for BeaconBlockBody { + fn serialize(&self, buffer: &mut Vec) -> Result { + match self { + BeaconBlockBody::Bellatrix(body) => body.serialize(buffer), + BeaconBlockBody::Capella(body) => body.serialize(buffer), + } + } +} + +impl ssz_rs::Deserialize for BeaconBlockBody { + fn deserialize(_encoding: &[u8]) -> Result + where + Self: Sized, + { + panic!("not implemented"); + } +} + +#[derive(Default, Clone, Debug, SimpleSerialize, serde::Deserialize)] +pub struct SignedBlsToExecutionChange { + message: BlsToExecutionChange, + #[serde(deserialize_with = "signature_deserialize")] + signature: SignatureBytes, +} + +#[derive(Default, Clone, Debug, SimpleSerialize, serde::Deserialize)] +pub struct BlsToExecutionChange { + #[serde(deserialize_with = "u64_deserialize")] + validator_index: u64, + #[serde(deserialize_with = "pubkey_deserialize")] + from_bls_pubkey: BLSPubKey, + #[serde(deserialize_with = "address_deserialize")] + to_execution_address: Address, +} + +impl Default for BeaconBlockBody { + fn default() -> Self { + BeaconBlockBody::Bellatrix(BeaconBlockBodyBellatrix::default()) + } +} + +#[superstruct( + variants(Bellatrix, Capella), + variant_attributes( + derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone), + serde(deny_unknown_fields) + ) +)] +#[derive(serde::Deserialize, Debug, Clone)] +#[serde(untagged)] pub struct ExecutionPayload { #[serde(deserialize_with = "bytes32_deserialize")] pub parent_hash: Bytes32, @@ -70,10 +149,67 @@ pub struct ExecutionPayload { pub block_hash: Bytes32, #[serde(deserialize_with = "transactions_deserialize")] pub transactions: List, + #[superstruct(only(Capella))] + withdrawals: List, +} + +#[derive(Default, Clone, Debug, SimpleSerialize, serde::Deserialize)] +pub struct Withdrawal { + #[serde(deserialize_with = "u64_deserialize")] + index: u64, + #[serde(deserialize_with = "u64_deserialize")] + validator_index: u64, + #[serde(deserialize_with = "address_deserialize")] + address: Address, + #[serde(deserialize_with = "u64_deserialize")] + amount: u64, +} + +impl ssz_rs::Merkleized for ExecutionPayload { + fn hash_tree_root(&mut self) -> Result { + match self { + ExecutionPayload::Bellatrix(payload) => payload.hash_tree_root(), + ExecutionPayload::Capella(payload) => payload.hash_tree_root(), + } + } +} + +impl ssz_rs::Sized for ExecutionPayload { + fn is_variable_size() -> bool { + true + } + + fn size_hint() -> usize { + 0 + } +} + +impl ssz_rs::Serialize for ExecutionPayload { + fn serialize(&self, buffer: &mut Vec) -> Result { + match self { + ExecutionPayload::Bellatrix(payload) => payload.serialize(buffer), + ExecutionPayload::Capella(payload) => payload.serialize(buffer), + } + } +} + +impl ssz_rs::Deserialize for ExecutionPayload { + fn deserialize(_encoding: &[u8]) -> Result + where + Self: Sized, + { + panic!("not implemented"); + } +} + +impl Default for ExecutionPayload { + fn default() -> Self { + ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix::default()) + } } #[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)] -struct ProposerSlashing { +pub struct ProposerSlashing { signed_header_1: SignedBeaconBlockHeader, signed_header_2: SignedBeaconBlockHeader, } @@ -100,7 +236,7 @@ struct BeaconBlockHeader { } #[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)] -struct AttesterSlashing { +pub struct AttesterSlashing { attestation_1: IndexedAttestation, attestation_2: IndexedAttestation, } @@ -115,7 +251,7 @@ struct IndexedAttestation { } #[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)] -struct Attestation { +pub struct Attestation { aggregation_bits: Bitlist<2048>, data: AttestationData, #[serde(deserialize_with = "signature_deserialize")] @@ -143,7 +279,7 @@ struct Checkpoint { } #[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)] -struct SignedVoluntaryExit { +pub struct SignedVoluntaryExit { message: VoluntaryExit, #[serde(deserialize_with = "signature_deserialize")] signature: SignatureBytes, @@ -158,7 +294,7 @@ struct VoluntaryExit { } #[derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone)] -struct Deposit { +pub struct Deposit { #[serde(deserialize_with = "bytes_vector_deserialize")] proof: Vector, data: DepositData, diff --git a/consensus/tests/sync.rs b/consensus/tests/sync.rs index 1b019c0..3d78a5d 100644 --- a/consensus/tests/sync.rs +++ b/consensus/tests/sync.rs @@ -38,5 +38,5 @@ async fn test_get_payload() { client.sync().await.unwrap(); let payload = client.get_execution_payload(&None).await.unwrap(); - assert_eq!(payload.block_number, 7530932); + assert_eq!(*payload.block_number(), 7530932); } diff --git a/execution/src/evm.rs b/execution/src/evm.rs index 6e7c003..46359c6 100644 --- a/execution/src/evm.rs +++ b/execution/src/evm.rs @@ -111,7 +111,7 @@ impl<'a, R: ExecutionRpc> Evm<'a, R> { let rpc = db.execution.rpc.clone(); let payload = db.current_payload.clone(); let execution = db.execution.clone(); - let block = db.current_payload.block_number; + let block = *db.current_payload.block_number(); let opts_moved = CallOpts { from: opts.from, @@ -139,7 +139,7 @@ impl<'a, R: ExecutionRpc> Evm<'a, R> { }; let producer_account = AccessListItem { - address: Address::from_slice(&payload.fee_recipient), + address: Address::from_slice(payload.fee_recipient()), storage_keys: Vec::default(), }; @@ -182,10 +182,10 @@ impl<'a, R: ExecutionRpc> Evm<'a, R> { env.tx.gas_limit = opts.gas.map(|v| v.as_u64()).unwrap_or(u64::MAX); env.tx.gas_price = opts.gas_price.unwrap_or(U256::zero()); - env.block.number = U256::from(payload.block_number); - env.block.coinbase = Address::from_slice(&payload.fee_recipient); - env.block.timestamp = U256::from(payload.timestamp); - env.block.difficulty = U256::from_little_endian(&payload.prev_randao); + env.block.number = U256::from(*payload.block_number()); + env.block.coinbase = Address::from_slice(payload.fee_recipient()); + env.block.timestamp = U256::from(*payload.timestamp()); + env.block.difficulty = U256::from_little_endian(payload.prev_randao()); env.cfg.chain_id = self.chain_id.into(); @@ -266,7 +266,7 @@ impl<'a, R: ExecutionRpc> Database for ProofDB<'a, R> { .payloads .get(&number) .ok_or(BlockNotFoundError::new(BlockTag::Number(number)))?; - Ok(H256::from_slice(&payload.block_hash)) + Ok(H256::from_slice(payload.block_hash())) } fn storage(&mut self, address: H160, slot: U256) -> Result { @@ -304,6 +304,7 @@ fn is_precompile(address: &Address) -> bool { #[cfg(test)] mod tests { use common::utils::hex_str_to_bytes; + use consensus::types::ExecutionPayloadBellatrix; use ssz_rs::Vector; use crate::rpc::mock_rpc::MockRpc; @@ -319,15 +320,16 @@ mod tests { // Construct proofdb params let execution = get_client(); let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap(); - let payload = ExecutionPayload { + let payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix { state_root: Vector::from_iter( hex_str_to_bytes( "0xaa02f5db2ee75e3da400d10f3c30e894b6016ce8a2501680380a907b6674ce0d", ) .unwrap(), ), - ..ExecutionPayload::default() - }; + ..ExecutionPayloadBellatrix::default() + }); + let mut payloads = BTreeMap::new(); payloads.insert(7530933, payload.clone()); diff --git a/execution/src/execution.rs b/execution/src/execution.rs index a7e8b03..38768d9 100644 --- a/execution/src/execution.rs +++ b/execution/src/execution.rs @@ -54,7 +54,7 @@ impl ExecutionClient { let proof = self .rpc - .get_proof(address, slots, payload.block_number) + .get_proof(address, slots, *payload.block_number()) .await?; let account_path = keccak256(address.as_bytes()).to_vec(); @@ -62,7 +62,7 @@ impl ExecutionClient { let is_valid = verify_proof( &proof.account_proof, - &payload.state_root, + payload.state_root(), &account_path, &account_encoded, ); @@ -98,7 +98,7 @@ impl ExecutionClient { let code = if proof.code_hash == KECCAK_EMPTY { Vec::new() } else { - let code = self.rpc.get_code(address, payload.block_number).await?; + let code = self.rpc.get_code(address, *payload.block_number()).await?; let code_hash = keccak256(&code).into(); if proof.code_hash != code_hash { @@ -136,7 +136,7 @@ impl ExecutionClient { let empty_uncle_hash = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"; let tx_hashes = payload - .transactions + .transactions() .iter() .map(|tx| H256::from_slice(&keccak256(tx))) .collect::>(); @@ -144,7 +144,7 @@ impl ExecutionClient { let txs = if full_tx { let txs_fut = tx_hashes.iter().map(|hash| async move { let mut payloads = BTreeMap::new(); - payloads.insert(payload.block_number, payload.clone()); + payloads.insert(*payload.block_number(), payload.clone()); let tx = self .get_transaction(hash, &payloads) .await? @@ -163,22 +163,22 @@ impl ExecutionClient { }; Ok(ExecutionBlock { - number: payload.block_number, - base_fee_per_gas: U256::from_little_endian(&payload.base_fee_per_gas.to_bytes_le()), + number: *payload.block_number(), + base_fee_per_gas: U256::from_little_endian(&payload.base_fee_per_gas().to_bytes_le()), difficulty: U256::from(0), - extra_data: payload.extra_data.to_vec(), - gas_limit: payload.gas_limit, - gas_used: payload.gas_used, - hash: H256::from_slice(&payload.block_hash), - logs_bloom: payload.logs_bloom.to_vec(), - miner: Address::from_slice(&payload.fee_recipient), - parent_hash: H256::from_slice(&payload.parent_hash), - receipts_root: H256::from_slice(&payload.receipts_root), - state_root: H256::from_slice(&payload.state_root), - timestamp: payload.timestamp, + extra_data: payload.extra_data().to_vec(), + gas_limit: *payload.gas_limit(), + gas_used: *payload.gas_used(), + hash: H256::from_slice(payload.block_hash()), + logs_bloom: payload.logs_bloom().to_vec(), + miner: Address::from_slice(payload.fee_recipient()), + parent_hash: H256::from_slice(payload.parent_hash()), + receipts_root: H256::from_slice(payload.receipts_root()), + state_root: H256::from_slice(payload.state_root()), + timestamp: *payload.timestamp(), total_difficulty: 0, transactions: txs, - mix_hash: H256::from_slice(&payload.prev_randao), + mix_hash: H256::from_slice(payload.prev_randao()), nonce: empty_nonce, sha3_uncles: H256::from_str(empty_uncle_hash)?, size: 0, @@ -192,10 +192,10 @@ impl ExecutionClient { payload: &ExecutionPayload, index: usize, ) -> Result> { - let tx = payload.transactions[index].clone(); + let tx = payload.transactions()[index].clone(); let tx_hash = H256::from_slice(&keccak256(tx)); let mut payloads = BTreeMap::new(); - payloads.insert(payload.block_number, payload.clone()); + payloads.insert(*payload.block_number(), payload.clone()); let tx_option = self.get_transaction(&tx_hash, &payloads).await?; let tx = tx_option.ok_or(eyre::eyre!("not reachable"))?; @@ -222,7 +222,7 @@ impl ExecutionClient { let payload = payload.unwrap(); let tx_hashes = payload - .transactions + .transactions() .iter() .map(|tx| H256::from_slice(&keccak256(tx))) .collect::>(); @@ -239,7 +239,7 @@ impl ExecutionClient { let expected_receipt_root = ordered_trie_root(receipts_encoded); let expected_receipt_root = H256::from_slice(&expected_receipt_root.to_fixed_bytes()); - let payload_receipt_root = H256::from_slice(&payload.receipts_root); + let payload_receipt_root = H256::from_slice(payload.receipts_root()); if expected_receipt_root != payload_receipt_root || !receipts.contains(&receipt) { return Err(ExecutionError::ReceiptRootMismatch(tx_hash.to_string()).into()); @@ -275,7 +275,7 @@ impl ExecutionClient { let tx_encoded = tx.rlp().to_vec(); let txs_encoded = payload - .transactions + .transactions() .iter() .map(|tx| tx.to_vec()) .collect::>(); @@ -396,29 +396,19 @@ impl ExecutionClient { .get(&block_id) .ok_or(ExecutionError::EmptyExecutionPayload())?; let converted_base_fee_per_gas = ethers::types::U256::from_little_endian( - &execution_payload.base_fee_per_gas.to_bytes_le(), + &execution_payload.base_fee_per_gas().to_bytes_le(), ); fee_history .base_fee_per_gas .push(converted_base_fee_per_gas); - let gas_used_ratio_helios = ((execution_payload.gas_used as f64 - / execution_payload.gas_limit as f64) + let gas_used_ratio_helios = ((*execution_payload.gas_used() as f64 + / *execution_payload.gas_limit() as f64) * 10.0_f64.powi(12)) .round() / 10.0_f64.powi(12); fee_history.gas_used_ratio.push(gas_used_ratio_helios); } - // TODO: Maybe place behind a query option param? - // Optionally verify the computed fee history using the rpc - // verify_fee_history( - // &self.rpc, - // &fee_history, - // fee_history.base_fee_per_gas.len(), - // request_latest_block, - // reward_percentiles, - // ).await?; - Ok(Some(fee_history)) } } diff --git a/execution/tests/execution.rs b/execution/tests/execution.rs index 0994e22..f5c77cd 100644 --- a/execution/tests/execution.rs +++ b/execution/tests/execution.rs @@ -5,7 +5,7 @@ use ethers::types::{Address, Filter, H256, U256}; use ssz_rs::{List, Vector}; use common::utils::hex_str_to_bytes; -use consensus::types::ExecutionPayload; +use consensus::types::{ExecutionPayload, ExecutionPayloadBellatrix}; use execution::rpc::mock_rpc::MockRpc; use execution::ExecutionClient; @@ -18,13 +18,13 @@ async fn test_get_account() { let execution = get_client(); let address = Address::from_str("14f9D4aF749609c1438528C0Cce1cC3f6D411c47").unwrap(); - let payload = ExecutionPayload { + let payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix { state_root: Vector::from_iter( hex_str_to_bytes("0xaa02f5db2ee75e3da400d10f3c30e894b6016ce8a2501680380a907b6674ce0d") .unwrap(), ), - ..ExecutionPayload::default() - }; + ..ExecutionPayloadBellatrix::default() + }); let account = execution .get_account(&address, None, &payload) @@ -55,7 +55,7 @@ async fn test_get_tx() { H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap(); let mut payload = ExecutionPayload::default(); - payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); + payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); let mut payloads = BTreeMap::new(); payloads.insert(7530933, payload); @@ -104,15 +104,15 @@ async fn test_get_tx_not_included() { #[tokio::test] async fn test_get_logs() { let execution = get_client(); - let mut payload = ExecutionPayload { + let mut payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix { receipts_root: Vector::from_iter( hex_str_to_bytes("dd82a78eccb333854f0c99e5632906e092d8a49c27a21c25cae12b82ec2a113f") .unwrap(), ), - ..ExecutionPayload::default() - }; + ..ExecutionPayloadBellatrix::default() + }); - payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); + payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); let mut payloads = BTreeMap::new(); payloads.insert(7530933, payload); @@ -134,15 +134,15 @@ async fn test_get_receipt() { let tx_hash = H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap(); - let mut payload = ExecutionPayload { + let mut payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix { receipts_root: Vector::from_iter( hex_str_to_bytes("dd82a78eccb333854f0c99e5632906e092d8a49c27a21c25cae12b82ec2a113f") .unwrap(), ), - ..ExecutionPayload::default() - }; + ..ExecutionPayloadBellatrix::default() + }); - payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); + payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); let mut payloads = BTreeMap::new(); payloads.insert(7530933, payload); @@ -163,7 +163,7 @@ async fn test_get_receipt_bad_proof() { H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap(); let mut payload = ExecutionPayload::default(); - payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); + payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); let mut payloads = BTreeMap::new(); payloads.insert(7530933, payload); @@ -191,10 +191,10 @@ async fn test_get_receipt_not_included() { #[tokio::test] async fn test_get_block() { let execution = get_client(); - let payload = ExecutionPayload { + let payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix { block_number: 12345, - ..ExecutionPayload::default() - }; + ..ExecutionPayloadBellatrix::default() + }); let block = execution.get_block(&payload, false).await.unwrap(); @@ -207,11 +207,11 @@ async fn test_get_tx_by_block_hash_and_index() { let tx_hash = H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap(); - let mut payload = ExecutionPayload { + let mut payload = ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix { block_number: 7530933, - ..ExecutionPayload::default() - }; - payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); + ..ExecutionPayloadBellatrix::default() + }); + payload.transactions_mut().push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); let tx = execution .get_transaction_by_block_hash_and_index(&payload, 0)