diff --git a/Cargo.lock b/Cargo.lock index 9aa08ce13..995f36e5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6577,6 +6577,7 @@ dependencies = [ "alloy-eips", "alloy-genesis", "alloy-primitives", + "alloy-rlp", "alloy-trie", "arbitrary", "bytes", @@ -6584,6 +6585,7 @@ dependencies = [ "op-alloy-consensus", "proptest", "proptest-arbitrary-interop", + "rand 0.8.5", "reth-codecs-derive", "serde", "serde_json", @@ -8250,7 +8252,6 @@ dependencies = [ "alloy-genesis", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types-eth", "arbitrary", "byteorder", "bytes", diff --git a/bin/reth-bench/src/bench/new_payload_fcu.rs b/bin/reth-bench/src/bench/new_payload_fcu.rs index 908cf81b4..61780b3ab 100644 --- a/bin/reth-bench/src/bench/new_payload_fcu.rs +++ b/bin/reth-bench/src/bench/new_payload_fcu.rs @@ -100,7 +100,8 @@ impl Command { ) .await?; - let new_payload_result = NewPayloadResult { gas_used, latency: start.elapsed() }; + let new_payload_result = + NewPayloadResult { gas_used: gas_used as u64, latency: start.elapsed() }; call_forkchoice_updated(&auth_provider, message_version, forkchoice_state, None) .await?; @@ -118,7 +119,8 @@ impl Command { info!(%combined_result); // record the current result - let gas_row = TotalGasRow { block_number, gas_used, time: current_duration }; + let gas_row = + TotalGasRow { block_number, gas_used: gas_used as u64, time: current_duration }; results.push((gas_row, combined_result)); } diff --git a/bin/reth-bench/src/bench/new_payload_only.rs b/bin/reth-bench/src/bench/new_payload_only.rs index 83a5f8c95..866ffa5b4 100644 --- a/bin/reth-bench/src/bench/new_payload_only.rs +++ b/bin/reth-bench/src/bench/new_payload_only.rs @@ -77,14 +77,16 @@ impl Command { call_new_payload(&auth_provider, payload, parent_beacon_block_root, versioned_hashes) .await?; - let new_payload_result = NewPayloadResult { gas_used, latency: start.elapsed() }; + let new_payload_result = + NewPayloadResult { gas_used: gas_used as u64, latency: start.elapsed() }; info!(%new_payload_result); // current duration since the start of the benchmark let current_duration = total_benchmark_duration.elapsed(); // record the current result - let row = TotalGasRow { block_number, gas_used, time: current_duration }; + let row = + TotalGasRow { block_number, gas_used: gas_used as u64, time: current_duration }; results.push((row, new_payload_result)); } diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 5cb22e317..f5f7698f5 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -414,8 +414,9 @@ where let parent_header = provider .header(&block.parent_hash)? - .ok_or_else(|| BlockchainTreeError::CanonicalChain { block_hash: block.parent_hash })? - .seal(block.parent_hash); + .ok_or_else(|| BlockchainTreeError::CanonicalChain { block_hash: block.parent_hash })?; + + let parent_sealed_header = SealedHeader::new(parent_header, block.parent_hash); let canonical_chain = self.state.block_indices.canonical_chain(); @@ -427,7 +428,7 @@ where let chain = AppendableChain::new_canonical_fork( block, - &parent_header, + &parent_sealed_header, canonical_chain.inner(), parent, &self.externals, @@ -993,7 +994,7 @@ where header = provider.header(hash)? } - Ok(header.map(|header| header.seal(*hash))) + Ok(header.map(|header| SealedHeader::new(header, *hash))) } /// Determines whether or not a block is canonical, checking the db if necessary. @@ -1375,7 +1376,7 @@ where mod tests { use super::*; use alloy_genesis::{Genesis, GenesisAccount}; - use alloy_primitives::{keccak256, Address, B256}; + use alloy_primitives::{keccak256, Address, Sealable, B256}; use assert_matches::assert_matches; use linked_hash_set::LinkedHashSet; use reth_chainspec::{ChainSpecBuilder, MAINNET, MIN_TRANSACTION_GAS}; @@ -1598,32 +1599,35 @@ mod tests { // receipts root computation is different for OP let receipts_root = calculate_receipt_root(&receipts); + let sealed = Header { + number, + parent_hash: parent.unwrap_or_default(), + gas_used: (body.len() as u64 * MIN_TRANSACTION_GAS) as u128, + gas_limit: chain_spec.max_gas_limit.into(), + mix_hash: B256::random(), + base_fee_per_gas: Some(EIP1559_INITIAL_BASE_FEE.into()), + transactions_root, + receipts_root, + state_root: state_root_unhashed(HashMap::from([( + signer, + ( + AccountInfo { + balance: initial_signer_balance - + (single_tx_cost * U256::from(num_of_signer_txs)), + nonce: num_of_signer_txs, + ..Default::default() + }, + EMPTY_ROOT_HASH, + ), + )])), + ..Default::default() + } + .seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedBlockWithSenders::new( SealedBlock { - header: Header { - number, - parent_hash: parent.unwrap_or_default(), - gas_used: body.len() as u64 * MIN_TRANSACTION_GAS, - gas_limit: chain_spec.max_gas_limit, - mix_hash: B256::random(), - base_fee_per_gas: Some(EIP1559_INITIAL_BASE_FEE), - transactions_root, - receipts_root, - state_root: state_root_unhashed(HashMap::from([( - signer, - ( - AccountInfo { - balance: initial_signer_balance - - (single_tx_cost * U256::from(num_of_signer_txs)), - nonce: num_of_signer_txs, - ..Default::default() - }, - EMPTY_ROOT_HASH, - ), - )])), - ..Default::default() - } - .seal_slow(), + header: SealedHeader::new(header, seal), body: body.clone().into_iter().map(|tx| tx.into_signed()).collect(), ommers: Vec::new(), withdrawals: Some(Withdrawals::default()), diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index c78baf4dd..a098e10c2 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -569,9 +569,18 @@ impl CanonicalInMemoryState { index: index as u64, block_hash: block_state.hash(), block_number: block_state.block().block.number, - base_fee: block_state.block().block().header.base_fee_per_gas, + base_fee: block_state + .block() + .block() + .header + .base_fee_per_gas + .map(|base_fee| base_fee as u64), timestamp: block_state.block().block.timestamp, - excess_blob_gas: block_state.block().block.excess_blob_gas, + excess_blob_gas: block_state + .block() + .block + .excess_blob_gas + .map(|excess_blob| excess_blob as u64), }; return Some((tx.clone(), meta)) } diff --git a/crates/chain-state/src/test_utils.rs b/crates/chain-state/src/test_utils.rs index ed687ec03..84a50dd44 100644 --- a/crates/chain-state/src/test_utils.rs +++ b/crates/chain-state/src/test_utils.rs @@ -9,10 +9,11 @@ use rand::{thread_rng, Rng}; use reth_chainspec::{ChainSpec, EthereumHardfork, MIN_TRANSACTION_GAS}; use reth_execution_types::{Chain, ExecutionOutcome}; use reth_primitives::{ + alloy_primitives::Sealable, constants::{EIP1559_INITIAL_BASE_FEE, EMPTY_ROOT_HASH}, proofs::{calculate_receipt_root, calculate_transaction_root, calculate_withdrawals_root}, - Header, Receipt, Receipts, Requests, SealedBlock, SealedBlockWithSenders, Signature, - Transaction, TransactionSigned, TransactionSignedEcRecovered, TxEip1559, + Header, Receipt, Receipts, Requests, SealedBlock, SealedBlockWithSenders, SealedHeader, + Signature, Transaction, TransactionSigned, TransactionSignedEcRecovered, TxEip1559, }; use reth_trie::{root::state_root_unhashed, updates::TrieUpdates, HashedPostState}; use revm::{db::BundleState, primitives::AccountInfo}; @@ -138,10 +139,10 @@ impl TestBlockBuilder { let header = Header { number, parent_hash, - gas_used: transactions.len() as u64 * MIN_TRANSACTION_GAS, - gas_limit: self.chain_spec.max_gas_limit, + gas_used: transactions.len() as u128 * MIN_TRANSACTION_GAS as u128, + gas_limit: self.chain_spec.max_gas_limit.into(), mix_hash: B256::random(), - base_fee_per_gas: Some(EIP1559_INITIAL_BASE_FEE), + base_fee_per_gas: Some(EIP1559_INITIAL_BASE_FEE.into()), transactions_root: calculate_transaction_root(&transactions), receipts_root: calculate_receipt_root(&receipts), beneficiary: Address::random(), @@ -166,8 +167,11 @@ impl TestBlockBuilder { ..Default::default() }; + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + let block = SealedBlock { - header: header.seal_slow(), + header: SealedHeader::new(header, seal), body: transactions.into_iter().map(|tx| tx.into_signed()).collect(), ommers: Vec::new(), withdrawals: Some(vec![].into()), diff --git a/crates/chainspec/src/spec.rs b/crates/chainspec/src/spec.rs index 52897ef95..6b0206135 100644 --- a/crates/chainspec/src/spec.rs +++ b/crates/chainspec/src/spec.rs @@ -304,19 +304,19 @@ impl ChainSpec { }; Header { - gas_limit: self.genesis.gas_limit as u64, + gas_limit: self.genesis.gas_limit, difficulty: self.genesis.difficulty, - nonce: self.genesis.nonce, + nonce: self.genesis.nonce.into(), extra_data: self.genesis.extra_data.clone(), state_root: state_root_ref_unhashed(&self.genesis.alloc), timestamp: self.genesis.timestamp, mix_hash: self.genesis.mix_hash, beneficiary: self.genesis.coinbase, - base_fee_per_gas, + base_fee_per_gas: base_fee_per_gas.map(Into::into), withdrawals_root, parent_beacon_block_root, - blob_gas_used, - excess_blob_gas, + blob_gas_used: blob_gas_used.map(Into::into), + excess_blob_gas: excess_blob_gas.map(Into::into), requests_root, ..Default::default() } diff --git a/crates/consensus/auto-seal/src/lib.rs b/crates/consensus/auto-seal/src/lib.rs index 902566472..cb80f6b23 100644 --- a/crates/consensus/auto-seal/src/lib.rs +++ b/crates/consensus/auto-seal/src/lib.rs @@ -292,10 +292,10 @@ impl StorageInner { withdrawals_root: withdrawals.map(|w| proofs::calculate_withdrawals_root(w)), difficulty: U256::from(2), number: self.best_block + 1, - gas_limit: chain_spec.max_gas_limit, + gas_limit: chain_spec.max_gas_limit.into(), timestamp, base_fee_per_gas, - blob_gas_used, + blob_gas_used: blob_gas_used.map(Into::into), requests_root: requests.map(|r| proofs::calculate_requests_root(&r.0)), ..Default::default() }; @@ -317,8 +317,13 @@ impl StorageInner { } _ => (0, 0), }; - header.excess_blob_gas = - Some(calculate_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used)) + header.excess_blob_gas = Some( + calculate_excess_blob_gas( + parent_excess_blob_gas as u64, + parent_blob_gas_used as u64, + ) + .into(), + ) } header @@ -392,7 +397,7 @@ impl StorageInner { // now we need to update certain header fields with the results of the execution header.state_root = db.state_root(hashed_state)?; - header.gas_used = gas_used; + header.gas_used = gas_used.into(); let receipts = execution_outcome.receipts_by_block(header.number); @@ -420,7 +425,7 @@ impl StorageInner { self.insert_new_block(header.clone(), body); // set new header with hash that should have been updated by insert_new_block - let new_header = header.seal(self.best_hash); + let new_header = SealedHeader::new(header, self.best_hash); Ok((new_header, execution_outcome)) } @@ -574,7 +579,7 @@ mod tests { assert_eq!(header.parent_hash, best_block_hash); assert_eq!(header.number, best_block_number + 1); assert_eq!(header.timestamp, timestamp); - assert_eq!(header.gas_limit, chain_spec.max_gas_limit); + assert_eq!(header.gas_limit, chain_spec.max_gas_limit.into()); } #[test] @@ -668,7 +673,7 @@ mod tests { withdrawals_root: None, difficulty: U256::from(2), number: 1, - gas_limit: chain_spec.max_gas_limit, + gas_limit: chain_spec.max_gas_limit.into(), timestamp, base_fee_per_gas: None, blob_gas_used: Some(0), diff --git a/crates/consensus/beacon/src/engine/invalid_headers.rs b/crates/consensus/beacon/src/engine/invalid_headers.rs index ff5ede5a7..8a1c95d73 100644 --- a/crates/consensus/beacon/src/engine/invalid_headers.rs +++ b/crates/consensus/beacon/src/engine/invalid_headers.rs @@ -106,11 +106,14 @@ struct InvalidHeaderCacheMetrics { #[cfg(test)] mod tests { use super::*; + use alloy_primitives::Sealable; #[test] fn test_hit_eviction() { let mut cache = InvalidHeaderCache::new(10); - let header = Header::default().seal_slow(); + let sealed = Header::default().seal_slow(); + let (header, seal) = sealed.into_parts(); + let header = SealedHeader::new(header, seal); cache.insert(header.clone()); assert_eq!(cache.headers.get(&header.hash()).unwrap().hit_count, 0); diff --git a/crates/consensus/beacon/src/engine/mod.rs b/crates/consensus/beacon/src/engine/mod.rs index 8a785aa9e..4c39c052a 100644 --- a/crates/consensus/beacon/src/engine/mod.rs +++ b/crates/consensus/beacon/src/engine/mod.rs @@ -946,7 +946,7 @@ where .blockchain .find_block_by_hash(safe_block_hash, BlockSource::Any)? .ok_or_else(|| ProviderError::UnknownBlockHash(safe_block_hash))?; - self.blockchain.set_safe(safe.header.seal(safe_block_hash)); + self.blockchain.set_safe(SealedHeader::new(safe.header, safe_block_hash)); } Ok(()) } @@ -967,7 +967,8 @@ where .find_block_by_hash(finalized_block_hash, BlockSource::Any)? .ok_or_else(|| ProviderError::UnknownBlockHash(finalized_block_hash))?; self.blockchain.finalize_block(finalized.number)?; - self.blockchain.set_finalized(finalized.header.seal(finalized_block_hash)); + self.blockchain + .set_finalized(SealedHeader::new(finalized.header, finalized_block_hash)); } Ok(()) } diff --git a/crates/consensus/beacon/src/engine/sync.rs b/crates/consensus/beacon/src/engine/sync.rs index 5f73c145e..6e010a59d 100644 --- a/crates/consensus/beacon/src/engine/sync.rs +++ b/crates/consensus/beacon/src/engine/sync.rs @@ -410,6 +410,7 @@ impl PipelineState { #[cfg(test)] mod tests { use super::*; + use alloy_primitives::Sealable; use assert_matches::assert_matches; use futures::poll; use reth_chainspec::{ChainSpec, ChainSpecBuilder, MAINNET}; @@ -598,7 +599,9 @@ mod tests { header.parent_hash = hash; header.number += 1; header.timestamp += 1; - sealed_header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + sealed_header = SealedHeader::new(header, seal); client.insert(sealed_header.clone(), body.clone()); } } @@ -614,12 +617,14 @@ mod tests { ); let client = TestFullBlockClient::default(); - let header = Header { + let sealed = Header { base_fee_per_gas: Some(7), - gas_limit: chain_spec.max_gas_limit, + gas_limit: chain_spec.max_gas_limit.into(), ..Default::default() } .seal_slow(); + let (header, seal) = sealed.into_parts(); + let header = SealedHeader::new(header, seal); insert_headers_into_client(&client, header, 0..10); // set up a pipeline diff --git a/crates/consensus/beacon/src/engine/test_utils.rs b/crates/consensus/beacon/src/engine/test_utils.rs index 79d17e085..44d1d0f05 100644 --- a/crates/consensus/beacon/src/engine/test_utils.rs +++ b/crates/consensus/beacon/src/engine/test_utils.rs @@ -1,6 +1,10 @@ #![allow(missing_docs)] - -use alloy_primitives::{BlockNumber, B256}; +use crate::{ + engine::hooks::PruneHook, hooks::EngineHooks, BeaconConsensusEngine, + BeaconConsensusEngineError, BeaconConsensusEngineHandle, BeaconForkChoiceUpdateError, + BeaconOnNewPayloadError, EthBeaconConsensus, MIN_BLOCKS_FOR_PIPELINE_RUN, +}; +use alloy_primitives::{BlockNumber, Sealable, B256}; use reth_blockchain_tree::{ config::BlockchainTreeConfig, externals::TreeExternals, BlockchainTree, ShareableBlockchainTree, }; @@ -18,6 +22,7 @@ use reth_evm_ethereum::execute::EthExecutorProvider; use reth_exex_types::FinishedExExHeight; use reth_network_p2p::{sync::NoopSyncStateUpdater, test_utils::NoopFullBlockClient, BlockClient}; use reth_payload_builder::test_utils::spawn_test_payload_service; +use reth_primitives::SealedHeader; use reth_provider::{ providers::BlockchainProvider, test_utils::{create_test_provider_factory_with_chain_spec, MockNodeTypesWithDB}, @@ -34,12 +39,6 @@ use reth_tasks::TokioTaskExecutor; use std::{collections::VecDeque, sync::Arc}; use tokio::sync::{oneshot, watch}; -use crate::{ - engine::hooks::PruneHook, hooks::EngineHooks, BeaconConsensusEngine, - BeaconConsensusEngineError, BeaconConsensusEngineHandle, BeaconForkChoiceUpdateError, - BeaconOnNewPayloadError, EthBeaconConsensus, MIN_BLOCKS_FOR_PIPELINE_RUN, -}; - type DatabaseEnv = TempDatabase; type TestBeaconConsensusEngine = BeaconConsensusEngine< @@ -395,7 +394,9 @@ where BlockchainTree::new(externals, BlockchainTreeConfig::new(1, 2, 3, 2)) .expect("failed to create tree"), )); - let genesis_block = self.base_config.chain_spec.genesis_header().clone().seal_slow(); + let sealed = self.base_config.chain_spec.genesis_header().clone().seal_slow(); + let (header, seal) = sealed.into_parts(); + let genesis_block = SealedHeader::new(header, seal); let blockchain_provider = BlockchainProvider::with_blocks(provider_factory.clone(), tree, genesis_block, None); diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index 0eadb75a7..51640cbf1 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -16,8 +16,8 @@ use reth_primitives::{ pub const fn validate_header_gas(header: &Header) -> Result<(), ConsensusError> { if header.gas_used > header.gas_limit { return Err(ConsensusError::HeaderGasUsedExceedsGasLimit { - gas_used: header.gas_used, - gas_limit: header.gas_limit, + gas_used: header.gas_used as u64, + gas_limit: header.gas_limit as u64, }) } Ok(()) @@ -65,7 +65,8 @@ pub fn validate_shanghai_withdrawals(block: &SealedBlock) -> Result<(), Consensu pub fn validate_cancun_gas(block: &SealedBlock) -> Result<(), ConsensusError> { // Check that the blob gas used in the header matches the sum of the blob gas used by each // blob tx - let header_blob_gas_used = block.blob_gas_used.ok_or(ConsensusError::BlobGasUsedMissing)?; + let header_blob_gas_used = + block.blob_gas_used.ok_or(ConsensusError::BlobGasUsedMissing)? as u64; let total_blob_gas = block.blob_gas_used(); if total_blob_gas != header_blob_gas_used { return Err(ConsensusError::BlobGasUsedDiff(GotExpected { @@ -150,25 +151,25 @@ pub fn validate_4844_header_standalone(header: &Header) -> Result<(), ConsensusE return Err(ConsensusError::ParentBeaconBlockRootMissing) } - if blob_gas_used > MAX_DATA_GAS_PER_BLOCK { + if blob_gas_used as u64 > MAX_DATA_GAS_PER_BLOCK { return Err(ConsensusError::BlobGasUsedExceedsMaxBlobGasPerBlock { - blob_gas_used, + blob_gas_used: blob_gas_used as u64, max_blob_gas_per_block: MAX_DATA_GAS_PER_BLOCK, }) } - if blob_gas_used % DATA_GAS_PER_BLOB != 0 { + if blob_gas_used as u64 % DATA_GAS_PER_BLOB != 0 { return Err(ConsensusError::BlobGasUsedNotMultipleOfBlobGasPerBlob { - blob_gas_used, + blob_gas_used: blob_gas_used as u64, blob_gas_per_blob: DATA_GAS_PER_BLOB, }) } // `excess_blob_gas` must also be a multiple of `DATA_GAS_PER_BLOB`. This will be checked later // (via `calculate_excess_blob_gas`), but it doesn't hurt to catch the problem sooner. - if excess_blob_gas % DATA_GAS_PER_BLOB != 0 { + if excess_blob_gas as u64 % DATA_GAS_PER_BLOB != 0 { return Err(ConsensusError::ExcessBlobGasNotMultipleOfBlobGasPerBlob { - excess_blob_gas, + excess_blob_gas: excess_blob_gas as u64, blob_gas_per_blob: DATA_GAS_PER_BLOB, }) } @@ -224,7 +225,7 @@ pub fn validate_against_parent_eip1559_base_fee Result<(), ConsensusError> { if chain_spec.fork(EthereumHardfork::London).active_at_block(header.number) { - let base_fee = header.base_fee_per_gas.ok_or(ConsensusError::BaseFeeMissing)?; + let base_fee = header.base_fee_per_gas.ok_or(ConsensusError::BaseFeeMissing)? as u64; let expected_base_fee = if chain_spec.fork(EthereumHardfork::London).transitions_at_block(header.number) { @@ -234,7 +235,7 @@ pub fn validate_against_parent_eip1559_base_fee Result<(), ConsensusError> { - if header.is_timestamp_in_past(parent.timestamp) { + if header.timestamp <= parent.timestamp { return Err(ConsensusError::TimestampIsInPast { parent_timestamp: parent.timestamp, timestamp: header.timestamp, @@ -276,13 +277,14 @@ pub fn validate_against_parent_4844( // > are evaluated as 0. // // This means in the first post-fork block, calculate_excess_blob_gas will return 0. - let parent_blob_gas_used = parent.blob_gas_used.unwrap_or(0); - let parent_excess_blob_gas = parent.excess_blob_gas.unwrap_or(0); + let parent_blob_gas_used = parent.blob_gas_used.unwrap_or(0) as u64; + let parent_excess_blob_gas = parent.excess_blob_gas.unwrap_or(0) as u64; if header.blob_gas_used.is_none() { return Err(ConsensusError::BlobGasUsedMissing) } - let excess_blob_gas = header.excess_blob_gas.ok_or(ConsensusError::ExcessBlobGasMissing)?; + let excess_blob_gas = + header.excess_blob_gas.ok_or(ConsensusError::ExcessBlobGasMissing)? as u64; let expected_excess_blob_gas = calculate_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used); @@ -300,7 +302,9 @@ pub fn validate_against_parent_4844( #[cfg(test)] mod tests { use super::*; - use alloy_primitives::{hex_literal::hex, Address, BlockHash, BlockNumber, Bytes, U256}; + use alloy_primitives::{ + hex_literal::hex, Address, BlockHash, BlockNumber, Bytes, Sealable, U256, + }; use mockall::mock; use rand::Rng; use reth_chainspec::ChainSpecBuilder; @@ -451,7 +455,7 @@ mod tests { timestamp: 0x635f9657, extra_data: hex!("")[..].into(), mix_hash: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: 0x0000000000000000, + nonce: 0x0000000000000000u64.into(), base_fee_per_gas: 0x28f0001df.into(), withdrawals_root: None, blob_gas_used: None, @@ -471,9 +475,12 @@ mod tests { let ommers = Vec::new(); let body = Vec::new(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + ( SealedBlock { - header: header.seal_slow(), + header: SealedHeader::new(header, seal), body, ommers, withdrawals: None, @@ -494,12 +501,16 @@ mod tests { .map(|idx| Withdrawal { index: *idx, ..Default::default() }) .collect(), ); + + let sealed = Header { + withdrawals_root: Some(proofs::calculate_withdrawals_root(&withdrawals)), + ..Default::default() + } + .seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedBlock { - header: Header { - withdrawals_root: Some(proofs::calculate_withdrawals_root(&withdrawals)), - ..Default::default() - } - .seal_slow(), + header: SealedHeader::new(header, seal), withdrawals: Some(withdrawals), ..Default::default() } @@ -531,14 +542,16 @@ mod tests { // create a tx with 10 blobs let transaction = mock_blob_tx(1, 10); - let header = Header { - base_fee_per_gas: Some(1337u64), + let sealed = Header { + base_fee_per_gas: Some(1337u128), withdrawals_root: Some(proofs::calculate_withdrawals_root(&[])), blob_gas_used: Some(1), transactions_root: proofs::calculate_transaction_root(&[transaction.clone()]), ..Default::default() } .seal_slow(); + let (header, seal) = sealed.into_parts(); + let header = SealedHeader::new(header, seal); let body = BlockBody { transactions: vec![transaction], diff --git a/crates/engine/tree/src/backfill.rs b/crates/engine/tree/src/backfill.rs index 0877002a4..440e86693 100644 --- a/crates/engine/tree/src/backfill.rs +++ b/crates/engine/tree/src/backfill.rs @@ -235,7 +235,7 @@ mod tests { use futures::poll; use reth_chainspec::{ChainSpecBuilder, MAINNET}; use reth_network_p2p::test_utils::TestFullBlockClient; - use reth_primitives::Header; + use reth_primitives::{alloy_primitives::Sealable, Header, SealedHeader}; use reth_provider::test_utils::MockNodeTypesWithDB; use reth_stages::ExecOutput; use reth_stages_api::StageCheckpoint; @@ -267,12 +267,14 @@ mod tests { let pipeline_sync = PipelineSync::new(pipeline, Box::::default()); let client = TestFullBlockClient::default(); - let header = Header { + let sealed = Header { base_fee_per_gas: Some(7), - gas_limit: chain_spec.max_gas_limit, + gas_limit: chain_spec.max_gas_limit.into(), ..Default::default() } .seal_slow(); + let (header, seal) = sealed.into_parts(); + let header = SealedHeader::new(header, seal); insert_headers_into_client(&client, header, 0..total_blocks); let tip = client.highest_block().expect("there should be blocks here").hash(); diff --git a/crates/engine/tree/src/download.rs b/crates/engine/tree/src/download.rs index f1538c5c9..aff99c884 100644 --- a/crates/engine/tree/src/download.rs +++ b/crates/engine/tree/src/download.rs @@ -309,7 +309,7 @@ mod tests { use reth_beacon_consensus::EthBeaconConsensus; use reth_chainspec::{ChainSpecBuilder, MAINNET}; use reth_network_p2p::test_utils::TestFullBlockClient; - use reth_primitives::Header; + use reth_primitives::{alloy_primitives::Sealable, Header, SealedHeader}; use std::{future::poll_fn, sync::Arc}; struct TestHarness { @@ -328,12 +328,14 @@ mod tests { ); let client = TestFullBlockClient::default(); - let header = Header { + let sealed = Header { base_fee_per_gas: Some(7), - gas_limit: chain_spec.max_gas_limit, + gas_limit: chain_spec.max_gas_limit.into(), ..Default::default() } .seal_slow(); + let (header, seal) = sealed.into_parts(); + let header = SealedHeader::new(header, seal); insert_headers_into_client(&client, header, 0..total_blocks); let consensus = Arc::new(EthBeaconConsensus::new(chain_spec)); diff --git a/crates/engine/tree/src/test_utils.rs b/crates/engine/tree/src/test_utils.rs index 0b999cef6..3d04e2db7 100644 --- a/crates/engine/tree/src/test_utils.rs +++ b/crates/engine/tree/src/test_utils.rs @@ -1,7 +1,7 @@ use alloy_primitives::B256; use reth_chainspec::ChainSpec; use reth_network_p2p::test_utils::TestFullBlockClient; -use reth_primitives::{BlockBody, SealedHeader}; +use reth_primitives::{alloy_primitives::Sealable, BlockBody, SealedHeader}; use reth_provider::{ test_utils::{create_test_provider_factory_with_chain_spec, MockNodeTypesWithDB}, ExecutionOutcome, @@ -76,7 +76,9 @@ pub fn insert_headers_into_client( header.parent_hash = hash; header.number += 1; header.timestamp += 1; - sealed_header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + sealed_header = SealedHeader::new(header, seal); client.insert(sealed_header.clone(), body.clone()); } } diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index 3aff602e7..0a205ae58 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -2336,7 +2336,7 @@ where let mut canonical = self.canonical_in_memory_state.header_by_hash(hash); if canonical.is_none() { - canonical = self.provider.header(&hash)?.map(|header| header.seal(hash)); + canonical = self.provider.header(&hash)?.map(|header| SealedHeader::new(header, hash)); } Ok(canonical) @@ -2597,6 +2597,7 @@ mod tests { use reth_chainspec::{ChainSpec, HOLESKY, MAINNET}; use reth_ethereum_engine_primitives::EthEngineTypes; use reth_evm::test_utils::MockExecutorProvider; + use reth_primitives::alloy_primitives::Sealable; use reth_provider::test_utils::MockEthProvider; use reth_rpc_types_compat::engine::{block_to_payload_v1, payload::block_to_payload_v3}; use reth_trie::updates::TrieUpdates; @@ -2701,7 +2702,9 @@ mod tests { let (from_tree_tx, from_tree_rx) = unbounded_channel(); - let header = chain_spec.genesis_header().clone().seal_slow(); + let sealed = chain_spec.genesis_header().clone().seal_slow(); + let (header, seal) = sealed.into_parts(); + let header = SealedHeader::new(header, seal); let engine_api_tree_state = EngineApiTreeState::new(10, 10, header.num_hash()); let canonical_in_memory_state = CanonicalInMemoryState::with_head(header, None); diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index ff699ffaa..d72115294 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -303,7 +303,7 @@ where let mut versioned_hashes = Vec::new(); for tx in candidate_transactions { // ensure we still have capacity for this transaction - if cumulative_gas_used + tx.gas_limit() > reorg_target.gas_limit { + if cumulative_gas_used + tx.gas_limit() > reorg_target.gas_limit as u64 { continue } @@ -372,8 +372,8 @@ where ( Some(sum_blob_gas_used), Some(calculate_excess_blob_gas( - reorg_target_parent.excess_blob_gas.unwrap_or_default(), - reorg_target_parent.blob_gas_used.unwrap_or_default(), + reorg_target_parent.excess_blob_gas.unwrap_or_default() as u64, + reorg_target_parent.blob_gas_used.unwrap_or_default() as u64, )), ) } else { @@ -402,9 +402,9 @@ where receipts_root: outcome.receipts_root_slow(reorg_target.header.number).unwrap(), logs_bloom: outcome.block_logs_bloom(reorg_target.header.number).unwrap(), requests_root: None, // TODO(prague) - gas_used: cumulative_gas_used, - blob_gas_used, - excess_blob_gas, + gas_used: cumulative_gas_used.into(), + blob_gas_used: blob_gas_used.map(Into::into), + excess_blob_gas: excess_blob_gas.map(Into::into), state_root: state_provider.state_root(hashed_state)?, }, body: transactions, diff --git a/crates/ethereum/consensus/src/lib.rs b/crates/ethereum/consensus/src/lib.rs index 9fb07cca9..15b9ed091 100644 --- a/crates/ethereum/consensus/src/lib.rs +++ b/crates/ethereum/consensus/src/lib.rs @@ -55,34 +55,40 @@ impl EthBeaconConsensus // Determine the parent gas limit, considering elasticity multiplier on the London fork. let parent_gas_limit = if self.chain_spec.fork(EthereumHardfork::London).transitions_at_block(header.number) { - parent.gas_limit * + parent.gas_limit as u64 * self.chain_spec .base_fee_params_at_timestamp(header.timestamp) .elasticity_multiplier as u64 } else { - parent.gas_limit + parent.gas_limit as u64 }; // Check for an increase in gas limit beyond the allowed threshold. - if header.gas_limit > parent_gas_limit { - if header.gas_limit - parent_gas_limit >= parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR { + + if header.gas_limit as u64 > parent_gas_limit { + if header.gas_limit as u64 - parent_gas_limit >= + parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR + { return Err(ConsensusError::GasLimitInvalidIncrease { parent_gas_limit, - child_gas_limit: header.gas_limit, + child_gas_limit: header.gas_limit as u64, }) } } // Check for a decrease in gas limit beyond the allowed threshold. - else if parent_gas_limit - header.gas_limit >= parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR + else if parent_gas_limit - header.gas_limit as u64 >= + parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR { return Err(ConsensusError::GasLimitInvalidDecrease { parent_gas_limit, - child_gas_limit: header.gas_limit, + child_gas_limit: header.gas_limit as u64, }) } // Check if the self gas limit is below the minimum required limit. - else if header.gas_limit < MINIMUM_GAS_LIMIT { - return Err(ConsensusError::GasLimitInvalidMinimum { child_gas_limit: header.gas_limit }) + else if header.gas_limit < MINIMUM_GAS_LIMIT.into() { + return Err(ConsensusError::GasLimitInvalidMinimum { + child_gas_limit: header.gas_limit as u64, + }) } Ok(()) @@ -167,7 +173,7 @@ impl Consensu return Err(ConsensusError::TheMergeDifficultyIsNotZero) } - if header.nonce != 0 { + if !header.nonce.is_zero() { return Err(ConsensusError::TheMergeNonceIsNotZero) } @@ -227,17 +233,17 @@ impl Consensu mod tests { use super::*; use reth_chainspec::{ChainSpec, ChainSpecBuilder}; - use reth_primitives::{proofs, B256}; + use reth_primitives::{alloy_primitives::Sealable, proofs, B256}; fn header_with_gas_limit(gas_limit: u64) -> SealedHeader { - let header = Header { gas_limit, ..Default::default() }; - header.seal(B256::ZERO) + let header = Header { gas_limit: gas_limit.into(), ..Default::default() }; + SealedHeader::new(header, B256::ZERO) } #[test] fn test_valid_gas_limit_increase() { let parent = header_with_gas_limit(GAS_LIMIT_BOUND_DIVISOR * 10); - let child = header_with_gas_limit(parent.gas_limit + 5); + let child = header_with_gas_limit((parent.gas_limit + 5) as u64); assert_eq!( EthBeaconConsensus::new(Arc::new(ChainSpec::default())) @@ -254,7 +260,7 @@ mod tests { assert_eq!( EthBeaconConsensus::new(Arc::new(ChainSpec::default())) .validate_against_parent_gas_limit(&child, &parent), - Err(ConsensusError::GasLimitInvalidMinimum { child_gas_limit: child.gas_limit }) + Err(ConsensusError::GasLimitInvalidMinimum { child_gas_limit: child.gas_limit as u64 }) ); } @@ -262,15 +268,15 @@ mod tests { fn test_invalid_gas_limit_increase_exceeding_limit() { let parent = header_with_gas_limit(GAS_LIMIT_BOUND_DIVISOR * 10); let child = header_with_gas_limit( - parent.gas_limit + parent.gas_limit / GAS_LIMIT_BOUND_DIVISOR + 1, + (parent.gas_limit + parent.gas_limit / GAS_LIMIT_BOUND_DIVISOR as u128 + 1) as u64, ); assert_eq!( EthBeaconConsensus::new(Arc::new(ChainSpec::default())) .validate_against_parent_gas_limit(&child, &parent), Err(ConsensusError::GasLimitInvalidIncrease { - parent_gas_limit: parent.gas_limit, - child_gas_limit: child.gas_limit, + parent_gas_limit: parent.gas_limit as u64, + child_gas_limit: child.gas_limit as u64, }) ); } @@ -278,7 +284,7 @@ mod tests { #[test] fn test_valid_gas_limit_decrease_within_limit() { let parent = header_with_gas_limit(GAS_LIMIT_BOUND_DIVISOR * 10); - let child = header_with_gas_limit(parent.gas_limit - 5); + let child = header_with_gas_limit(parent.gas_limit as u64 - 5); assert_eq!( EthBeaconConsensus::new(Arc::new(ChainSpec::default())) @@ -291,15 +297,15 @@ mod tests { fn test_invalid_gas_limit_decrease_exceeding_limit() { let parent = header_with_gas_limit(GAS_LIMIT_BOUND_DIVISOR * 10); let child = header_with_gas_limit( - parent.gas_limit - parent.gas_limit / GAS_LIMIT_BOUND_DIVISOR - 1, + (parent.gas_limit - parent.gas_limit / GAS_LIMIT_BOUND_DIVISOR as u128 - 1) as u64, ); assert_eq!( EthBeaconConsensus::new(Arc::new(ChainSpec::default())) .validate_against_parent_gas_limit(&child, &parent), Err(ConsensusError::GasLimitInvalidDecrease { - parent_gas_limit: parent.gas_limit, - child_gas_limit: child.gas_limit, + parent_gas_limit: parent.gas_limit as u64, + child_gas_limit: child.gas_limit as u64, }) ); } @@ -310,13 +316,17 @@ mod tests { // that the header is valid let chain_spec = Arc::new(ChainSpecBuilder::mainnet().shanghai_activated().build()); - let header = Header { - base_fee_per_gas: Some(1337u64), + let sealed = Header { + base_fee_per_gas: Some(1337u128), withdrawals_root: Some(proofs::calculate_withdrawals_root(&[])), ..Default::default() } .seal_slow(); + let (header, seal) = sealed.into_parts(); - assert_eq!(EthBeaconConsensus::new(chain_spec).validate_header(&header), Ok(())); + assert_eq!( + EthBeaconConsensus::new(chain_spec).validate_header(&SealedHeader::new(header, seal)), + Ok(()) + ); } } diff --git a/crates/ethereum/consensus/src/validation.rs b/crates/ethereum/consensus/src/validation.rs index c8cdf3941..df966bc3c 100644 --- a/crates/ethereum/consensus/src/validation.rs +++ b/crates/ethereum/consensus/src/validation.rs @@ -17,9 +17,9 @@ pub fn validate_block_post_execution( // Check if gas used matches the value set in header. let cumulative_gas_used = receipts.last().map(|receipt| receipt.cumulative_gas_used).unwrap_or(0); - if block.gas_used != cumulative_gas_used { + if block.gas_used as u64 != cumulative_gas_used { return Err(ConsensusError::BlockGasUsed { - gas: GotExpected { got: cumulative_gas_used, expected: block.gas_used }, + gas: GotExpected { got: cumulative_gas_used, expected: block.gas_used as u64 }, gas_spent_by_tx: gas_spent_by_transactions(receipts), }) } diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index 096b44d0e..7a3d6d4cc 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -171,7 +171,7 @@ where for (sender, transaction) in block.transactions_with_sender() { // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block’s gasLimit. - let block_available_gas = block.header.gas_limit - cumulative_gas_used; + let block_available_gas = (block.header.gas_limit - cumulative_gas_used) as u64; if transaction.gas_limit() > block_available_gas { return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { transaction_gas_limit: transaction.gas_limit(), @@ -194,7 +194,7 @@ where evm.db_mut().commit(state); // append gas used - cumulative_gas_used += result.gas_used(); + cumulative_gas_used += result.gas_used() as u128; // Push transaction changeset and calculate header bloom filter for receipt. receipts.push( @@ -204,7 +204,7 @@ where // Success flag was added in `EIP-658: Embedding transaction status code in // receipts`. success: result.is_success(), - cumulative_gas_used, + cumulative_gas_used: cumulative_gas_used as u64, // convert to reth log logs: result.into_logs(), ..Default::default() @@ -230,7 +230,7 @@ where vec![] }; - Ok(EthExecuteOutput { receipts, requests, gas_used: cumulative_gas_used }) + Ok(EthExecuteOutput { receipts, requests, gas_used: cumulative_gas_used as u64 }) } } @@ -880,7 +880,7 @@ mod tests { timestamp: 1, number: 1, parent_beacon_block_root: Some(B256::with_last_byte(0x69)), - base_fee_per_gas: Some(u64::MAX), + base_fee_per_gas: Some(u64::MAX.into()), excess_blob_gas: Some(0), ..Header::default() }; @@ -1370,7 +1370,7 @@ mod tests { Transaction::Legacy(TxLegacy { chain_id: Some(chain_spec.chain.id()), nonce: 1, - gas_price: header.base_fee_per_gas.unwrap().into(), + gas_price: header.base_fee_per_gas.unwrap(), gas_limit: 134_807, to: TxKind::Call(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS), // `MIN_WITHDRAWAL_REQUEST_FEE` @@ -1460,7 +1460,7 @@ mod tests { Transaction::Legacy(TxLegacy { chain_id: Some(chain_spec.chain.id()), nonce: 1, - gas_price: header.base_fee_per_gas.unwrap().into(), + gas_price: header.base_fee_per_gas.unwrap(), gas_limit: 2_500_000, // higher than block gas limit to: TxKind::Call(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS), value: U256::from(1), diff --git a/crates/ethereum/evm/src/lib.rs b/crates/ethereum/evm/src/lib.rs index df6ac8bcc..2c9471b77 100644 --- a/crates/ethereum/evm/src/lib.rs +++ b/crates/ethereum/evm/src/lib.rs @@ -145,7 +145,7 @@ impl ConfigureEvmEnv for EthEvmConfig { None } }) - .map(BlobExcessGasAndPrice::new); + .map(|excess_blob_gas| BlobExcessGasAndPrice::new(excess_blob_gas as u64)); let mut basefee = parent.next_block_base_fee( self.chain_spec.base_fee_params_at_timestamp(attributes.timestamp), @@ -165,7 +165,7 @@ impl ConfigureEvmEnv for EthEvmConfig { gas_limit *= U256::from(elasticity_multiplier); // set the base fee to the initial base fee from the EIP-1559 spec - basefee = Some(EIP1559_INITIAL_BASE_FEE) + basefee = Some(EIP1559_INITIAL_BASE_FEE.into()) } let block_env = BlockEnv { diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 0a013495b..0678d73c9 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -389,7 +389,10 @@ where excess_blob_gas = if chain_spec.is_cancun_active_at_timestamp(parent_block.timestamp) { let parent_excess_blob_gas = parent_block.excess_blob_gas.unwrap_or_default(); let parent_blob_gas_used = parent_block.blob_gas_used.unwrap_or_default(); - Some(calculate_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used)) + Some(calculate_excess_blob_gas( + parent_excess_blob_gas as u64, + parent_blob_gas_used as u64, + )) } else { // for the first post-fork block, both parent.blob_gas_used and // parent.excess_blob_gas are evaluated as 0 @@ -410,16 +413,16 @@ where logs_bloom, timestamp: attributes.timestamp, mix_hash: attributes.prev_randao, - nonce: BEACON_NONCE, - base_fee_per_gas: Some(base_fee), + nonce: BEACON_NONCE.into(), + base_fee_per_gas: Some(base_fee.into()), number: parent_block.number + 1, - gas_limit: block_gas_limit, + gas_limit: block_gas_limit.into(), difficulty: U256::ZERO, - gas_used: cumulative_gas_used, + gas_used: cumulative_gas_used.into(), extra_data, parent_beacon_block_root: attributes.parent_beacon_block_root, - blob_gas_used, - excess_blob_gas, + blob_gas_used: blob_gas_used.map(Into::into), + excess_blob_gas: excess_blob_gas.map(Into::into), requests_root, }; diff --git a/crates/evm/src/metrics.rs b/crates/evm/src/metrics.rs index d6ffe0d79..888748286 100644 --- a/crates/evm/src/metrics.rs +++ b/crates/evm/src/metrics.rs @@ -30,7 +30,7 @@ impl ExecutorMetrics { where F: FnOnce(BlockExecutionInput<'_, BlockWithSenders>) -> R, { - let gas_used = input.block.gas_used; + let gas_used = input.block.gas_used as u64; // Execute the block and record the elapsed time. let execute_start = Instant::now(); diff --git a/crates/exex/exex/src/backfill/job.rs b/crates/exex/exex/src/backfill/job.rs index 9a88a1a22..948f8f606 100644 --- a/crates/exex/exex/src/backfill/job.rs +++ b/crates/exex/exex/src/backfill/job.rs @@ -125,7 +125,7 @@ where if self.thresholds.is_end_of_batch( block_number - *self.range.start(), bundle_size_hint, - cumulative_gas, + cumulative_gas as u64, batch_start.elapsed(), ) { break @@ -138,7 +138,7 @@ where range = ?*self.range.start()..=last_block_number, block_fetch = ?fetch_block_duration, execution = ?execution_duration, - throughput = format_gas_throughput(cumulative_gas, execution_duration), + throughput = format_gas_throughput(cumulative_gas as u64, execution_duration), "Finished executing block range" ); self.range = last_block_number + 1..=*self.range.end(); diff --git a/crates/exex/exex/src/backfill/test_utils.rs b/crates/exex/exex/src/backfill/test_utils.rs index 975de1dfe..780a714b5 100644 --- a/crates/exex/exex/src/backfill/test_utils.rs +++ b/crates/exex/exex/src/backfill/test_utils.rs @@ -99,8 +99,8 @@ fn blocks( ), difficulty: chain_spec.fork(EthereumHardfork::Paris).ttd().expect("Paris TTD"), number: 1, - gas_limit: MIN_TRANSACTION_GAS, - gas_used: MIN_TRANSACTION_GAS, + gas_limit: MIN_TRANSACTION_GAS.into(), + gas_used: MIN_TRANSACTION_GAS.into(), ..Default::default() }, body: vec![sign_tx_with_key_pair( @@ -129,8 +129,8 @@ fn blocks( ), difficulty: chain_spec.fork(EthereumHardfork::Paris).ttd().expect("Paris TTD"), number: 2, - gas_limit: MIN_TRANSACTION_GAS, - gas_used: MIN_TRANSACTION_GAS, + gas_limit: MIN_TRANSACTION_GAS.into(), + gas_used: MIN_TRANSACTION_GAS.into(), ..Default::default() }, body: vec![sign_tx_with_key_pair( diff --git a/crates/net/downloaders/src/file_client.rs b/crates/net/downloaders/src/file_client.rs index 10e96aee3..d618de5d5 100644 --- a/crates/net/downloaders/src/file_client.rs +++ b/crates/net/downloaders/src/file_client.rs @@ -12,7 +12,7 @@ use reth_network_p2p::{ priority::Priority, }; use reth_network_peers::PeerId; -use reth_primitives::{BlockBody, Header, SealedHeader}; +use reth_primitives::{alloy_primitives::Sealable, BlockBody, Header, SealedHeader}; use thiserror::Error; use tokio::{fs::File, io::AsyncReadExt}; use tokio_stream::StreamExt; @@ -115,7 +115,11 @@ impl FileClient { /// Clones and returns the highest header of this client has or `None` if empty. Seals header /// before returning. pub fn tip_header(&self) -> Option { - self.headers.get(&self.max_block()?).map(|h| h.clone().seal_slow()) + self.headers.get(&self.max_block()?).map(|h| { + let sealed = h.clone().seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) + }) } /// Returns true if all blocks are canonical (no gaps) diff --git a/crates/net/downloaders/src/headers/reverse_headers.rs b/crates/net/downloaders/src/headers/reverse_headers.rs index 0a05021e8..f0bbe8295 100644 --- a/crates/net/downloaders/src/headers/reverse_headers.rs +++ b/crates/net/downloaders/src/headers/reverse_headers.rs @@ -19,7 +19,7 @@ use reth_network_p2p::{ priority::Priority, }; use reth_network_peers::PeerId; -use reth_primitives::{GotExpected, Header, SealedHeader}; +use reth_primitives::{alloy_primitives::Sealable, GotExpected, Header, SealedHeader}; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; use std::{ cmp::{Ordering, Reverse}, @@ -249,7 +249,15 @@ where ) -> Result<(), ReverseHeadersDownloaderError> { let mut validated = Vec::with_capacity(headers.len()); - let sealed_headers = headers.into_par_iter().map(|h| h.seal_slow()).collect::>(); + let sealed_headers = headers + .into_par_iter() + .map(|h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + + SealedHeader::new(header, seal) + }) + .collect::>(); for parent in sealed_headers { // Validate that the header is the parent header of the last validated header. if let Some(validated_header) = @@ -375,7 +383,9 @@ where .into()) } - let target = headers.remove(0).seal_slow(); + let sealed_target = headers.remove(0).seal_slow(); + let (header, seal) = sealed_target.into_parts(); + let target = SealedHeader::new(header, seal); match sync_target { SyncTargetBlock::Hash(hash) | SyncTargetBlock::HashAndNumber { hash, .. } => { @@ -1286,7 +1296,7 @@ mod tests { assert!(downloader.sync_target_request.is_some()); downloader.sync_target_request.take(); - let target = SyncTarget::Gap(Header::default().seal(B256::random())); + let target = SyncTarget::Gap(SealedHeader::new(Header::default(), B256::random())); downloader.update_sync_target(target); assert!(downloader.sync_target_request.is_none()); assert_matches!( @@ -1310,7 +1320,7 @@ mod tests { downloader.queued_validated_headers.push(header.clone()); let mut next = header.as_ref().clone(); next.number += 1; - downloader.update_local_head(next.seal(B256::random())); + downloader.update_local_head(SealedHeader::new(next, B256::random())); assert!(downloader.queued_validated_headers.is_empty()); } diff --git a/crates/net/downloaders/src/headers/test_utils.rs b/crates/net/downloaders/src/headers/test_utils.rs index 536b267f2..321b0a335 100644 --- a/crates/net/downloaders/src/headers/test_utils.rs +++ b/crates/net/downloaders/src/headers/test_utils.rs @@ -2,12 +2,14 @@ #![allow(dead_code)] -use reth_primitives::SealedHeader; +use reth_primitives::{alloy_primitives::Sealable, SealedHeader}; /// Returns a new [`SealedHeader`] that's the child header of the given `parent`. pub(crate) fn child_header(parent: &SealedHeader) -> SealedHeader { let mut child = parent.as_ref().clone(); child.number += 1; child.parent_hash = parent.hash_slow(); - child.seal_slow() + let sealed = child.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) } diff --git a/crates/net/eth-wire-types/src/blocks.rs b/crates/net/eth-wire-types/src/blocks.rs index c2ee8ef59..8dc84aa3a 100644 --- a/crates/net/eth-wire-types/src/blocks.rs +++ b/crates/net/eth-wire-types/src/blocks.rs @@ -267,12 +267,12 @@ mod tests { logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into(), difficulty: U256::from(0x8aeu64), number: 0xd05u64, - gas_limit: 0x115cu64, - gas_used: 0x15b3u64, + gas_limit: 0x115cu128, + gas_used: 0x15b3u128, timestamp: 0x1a0au64, extra_data: hex!("7788")[..].into(), mix_hash: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: 0x0000000000000000u64, + nonce: 0x0000000000000000u64.into(), base_fee_per_gas: None, withdrawals_root: None, blob_gas_used: None, @@ -302,12 +302,12 @@ mod tests { logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into(), difficulty: U256::from(0x8aeu64), number: 0xd05u64, - gas_limit: 0x115cu64, - gas_used: 0x15b3u64, + gas_limit: 0x115cu128, + gas_used: 0x15b3u128, timestamp: 0x1a0au64, extra_data: hex!("7788")[..].into(), mix_hash: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: 0x0000000000000000u64, + nonce: 0x0000000000000000u64.into(), base_fee_per_gas: None, withdrawals_root: None, blob_gas_used: None, @@ -403,12 +403,12 @@ mod tests { logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into(), difficulty: U256::from(0x8aeu64), number: 0xd05u64, - gas_limit: 0x115cu64, - gas_used: 0x15b3u64, + gas_limit: 0x115cu128, + gas_used: 0x15b3u128, timestamp: 0x1a0au64, extra_data: hex!("7788")[..].into(), mix_hash: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: 0x0000000000000000u64, + nonce: 0x0000000000000000u64.into(), base_fee_per_gas: None, withdrawals_root: None, blob_gas_used: None, @@ -479,12 +479,12 @@ mod tests { logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into(), difficulty: U256::from(0x8aeu64), number: 0xd05u64, - gas_limit: 0x115cu64, - gas_used: 0x15b3u64, + gas_limit: 0x115cu128, + gas_used: 0x15b3u128, timestamp: 0x1a0au64, extra_data: hex!("7788")[..].into(), mix_hash: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: 0x0000000000000000u64, + nonce: 0x0000000000000000u64.into(), base_fee_per_gas: None, withdrawals_root: None, blob_gas_used: None, diff --git a/crates/net/eth-wire-types/src/header.rs b/crates/net/eth-wire-types/src/header.rs index 2e2dbcfb1..f809d408d 100644 --- a/crates/net/eth-wire-types/src/header.rs +++ b/crates/net/eth-wire-types/src/header.rs @@ -99,8 +99,8 @@ mod tests { let header = Header { difficulty: U256::from(0x8ae_u64), number: 0xd05_u64, - gas_limit: 0x115c_u64, - gas_used: 0x15b3_u64, + gas_limit: 0x115c_u128, + gas_used: 0x15b3_u128, timestamp: 0x1a0a_u64, extra_data: Bytes::from_str("7788").unwrap(), ommers_hash: B256::ZERO, @@ -131,13 +131,13 @@ mod tests { logs_bloom: bloom!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), difficulty: U256::from(0x020000), number: 0x01_u64, - gas_limit: 0x016345785d8a0000_u64, - gas_used: 0x015534_u64, + gas_limit: 0x016345785d8a0000_u128, + gas_used: 0x015534_u128, timestamp: 0x079e, extra_data: bytes!("42"), mix_hash: b256!("0000000000000000000000000000000000000000000000000000000000000000"), - nonce: 0, - base_fee_per_gas: Some(0x036b_u64), + nonce: 0u64.into() , + base_fee_per_gas: Some(0x036b_u128), withdrawals_root: None, blob_gas_used: None, excess_blob_gas: None, @@ -154,8 +154,8 @@ mod tests { let expected = Header { difficulty: U256::from(0x8aeu64), number: 0xd05u64, - gas_limit: 0x115cu64, - gas_used: 0x15b3u64, + gas_limit: 0x115cu128, + gas_used: 0x15b3u128, timestamp: 0x1a0au64, extra_data: Bytes::from_str("7788").unwrap(), ommers_hash: B256::ZERO, @@ -258,7 +258,7 @@ mod tests { "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", ) .unwrap(), - nonce: 0, + nonce: 0u64.into(), base_fee_per_gas: Some(9), withdrawals_root: Some( B256::from_str("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") @@ -305,7 +305,7 @@ mod tests { timestamp: 0x64c40d54, extra_data: bytes!("d883010c01846765746888676f312e32302e35856c696e7578"), mix_hash: b256!("70ccadc40b16e2094954b1064749cc6fbac783c1712f1b271a8aac3eda2f2325"), - nonce: 0, + nonce: 0u64.into(), base_fee_per_gas: Some(7), withdrawals_root: Some(b256!( "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" @@ -344,12 +344,4 @@ mod tests { direction.encode(&mut buf); assert_eq!(direction, HeadersDirection::decode(&mut buf.as_slice()).unwrap()); } - - #[test] - fn test_decode_block_header_with_invalid_blob_gas_used() { - // This should error because the blob_gas_used is too large - let data = hex!("f90242a013a7ec98912f917b3e804654e37c9866092043c13eb8eab94eb64818e886cff5a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f97e180c050e5ab072211ad2c213eb5aee4df134a0ec229dbe85b0d3643ad0f471e6ec1a36bbc87deffbbd970762d22a53b35d068aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080830305988401c9c380808464c40d5499d883010c01846765746888676f312e32302e35856c696e7578a070ccadc40b16e2094954b1064749cc6fbac783c1712f1b271a8aac3eda2f232588000000000000000007a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421891122334455667788998401600000"); - Header::decode(&mut data.as_slice()) - .expect_err("blob_gas_used size should make this header decoding fail"); - } } diff --git a/crates/net/p2p/src/full_block.rs b/crates/net/p2p/src/full_block.rs index 07aa34a8d..609df9b6c 100644 --- a/crates/net/p2p/src/full_block.rs +++ b/crates/net/p2p/src/full_block.rs @@ -9,7 +9,9 @@ use alloy_primitives::B256; use reth_consensus::{Consensus, ConsensusError}; use reth_eth_wire_types::HeadersDirection; use reth_network_peers::WithPeerId; -use reth_primitives::{BlockBody, GotExpected, Header, SealedBlock, SealedHeader}; +use reth_primitives::{ + alloy_primitives::Sealable, BlockBody, GotExpected, Header, SealedBlock, SealedHeader, +}; use std::{ cmp::Reverse, collections::{HashMap, VecDeque}, @@ -182,8 +184,15 @@ where ResponseResult::Header(res) => { match res { Ok(maybe_header) => { - let (peer, maybe_header) = - maybe_header.map(|h| h.map(|h| h.seal_slow())).split(); + let (peer, maybe_header) = maybe_header + .map(|h| { + h.map(|h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) + }) + }) + .split(); if let Some(header) = maybe_header { if header.hash() == this.hash { this.header = Some(header); @@ -483,8 +492,17 @@ where } fn on_headers_response(&mut self, headers: WithPeerId>) { - let (peer, mut headers_falling) = - headers.map(|h| h.into_iter().map(|h| h.seal_slow()).collect::>()).split(); + let (peer, mut headers_falling) = headers + .map(|h| { + h.into_iter() + .map(|h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) + }) + .collect::>() + }) + .split(); // fill in the response if it's the correct length if headers_falling.len() == self.count as usize { @@ -719,7 +737,10 @@ mod tests { header.parent_hash = hash; header.number += 1; - sealed_header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + sealed_header = SealedHeader::new(header, seal); + client.insert(sealed_header.clone(), body.clone()); } diff --git a/crates/net/p2p/src/test_utils/full_block.rs b/crates/net/p2p/src/test_utils/full_block.rs index 3a12d4424..1372ccc2c 100644 --- a/crates/net/p2p/src/test_utils/full_block.rs +++ b/crates/net/p2p/src/test_utils/full_block.rs @@ -130,10 +130,9 @@ impl TestFullBlockClient { pub fn highest_block(&self) -> Option { self.headers.lock().iter().max_by_key(|(_, header)| header.number).and_then( |(hash, header)| { - self.bodies - .lock() - .get(hash) - .map(|body| SealedBlock::new(header.clone().seal(*hash), body.clone())) + self.bodies.lock().get(hash).map(|body| { + SealedBlock::new(SealedHeader::new(header.clone(), *hash), body.clone()) + }) }, ) } diff --git a/crates/net/p2p/src/test_utils/headers.rs b/crates/net/p2p/src/test_utils/headers.rs index e61ec2213..14a2e3fca 100644 --- a/crates/net/p2p/src/test_utils/headers.rs +++ b/crates/net/p2p/src/test_utils/headers.rs @@ -14,7 +14,7 @@ use futures::{Future, FutureExt, Stream, StreamExt}; use reth_consensus::{test_utils::TestConsensus, Consensus}; use reth_eth_wire_types::HeadersDirection; use reth_network_peers::{PeerId, WithPeerId}; -use reth_primitives::{Header, SealedHeader}; +use reth_primitives::{alloy_primitives::Sealable, Header, SealedHeader}; use std::{ fmt, pin::Pin, @@ -155,8 +155,16 @@ impl Stream for TestDownload { match ready!(this.get_or_init_fut().poll_unpin(cx)) { Ok(resp) => { // Skip head and seal headers - let mut headers = - resp.1.into_iter().skip(1).map(Header::seal_slow).collect::>(); + let mut headers = resp + .1 + .into_iter() + .skip(1) + .map(|header| { + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) + }) + .collect::>(); headers.sort_unstable_by_key(|h| h.number); headers.into_iter().for_each(|h| this.buffer.push(h)); this.done = true; diff --git a/crates/node/core/src/utils.rs b/crates/node/core/src/utils.rs index 75672cd34..e6b970b90 100644 --- a/crates/node/core/src/utils.rs +++ b/crates/node/core/src/utils.rs @@ -1,6 +1,7 @@ //! Utility functions for node startup and shutdown, for example path parsing and retrieving single //! blocks from the network. +use alloy_primitives::Sealable; use eyre::Result; use reth_chainspec::ChainSpec; use reth_consensus_common::validation::validate_block_pre_execution; @@ -53,7 +54,9 @@ where eyre::bail!("Invalid number of headers received. Expected: 1. Received: {}", response.len()) } - let header = response.into_iter().next().unwrap().seal_slow(); + let sealed_header = response.into_iter().next().unwrap().seal_slow(); + let (header, seal) = sealed_header.into_parts(); + let header = SealedHeader::new(header, seal); let valid = match id { BlockHashOrNumber::Hash(hash) => header.hash() == hash, diff --git a/crates/node/events/src/node.rs b/crates/node/events/src/node.rs index 9c554478a..d72c64f29 100644 --- a/crates/node/events/src/node.rs +++ b/crates/node/events/src/node.rs @@ -260,12 +260,12 @@ impl NodeState { hash=?block.hash(), peers=self.num_connected_peers(), txs=block.body.len(), - gas=%format_gas(block.header.gas_used), - gas_throughput=%format_gas_throughput(block.header.gas_used, elapsed), + gas=%format_gas(block.header.gas_used as u64), + gas_throughput=%format_gas_throughput(block.header.gas_used as u64, elapsed), full=%format!("{:.1}%", block.header.gas_used as f64 * 100.0 / block.header.gas_limit as f64), base_fee=%format!("{:.2}gwei", block.header.base_fee_per_gas.unwrap_or(0) as f64 / constants::GWEI_TO_WEI as f64), - blobs=block.header.blob_gas_used.unwrap_or(0) / constants::eip4844::DATA_GAS_PER_BLOB, - excess_blobs=block.header.excess_blob_gas.unwrap_or(0) / constants::eip4844::DATA_GAS_PER_BLOB, + blobs=block.header.blob_gas_used.unwrap_or(0) as u64 / constants::eip4844::DATA_GAS_PER_BLOB, + excess_blobs=block.header.excess_blob_gas.unwrap_or(0) as u64 / constants::eip4844::DATA_GAS_PER_BLOB, ?elapsed, "Block added to canonical chain" ); diff --git a/crates/optimism/consensus/src/lib.rs b/crates/optimism/consensus/src/lib.rs index 413f34b01..bcad8facd 100644 --- a/crates/optimism/consensus/src/lib.rs +++ b/crates/optimism/consensus/src/lib.rs @@ -9,7 +9,7 @@ // The `optimism` feature must be enabled to use this crate. #![cfg(feature = "optimism")] -use alloy_primitives::U256; +use alloy_primitives::{B64, U256}; use reth_chainspec::{ChainSpec, EthereumHardforks}; use reth_consensus::{Consensus, ConsensusError, PostExecutionInput}; use reth_consensus_common::validation::{ @@ -85,7 +85,7 @@ impl Consensus for OptimismBeaconConsensus { let is_post_merge = self.chain_spec.is_bedrock_active_at_block(header.number); if is_post_merge { - if header.nonce != 0 { + if header.nonce != B64::ZERO { return Err(ConsensusError::TheMergeNonceIsNotZero) } diff --git a/crates/optimism/consensus/src/validation.rs b/crates/optimism/consensus/src/validation.rs index 3a76ec138..cbd5752e2 100644 --- a/crates/optimism/consensus/src/validation.rs +++ b/crates/optimism/consensus/src/validation.rs @@ -33,9 +33,9 @@ pub fn validate_block_post_execution( // Check if gas used matches the value set in header. let cumulative_gas_used = receipts.last().map(|receipt| receipt.cumulative_gas_used).unwrap_or(0); - if block.gas_used != cumulative_gas_used { + if block.gas_used != cumulative_gas_used.into() { return Err(ConsensusError::BlockGasUsed { - gas: GotExpected { got: cumulative_gas_used, expected: block.gas_used }, + gas: GotExpected { got: cumulative_gas_used, expected: block.gas_used as u64 }, gas_spent_by_tx: gas_spent_by_transactions(receipts), }) } diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index 08ec7e734..f21c3c89b 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -154,12 +154,12 @@ where // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block’s gasLimit. let block_available_gas = block.header.gas_limit - cumulative_gas_used; - if transaction.gas_limit() > block_available_gas && + if transaction.gas_limit() > block_available_gas as u64 && (is_regolith || !transaction.is_system_transaction()) { return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { transaction_gas_limit: transaction.gas_limit(), - block_available_gas, + block_available_gas: block_available_gas as u64, } .into()) } @@ -204,7 +204,7 @@ where evm.db_mut().commit(state); // append gas used - cumulative_gas_used += result.gas_used(); + cumulative_gas_used += result.gas_used() as u128; // Push transaction changeset and calculate header bloom filter for receipt. receipts.push(Receipt { @@ -212,7 +212,7 @@ where // Success flag was added in `EIP-658: Embedding transaction status code in // receipts`. success: result.is_success(), - cumulative_gas_used, + cumulative_gas_used: cumulative_gas_used as u64, logs: result.into_logs(), deposit_nonce: depositor.map(|account| account.nonce), // The deposit receipt version was introduced in Canyon to indicate an update to how @@ -226,7 +226,7 @@ where } drop(evm); - Ok((receipts, cumulative_gas_used)) + Ok((receipts, cumulative_gas_used as u64)) } } diff --git a/crates/optimism/evm/src/lib.rs b/crates/optimism/evm/src/lib.rs index 14cb4dc3a..ce95a7653 100644 --- a/crates/optimism/evm/src/lib.rs +++ b/crates/optimism/evm/src/lib.rs @@ -150,7 +150,7 @@ impl ConfigureEvmEnv for OptimismEvmConfig { None } }) - .map(BlobExcessGasAndPrice::new); + .map(|excess_blob_gas| BlobExcessGasAndPrice::new(excess_blob_gas as u64)); let block_env = BlockEnv { number: U256::from(parent.number + 1), diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 00a8d527b..2565329eb 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -476,7 +476,10 @@ where excess_blob_gas = if chain_spec.is_cancun_active_at_timestamp(parent_block.timestamp) { let parent_excess_blob_gas = parent_block.excess_blob_gas.unwrap_or_default(); let parent_blob_gas_used = parent_block.blob_gas_used.unwrap_or_default(); - Some(calculate_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used)) + Some(calculate_excess_blob_gas( + parent_excess_blob_gas as u64, + parent_blob_gas_used as u64, + )) } else { // for the first post-fork block, both parent.blob_gas_used and // parent.excess_blob_gas are evaluated as 0 @@ -497,16 +500,16 @@ where logs_bloom, timestamp: attributes.payload_attributes.timestamp, mix_hash: attributes.payload_attributes.prev_randao, - nonce: BEACON_NONCE, - base_fee_per_gas: Some(base_fee), + nonce: BEACON_NONCE.into(), + base_fee_per_gas: Some(base_fee.into()), number: parent_block.number + 1, - gas_limit: block_gas_limit, + gas_limit: block_gas_limit.into(), difficulty: U256::ZERO, - gas_used: cumulative_gas_used, + gas_used: cumulative_gas_used.into(), extra_data, parent_beacon_block_root: attributes.payload_attributes.parent_beacon_block_root, blob_gas_used, - excess_blob_gas, + excess_blob_gas: excess_blob_gas.map(Into::into), requests_root: None, }; diff --git a/crates/optimism/primitives/src/bedrock.rs b/crates/optimism/primitives/src/bedrock.rs index f63fc1917..774eb70f8 100644 --- a/crates/optimism/primitives/src/bedrock.rs +++ b/crates/optimism/primitives/src/bedrock.rs @@ -1,6 +1,6 @@ //! OP mainnet bedrock related data. -use alloy_primitives::{b256, bloom, bytes, B256, U256}; +use alloy_primitives::{b256, bloom, bytes, B256, B64, U256}; use reth_primitives::{address, Header}; use reth_primitives_traits::constants::EMPTY_OMMER_ROOT_HASH; @@ -66,7 +66,7 @@ pub const BEDROCK_HEADER: Header = Header { gas_limit: 30000000, gas_used: 0, logs_bloom: bloom!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - nonce: 0, + nonce: B64::ZERO, number: 105235063, parent_hash: b256!("21a168dfa5e727926063a28ba16fd5ee84c814e847c81a699c7a0ea551e4ca50"), receipts_root: b256!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), diff --git a/crates/optimism/rpc/src/eth/block.rs b/crates/optimism/rpc/src/eth/block.rs index eb8c192ba..ec210dbe1 100644 --- a/crates/optimism/rpc/src/eth/block.rs +++ b/crates/optimism/rpc/src/eth/block.rs @@ -57,8 +57,9 @@ where index: idx as u64, block_hash, block_number, - base_fee, - excess_blob_gas, + base_fee: base_fee.map(|base_fee| base_fee as u64), + excess_blob_gas: excess_blob_gas + .map(|excess_blob_gas| excess_blob_gas as u64), timestamp, }; diff --git a/crates/primitives-traits/Cargo.toml b/crates/primitives-traits/Cargo.toml index ede1af20c..ca57a2e57 100644 --- a/crates/primitives-traits/Cargo.toml +++ b/crates/primitives-traits/Cargo.toml @@ -19,7 +19,6 @@ alloy-eips.workspace = true alloy-genesis.workspace = true alloy-primitives.workspace = true alloy-rlp.workspace = true -alloy-rpc-types-eth = { workspace = true, optional = true } derive_more.workspace = true revm-primitives = { workspace = true, features = ["serde"] } @@ -60,4 +59,3 @@ arbitrary = [ "dep:proptest", "dep:proptest-arbitrary-interop", ] -alloy-compat = ["alloy-rpc-types-eth"] diff --git a/crates/primitives-traits/src/alloy_compat.rs b/crates/primitives-traits/src/alloy_compat.rs deleted file mode 100644 index 9a92dd520..000000000 --- a/crates/primitives-traits/src/alloy_compat.rs +++ /dev/null @@ -1,47 +0,0 @@ -use super::Header; -use alloy_rpc_types_eth::{ConversionError, Header as RpcHeader}; - -impl TryFrom for Header { - type Error = ConversionError; - - fn try_from(header: RpcHeader) -> Result { - Ok(Self { - base_fee_per_gas: header - .base_fee_per_gas - .map(|base_fee_per_gas| { - base_fee_per_gas.try_into().map_err(ConversionError::BaseFeePerGasConversion) - }) - .transpose()?, - beneficiary: header.miner, - blob_gas_used: header - .blob_gas_used - .map(|blob_gas_used| { - blob_gas_used.try_into().map_err(ConversionError::BlobGasUsedConversion) - }) - .transpose()?, - difficulty: header.difficulty, - excess_blob_gas: header - .excess_blob_gas - .map(|excess_blob_gas| { - excess_blob_gas.try_into().map_err(ConversionError::ExcessBlobGasConversion) - }) - .transpose()?, - extra_data: header.extra_data, - gas_limit: header.gas_limit.try_into().map_err(ConversionError::GasLimitConversion)?, - gas_used: header.gas_used.try_into().map_err(ConversionError::GasUsedConversion)?, - logs_bloom: header.logs_bloom, - mix_hash: header.mix_hash.unwrap_or_default(), - nonce: u64::from_be_bytes(header.nonce.unwrap_or_default().0), - number: header.number, - ommers_hash: header.uncles_hash, - parent_beacon_block_root: header.parent_beacon_block_root, - parent_hash: header.parent_hash, - receipts_root: header.receipts_root, - state_root: header.state_root, - timestamp: header.timestamp, - transactions_root: header.transactions_root, - withdrawals_root: header.withdrawals_root, - requests_root: header.requests_root, - }) - } -} diff --git a/crates/primitives-traits/src/header/mod.rs b/crates/primitives-traits/src/header/mod.rs index cb029b4b1..e4905c865 100644 --- a/crates/primitives-traits/src/header/mod.rs +++ b/crates/primitives-traits/src/header/mod.rs @@ -7,526 +7,9 @@ pub use error::HeaderError; #[cfg(any(test, feature = "test-utils", feature = "arbitrary"))] pub mod test_utils; -use alloy_consensus::constants::{EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH}; -use alloy_eips::{ - calc_next_block_base_fee, eip1559::BaseFeeParams, merge::ALLOWED_FUTURE_BLOCK_TIME_SECONDS, - BlockNumHash, -}; -use alloy_primitives::{keccak256, Address, BlockNumber, Bloom, Bytes, B256, B64, U256}; -use alloy_rlp::{length_of_length, Decodable, Encodable}; -use bytes::BufMut; -use core::mem; -use reth_codecs::{add_arbitrary_tests, Compact}; -use revm_primitives::{calc_blob_gasprice, calc_excess_blob_gas}; -use serde::{Deserialize, Serialize}; +pub use alloy_consensus::Header; -/// Block header -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Compact)] -#[add_arbitrary_tests(rlp, 25)] -pub struct Header { - /// The Keccak 256-bit hash of the parent - /// block’s header, in its entirety; formally Hp. - pub parent_hash: B256, - /// The Keccak 256-bit hash of the ommers list portion of this block; formally Ho. - pub ommers_hash: B256, - /// The 160-bit address to which all fees collected from the successful mining of this block - /// be transferred; formally Hc. - pub beneficiary: Address, - /// The Keccak 256-bit hash of the root node of the state trie, after all transactions are - /// executed and finalisations applied; formally Hr. - pub state_root: B256, - /// The Keccak 256-bit hash of the root node of the trie structure populated with each - /// transaction in the transactions list portion of the block; formally Ht. - pub transactions_root: B256, - /// The Keccak 256-bit hash of the root node of the trie structure populated with the receipts - /// of each transaction in the transactions list portion of the block; formally He. - pub receipts_root: B256, - /// The Keccak 256-bit hash of the withdrawals list portion of this block. - /// - /// See [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895). - pub withdrawals_root: Option, - /// The Bloom filter composed from indexable information (logger address and log topics) - /// contained in each log entry from the receipt of each transaction in the transactions list; - /// formally Hb. - pub logs_bloom: Bloom, - /// A scalar value corresponding to the difficulty level of this block. This can be calculated - /// from the previous block’s difficulty level and the timestamp; formally Hd. - pub difficulty: U256, - /// A scalar value equal to the number of ancestor blocks. The genesis block has a number of - /// zero; formally Hi. - pub number: BlockNumber, - /// A scalar value equal to the current limit of gas expenditure per block; formally Hl. - pub gas_limit: u64, - /// A scalar value equal to the total gas used in transactions in this block; formally Hg. - pub gas_used: u64, - /// A scalar value equal to the reasonable output of Unix’s time() at this block’s inception; - /// formally Hs. - pub timestamp: u64, - /// A 256-bit hash which, combined with the - /// nonce, proves that a sufficient amount of computation has been carried out on this block; - /// formally Hm. - pub mix_hash: B256, - /// A 64-bit value which, combined with the mixhash, proves that a sufficient amount of - /// computation has been carried out on this block; formally Hn. - pub nonce: u64, - /// A scalar representing EIP1559 base fee which can move up or down each block according - /// to a formula which is a function of gas used in parent block and gas target - /// (block gas limit divided by elasticity multiplier) of parent block. - /// The algorithm results in the base fee per gas increasing when blocks are - /// above the gas target, and decreasing when blocks are below the gas target. The base fee per - /// gas is burned. - pub base_fee_per_gas: Option, - /// The total amount of blob gas consumed by the transactions within the block, added in - /// EIP-4844. - pub blob_gas_used: Option, - /// A running total of blob gas consumed in excess of the target, prior to the block. Blocks - /// with above-target blob gas consumption increase this value, blocks with below-target blob - /// gas consumption decrease it (bounded at 0). This was added in EIP-4844. - pub excess_blob_gas: Option, - /// The hash of the parent beacon block's root is included in execution blocks, as proposed by - /// EIP-4788. - /// - /// This enables trust-minimized access to consensus state, supporting staking pools, bridges, - /// and more. - /// - /// The beacon roots contract handles root storage, enhancing Ethereum's functionalities. - pub parent_beacon_block_root: Option, - /// The Keccak 256-bit hash of the root node of the trie structure populated with each - /// [EIP-7685] request in the block body. - /// - /// [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685 - pub requests_root: Option, - /// An arbitrary byte array containing data relevant to this block. This must be 32 bytes or - /// fewer; formally Hx. - pub extra_data: Bytes, -} - -impl AsRef for Header { - fn as_ref(&self) -> &Self { - self - } -} - -impl Default for Header { - fn default() -> Self { - Self { - parent_hash: Default::default(), - ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: Default::default(), - state_root: EMPTY_ROOT_HASH, - transactions_root: EMPTY_ROOT_HASH, - receipts_root: EMPTY_ROOT_HASH, - logs_bloom: Default::default(), - difficulty: Default::default(), - number: 0, - gas_limit: 0, - gas_used: 0, - timestamp: 0, - extra_data: Default::default(), - mix_hash: Default::default(), - nonce: 0, - base_fee_per_gas: None, - withdrawals_root: None, - blob_gas_used: None, - excess_blob_gas: None, - parent_beacon_block_root: None, - requests_root: None, - } - } -} - -impl Header { - /// Checks if the block's difficulty is set to zero, indicating a Proof-of-Stake header. - /// - /// This function is linked to EIP-3675, proposing the consensus upgrade to Proof-of-Stake: - /// [EIP-3675](https://eips.ethereum.org/EIPS/eip-3675#replacing-difficulty-with-0) - /// - /// Verifies whether, as per the EIP, the block's difficulty is updated to zero, - /// signifying the transition to a Proof-of-Stake mechanism. - /// - /// Returns `true` if the block's difficulty matches the constant zero set by the EIP. - pub fn is_zero_difficulty(&self) -> bool { - self.difficulty.is_zero() - } - - /// Performs a sanity check on the extradata field of the header. - /// - /// # Errors - /// - /// Returns an error if the extradata size is larger than 100 KB. - pub fn ensure_extradata_valid(&self) -> Result<(), HeaderError> { - if self.extra_data.len() > 100 * 1024 { - return Err(HeaderError::LargeExtraData) - } - Ok(()) - } - - /// Performs a sanity check on the block difficulty field of the header. - /// - /// # Errors - /// - /// Returns an error if the block difficulty exceeds 80 bits. - pub fn ensure_difficulty_valid(&self) -> Result<(), HeaderError> { - if self.difficulty.bit_len() > 80 { - return Err(HeaderError::LargeDifficulty) - } - Ok(()) - } - - /// Performs combined sanity checks on multiple header fields. - /// - /// This method combines checks for block difficulty and extradata sizes. - /// - /// # Errors - /// - /// Returns an error if either the block difficulty exceeds 80 bits - /// or if the extradata size is larger than 100 KB. - pub fn ensure_well_formed(&self) -> Result<(), HeaderError> { - self.ensure_difficulty_valid()?; - self.ensure_extradata_valid()?; - Ok(()) - } - - /// Checks if the block's timestamp is in the past compared to the parent block's timestamp. - /// - /// Note: This check is relevant only pre-merge. - pub const fn is_timestamp_in_past(&self, parent_timestamp: u64) -> bool { - self.timestamp <= parent_timestamp - } - - /// Checks if the block's timestamp is in the future based on the present timestamp. - /// - /// Clock can drift but this can be consensus issue. - /// - /// Note: This check is relevant only pre-merge. - pub const fn exceeds_allowed_future_timestamp(&self, present_timestamp: u64) -> bool { - self.timestamp > present_timestamp + ALLOWED_FUTURE_BLOCK_TIME_SECONDS - } - - /// Returns the parent block's number and hash - pub const fn parent_num_hash(&self) -> BlockNumHash { - BlockNumHash { number: self.number.saturating_sub(1), hash: self.parent_hash } - } - - /// Heavy function that will calculate hash of data and will *not* save the change to metadata. - /// Use [`Header::seal`], [`SealedHeader`] and unlock if you need hash to be persistent. - pub fn hash_slow(&self) -> B256 { - keccak256(alloy_rlp::encode(self)) - } - - /// Checks if the header is empty - has no transactions and no ommers - pub fn is_empty(&self) -> bool { - self.transaction_root_is_empty() && - self.ommers_hash_is_empty() && - self.withdrawals_root.map_or(true, |root| root == EMPTY_ROOT_HASH) - } - - /// Check if the ommers hash equals to empty hash list. - pub fn ommers_hash_is_empty(&self) -> bool { - self.ommers_hash == EMPTY_OMMER_ROOT_HASH - } - - /// Check if the transaction root equals to empty root. - pub fn transaction_root_is_empty(&self) -> bool { - self.transactions_root == EMPTY_ROOT_HASH - } - - /// Returns the blob fee for _this_ block according to the EIP-4844 spec. - /// - /// Returns `None` if `excess_blob_gas` is None - pub fn blob_fee(&self) -> Option { - self.excess_blob_gas.map(calc_blob_gasprice) - } - - /// Returns the blob fee for the next block according to the EIP-4844 spec. - /// - /// Returns `None` if `excess_blob_gas` is None. - /// - /// See also [`Self::next_block_excess_blob_gas`] - pub fn next_block_blob_fee(&self) -> Option { - self.next_block_excess_blob_gas().map(calc_blob_gasprice) - } - - /// Calculate base fee for next block according to the EIP-1559 spec. - /// - /// Returns a `None` if no base fee is set, no EIP-1559 support - pub fn next_block_base_fee(&self, base_fee_params: BaseFeeParams) -> Option { - Some(calc_next_block_base_fee( - self.gas_used as u128, - self.gas_limit as u128, - self.base_fee_per_gas? as u128, - base_fee_params, - ) as u64) - } - - /// Calculate excess blob gas for the next block according to the EIP-4844 spec. - /// - /// Returns a `None` if no excess blob gas is set, no EIP-4844 support - pub fn next_block_excess_blob_gas(&self) -> Option { - Some(calc_excess_blob_gas(self.excess_blob_gas?, self.blob_gas_used?)) - } - - /// Seal the header with a known hash. - /// - /// WARNING: This method does not perform validation whether the hash is correct. - #[inline] - pub const fn seal(self, hash: B256) -> SealedHeader { - SealedHeader::new(self, hash) - } - - /// Calculate hash and seal the Header so that it can't be changed. - #[inline] - pub fn seal_slow(self) -> SealedHeader { - let hash = self.hash_slow(); - self.seal(hash) - } - - /// Calculate a heuristic for the in-memory size of the [Header]. - #[inline] - pub fn size(&self) -> usize { - mem::size_of::() + // parent hash - mem::size_of::() + // ommers hash - mem::size_of::
() + // beneficiary - mem::size_of::() + // state root - mem::size_of::() + // transactions root - mem::size_of::() + // receipts root - mem::size_of::>() + // withdrawals root - mem::size_of::() + // logs bloom - mem::size_of::() + // difficulty - mem::size_of::() + // number - mem::size_of::() + // gas limit - mem::size_of::() + // gas used - mem::size_of::() + // timestamp - mem::size_of::() + // mix hash - mem::size_of::() + // nonce - mem::size_of::>() + // base fee per gas - mem::size_of::>() + // blob gas used - mem::size_of::>() + // excess blob gas - mem::size_of::>() + // parent beacon block root - self.extra_data.len() // extra data - } - - fn header_payload_length(&self) -> usize { - let mut length = 0; - length += self.parent_hash.length(); // Hash of the previous block. - length += self.ommers_hash.length(); // Hash of uncle blocks. - length += self.beneficiary.length(); // Address that receives rewards. - length += self.state_root.length(); // Root hash of the state object. - length += self.transactions_root.length(); // Root hash of transactions in the block. - length += self.receipts_root.length(); // Hash of transaction receipts. - length += self.logs_bloom.length(); // Data structure containing event logs. - length += self.difficulty.length(); // Difficulty value of the block. - length += U256::from(self.number).length(); // Block number. - length += U256::from(self.gas_limit).length(); // Maximum gas allowed. - length += U256::from(self.gas_used).length(); // Actual gas used. - length += self.timestamp.length(); // Block timestamp. - length += self.extra_data.length(); // Additional arbitrary data. - length += self.mix_hash.length(); // Hash used for mining. - length += B64::new(self.nonce.to_be_bytes()).length(); // Nonce for mining. - - if let Some(base_fee) = self.base_fee_per_gas { - // Adding base fee length if it exists. - length += U256::from(base_fee).length(); - } - - if let Some(root) = self.withdrawals_root { - // Adding withdrawals_root length if it exists. - length += root.length(); - } - - if let Some(blob_gas_used) = self.blob_gas_used { - // Adding blob_gas_used length if it exists. - length += U256::from(blob_gas_used).length(); - } - - if let Some(excess_blob_gas) = self.excess_blob_gas { - // Adding excess_blob_gas length if it exists. - length += U256::from(excess_blob_gas).length(); - } - - if let Some(parent_beacon_block_root) = self.parent_beacon_block_root { - length += parent_beacon_block_root.length(); - } - - if let Some(requests_root) = self.requests_root { - length += requests_root.length(); - } - - length - } -} - -impl Encodable for Header { - fn encode(&self, out: &mut dyn BufMut) { - // Create a header indicating the encoded content is a list with the payload length computed - // from the header's payload calculation function. - let list_header = - alloy_rlp::Header { list: true, payload_length: self.header_payload_length() }; - list_header.encode(out); - - // Encode each header field sequentially - self.parent_hash.encode(out); // Encode parent hash. - self.ommers_hash.encode(out); // Encode ommer's hash. - self.beneficiary.encode(out); // Encode beneficiary. - self.state_root.encode(out); // Encode state root. - self.transactions_root.encode(out); // Encode transactions root. - self.receipts_root.encode(out); // Encode receipts root. - self.logs_bloom.encode(out); // Encode logs bloom. - self.difficulty.encode(out); // Encode difficulty. - U256::from(self.number).encode(out); // Encode block number. - U256::from(self.gas_limit).encode(out); // Encode gas limit. - U256::from(self.gas_used).encode(out); // Encode gas used. - self.timestamp.encode(out); // Encode timestamp. - self.extra_data.encode(out); // Encode extra data. - self.mix_hash.encode(out); // Encode mix hash. - B64::new(self.nonce.to_be_bytes()).encode(out); // Encode nonce. - - // Encode base fee. - if let Some(ref base_fee) = self.base_fee_per_gas { - U256::from(*base_fee).encode(out); - } - - // Encode withdrawals root. - if let Some(ref root) = self.withdrawals_root { - root.encode(out); - } - - // Encode blob gas used. - if let Some(ref blob_gas_used) = self.blob_gas_used { - U256::from(*blob_gas_used).encode(out); - } - - // Encode excess blob gas. - if let Some(ref excess_blob_gas) = self.excess_blob_gas { - U256::from(*excess_blob_gas).encode(out); - } - - // Encode parent beacon block root. - if let Some(ref parent_beacon_block_root) = self.parent_beacon_block_root { - parent_beacon_block_root.encode(out); - } - - // Encode EIP-7685 requests root - if let Some(ref requests_root) = self.requests_root { - requests_root.encode(out); - } - } - - fn length(&self) -> usize { - let mut length = 0; - length += self.header_payload_length(); - length += length_of_length(length); - length - } -} - -impl Decodable for Header { - fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { - let rlp_head = alloy_rlp::Header::decode(buf)?; - if !rlp_head.list { - return Err(alloy_rlp::Error::UnexpectedString) - } - let started_len = buf.len(); - let mut this = Self { - parent_hash: Decodable::decode(buf)?, - ommers_hash: Decodable::decode(buf)?, - beneficiary: Decodable::decode(buf)?, - state_root: Decodable::decode(buf)?, - transactions_root: Decodable::decode(buf)?, - receipts_root: Decodable::decode(buf)?, - logs_bloom: Decodable::decode(buf)?, - difficulty: Decodable::decode(buf)?, - number: u64::decode(buf)?, - gas_limit: u64::decode(buf)?, - gas_used: u64::decode(buf)?, - timestamp: Decodable::decode(buf)?, - extra_data: Decodable::decode(buf)?, - mix_hash: Decodable::decode(buf)?, - nonce: u64::from_be_bytes(B64::decode(buf)?.0), - base_fee_per_gas: None, - withdrawals_root: None, - blob_gas_used: None, - excess_blob_gas: None, - parent_beacon_block_root: None, - requests_root: None, - }; - if started_len - buf.len() < rlp_head.payload_length { - this.base_fee_per_gas = Some(u64::decode(buf)?); - } - - // Withdrawals root for post-shanghai headers - if started_len - buf.len() < rlp_head.payload_length { - this.withdrawals_root = Some(Decodable::decode(buf)?); - } - - // Blob gas used and excess blob gas for post-cancun headers - if started_len - buf.len() < rlp_head.payload_length { - this.blob_gas_used = Some(u64::decode(buf)?); - } - - if started_len - buf.len() < rlp_head.payload_length { - this.excess_blob_gas = Some(u64::decode(buf)?); - } - - // Decode parent beacon block root. - if started_len - buf.len() < rlp_head.payload_length { - this.parent_beacon_block_root = Some(B256::decode(buf)?); - } - - // Decode requests root. - if started_len - buf.len() < rlp_head.payload_length { - this.requests_root = Some(B256::decode(buf)?); - } - - let consumed = started_len - buf.len(); - if consumed != rlp_head.payload_length { - return Err(alloy_rlp::Error::ListLengthMismatch { - expected: rlp_head.payload_length, - got: consumed, - }) - } - Ok(this) - } -} - -#[cfg(any(test, feature = "test-utils", feature = "arbitrary"))] -impl<'a> arbitrary::Arbitrary<'a> for Header { - fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - // Generate an arbitrary header, passing it to the generate_valid_header function to make - // sure it is valid _with respect to hardforks only_. - let base = Self { - parent_hash: u.arbitrary()?, - ommers_hash: u.arbitrary()?, - beneficiary: u.arbitrary()?, - state_root: u.arbitrary()?, - transactions_root: u.arbitrary()?, - receipts_root: u.arbitrary()?, - logs_bloom: u.arbitrary()?, - difficulty: u.arbitrary()?, - number: u.arbitrary()?, - gas_limit: u.arbitrary()?, - gas_used: u.arbitrary()?, - timestamp: u.arbitrary()?, - extra_data: u.arbitrary()?, - mix_hash: u.arbitrary()?, - nonce: u.arbitrary()?, - base_fee_per_gas: u.arbitrary()?, - blob_gas_used: u.arbitrary()?, - excess_blob_gas: u.arbitrary()?, - parent_beacon_block_root: u.arbitrary()?, - requests_root: u.arbitrary()?, - withdrawals_root: u.arbitrary()?, - }; - - Ok(test_utils::generate_valid_header( - base, - u.arbitrary()?, - u.arbitrary()?, - u.arbitrary()?, - u.arbitrary()?, - )) - } -} +use alloy_primitives::{Address, BlockNumber, B256, U256}; /// Trait for extracting specific Ethereum block data from a header pub trait BlockHeader { @@ -569,7 +52,7 @@ impl BlockHeader for Header { } fn gas_limit(&self) -> u64 { - self.gas_limit + self.gas_limit as u64 } fn timestamp(&self) -> u64 { @@ -581,10 +64,10 @@ impl BlockHeader for Header { } fn base_fee_per_gas(&self) -> Option { - self.base_fee_per_gas + self.base_fee_per_gas.map(|base_fee| base_fee as u64) } fn excess_blob_gas(&self) -> Option { - self.excess_blob_gas + self.excess_blob_gas.map(|excess_blob_gas| excess_blob_gas as u64) } } diff --git a/crates/primitives-traits/src/header/sealed.rs b/crates/primitives-traits/src/header/sealed.rs index 069e60ac8..80a5414df 100644 --- a/crates/primitives-traits/src/header/sealed.rs +++ b/crates/primitives-traits/src/header/sealed.rs @@ -1,6 +1,6 @@ use super::Header; use alloy_eips::BlockNumHash; -use alloy_primitives::{keccak256, BlockHash}; +use alloy_primitives::{keccak256, BlockHash, Sealable}; #[cfg(any(test, feature = "test-utils"))] use alloy_primitives::{BlockNumber, B256, U256}; use alloy_rlp::{Decodable, Encodable}; @@ -66,7 +66,9 @@ impl SealedHeader { impl Default for SealedHeader { fn default() -> Self { - Header::default().seal_slow() + let sealed = Header::default().seal_slow(); + let (header, hash) = sealed.into_parts(); + Self { header, hash } } } @@ -131,6 +133,18 @@ impl SealedHeader { #[cfg(any(test, feature = "arbitrary"))] impl<'a> arbitrary::Arbitrary<'a> for SealedHeader { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - Ok(Header::arbitrary(u)?.seal_slow()) + let mut header = Header::arbitrary(u)?; + header.gas_limit = (header.gas_limit as u64).into(); + header.gas_used = (header.gas_used as u64).into(); + header.base_fee_per_gas = + header.base_fee_per_gas.map(|base_fee_per_gas| (base_fee_per_gas as u64).into()); + header.blob_gas_used = + header.blob_gas_used.map(|blob_gas_used| (blob_gas_used as u64).into()); + header.excess_blob_gas = + header.excess_blob_gas.map(|excess_blob_gas| (excess_blob_gas as u64).into()); + + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + Ok(Self::new(header, seal)) } } diff --git a/crates/primitives-traits/src/header/test_utils.rs b/crates/primitives-traits/src/header/test_utils.rs index ef5c0d025..a6f37e220 100644 --- a/crates/primitives-traits/src/header/test_utils.rs +++ b/crates/primitives-traits/src/header/test_utils.rs @@ -27,8 +27,8 @@ pub const fn generate_valid_header( // Set fields based on EIP-4844 being active if eip_4844_active { - header.blob_gas_used = Some(blob_gas_used); - header.excess_blob_gas = Some(excess_blob_gas); + header.blob_gas_used = Some(blob_gas_used as u128); + header.excess_blob_gas = Some(excess_blob_gas as u128); header.parent_beacon_block_root = Some(parent_beacon_block_root); } else { header.blob_gas_used = None; diff --git a/crates/primitives-traits/src/lib.rs b/crates/primitives-traits/src/lib.rs index 116f5ebf5..e5c57de74 100644 --- a/crates/primitives-traits/src/lib.rs +++ b/crates/primitives-traits/src/lib.rs @@ -12,9 +12,6 @@ #[macro_use] extern crate alloc; -#[cfg(feature = "alloy-compat")] -mod alloy_compat; - /// Common constants. pub mod constants; pub use constants::gas_units::{format_gas, format_gas_throughput}; diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 9b95d0060..0e7cb2c5d 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -119,7 +119,6 @@ optimism = [ "reth-optimism-forks", ] alloy-compat = [ - "reth-primitives-traits/alloy-compat", "dep:alloy-rpc-types", "dep:alloy-serde", "dep:op-alloy-rpc-types", diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index acf05fd11..c26019226 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -6,6 +6,7 @@ use alloc::vec::Vec; pub use alloy_eips::eip1898::{ BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag, ForkBlock, RpcBlockHash, }; +use alloy_primitives::Sealable; use alloy_rlp::{RlpDecodable, RlpEncodable}; use derive_more::{Deref, DerefMut}; #[cfg(any(test, feature = "arbitrary"))] @@ -50,8 +51,10 @@ pub struct Block { impl Block { /// Calculate the header hash and seal the block so that it can't be changed. pub fn seal_slow(self) -> SealedBlock { + let sealed = self.header.seal_slow(); + let (header, seal) = sealed.into_parts(); SealedBlock { - header: self.header.seal_slow(), + header: SealedHeader::new(header, seal), body: self.body, ommers: self.ommers, withdrawals: self.withdrawals, @@ -64,7 +67,7 @@ impl Block { /// WARNING: This method does not perform validation whether the hash is correct. pub fn seal(self, hash: B256) -> SealedBlock { SealedBlock { - header: self.header.seal(hash), + header: SealedHeader::new(self.header, hash), body: self.body, ommers: self.ommers, withdrawals: self.withdrawals, @@ -183,7 +186,22 @@ impl<'a> arbitrary::Arbitrary<'a> for Block { .collect::>>()?; // then generate up to 2 ommers - let ommers = (0..2).map(|_| Header::arbitrary(u)).collect::>>()?; + let ommers = (0..2) + .map(|_| { + let mut header = Header::arbitrary(u)?; + header.gas_limit = (header.gas_limit as u64).into(); + header.gas_used = (header.gas_used as u64).into(); + header.base_fee_per_gas = header + .base_fee_per_gas + .map(|base_fee_per_gas| (base_fee_per_gas as u64).into()); + header.blob_gas_used = + header.blob_gas_used.map(|blob_gas_used| (blob_gas_used as u64).into()); + header.excess_blob_gas = + header.excess_blob_gas.map(|excess_blob_gas| (excess_blob_gas as u64).into()); + + Ok(header) + }) + .collect::>>()?; Ok(Self { header: u.arbitrary()?, @@ -633,7 +651,22 @@ impl<'a> arbitrary::Arbitrary<'a> for BlockBody { .collect::>>()?; // then generate up to 2 ommers - let ommers = (0..2).map(|_| Header::arbitrary(u)).collect::>>()?; + let ommers = (0..2) + .map(|_| { + let mut header = Header::arbitrary(u)?; + header.gas_limit = (header.gas_limit as u64).into(); + header.gas_used = (header.gas_used as u64).into(); + header.base_fee_per_gas = header + .base_fee_per_gas + .map(|base_fee_per_gas| (base_fee_per_gas as u64).into()); + header.blob_gas_used = + header.blob_gas_used.map(|blob_gas_used| (blob_gas_used as u64).into()); + header.excess_blob_gas = + header.excess_blob_gas.map(|excess_blob_gas| (excess_blob_gas as u64).into()); + + Ok(header) + }) + .collect::>>()?; // for now just generate empty requests, see HACK above Ok(Self { transactions, ommers, requests: None, withdrawals: u.arbitrary()? }) diff --git a/crates/rpc/rpc-engine-api/tests/it/payload.rs b/crates/rpc/rpc-engine-api/tests/it/payload.rs index 0587de684..dd6f3ffd5 100644 --- a/crates/rpc/rpc-engine-api/tests/it/payload.rs +++ b/crates/rpc/rpc-engine-api/tests/it/payload.rs @@ -3,7 +3,10 @@ use alloy_primitives::{Bytes, U256}; use alloy_rlp::{Decodable, Error as RlpError}; use assert_matches::assert_matches; -use reth_primitives::{proofs, Block, SealedBlock, TransactionSigned, Withdrawals}; +use reth_primitives::{ + alloy_primitives::Sealable, proofs, Block, SealedBlock, SealedHeader, TransactionSigned, + Withdrawals, +}; use reth_rpc_types::engine::{ ExecutionPayload, ExecutionPayloadBodyV1, ExecutionPayloadV1, PayloadError, }; @@ -21,8 +24,10 @@ fn transform_block Block>(src: SealedBlock, f: F) -> Executi // Recalculate roots transformed.header.transactions_root = proofs::calculate_transaction_root(&transformed.body); transformed.header.ommers_hash = proofs::calculate_ommers_root(&transformed.ommers); + let sealed = transformed.header.seal_slow(); + let (header, seal) = sealed.into_parts(); block_to_payload(SealedBlock { - header: transformed.header.seal_slow(), + header: SealedHeader::new(header, seal), body: transformed.body, ommers: transformed.ommers, withdrawals: transformed.withdrawals, @@ -133,7 +138,7 @@ fn payload_validation() { // None zero nonce let block_with_nonce = transform_block(block.clone(), |mut b| { - b.header.nonce = 1; + b.header.nonce = 1u64.into(); b }); assert_matches!( diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index 5c651b10b..70fab6edd 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -130,7 +130,7 @@ pub trait EthCall: Call + LoadPendingBlock { base_block .header .next_block_base_fee(base_fee_params) - .unwrap_or_default() as u128 + .unwrap_or_default() }; block_env.basefee = U256::from(base_fee); } else { diff --git a/crates/rpc/rpc-eth-api/src/helpers/fee.rs b/crates/rpc/rpc-eth-api/src/helpers/fee.rs index 736e34191..e300ed802 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/fee.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/fee.rs @@ -160,8 +160,9 @@ pub trait EthFees: LoadFee { return Err(EthApiError::InvalidBlockRange.into()) } + for header in &headers { - base_fee_per_gas.push(header.base_fee_per_gas.unwrap_or_default() as u128); + base_fee_per_gas.push(header.base_fee_per_gas.unwrap_or_default()); gas_used_ratio.push(header.gas_used as f64 / header.gas_limit as f64); base_fee_per_blob_gas.push(header.blob_fee().unwrap_or_default()); blob_gas_used_ratio.push( @@ -179,8 +180,8 @@ pub trait EthFees: LoadFee { rewards.push( calculate_reward_percentiles_for_block( percentiles, - header.gas_used, - header.base_fee_per_gas.unwrap_or_default(), + header.gas_used as u64, + header.base_fee_per_gas.unwrap_or_default() as u64, &transactions, &receipts, ) @@ -200,9 +201,9 @@ pub trait EthFees: LoadFee { .chain_spec() .base_fee_params_at_timestamp(last_header.timestamp) .next_block_base_fee( - last_header.gas_used as u128, - last_header.gas_limit as u128, - last_header.base_fee_per_gas.unwrap_or_default() as u128, + last_header.gas_used , + last_header.gas_limit, + last_header.base_fee_per_gas.unwrap_or_default() , ), ); diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index 2bebb9afc..e116274b0 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -443,14 +443,14 @@ pub trait LoadPendingBlock: EthApiTypes { logs_bloom, timestamp: block_env.timestamp.to::(), mix_hash: block_env.prevrandao.unwrap_or_default(), - nonce: BEACON_NONCE, - base_fee_per_gas: Some(base_fee), + nonce: BEACON_NONCE.into(), + base_fee_per_gas: Some(base_fee.into()), number: block_number, - gas_limit: block_gas_limit, + gas_limit: block_gas_limit.into(), difficulty: U256::ZERO, - gas_used: cumulative_gas_used, - blob_gas_used, - excess_blob_gas: block_env.get_blob_excess_gas(), + gas_used: cumulative_gas_used.into(), + blob_gas_used: blob_gas_used.map(Into::into), + excess_blob_gas: block_env.get_blob_excess_gas().map(Into::into), extra_data: Default::default(), parent_beacon_block_root, requests_root, diff --git a/crates/rpc/rpc-eth-types/src/fee_history.rs b/crates/rpc/rpc-eth-types/src/fee_history.rs index b511af7a3..0aa5a245b 100644 --- a/crates/rpc/rpc-eth-types/src/fee_history.rs +++ b/crates/rpc/rpc-eth-types/src/fee_history.rs @@ -361,16 +361,16 @@ impl FeeHistoryEntry { /// Note: This does not calculate the rewards for the block. pub fn new(block: &SealedBlock) -> Self { Self { - base_fee_per_gas: block.base_fee_per_gas.unwrap_or_default(), + base_fee_per_gas: block.base_fee_per_gas.unwrap_or_default() as u64, gas_used_ratio: block.gas_used as f64 / block.gas_limit as f64, base_fee_per_blob_gas: block.blob_fee(), blob_gas_used_ratio: block.blob_gas_used() as f64 / reth_primitives::constants::eip4844::MAX_DATA_GAS_PER_BLOCK as f64, - excess_blob_gas: block.excess_blob_gas, - blob_gas_used: block.blob_gas_used, - gas_used: block.gas_used, + excess_blob_gas: block.excess_blob_gas.map(|excess_blob| excess_blob as u64), + blob_gas_used: block.blob_gas_used.map(|block_gas| block_gas as u64), + gas_used: block.gas_used as u64, header_hash: block.hash(), - gas_limit: block.gas_limit, + gas_limit: block.gas_limit as u64, rewards: Vec::new(), timestamp: block.timestamp, } diff --git a/crates/rpc/rpc-eth-types/src/gas_oracle.rs b/crates/rpc/rpc-eth-types/src/gas_oracle.rs index f853778ba..173668a07 100644 --- a/crates/rpc/rpc-eth-types/src/gas_oracle.rs +++ b/crates/rpc/rpc-eth-types/src/gas_oracle.rs @@ -221,7 +221,9 @@ where let parent_hash = block.parent_hash; // sort the functions by ascending effective tip first - block.body.sort_by_cached_key(|tx| tx.effective_tip_per_gas(base_fee_per_gas)); + block.body.sort_by_cached_key(|tx| { + tx.effective_tip_per_gas(base_fee_per_gas.map(|base_fee| base_fee as u64)) + }); let mut prices = Vec::with_capacity(limit); @@ -229,7 +231,8 @@ where let mut effective_gas_tip = None; // ignore transactions with a tip under the configured threshold if let Some(ignore_under) = self.ignore_price { - let tip = tx.effective_tip_per_gas(base_fee_per_gas); + let tip = + tx.effective_tip_per_gas(base_fee_per_gas.map(|base_fee| base_fee as u64)); effective_gas_tip = Some(tip); if tip < Some(ignore_under) { continue @@ -246,7 +249,9 @@ where // a `None` effective_gas_tip represents a transaction where the max_fee_per_gas is // less than the base fee which would be invalid let effective_gas_tip = effective_gas_tip - .unwrap_or_else(|| tx.effective_tip_per_gas(base_fee_per_gas)) + .unwrap_or_else(|| { + tx.effective_tip_per_gas(base_fee_per_gas.map(|base_fee| base_fee as u64)) + }) .ok_or(RpcInvalidTransactionError::FeeCapTooLow)?; prices.push(U256::from(effective_gas_tip)); diff --git a/crates/rpc/rpc-eth-types/src/simulate.rs b/crates/rpc/rpc-eth-types/src/simulate.rs index da7ee796f..29bfa76f2 100644 --- a/crates/rpc/rpc-eth-types/src/simulate.rs +++ b/crates/rpc/rpc-eth-types/src/simulate.rs @@ -280,7 +280,7 @@ pub fn build_block( timestamp: block_env.timestamp.to(), base_fee_per_gas: Some(block_env.basefee.to()), gas_limit: block_env.gas_limit.to(), - gas_used: calls.iter().map(|c| c.gas_used).sum::(), + gas_used: calls.iter().map(|c| c.gas_used).sum::() as u128, blob_gas_used: Some(0), parent_hash, receipts_root: calculate_receipt_root(&receipts), diff --git a/crates/rpc/rpc-types-compat/src/block.rs b/crates/rpc/rpc-types-compat/src/block.rs index 6e918cefb..d20aa3bfb 100644 --- a/crates/rpc/rpc-types-compat/src/block.rs +++ b/crates/rpc/rpc-types-compat/src/block.rs @@ -6,7 +6,7 @@ use alloy_rpc_types::{ Block, BlockError, BlockTransactions, BlockTransactionsKind, Header, TransactionInfo, }; use reth_primitives::{ - Block as PrimitiveBlock, BlockWithSenders, Header as PrimitiveHeader, Withdrawals, + Block as PrimitiveBlock, BlockWithSenders, Header as PrimitiveHeader, SealedHeader, Withdrawals, }; use crate::{transaction::from_recovered_with_block_context, TransactionCompat}; @@ -137,14 +137,14 @@ pub fn from_primitive_with_hash(primitive_header: reth_primitives::SealedHeader) receipts_root, withdrawals_root, number, - gas_used: gas_used as u128, - gas_limit: gas_limit as u128, + gas_used, + gas_limit, extra_data, logs_bloom, timestamp, difficulty, mix_hash: Some(mix_hash), - nonce: Some(nonce.to_be_bytes().into()), + nonce: Some(nonce), base_fee_per_gas: base_fee_per_gas.map(u128::from), blob_gas_used: blob_gas_used.map(u128::from), excess_blob_gas: excess_blob_gas.map(u128::from), @@ -163,7 +163,7 @@ fn from_block_with_transactions( transactions: BlockTransactions, ) -> Block { let uncles = block.ommers.into_iter().map(|h| h.hash_slow()).collect(); - let mut header = from_primitive_with_hash(block.header.seal(block_hash)); + let mut header = from_primitive_with_hash(SealedHeader::new(block.header, block_hash)); header.total_difficulty = Some(total_difficulty); let withdrawals = header @@ -179,7 +179,7 @@ fn from_block_with_transactions( /// an Uncle from its header. pub fn uncle_block_from_header(header: PrimitiveHeader) -> Block { let hash = header.hash_slow(); - let rpc_header = from_primitive_with_hash(header.clone().seal(hash)); + let rpc_header = from_primitive_with_hash(SealedHeader::new(header.clone(), hash)); let uncle_block = PrimitiveBlock { header, ..Default::default() }; let size = Some(U256::from(uncle_block.length())); Block { diff --git a/crates/rpc/rpc-types-compat/src/engine/payload.rs b/crates/rpc/rpc-types-compat/src/engine/payload.rs index b5820fd5b..8b52d8225 100644 --- a/crates/rpc/rpc-types-compat/src/engine/payload.rs +++ b/crates/rpc/rpc-types-compat/src/engine/payload.rs @@ -38,8 +38,8 @@ pub fn try_payload_v1_to_block(payload: ExecutionPayloadV1) -> Result Result ExecutionPayloadV1 { logs_bloom: value.logs_bloom, prev_randao: value.mix_hash, block_number: value.number, - gas_limit: value.gas_limit, - gas_used: value.gas_used, + gas_limit: value.gas_limit as u64, + gas_used: value.gas_used as u64, timestamp: value.timestamp, extra_data: value.extra_data.clone(), base_fee_per_gas: U256::from(value.base_fee_per_gas.unwrap_or_default()), @@ -171,8 +171,8 @@ pub fn block_to_payload_v2(value: SealedBlock) -> ExecutionPayloadV2 { logs_bloom: value.logs_bloom, prev_randao: value.mix_hash, block_number: value.number, - gas_limit: value.gas_limit, - gas_used: value.gas_used, + gas_limit: value.gas_limit as u64, + gas_used: value.gas_used as u64, timestamp: value.timestamp, extra_data: value.extra_data.clone(), base_fee_per_gas: U256::from(value.base_fee_per_gas.unwrap_or_default()), @@ -187,8 +187,8 @@ pub fn block_to_payload_v2(value: SealedBlock) -> ExecutionPayloadV2 { pub fn block_to_payload_v3(value: SealedBlock) -> ExecutionPayloadV3 { let transactions = value.raw_transactions(); ExecutionPayloadV3 { - blob_gas_used: value.blob_gas_used.unwrap_or_default(), - excess_blob_gas: value.excess_blob_gas.unwrap_or_default(), + blob_gas_used: value.blob_gas_used.unwrap_or_default() as u64, + excess_blob_gas: value.excess_blob_gas.unwrap_or_default() as u64, payload_inner: ExecutionPayloadV2 { payload_inner: ExecutionPayloadV1 { parent_hash: value.parent_hash, @@ -198,8 +198,8 @@ pub fn block_to_payload_v3(value: SealedBlock) -> ExecutionPayloadV3 { logs_bloom: value.logs_bloom, prev_randao: value.mix_hash, block_number: value.number, - gas_limit: value.gas_limit, - gas_used: value.gas_used, + gas_limit: value.gas_limit as u64, + gas_used: value.gas_used as u64, timestamp: value.timestamp, extra_data: value.extra_data.clone(), base_fee_per_gas: U256::from(value.base_fee_per_gas.unwrap_or_default()), @@ -431,8 +431,8 @@ pub fn execution_payload_from_sealed_block(value: SealedBlock) -> ExecutionPaylo logs_bloom: value.logs_bloom, prev_randao: value.mix_hash, block_number: value.number, - gas_limit: value.gas_limit, - gas_used: value.gas_used, + gas_limit: value.gas_limit as u64, + gas_used: value.gas_used as u64, timestamp: value.timestamp, extra_data: value.extra_data.clone(), base_fee_per_gas: U256::from(value.base_fee_per_gas.unwrap_or_default()), diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index c56011250..31ecc818e 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -455,9 +455,9 @@ mod tests { let header = Header { number: newest_block - i, - gas_limit, - gas_used, - base_fee_per_gas, + gas_limit: gas_limit.into(), + gas_used: gas_used.into(), + base_fee_per_gas: base_fee_per_gas.map(Into::into), parent_hash, ..Default::default() }; @@ -473,7 +473,7 @@ mod tests { transaction: reth_primitives::Transaction::Eip1559( reth_primitives::TxEip1559 { max_priority_fee_per_gas: random_fee, - max_fee_per_gas: random_fee + base_fee_per_gas as u128, + max_fee_per_gas: random_fee + base_fee_per_gas, ..Default::default() }, ), @@ -505,9 +505,9 @@ mod tests { // Add final base fee (for the next block outside of the request) let last_header = last_header.unwrap(); base_fees_per_gas.push(BaseFeeParams::ethereum().next_block_base_fee( - last_header.gas_used as u128, - last_header.gas_limit as u128, - last_header.base_fee_per_gas.unwrap_or_default() as u128, + last_header.gas_used, + last_header.gas_limit, + last_header.base_fee_per_gas.unwrap_or_default(), )); let eth_api = build_test_eth_api(mock_provider); diff --git a/crates/rpc/rpc/src/eth/helpers/block.rs b/crates/rpc/rpc/src/eth/helpers/block.rs index 4a53dde3a..cc6df1aa0 100644 --- a/crates/rpc/rpc/src/eth/helpers/block.rs +++ b/crates/rpc/rpc/src/eth/helpers/block.rs @@ -50,8 +50,9 @@ where index: idx as u64, block_hash, block_number, - base_fee, - excess_blob_gas, + base_fee: base_fee.map(|base_fee| base_fee as u64), + excess_blob_gas: excess_blob_gas + .map(|excess_blob_gas| excess_blob_gas as u64), timestamp, }; diff --git a/crates/stages/stages/benches/setup/mod.rs b/crates/stages/stages/benches/setup/mod.rs index 898dfdc8e..41570c057 100644 --- a/crates/stages/stages/benches/setup/mod.rs +++ b/crates/stages/stages/benches/setup/mod.rs @@ -6,7 +6,9 @@ use reth_db_api::{ cursor::DbCursorRO, transaction::{DbTx, DbTxMut}, }; -use reth_primitives::{Account, Address, SealedBlock, B256, U256}; +use reth_primitives::{ + alloy_primitives::Sealable, Account, Address, SealedBlock, SealedHeader, B256, U256, +}; use reth_provider::{DatabaseProvider, DatabaseProviderFactory, TrieWriter}; use reth_stages::{ stages::{AccountHashingStage, StorageHashingStage}, @@ -143,7 +145,9 @@ pub(crate) fn txs_testdata(num_blocks: u64) -> TestStageDB { let cloned_second = second_block.clone(); let mut updated_header = cloned_second.header.unseal(); updated_header.state_root = root; - *second_block = SealedBlock { header: updated_header.seal_slow(), ..cloned_second }; + let sealed = updated_header.seal_slow(); + let (header, seal) = sealed.into_parts(); + *second_block = SealedBlock { header: SealedHeader::new(header, seal), ..cloned_second }; let offset = transitions.len() as u64; @@ -176,7 +180,9 @@ pub(crate) fn txs_testdata(num_blocks: u64) -> TestStageDB { let cloned_last = last_block.clone(); let mut updated_header = cloned_last.header.unseal(); updated_header.state_root = root; - *last_block = SealedBlock { header: updated_header.seal_slow(), ..cloned_last }; + let sealed = updated_header.seal_slow(); + let (header, seal) = sealed.into_parts(); + *last_block = SealedBlock { header: SealedHeader::new(header, seal), ..cloned_last }; db.insert_blocks(blocks.iter(), StorageKind::Static).unwrap(); diff --git a/crates/stages/stages/src/stages/bodies.rs b/crates/stages/stages/src/stages/bodies.rs index 4152df807..1625237b9 100644 --- a/crates/stages/stages/src/stages/bodies.rs +++ b/crates/stages/stages/src/stages/bodies.rs @@ -922,7 +922,7 @@ mod tests { |cursor, number| cursor.get_two::>(number.into()), )? { let (header, hash) = header?; - self.headers.push_back(header.seal(hash)); + self.headers.push_back(SealedHeader::new(header, hash)); } Ok(()) diff --git a/crates/stages/stages/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index 8c42648ef..6f6e6d6f3 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -9,7 +9,9 @@ use reth_evm::{ }; use reth_execution_types::{Chain, ExecutionOutcome}; use reth_exex::{ExExManagerHandle, ExExNotification}; -use reth_primitives::{BlockNumber, Header, StaticFileSegment}; +use reth_primitives::{ + alloy_primitives::Sealable, BlockNumber, Header, SealedHeader, StaticFileSegment, +}; use reth_primitives_traits::format_gas_throughput; use reth_provider::{ providers::{StaticFileProvider, StaticFileProviderRWRefMut, StaticFileWriter}, @@ -275,8 +277,11 @@ where let execute_start = Instant::now(); self.metrics.metered((&block, td).into(), |input| { + let sealed = block.header.clone().seal_slow(); + let (header, seal) = sealed.into_parts(); + executor.execute_and_verify_one(input).map_err(|error| StageError::Block { - block: Box::new(block.header.clone().seal_slow()), + block: Box::new(SealedHeader::new(header, seal)), error: BlockErrorKind::Execution(error), }) })?; @@ -289,7 +294,7 @@ where target: "sync::stages::execution", start = last_block, end = block_number, - throughput = format_gas_throughput(cumulative_gas - last_cumulative_gas, execution_duration - last_execution_duration), + throughput = format_gas_throughput((cumulative_gas - last_cumulative_gas) as u64, execution_duration - last_execution_duration), "Executed block range" ); @@ -300,7 +305,7 @@ where } stage_progress = block_number; - stage_checkpoint.progress.processed += block.gas_used; + stage_checkpoint.progress.processed += block.gas_used as u64; // If we have ExExes we need to save the block in memory for later if self.exex_manager_handle.has_exexs() { @@ -312,7 +317,7 @@ where if self.thresholds.is_end_of_batch( block_number - start_block, bundle_size_hint, - cumulative_gas, + cumulative_gas as u64, batch_start.elapsed(), ) { break @@ -330,7 +335,7 @@ where target: "sync::stages::execution", start = start_block, end = stage_progress, - throughput = format_gas_throughput(cumulative_gas, execution_duration), + throughput = format_gas_throughput(cumulative_gas as u64, execution_duration), "Finished executing block range" ); @@ -455,7 +460,7 @@ where stage_checkpoint.progress.processed -= provider .block_by_number(block_number)? .ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))? - .gas_used; + .gas_used as u64; } } let checkpoint = if let Some(stage_checkpoint) = stage_checkpoint { @@ -568,7 +573,7 @@ fn calculate_gas_used_from_headers( let duration = start.elapsed(); debug!(target: "sync::stages::execution", ?range, ?duration, "Finished calculating gas used from headers"); - Ok(gas_total) + Ok(gas_total as u64) } /// Returns a `StaticFileProviderRWRefMut` static file producer after performing a consistency @@ -758,7 +763,7 @@ mod tests { total } }) if processed == previous_stage_checkpoint.progress.processed && - total == previous_stage_checkpoint.progress.total + block.gas_used); + total == previous_stage_checkpoint.progress.total + block.gas_used as u64); } #[test] @@ -799,7 +804,7 @@ mod tests { total } }) if processed == previous_stage_checkpoint.progress.processed && - total == previous_stage_checkpoint.progress.total + block.gas_used); + total == previous_stage_checkpoint.progress.total + block.gas_used as u64); } #[test] @@ -832,7 +837,7 @@ mod tests { processed: 0, total } - }) if total == block.gas_used); + }) if total == block.gas_used as u64); } #[tokio::test] @@ -923,7 +928,7 @@ mod tests { })) }, done: true - } if processed == total && total == block.gas_used); + } if processed == total && total == block.gas_used as u64); let provider = factory.provider().unwrap(); @@ -1075,7 +1080,7 @@ mod tests { } })) } - } if total == block.gas_used); + } if total == block.gas_used as u64); // assert unwind stage assert_eq!( diff --git a/crates/stages/stages/src/stages/headers.rs b/crates/stages/stages/src/stages/headers.rs index bcc490d67..f2ff1c666 100644 --- a/crates/stages/stages/src/stages/headers.rs +++ b/crates/stages/stages/src/stages/headers.rs @@ -133,7 +133,7 @@ where // Header validation self.consensus.validate_header_with_total_difficulty(&header, td).map_err(|error| { StageError::Block { - block: Box::new(header.clone().seal(header_hash)), + block: Box::new(SealedHeader::new(header.clone(), header_hash)), error: BlockErrorKind::Validation(error), } })?; @@ -379,7 +379,9 @@ mod tests { }; use assert_matches::assert_matches; use reth_execution_types::ExecutionOutcome; - use reth_primitives::{BlockBody, SealedBlock, SealedBlockWithSenders, B256}; + use reth_primitives::{ + alloy_primitives::Sealable, BlockBody, SealedBlock, SealedBlockWithSenders, B256, + }; use reth_provider::{BlockWriter, ProviderFactory, StaticFileProviderFactory}; use reth_stages_api::StageUnitCheckpoint; use reth_testing_utils::generators::{self, random_header, random_header_range}; @@ -489,7 +491,9 @@ mod tests { // validate the header let header = provider.header_by_number(block_num)?; assert!(header.is_some()); - let header = header.unwrap().seal_slow(); + let sealed = header.unwrap().seal_slow(); + let (header, seal) = sealed.into_parts(); + let header = SealedHeader::new(header, seal); assert_eq!(header.hash(), hash); // validate the header total difficulty diff --git a/crates/stages/stages/src/stages/merkle.rs b/crates/stages/stages/src/stages/merkle.rs index 39dc493ac..392179303 100644 --- a/crates/stages/stages/src/stages/merkle.rs +++ b/crates/stages/stages/src/stages/merkle.rs @@ -2,7 +2,7 @@ use reth_codecs::Compact; use reth_consensus::ConsensusError; use reth_db::tables; use reth_db_api::transaction::{DbTx, DbTxMut}; -use reth_primitives::{BlockNumber, GotExpected, SealedHeader, B256}; +use reth_primitives::{alloy_primitives::Sealable, BlockNumber, GotExpected, SealedHeader, B256}; use reth_provider::{ DBProvider, HeaderProvider, ProviderError, StageCheckpointReader, StageCheckpointWriter, StatsReader, TrieWriter, @@ -275,7 +275,10 @@ where // Reset the checkpoint self.save_execution_checkpoint(provider, None)?; - validate_state_root(trie_root, target_block.seal_slow(), to_block)?; + let sealed = target_block.seal_slow(); + let (header, seal) = sealed.into_parts(); + + validate_state_root(trie_root, SealedHeader::new(header, seal), to_block)?; Ok(ExecOutput { checkpoint: StageCheckpoint::new(to_block) @@ -327,7 +330,11 @@ where let target = provider .header_by_number(input.unwind_to)? .ok_or_else(|| ProviderError::HeaderNotFound(input.unwind_to.into()))?; - validate_state_root(block_root, target.seal_slow(), input.unwind_to)?; + + let sealed = target.seal_slow(); + let (header, seal) = sealed.into_parts(); + + validate_state_root(block_root, SealedHeader::new(header, seal), input.unwind_to)?; // Validation passed, apply unwind changes to the database. provider.write_trie_updates(&updates)?; @@ -529,8 +536,16 @@ mod tests { .into_iter() .map(|(address, account)| (address, (account, std::iter::empty()))), ); - let sealed_head = - SealedBlock { header: header.seal_slow(), body, ommers, withdrawals, requests }; + + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + let sealed_head = SealedBlock { + header: SealedHeader::new(header, seal), + body, + ommers, + withdrawals, + requests, + }; let head_hash = sealed_head.hash(); let mut blocks = vec![sealed_head]; diff --git a/crates/storage/codecs/Cargo.toml b/crates/storage/codecs/Cargo.toml index 1c47b4429..1b9882b47 100644 --- a/crates/storage/codecs/Cargo.toml +++ b/crates/storage/codecs/Cargo.toml @@ -40,6 +40,8 @@ alloy-primitives = { workspace = true, features = [ "rand", ] } alloy-consensus = { workspace = true, features = ["arbitrary"] } +alloy-rlp.workspace = true +rand.workspace = true test-fuzz.workspace = true serde_json.workspace = true diff --git a/crates/storage/codecs/src/alloy/header.rs b/crates/storage/codecs/src/alloy/header.rs new file mode 100644 index 000000000..c989f45e7 --- /dev/null +++ b/crates/storage/codecs/src/alloy/header.rs @@ -0,0 +1,107 @@ +use crate::Compact; +use alloy_consensus::Header as AlloyHeader; +use alloy_primitives::{Address, BlockNumber, Bloom, Bytes, B256, U256}; +use serde::{Deserialize, Serialize}; + +/// Block header +/// +/// This is a helper type to use derive on it instead of manually managing `bitfield`. +/// +/// By deriving `Compact` here, any future changes or enhancements to the `Compact` derive +/// will automatically apply to this type. +/// +/// Notice: Make sure this struct is 1:1 with [`alloy_consensus::Header`] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize, Compact)] +struct Header { + parent_hash: B256, + ommers_hash: B256, + beneficiary: Address, + state_root: B256, + transactions_root: B256, + receipts_root: B256, + withdrawals_root: Option, + logs_bloom: Bloom, + difficulty: U256, + number: BlockNumber, + gas_limit: u64, + gas_used: u64, + timestamp: u64, + mix_hash: B256, + nonce: u64, + base_fee_per_gas: Option, + blob_gas_used: Option, + excess_blob_gas: Option, + parent_beacon_block_root: Option, + requests_root: Option, + extra_data: Bytes, +} + +impl Compact for AlloyHeader { + fn to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + let header = Header { + parent_hash: self.parent_hash, + ommers_hash: self.ommers_hash, + beneficiary: self.beneficiary, + state_root: self.state_root, + transactions_root: self.transactions_root, + receipts_root: self.receipts_root, + withdrawals_root: self.withdrawals_root, + logs_bloom: self.logs_bloom, + difficulty: self.difficulty, + number: self.number, + gas_limit: self.gas_limit as u64, + gas_used: self.gas_used as u64, + timestamp: self.timestamp, + mix_hash: self.mix_hash, + nonce: self.nonce.into(), + base_fee_per_gas: self.base_fee_per_gas.map(|base_fee| base_fee as u64), + blob_gas_used: self.blob_gas_used.map(|blob_gas| blob_gas as u64), + excess_blob_gas: self.excess_blob_gas.map(|excess_blob| excess_blob as u64), + parent_beacon_block_root: self.parent_beacon_block_root, + requests_root: self.requests_root, + extra_data: self.extra_data.clone(), + }; + header.to_compact(buf) + } + + fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { + let (header, _) = Header::from_compact(buf, len); + let alloy_header = Self { + parent_hash: header.parent_hash, + ommers_hash: header.ommers_hash, + beneficiary: header.beneficiary, + state_root: header.state_root, + transactions_root: header.transactions_root, + receipts_root: header.receipts_root, + withdrawals_root: header.withdrawals_root, + logs_bloom: header.logs_bloom, + difficulty: header.difficulty, + number: header.number, + gas_limit: header.gas_limit.into(), + gas_used: header.gas_used.into(), + timestamp: header.timestamp, + mix_hash: header.mix_hash, + nonce: header.nonce.into(), + base_fee_per_gas: header.base_fee_per_gas.map(Into::into), + blob_gas_used: header.blob_gas_used.map(Into::into), + excess_blob_gas: header.excess_blob_gas.map(Into::into), + parent_beacon_block_root: header.parent_beacon_block_root, + requests_root: header.requests_root, + extra_data: header.extra_data, + }; + (alloy_header, buf) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ensure_backwards_compatibility() { + assert_eq!(Header::bitflag_encoded_bytes(), 4); + } +} diff --git a/crates/storage/codecs/src/alloy/mod.rs b/crates/storage/codecs/src/alloy/mod.rs index efd76b107..f15f859cd 100644 --- a/crates/storage/codecs/src/alloy/mod.rs +++ b/crates/storage/codecs/src/alloy/mod.rs @@ -1,6 +1,7 @@ mod access_list; mod authorization_list; mod genesis_account; +mod header; mod log; mod request; mod transaction; diff --git a/crates/storage/db-api/src/models/mod.rs b/crates/storage/db-api/src/models/mod.rs index 3720242ef..d01f2cc23 100644 --- a/crates/storage/db-api/src/models/mod.rs +++ b/crates/storage/db-api/src/models/mod.rs @@ -305,7 +305,7 @@ add_wrapper_struct!((ClientVersion, CompactClientVersion)); #[cfg(test)] mod tests { use super::*; - use reth_primitives::{Account, Header, Receipt, ReceiptWithBloom, SealedHeader, Withdrawals}; + use reth_primitives::{Account, Receipt, ReceiptWithBloom, SealedHeader, Withdrawals}; use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment}; use reth_stages_types::{ AccountHashingCheckpoint, CheckpointBlockRange, EntitiesCheckpoint, ExecutionCheckpoint, @@ -329,7 +329,6 @@ mod tests { assert_eq!(CompactU64::bitflag_encoded_bytes(), 1); assert_eq!(EntitiesCheckpoint::bitflag_encoded_bytes(), 1); assert_eq!(ExecutionCheckpoint::bitflag_encoded_bytes(), 0); - assert_eq!(Header::bitflag_encoded_bytes(), 4); assert_eq!(HeadersCheckpoint::bitflag_encoded_bytes(), 0); assert_eq!(IndexHistoryCheckpoint::bitflag_encoded_bytes(), 0); assert_eq!(PruneCheckpoint::bitflag_encoded_bytes(), 1); @@ -358,7 +357,6 @@ mod tests { assert_eq!(CompactU64::bitflag_encoded_bytes(), 1); assert_eq!(EntitiesCheckpoint::bitflag_encoded_bytes(), 1); assert_eq!(ExecutionCheckpoint::bitflag_encoded_bytes(), 0); - assert_eq!(Header::bitflag_encoded_bytes(), 4); assert_eq!(HeadersCheckpoint::bitflag_encoded_bytes(), 0); assert_eq!(IndexHistoryCheckpoint::bitflag_encoded_bytes(), 0); assert_eq!(PruneCheckpoint::bitflag_encoded_bytes(), 1); diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index c85ba9b5b..9b1e93624 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -20,8 +20,8 @@ use reth_evm::ConfigureEvmEnv; use reth_execution_types::ExecutionOutcome; use reth_node_types::NodeTypesWithDB; use reth_primitives::{ - Account, Block, BlockWithSenders, EthereumHardforks, Header, Receipt, SealedBlock, - SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned, + alloy_primitives::Sealable, Account, Block, BlockWithSenders, EthereumHardforks, Header, + Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned, TransactionSignedNoHash, Withdrawal, Withdrawals, }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; @@ -69,7 +69,7 @@ impl BlockchainProvider2 { match provider.header_by_number(best.best_number)? { Some(header) => { drop(provider); - Ok(Self::with_latest(database, header.seal(best.best_hash))?) + Ok(Self::with_latest(database, SealedHeader::new(header, best.best_hash))?) } None => Err(ProviderError::HeaderNotFound(best.best_number.into())), } @@ -1279,20 +1279,34 @@ where Ok(self.canonical_in_memory_state.get_finalized_header()) } BlockNumberOrTag::Safe => Ok(self.canonical_in_memory_state.get_safe_header()), - BlockNumberOrTag::Earliest => { - self.header_by_number(0)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow()))) - } + BlockNumberOrTag::Earliest => self.header_by_number(0)?.map_or_else( + || Ok(None), + |h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + Ok(Some(SealedHeader::new(header, seal))) + }, + ), BlockNumberOrTag::Pending => Ok(self.canonical_in_memory_state.pending_sealed_header()), - BlockNumberOrTag::Number(num) => { - self.header_by_number(num)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow()))) - } + BlockNumberOrTag::Number(num) => self.header_by_number(num)?.map_or_else( + || Ok(None), + |h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + Ok(Some(SealedHeader::new(header, seal))) + }, + ), } } fn sealed_header_by_id(&self, id: BlockId) -> ProviderResult> { Ok(match id { BlockId::Number(num) => self.sealed_header_by_number_or_tag(num)?, - BlockId::Hash(hash) => self.header(&hash.block_hash)?.map(|h| h.seal_slow()), + BlockId::Hash(hash) => self.header(&hash.block_hash)?.map(|h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) + }), }) } @@ -3744,7 +3758,10 @@ mod tests { index: 0, block_hash: in_memory_blocks[0].header.hash(), block_number: in_memory_blocks[0].header.number, - base_fee: in_memory_blocks[0].header.base_fee_per_gas, + base_fee: in_memory_blocks[0] + .header + .base_fee_per_gas + .map(|base_fee_per_gas| base_fee_per_gas as u64), excess_blob_gas: None, timestamp: in_memory_blocks[0].header.timestamp, }; @@ -3772,7 +3789,10 @@ mod tests { index: 0, block_hash: database_blocks[0].header.hash(), block_number: database_blocks[0].header.number, - base_fee: database_blocks[0].header.base_fee_per_gas, + base_fee: database_blocks[0] + .header + .base_fee_per_gas + .map(|base_fee_per_gas| base_fee_per_gas as u64), excess_blob_gas: None, timestamp: database_blocks[0].header.timestamp, }; diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 92cb9b950..61ee88f3d 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -752,7 +752,7 @@ impl DatabaseProvider { for ((main_block_number, header), (_, header_hash), (_, tx)) in izip!(block_header_iter, block_header_hashes_iter, block_tx_iter) { - let header = header.seal(header_hash); + let header = SealedHeader::new(header, header_hash); let (body, senders) = tx.into_iter().map(|tx| tx.to_components()).unzip(); @@ -1248,7 +1248,7 @@ impl DatabaseProvider { for ((main_block_number, header), (_, header_hash), (_, tx)) in izip!(block_header_iter, block_header_hashes_iter, block_tx_iter) { - let header = header.seal(header_hash); + let header = SealedHeader::new(header, header_hash); let (body, senders) = tx.into_iter().map(|tx| tx.to_components()).unzip(); @@ -1530,7 +1530,7 @@ impl HeaderProvider let hash = self .block_hash(number)? .ok_or_else(|| ProviderError::HeaderNotFound(number.into()))?; - Ok(Some(header.seal(hash))) + Ok(Some(SealedHeader::new(header, hash))) } else { Ok(None) } @@ -1554,7 +1554,7 @@ impl HeaderProvider let hash = self .block_hash(number)? .ok_or_else(|| ProviderError::HeaderNotFound(number.into()))?; - let sealed = header.seal(hash); + let sealed = SealedHeader::new(header, hash); if !predicate(&sealed) { break } @@ -1938,8 +1938,10 @@ impl TransactionsProvider index, block_hash, block_number, - base_fee: header.base_fee_per_gas, - excess_blob_gas: header.excess_blob_gas, + base_fee: header.base_fee_per_gas.map(|base_fee| base_fee as u64), + excess_blob_gas: header + .excess_blob_gas + .map(|excess_blob| excess_blob as u64), timestamp: header.timestamp, }; diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index d483c9ee1..1a43b611b 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -20,9 +20,9 @@ use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_evm::ConfigureEvmEnv; use reth_node_types::NodeTypesWithDB; use reth_primitives::{ - Account, Block, BlockWithSenders, Header, Receipt, SealedBlock, SealedBlockWithSenders, - SealedHeader, TransactionMeta, TransactionSigned, TransactionSignedNoHash, Withdrawal, - Withdrawals, + alloy_primitives::Sealable, Account, Block, BlockWithSenders, Header, Receipt, SealedBlock, + SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned, + TransactionSignedNoHash, Withdrawal, Withdrawals, }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; @@ -128,7 +128,12 @@ impl BlockchainProvider { .transpose()? .flatten(); - Ok(Self::with_blocks(database, tree, latest_header.seal(best.best_hash), finalized_header)) + Ok(Self::with_blocks( + database, + tree, + SealedHeader::new(latest_header, best.best_hash), + finalized_header, + )) } /// Ensures that the given block number is canonical (synced) @@ -839,20 +844,34 @@ where BlockNumberOrTag::Latest => Ok(Some(self.chain_info.get_canonical_head())), BlockNumberOrTag::Finalized => Ok(self.chain_info.get_finalized_header()), BlockNumberOrTag::Safe => Ok(self.chain_info.get_safe_header()), - BlockNumberOrTag::Earliest => { - self.header_by_number(0)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow()))) - } + BlockNumberOrTag::Earliest => self.header_by_number(0)?.map_or_else( + || Ok(None), + |h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + Ok(Some(SealedHeader::new(header, seal))) + }, + ), BlockNumberOrTag::Pending => Ok(self.tree.pending_header()), - BlockNumberOrTag::Number(num) => { - self.header_by_number(num)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow()))) - } + BlockNumberOrTag::Number(num) => self.header_by_number(num)?.map_or_else( + || Ok(None), + |h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + Ok(Some(SealedHeader::new(header, seal))) + }, + ), } } fn sealed_header_by_id(&self, id: BlockId) -> ProviderResult> { Ok(match id { BlockId::Number(num) => self.sealed_header_by_number_or_tag(num)?, - BlockId::Hash(hash) => self.header(&hash.block_hash)?.map(|h| h.seal_slow()), + BlockId::Hash(hash) => self.header(&hash.block_hash)?.map(|h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) + }), }) } diff --git a/crates/storage/provider/src/providers/static_file/jar.rs b/crates/storage/provider/src/providers/static_file/jar.rs index 16dbb3648..6372bad24 100644 --- a/crates/storage/provider/src/providers/static_file/jar.rs +++ b/crates/storage/provider/src/providers/static_file/jar.rs @@ -119,7 +119,7 @@ impl<'a> HeaderProvider for StaticFileJarProvider<'a> { Ok(self .cursor()? .get_two::>(number.into())? - .map(|(header, hash)| header.seal(hash))) + .map(|(header, hash)| SealedHeader::new(header, hash))) } fn sealed_headers_while( @@ -136,7 +136,7 @@ impl<'a> HeaderProvider for StaticFileJarProvider<'a> { if let Some((header, hash)) = cursor.get_two::>(number.into())? { - let sealed = header.seal(hash); + let sealed = SealedHeader::new(header, hash); if !predicate(&sealed) { break } diff --git a/crates/storage/provider/src/providers/static_file/manager.rs b/crates/storage/provider/src/providers/static_file/manager.rs index 36cb3629b..3ad294f0e 100644 --- a/crates/storage/provider/src/providers/static_file/manager.rs +++ b/crates/storage/provider/src/providers/static_file/manager.rs @@ -1271,7 +1271,7 @@ impl HeaderProvider for StaticFileProvider { |cursor, number| { Ok(cursor .get_two::>(number.into())? - .map(|(header, hash)| header.seal(hash))) + .map(|(header, hash)| SealedHeader::new(header, hash))) }, predicate, ) diff --git a/crates/storage/provider/src/test_utils/blocks.rs b/crates/storage/provider/src/test_utils/blocks.rs index a9d69755b..4e0798ff1 100644 --- a/crates/storage/provider/src/test_utils/blocks.rs +++ b/crates/storage/provider/src/test_utils/blocks.rs @@ -7,8 +7,9 @@ use once_cell::sync::Lazy; use reth_db::tables; use reth_db_api::{database::Database, models::StoredBlockBodyIndices}; use reth_primitives::{ - Account, Header, Receipt, Requests, SealedBlock, SealedBlockWithSenders, SealedHeader, - Signature, Transaction, TransactionSigned, TxLegacy, TxType, Withdrawal, Withdrawals, + alloy_primitives, alloy_primitives::Sealable, Account, Header, Receipt, Requests, SealedBlock, + SealedBlockWithSenders, SealedHeader, Signature, Transaction, TransactionSigned, TxLegacy, + TxType, Withdrawal, Withdrawals, }; use reth_trie::root::{state_root_unhashed, storage_root_unhashed}; use revm::{ @@ -154,8 +155,10 @@ impl Default for BlockchainTestData { /// Genesis block pub fn genesis() -> SealedBlock { SealedBlock { - header: Header { number: 0, difficulty: U256::from(1), ..Default::default() } - .seal(B256::ZERO), + header: SealedHeader::new( + Header { number: 0, difficulty: U256::from(1), ..Default::default() }, + B256::ZERO, + ), body: vec![], ommers: vec![], withdrawals: Some(Withdrawals::default()), @@ -232,7 +235,9 @@ fn block1(number: BlockNumber) -> (SealedBlockWithSenders, ExecutionOutcome) { header.number = number; header.state_root = state_root; header.parent_hash = B256::ZERO; - block.header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + block.header = SealedHeader::new(header, seal); (SealedBlockWithSenders { block, senders: vec![Address::new([0x30; 20])] }, execution_outcome) } @@ -296,7 +301,9 @@ fn block2( header.state_root = state_root; // parent_hash points to block1 hash header.parent_hash = parent_hash; - block.header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + block.header = SealedHeader::new(header, seal); (SealedBlockWithSenders { block, senders: vec![Address::new([0x31; 20])] }, execution_outcome) } @@ -361,7 +368,9 @@ fn block3( header.state_root = state_root; // parent_hash points to block1 hash header.parent_hash = parent_hash; - block.header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + block.header = SealedHeader::new(header, seal); (SealedBlockWithSenders { block, senders: vec![Address::new([0x31; 20])] }, execution_outcome) } @@ -452,7 +461,9 @@ fn block4( header.state_root = state_root; // parent_hash points to block1 hash header.parent_hash = parent_hash; - block.header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + block.header = SealedHeader::new(header, seal); (SealedBlockWithSenders { block, senders: vec![Address::new([0x31; 20])] }, execution_outcome) } @@ -538,7 +549,9 @@ fn block5( header.state_root = state_root; // parent_hash points to block1 hash header.parent_hash = parent_hash; - block.header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + block.header = SealedHeader::new(header, seal); (SealedBlockWithSenders { block, senders: vec![Address::new([0x31; 20])] }, execution_outcome) } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 2a380fb74..e7a79c339 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -18,8 +18,8 @@ use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_evm::ConfigureEvmEnv; use reth_execution_types::{Chain, ExecutionOutcome}; use reth_primitives::{ - Account, Block, BlockWithSenders, Bytecode, GotExpected, Header, Receipt, SealedBlock, - SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned, + alloy_primitives::Sealable, Account, Block, BlockWithSenders, Bytecode, GotExpected, Header, + Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned, TransactionSignedNoHash, Withdrawal, Withdrawals, }; use reth_stages_types::{StageCheckpoint, StageId}; @@ -200,7 +200,11 @@ impl HeaderProvider for MockEthProvider { } fn sealed_header(&self, number: BlockNumber) -> ProviderResult> { - Ok(self.header_by_number(number)?.map(|h| h.seal_slow())) + Ok(self.header_by_number(number)?.map(|h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) + })) } fn sealed_headers_while( @@ -211,7 +215,11 @@ impl HeaderProvider for MockEthProvider { Ok(self .headers_range(range)? .into_iter() - .map(|h| h.seal_slow()) + .map(|h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) + }) .take_while(|h| predicate(h)) .collect()) } @@ -279,8 +287,14 @@ impl TransactionsProvider for MockEthProvider { index: index as u64, block_hash: *block_hash, block_number: block.header.number, - base_fee: block.header.base_fee_per_gas, - excess_blob_gas: block.header.excess_blob_gas, + base_fee: block + .header + .base_fee_per_gas + .map(|base_fer_per_gas| base_fer_per_gas as u64), + excess_blob_gas: block + .header + .excess_blob_gas + .map(|excess_blob_gas| excess_blob_gas as u64), timestamp: block.header.timestamp, }; return Ok(Some((tx.clone(), meta))) @@ -550,7 +564,14 @@ impl BlockReaderIdExt for MockEthProvider { } fn sealed_header_by_id(&self, id: BlockId) -> ProviderResult> { - self.header_by_id(id)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow()))) + self.header_by_id(id)?.map_or_else( + || Ok(None), + |h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + Ok(Some(SealedHeader::new(header, seal))) + }, + ) } fn header_by_id(&self, id: BlockId) -> ProviderResult> { diff --git a/crates/storage/storage-api/src/block.rs b/crates/storage/storage-api/src/block.rs index 50d86f914..6590b47b4 100644 --- a/crates/storage/storage-api/src/block.rs +++ b/crates/storage/storage-api/src/block.rs @@ -6,7 +6,8 @@ use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag}; use alloy_primitives::{BlockNumber, B256}; use reth_db_models::StoredBlockBodyIndices; use reth_primitives::{ - Block, BlockWithSenders, Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, + alloy_primitives::Sealable, Block, BlockWithSenders, Header, Receipt, SealedBlock, + SealedBlockWithSenders, SealedHeader, }; use reth_storage_errors::provider::ProviderResult; use std::ops::RangeInclusive; @@ -244,7 +245,14 @@ pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt { ) -> ProviderResult> { self.convert_block_number(id)? .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))? - .map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow()))) + .map_or_else( + || Ok(None), + |h| { + let sealed = h.seal_slow(); + let (header, seal) = sealed.into_parts(); + Ok(Some(SealedHeader::new(header, seal))) + }, + ) } /// Returns the sealed header with the matching `BlockId` from the database. diff --git a/crates/transaction-pool/src/maintain.rs b/crates/transaction-pool/src/maintain.rs index 4865606ac..5a68b1660 100644 --- a/crates/transaction-pool/src/maintain.rs +++ b/crates/transaction-pool/src/maintain.rs @@ -17,8 +17,8 @@ use reth_chainspec::{ChainSpec, ChainSpecProvider}; use reth_execution_types::ChangedAccount; use reth_fs_util::FsPathError; use reth_primitives::{ - BlockNumberOrTag, IntoRecoveredTransaction, PooledTransactionsElementEcRecovered, - TransactionSigned, + alloy_primitives::Sealable, BlockNumberOrTag, IntoRecoveredTransaction, + PooledTransactionsElementEcRecovered, SealedHeader, TransactionSigned, }; use reth_storage_api::{errors::provider::ProviderError, BlockReaderIdExt, StateProviderFactory}; use reth_tasks::TaskSpawner; @@ -114,15 +114,17 @@ pub async fn maintain_transaction_pool( let MaintainPoolConfig { max_update_depth, max_reload_accounts, .. } = config; // ensure the pool points to latest state if let Ok(Some(latest)) = client.header_by_number_or_tag(BlockNumberOrTag::Latest) { - let latest = latest.seal_slow(); + let sealed = latest.seal_slow(); + let (header, seal) = sealed.into_parts(); + let latest = SealedHeader::new(header, seal); let chain_spec = client.chain_spec(); let info = BlockInfo { - block_gas_limit: latest.gas_limit, + block_gas_limit: latest.gas_limit as u64, last_seen_block_hash: latest.hash(), last_seen_block_number: latest.number, pending_basefee: latest .next_block_base_fee(chain_spec.base_fee_params_at_timestamp(latest.timestamp + 12)) - .unwrap_or_default(), + .unwrap_or_default() as u64, pending_blob_fee: latest.next_block_blob_fee(), }; pool.set_block_info(info); @@ -355,7 +357,7 @@ pub async fn maintain_transaction_pool( // update the pool first let update = CanonicalStateUpdate { new_tip: &new_tip.block, - pending_block_base_fee, + pending_block_base_fee: pending_block_base_fee as u64, pending_block_blob_fee, changed_accounts, // all transactions mined in the new chain need to be removed from the pool @@ -404,10 +406,10 @@ pub async fn maintain_transaction_pool( maintained_state = MaintainedPoolState::Drifted; debug!(target: "txpool", ?depth, "skipping deep canonical update"); let info = BlockInfo { - block_gas_limit: tip.gas_limit, + block_gas_limit: tip.gas_limit as u64, last_seen_block_hash: tip.hash(), last_seen_block_number: tip.number, - pending_basefee: pending_block_base_fee, + pending_basefee: pending_block_base_fee as u64, pending_blob_fee: pending_block_blob_fee, }; pool.set_block_info(info); @@ -438,7 +440,7 @@ pub async fn maintain_transaction_pool( // Canonical update let update = CanonicalStateUpdate { new_tip: &tip.block, - pending_block_base_fee, + pending_block_base_fee: pending_block_base_fee as u64, pending_block_blob_fee, changed_accounts, mined_transactions, diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index 8ebfb0970..d60054483 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -666,7 +666,7 @@ impl<'a> CanonicalStateUpdate<'a> { /// Returns the block info for the tip block. pub fn block_info(&self) -> BlockInfo { BlockInfo { - block_gas_limit: self.new_tip.gas_limit, + block_gas_limit: self.new_tip.gas_limit as u64, last_seen_block_hash: self.hash(), last_seen_block_number: self.number(), pending_basefee: self.pending_block_base_fee, diff --git a/examples/beacon-api-sidecar-fetcher/src/mined_sidecar.rs b/examples/beacon-api-sidecar-fetcher/src/mined_sidecar.rs index 70c6c98a9..04fbd5fbf 100644 --- a/examples/beacon-api-sidecar-fetcher/src/mined_sidecar.rs +++ b/examples/beacon-api-sidecar-fetcher/src/mined_sidecar.rs @@ -115,7 +115,7 @@ where let block_metadata = BlockMetadata { block_hash: block.hash(), block_number: block.number, - gas_used: block.gas_used, + gas_used: block.gas_used as u64, }; actions_to_queue.push(BlobTransactionEvent::Mined(MinedBlob { transaction, @@ -194,7 +194,7 @@ where let block_metadata = BlockMetadata { block_hash: new.tip().block.hash(), block_number: new.tip().block.number, - gas_used: new.tip().block.gas_used, + gas_used: new.tip().block.gas_used as u64, }; BlobTransactionEvent::Reorged(ReorgedBlob { transaction_hash, @@ -267,7 +267,7 @@ async fn fetch_blobs_for_block( let block_metadata = BlockMetadata { block_hash: block.hash(), block_number: block.number, - gas_used: block.gas_used, + gas_used: block.gas_used as u64, }; BlobTransactionEvent::Mined(MinedBlob { transaction, block_metadata }) }) diff --git a/examples/db-access/src/main.rs b/examples/db-access/src/main.rs index 810c7a355..53b56b738 100644 --- a/examples/db-access/src/main.rs +++ b/examples/db-access/src/main.rs @@ -2,7 +2,7 @@ use alloy_rpc_types::{Filter, FilteredParams}; use reth_chainspec::ChainSpecBuilder; use reth_node_ethereum::EthereumNode; use reth_node_types::NodeTypesWithDBAdapter; -use reth_primitives::{Address, B256}; +use reth_primitives::{alloy_primitives::Sealable, Address, SealedHeader, B256}; use reth_provider::{ providers::StaticFileProvider, AccountReader, BlockReader, BlockSource, HeaderProvider, ProviderFactory, ReceiptProvider, StateProvider, TransactionsProvider, @@ -62,7 +62,9 @@ fn header_provider_example(provider: T, number: u64) -> eyre: // We can convert a header to a sealed header which contains the hash w/o needing to re-compute // it every time. - let sealed_header = header.seal_slow(); + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + let sealed_header = SealedHeader::new(header, seal); // Can also query the header by hash! let header_by_hash = diff --git a/testing/ef-tests/src/models.rs b/testing/ef-tests/src/models.rs index 3021f8cb7..8c8c3189a 100644 --- a/testing/ef-tests/src/models.rs +++ b/testing/ef-tests/src/models.rs @@ -94,14 +94,14 @@ pub struct Header { impl From
for SealedHeader { fn from(value: Header) -> Self { let header = RethHeader { - base_fee_per_gas: value.base_fee_per_gas.map(|v| v.to::()), + base_fee_per_gas: value.base_fee_per_gas.map(|v| v.to::().into()), beneficiary: value.coinbase, difficulty: value.difficulty, extra_data: value.extra_data, - gas_limit: value.gas_limit.to::(), - gas_used: value.gas_used.to::(), + gas_limit: value.gas_limit.to::().into(), + gas_used: value.gas_used.to::().into(), mix_hash: value.mix_hash, - nonce: u64::from_be_bytes(value.nonce.0), + nonce: u64::from_be_bytes(value.nonce.0).into(), number: value.number.to::(), timestamp: value.timestamp.to::(), transactions_root: value.transactions_trie, @@ -111,12 +111,12 @@ impl From
for SealedHeader { parent_hash: value.parent_hash, logs_bloom: value.bloom, withdrawals_root: value.withdrawals_root, - blob_gas_used: value.blob_gas_used.map(|v| v.to::()), - excess_blob_gas: value.excess_blob_gas.map(|v| v.to::()), + blob_gas_used: value.blob_gas_used.map(|v| v.to::().into()), + excess_blob_gas: value.excess_blob_gas.map(|v| v.to::().into()), parent_beacon_block_root: value.parent_beacon_block_root, requests_root: value.requests_root, }; - header.seal(value.hash) + Self::new(header, value.hash) } } diff --git a/testing/testing-utils/src/generators.rs b/testing/testing-utils/src/generators.rs index 334df3ef3..ab8d8b703 100644 --- a/testing/testing-utils/src/generators.rs +++ b/testing/testing-utils/src/generators.rs @@ -3,7 +3,7 @@ use alloy_eips::{ eip6110::DepositRequest, eip7002::WithdrawalRequest, eip7251::ConsolidationRequest, }; -use alloy_primitives::{Address, BlockNumber, Bytes, TxKind, B256, U256}; +use alloy_primitives::{Address, BlockNumber, Bytes, Sealable, TxKind, B256, U256}; pub use rand::Rng; use rand::{ distributions::uniform::SampleRange, rngs::StdRng, seq::SliceRandom, thread_rng, SeedableRng, @@ -96,7 +96,9 @@ pub fn random_header(rng: &mut R, number: u64, parent: Option) -> parent_hash: parent.unwrap_or_default(), ..Default::default() }; - header.seal_slow() + let sealed = header.seal_slow(); + let (header, seal) = sealed.into_parts(); + SealedHeader::new(header, seal) } /// Generates a random legacy [Transaction]. @@ -195,20 +197,24 @@ pub fn random_block(rng: &mut R, number: u64, block_params: BlockParams) }); let withdrawals_root = withdrawals.as_ref().map(|w| proofs::calculate_withdrawals_root(w)); + let sealed = Header { + parent_hash: block_params.parent.unwrap_or_default(), + number, + gas_used: total_gas.into(), + gas_limit: total_gas.into(), + transactions_root, + ommers_hash, + base_fee_per_gas: Some(rng.gen::().into()), + requests_root, + withdrawals_root, + ..Default::default() + } + .seal_slow(); + + let (header, seal) = sealed.into_parts(); + SealedBlock { - header: Header { - parent_hash: block_params.parent.unwrap_or_default(), - number, - gas_used: total_gas, - gas_limit: total_gas, - transactions_root, - ommers_hash, - base_fee_per_gas: Some(rng.gen()), - requests_root, - withdrawals_root, - ..Default::default() - } - .seal_slow(), + header: SealedHeader::new(header, seal), body: transactions, ommers, withdrawals: withdrawals.map(Withdrawals::new),