diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index dc5914de21..4d587cdcb2 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -1248,7 +1248,7 @@ mod tests { stage::StageCheckpoint, Account, Address, ChainSpecBuilder, Genesis, GenesisAccount, Header, Signature, Transaction, TransactionKind, TransactionSigned, TransactionSignedEcRecovered, TxEip1559, - B256, MAINNET, + Withdrawals, B256, MAINNET, }; use reth_provider::{ test_utils::{ @@ -1492,7 +1492,7 @@ mod tests { .seal_slow(), body: body.clone().into_iter().map(|tx| tx.into_signed()).collect(), ommers: Vec::new(), - withdrawals: Some(Vec::new()), + withdrawals: Some(Withdrawals::default()), }, body.iter().map(|tx| tx.signer()).collect(), ) diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index 13a3571315..0fd6601761 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -478,7 +478,7 @@ mod tests { use reth_primitives::{ constants::eip4844::DATA_GAS_PER_BLOB, hex_literal::hex, proofs, Account, Address, BlockBody, BlockHash, BlockHashOrNumber, Bytes, ChainSpecBuilder, Header, Signature, - TransactionKind, TransactionSigned, Withdrawal, MAINNET, U256, + TransactionKind, TransactionSigned, Withdrawal, Withdrawals, MAINNET, U256, }; use std::ops::RangeBounds; @@ -492,7 +492,7 @@ mod tests { &self, _id: BlockHashOrNumber, _timestamp: u64, - ) -> ProviderResult>> ; + ) -> ProviderResult> ; } } @@ -579,7 +579,7 @@ mod tests { &self, _id: BlockHashOrNumber, _timestamp: u64, - ) -> ProviderResult>> { + ) -> ProviderResult> { self.withdrawals_provider.withdrawals_by_block(_id, _timestamp) } @@ -729,10 +729,12 @@ mod tests { let chain_spec = ChainSpecBuilder::mainnet().shanghai_activated().build(); let create_block_with_withdrawals = |indexes: &[u64]| { - let withdrawals = indexes - .iter() - .map(|idx| Withdrawal { index: *idx, ..Default::default() }) - .collect::>(); + let withdrawals = Withdrawals::new( + indexes + .iter() + .map(|idx| Withdrawal { index: *idx, ..Default::default() }) + .collect(), + ); SealedBlock { header: Header { withdrawals_root: Some(proofs::calculate_withdrawals_root(&withdrawals)), @@ -779,7 +781,7 @@ mod tests { let header = Header { base_fee_per_gas: Some(1337u64), - withdrawals_root: Some(proofs::calculate_withdrawals_root(&[])), + withdrawals_root: Some(proofs::calculate_withdrawals_root(&Withdrawals::default())), ..Default::default() } .seal_slow(); @@ -796,7 +798,7 @@ mod tests { let header = Header { base_fee_per_gas: Some(1337u64), - withdrawals_root: Some(proofs::calculate_withdrawals_root(&[])), + withdrawals_root: Some(proofs::calculate_withdrawals_root(&Withdrawals::default())), blob_gas_used: Some(1), transactions_root: proofs::calculate_transaction_root(&[transaction.clone()]), ..Default::default() @@ -806,7 +808,7 @@ mod tests { let body = BlockBody { transactions: vec![transaction], ommers: vec![], - withdrawals: Some(vec![]), + withdrawals: Some(Withdrawals::default()), }; let block = SealedBlock::new(header, body); diff --git a/crates/interfaces/src/p2p/full_block.rs b/crates/interfaces/src/p2p/full_block.rs index 939da65779..82d842670f 100644 --- a/crates/interfaces/src/p2p/full_block.rs +++ b/crates/interfaces/src/p2p/full_block.rs @@ -320,7 +320,10 @@ fn ensure_valid_body_response( )) } - let withdrawals = block.withdrawals.as_deref().unwrap_or(&[]); + let withdrawals = match &block.withdrawals { + Some(withdrawals) => withdrawals.as_slice(), + None => &[][..], + }; if let Some(header_withdrawals_root) = header.withdrawals_root { let withdrawals_root = reth_primitives::proofs::calculate_withdrawals_root(withdrawals); if withdrawals_root != header_withdrawals_root { diff --git a/crates/node-api/src/engine/mod.rs b/crates/node-api/src/engine/mod.rs index a620fec92c..af0ffea327 100644 --- a/crates/node-api/src/engine/mod.rs +++ b/crates/node-api/src/engine/mod.rs @@ -17,7 +17,7 @@ //! ```no_run //! # use reth_rpc_types::engine::{PayloadAttributes as EthPayloadAttributes, PayloadId}; //! # use reth_rpc_types::Withdrawal; -//! # use reth_primitives::{B256, ChainSpec, Address}; +//! # use reth_primitives::{B256, ChainSpec, Address, Withdrawals}; //! # use reth_node_api::{EngineTypes, EngineApiMessageVersion, validate_version_specific_fields, AttributesValidationError, PayloadAttributes, PayloadBuilderAttributes, PayloadOrAttributes}; //! # use reth_payload_builder::{EthPayloadBuilderAttributes, EthBuiltPayload}; //! # use serde::{Deserialize, Serialize}; @@ -108,7 +108,7 @@ //! self.0.prev_randao //! } //! -//! fn withdrawals(&self) -> &Vec { +//! fn withdrawals(&self) -> &Withdrawals { //! &self.0.withdrawals //! } //! } diff --git a/crates/node-api/src/engine/traits.rs b/crates/node-api/src/engine/traits.rs index ade1c9d978..479d0f3b76 100644 --- a/crates/node-api/src/engine/traits.rs +++ b/crates/node-api/src/engine/traits.rs @@ -2,7 +2,7 @@ use crate::{validate_version_specific_fields, AttributesValidationError, EngineA use reth_primitives::{ revm::config::revm_spec_by_timestamp_after_merge, revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, SpecId}, - Address, ChainSpec, Header, SealedBlock, B256, U256, + Address, ChainSpec, Header, SealedBlock, Withdrawals, B256, U256, }; use reth_rpc_types::{ engine::{ @@ -72,7 +72,7 @@ pub trait PayloadBuilderAttributes: Send + Sync + std::fmt::Debug { fn prev_randao(&self) -> B256; /// Returns the withdrawals for the running payload job. - fn withdrawals(&self) -> &Vec; + fn withdrawals(&self) -> &Withdrawals; /// Returns the configured [CfgEnv] and [BlockEnv] for the targeted payload (that has the /// `parent` as its parent). diff --git a/crates/payload/basic/src/lib.rs b/crates/payload/basic/src/lib.rs index ccacb7d268..49fa2141e1 100644 --- a/crates/payload/basic/src/lib.rs +++ b/crates/payload/basic/src/lib.rs @@ -20,7 +20,7 @@ use reth_payload_builder::{ use reth_primitives::{ bytes::BytesMut, constants::{EMPTY_WITHDRAWALS, ETHEREUM_BLOCK_GAS_LIMIT, RETH_CLIENT_VERSION, SLOT_DURATION}, - proofs, BlockNumberOrTag, Bytes, ChainSpec, SealedBlock, Withdrawal, B256, U256, + proofs, BlockNumberOrTag, Bytes, ChainSpec, SealedBlock, Withdrawals, B256, U256, }; use reth_provider::{ BlockReaderIdExt, BlockSource, CanonStateNotification, ProviderError, StateProviderFactory, @@ -794,7 +794,7 @@ pub trait PayloadBuilder: Send + Sync + Clone { #[derive(Default, Debug)] pub struct WithdrawalsOutcome { /// committed withdrawals, if any. - pub withdrawals: Option>, + pub withdrawals: Option, /// withdrawals root if any. pub withdrawals_root: Option, } @@ -807,7 +807,10 @@ impl WithdrawalsOutcome { /// No withdrawals pub fn empty() -> Self { - Self { withdrawals: Some(vec![]), withdrawals_root: Some(EMPTY_WITHDRAWALS) } + Self { + withdrawals: Some(Withdrawals::default()), + withdrawals_root: Some(EMPTY_WITHDRAWALS), + } } } @@ -820,7 +823,7 @@ pub fn commit_withdrawals>( db: &mut State, chain_spec: &ChainSpec, timestamp: u64, - withdrawals: Vec, + withdrawals: Withdrawals, ) -> RethResult { if !chain_spec.is_shanghai_active_at_timestamp(timestamp) { return Ok(WithdrawalsOutcome::pre_shanghai()) diff --git a/crates/payload/builder/src/optimism.rs b/crates/payload/builder/src/optimism.rs index 984de81c6b..6b8b272ace 100644 --- a/crates/payload/builder/src/optimism.rs +++ b/crates/payload/builder/src/optimism.rs @@ -1,7 +1,7 @@ use crate::EthPayloadBuilderAttributes; use alloy_rlp::{Encodable, Error as DecodeError}; use reth_node_api::PayloadBuilderAttributes; -use reth_primitives::{Address, TransactionSigned, Withdrawal, B256}; +use reth_primitives::{Address, TransactionSigned, Withdrawals, B256}; use reth_rpc_types::engine::{OptimismPayloadAttributes, PayloadId}; use reth_rpc_types_compat::engine::payload::convert_standalone_withdraw_to_withdrawal; @@ -39,10 +39,12 @@ impl PayloadBuilderAttributes for OptimismPayloadBuilderAttributes { let withdraw = attributes.payload_attributes.withdrawals.map( |withdrawals: Vec| { - withdrawals - .into_iter() - .map(convert_standalone_withdraw_to_withdrawal) // Removed the parentheses here - .collect::>() + Withdrawals::new( + withdrawals + .into_iter() + .map(convert_standalone_withdraw_to_withdrawal) // Removed the parentheses here + .collect(), + ) }, ); @@ -88,7 +90,7 @@ impl PayloadBuilderAttributes for OptimismPayloadBuilderAttributes { self.payload_attributes.prev_randao } - fn withdrawals(&self) -> &Vec { + fn withdrawals(&self) -> &Withdrawals { &self.payload_attributes.withdrawals } } diff --git a/crates/payload/builder/src/payload.rs b/crates/payload/builder/src/payload.rs index 4c416f6225..5aeabf684e 100644 --- a/crates/payload/builder/src/payload.rs +++ b/crates/payload/builder/src/payload.rs @@ -2,7 +2,7 @@ use alloy_rlp::Encodable; use reth_node_api::{BuiltPayload, PayloadBuilderAttributes}; -use reth_primitives::{Address, BlobTransactionSidecar, SealedBlock, Withdrawal, B256, U256}; +use reth_primitives::{Address, BlobTransactionSidecar, SealedBlock, Withdrawals, B256, U256}; use reth_rpc_types::engine::{ ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadV1, PayloadAttributes, PayloadId, @@ -153,7 +153,7 @@ pub struct EthPayloadBuilderAttributes { /// Randomness value for the generated payload pub prev_randao: B256, /// Withdrawals for the generated payload - pub withdrawals: Vec, + pub withdrawals: Withdrawals, /// Root of the parent beacon block pub parent_beacon_block_root: Option, } @@ -174,10 +174,12 @@ impl EthPayloadBuilderAttributes { let withdraw = attributes.withdrawals.map( |withdrawals: Vec| { - withdrawals - .into_iter() - .map(convert_standalone_withdraw_to_withdrawal) // Removed the parentheses here - .collect::>() + Withdrawals::new( + withdrawals + .into_iter() + .map(convert_standalone_withdraw_to_withdrawal) // Removed the parentheses here + .collect(), + ) }, ); @@ -228,7 +230,7 @@ impl PayloadBuilderAttributes for EthPayloadBuilderAttributes { self.prev_randao } - fn withdrawals(&self) -> &Vec { + fn withdrawals(&self) -> &Withdrawals { &self.withdrawals } } diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index e9b055c63c..fa253a04fc 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -1,6 +1,6 @@ use crate::{ Address, GotExpected, Header, SealedHeader, TransactionSigned, TransactionSignedEcRecovered, - Withdrawal, B256, + Withdrawal, Withdrawals, B256, }; use alloy_rlp::{RlpDecodable, RlpEncodable}; use reth_codecs::derive_arbitrary; @@ -27,7 +27,7 @@ pub struct Block { /// Ommers/uncles header. pub ommers: Vec
, /// Block withdrawals. - pub withdrawals: Option>, + pub withdrawals: Option, } impl Block { @@ -119,7 +119,7 @@ impl Block { // take into account capacity self.body.iter().map(TransactionSigned::size).sum::() + self.body.capacity() * std::mem::size_of::() + self.ommers.iter().map(Header::size).sum::() + self.ommers.capacity() * std::mem::size_of::
() + - self.withdrawals.as_ref().map(|w| w.iter().map(Withdrawal::size).sum::() + w.capacity() * std::mem::size_of::()).unwrap_or(std::mem::size_of::>>()) + self.withdrawals.as_ref().map(|w| w.size() + w.capacity() * std::mem::size_of::()).unwrap_or(std::mem::size_of::>()) } } @@ -219,7 +219,7 @@ pub struct SealedBlock { /// Ommer/uncle headers pub ommers: Vec
, /// Block withdrawals. - pub withdrawals: Option>, + pub withdrawals: Option, } impl SealedBlock { @@ -316,7 +316,7 @@ impl SealedBlock { // take into account capacity self.body.iter().map(TransactionSigned::size).sum::() + self.body.capacity() * std::mem::size_of::() + self.ommers.iter().map(Header::size).sum::() + self.ommers.capacity() * std::mem::size_of::
() + - self.withdrawals.as_ref().map(|w| w.iter().map(Withdrawal::size).sum::() + w.capacity() * std::mem::size_of::()).unwrap_or(std::mem::size_of::>>()) + self.withdrawals.as_ref().map(|w| w.size() + w.capacity() * std::mem::size_of::()).unwrap_or(std::mem::size_of::>()) } /// Calculates the total gas used by blob transactions in the sealed block. @@ -469,11 +469,9 @@ pub struct BlockBody { /// Withdrawals in the block. #[cfg_attr( any(test, feature = "arbitrary"), - proptest( - strategy = "proptest::option::of(proptest::collection::vec(proptest::arbitrary::any::(), 0..=16))" - ) + proptest(strategy = "proptest::option::of(proptest::arbitrary::any::())") )] - pub withdrawals: Option>, + pub withdrawals: Option, } impl BlockBody { @@ -512,11 +510,8 @@ impl BlockBody { self.ommers.capacity() * std::mem::size_of::
() + self.withdrawals .as_ref() - .map(|w| { - w.iter().map(Withdrawal::size).sum::() + - w.capacity() * std::mem::size_of::() - }) - .unwrap_or(std::mem::size_of::>>()) + .map(|w| w.size() + w.capacity() * std::mem::size_of::()) + .unwrap_or(std::mem::size_of::>()) } } diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index f63f1d7924..72c8080713 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -92,7 +92,7 @@ pub use transaction::{ TxEip4844, TxHashOrNumber, TxLegacy, TxType, TxValue, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID, }; -pub use withdrawal::Withdrawal; +pub use withdrawal::{Withdrawal, Withdrawals}; // Re-exports pub use self::ruint::UintTryTo; diff --git a/crates/primitives/src/transaction/sidecar.rs b/crates/primitives/src/transaction/sidecar.rs index 0a29633653..8ff5426579 100644 --- a/crates/primitives/src/transaction/sidecar.rs +++ b/crates/primitives/src/transaction/sidecar.rs @@ -1,30 +1,27 @@ #![cfg(feature = "c-kzg")] #![cfg_attr(docsrs, doc(cfg(feature = "c-kzg")))] -use crate::{ - keccak256, Signature, Transaction, TransactionSigned, TxEip4844, TxHash, EIP4844_TX_TYPE_ID, -}; - -use crate::kzg::{ - self, Blob, Bytes48, KzgSettings, BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_PROOF, -}; -use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header}; -use bytes::BufMut; - -use serde::{Deserialize, Serialize}; - -#[cfg(any(test, feature = "arbitrary"))] -use proptest::{ - arbitrary::{any as proptest_any, ParamsFor}, - collection::vec as proptest_vec, - strategy::{BoxedStrategy, Strategy}, -}; - #[cfg(any(test, feature = "arbitrary"))] use crate::{ constants::eip4844::{FIELD_ELEMENTS_PER_BLOB, MAINNET_KZG_TRUSTED_SETUP}, kzg::{KzgCommitment, KzgProof, BYTES_PER_FIELD_ELEMENT}, }; +use crate::{ + keccak256, + kzg::{ + self, Blob, Bytes48, KzgSettings, BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_PROOF, + }, + Signature, Transaction, TransactionSigned, TxEip4844, TxHash, EIP4844_TX_TYPE_ID, +}; +use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header}; +use bytes::BufMut; +#[cfg(any(test, feature = "arbitrary"))] +use proptest::{ + arbitrary::{any as proptest_any, ParamsFor}, + collection::vec as proptest_vec, + strategy::{BoxedStrategy, Strategy}, +}; +use serde::{Deserialize, Serialize}; /// An error that can occur when validating a [BlobTransaction]. #[derive(Debug, thiserror::Error)] diff --git a/crates/primitives/src/withdrawal.rs b/crates/primitives/src/withdrawal.rs index c99a51664c..9394954c45 100644 --- a/crates/primitives/src/withdrawal.rs +++ b/crates/primitives/src/withdrawal.rs @@ -1,7 +1,10 @@ use crate::{constants::GWEI_TO_WEI, serde_helper::u64_hex, Address}; -use alloy_rlp::{RlpDecodable, RlpEncodable}; +use alloy_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; use reth_codecs::{main_codec, Compact}; -use std::mem; +use std::{ + mem, + ops::{Deref, DerefMut}, +}; /// Withdrawal represents a validator withdrawal from the consensus layer. #[main_codec] @@ -33,6 +36,57 @@ impl Withdrawal { } } +/// Represents a collection of Withdrawals. +#[main_codec] +#[derive(Debug, Clone, PartialEq, Eq, Default, Hash, RlpEncodableWrapper, RlpDecodableWrapper)] +pub struct Withdrawals(Vec); + +impl Withdrawals { + /// Create a new Withdrawals instance. + pub fn new(withdrawals: Vec) -> Self { + Withdrawals(withdrawals) + } + + /// Calculate a heuristic for the in-memory size of the [Withdrawals]. + #[inline] + pub fn size(&self) -> usize { + self.iter().map(Withdrawal::size).sum() + } + + /// Get an iterator over the Withdrawals. + pub fn iter(&self) -> std::slice::Iter<'_, Withdrawal> { + self.0.iter() + } + + /// Get a mutable iterator over the Withdrawals. + pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Withdrawal> { + self.0.iter_mut() + } +} + +impl IntoIterator for Withdrawals { + type Item = Withdrawal; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl Deref for Withdrawals { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Withdrawals { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/revm/src/processor.rs b/crates/revm/src/processor.rs index ced3206b80..bc958c42cb 100644 --- a/crates/revm/src/processor.rs +++ b/crates/revm/src/processor.rs @@ -213,7 +213,7 @@ where block.timestamp, total_difficulty, &block.ommers, - block.withdrawals.as_deref(), + block.withdrawals.as_ref(), ); // Irregular state change at Ethereum DAO hardfork diff --git a/crates/revm/src/state_change.rs b/crates/revm/src/state_change.rs index 6fe24790f4..c238583108 100644 --- a/crates/revm/src/state_change.rs +++ b/crates/revm/src/state_change.rs @@ -2,7 +2,7 @@ use reth_consensus_common::calc; use reth_interfaces::executor::{BlockExecutionError, BlockValidationError}; use reth_primitives::{ constants::SYSTEM_ADDRESS, revm::env::fill_tx_env_with_beacon_root_contract_call, Address, - ChainSpec, Header, Withdrawal, B256, U256, + ChainSpec, Header, Withdrawals, B256, U256, }; use revm::{Database, DatabaseCommit, EVM}; use std::collections::HashMap; @@ -21,7 +21,7 @@ pub fn post_block_balance_increments( block_timestamp: u64, total_difficulty: U256, ommers: &[Header], - withdrawals: Option<&[Withdrawal]>, + withdrawals: Option<&Withdrawals>, ) -> HashMap { let mut balance_increments = HashMap::new(); @@ -124,7 +124,7 @@ where pub fn post_block_withdrawals_balance_increments( chain_spec: &ChainSpec, block_timestamp: u64, - withdrawals: &[Withdrawal], + withdrawals: &Withdrawals, ) -> HashMap { let mut balance_increments = HashMap::with_capacity(withdrawals.len()); insert_post_block_withdrawals_balance_increments( @@ -144,13 +144,13 @@ pub fn post_block_withdrawals_balance_increments( pub fn insert_post_block_withdrawals_balance_increments( chain_spec: &ChainSpec, block_timestamp: u64, - withdrawals: Option<&[Withdrawal]>, + withdrawals: Option<&Withdrawals>, balance_increments: &mut HashMap, ) { // Process withdrawals if chain_spec.is_shanghai_active_at_timestamp(block_timestamp) { if let Some(withdrawals) = withdrawals { - for withdrawal in withdrawals { + for withdrawal in withdrawals.iter() { if withdrawal.amount > 0 { *balance_increments.entry(withdrawal.address).or_default() += withdrawal.amount_wei(); diff --git a/crates/rpc/rpc-engine-api/tests/it/payload.rs b/crates/rpc/rpc-engine-api/tests/it/payload.rs index 0b9ec850a4..8853b5c88b 100644 --- a/crates/rpc/rpc-engine-api/tests/it/payload.rs +++ b/crates/rpc/rpc-engine-api/tests/it/payload.rs @@ -7,7 +7,7 @@ use reth_interfaces::test_utils::generators::{ }; use reth_primitives::{ bytes::{Bytes, BytesMut}, - proofs, Block, SealedBlock, TransactionSigned, B256, U256, + proofs, Block, SealedBlock, TransactionSigned, Withdrawals, B256, U256, }; use reth_rpc_types::engine::{ ExecutionPayload, ExecutionPayloadBodyV1, ExecutionPayloadV1, PayloadError, @@ -47,10 +47,9 @@ fn payload_body_roundtrip() { .collect::, _>>(), ); let withdraw = payload_body.withdrawals.map(|withdrawals| { - withdrawals - .into_iter() - .map(convert_standalone_withdraw_to_withdrawal) - .collect::>() + Withdrawals::new( + withdrawals.into_iter().map(convert_standalone_withdraw_to_withdrawal).collect(), + ) }); assert_eq!(block.withdrawals, withdraw); } diff --git a/crates/rpc/rpc-types-compat/src/engine/payload.rs b/crates/rpc/rpc-types-compat/src/engine/payload.rs index a37024d054..61b07fe099 100644 --- a/crates/rpc/rpc-types-compat/src/engine/payload.rs +++ b/crates/rpc/rpc-types-compat/src/engine/payload.rs @@ -4,7 +4,7 @@ use reth_primitives::{ constants::{EMPTY_OMMER_ROOT_HASH, MAXIMUM_EXTRA_DATA_SIZE, MIN_PROTOCOL_BASE_FEE_U256}, proofs::{self}, - Block, Header, SealedBlock, TransactionSigned, UintTryTo, Withdrawal, B256, U256, + Block, Header, SealedBlock, TransactionSigned, UintTryTo, Withdrawal, Withdrawals, B256, U256, }; use reth_rpc_types::engine::{ payload::{ExecutionPayloadBodyV1, ExecutionPayloadFieldV2, ExecutionPayloadInputV2}, @@ -65,8 +65,9 @@ pub fn try_payload_v2_to_block(payload: ExecutionPayloadV2) -> Result = - payload.withdrawals.iter().map(|w| convert_standalone_withdraw_to_withdrawal(*w)).collect(); + let withdrawals = Withdrawals::new( + payload.withdrawals.iter().map(|w| convert_standalone_withdraw_to_withdrawal(*w)).collect(), + ); let withdrawals_root = proofs::calculate_withdrawals_root(&withdrawals); base_sealed_block.withdrawals = Some(withdrawals); base_sealed_block.header.withdrawals_root = Some(withdrawals_root); diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 46f8efc24e..8686b9edc5 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -16,7 +16,8 @@ use jsonrpsee::core::RpcResult; use reth_primitives::{ revm::env::tx_env_with_recovered, revm_primitives::{db::DatabaseCommit, BlockEnv, CfgEnv}, - Address, Block, BlockId, BlockNumberOrTag, Bytes, TransactionSignedEcRecovered, B256, + Address, Block, BlockId, BlockNumberOrTag, Bytes, TransactionSignedEcRecovered, Withdrawals, + B256, }; use reth_provider::{ BlockReaderIdExt, ChainSpecProvider, HeaderProvider, StateProviderBox, TransactionVariant, @@ -606,7 +607,7 @@ where if let Some(mut block) = block { // In RPC withdrawals are always present if block.withdrawals.is_none() { - block.withdrawals = Some(vec![]); + block.withdrawals = Some(Withdrawals::default()); } block.encode(&mut res); } diff --git a/crates/rpc/rpc/src/eth/api/pending_block.rs b/crates/rpc/rpc/src/eth/api/pending_block.rs index 917a205d49..ecef1e5bae 100644 --- a/crates/rpc/rpc/src/eth/api/pending_block.rs +++ b/crates/rpc/rpc/src/eth/api/pending_block.rs @@ -196,7 +196,7 @@ impl PendingBlockEnv { let balance_increments = post_block_withdrawals_balance_increments( &chain_spec, block_env.timestamp.try_into().unwrap_or(u64::MAX), - withdrawals.clone().unwrap_or_default().as_ref(), + &withdrawals.clone().unwrap_or_default(), ); // increment account balances for withdrawals diff --git a/crates/storage/db/src/tables/models/blocks.rs b/crates/storage/db/src/tables/models/blocks.rs index 909024d6a0..905f336b59 100644 --- a/crates/storage/db/src/tables/models/blocks.rs +++ b/crates/storage/db/src/tables/models/blocks.rs @@ -1,7 +1,7 @@ //! Block related models and types. use reth_codecs::{main_codec, Compact}; -use reth_primitives::{Header, TxNumber, Withdrawal, B256}; +use reth_primitives::{Header, TxNumber, Withdrawals, B256}; use std::ops::Range; /// Total number of transactions. @@ -80,7 +80,7 @@ pub struct StoredBlockOmmers { #[derive(Debug, Default, Eq, PartialEq, Clone)] pub struct StoredBlockWithdrawals { /// The block withdrawals. - pub withdrawals: Vec, + pub withdrawals: Withdrawals, } /// Hash of the block header. Value for [`CanonicalHeaders`][crate::tables::CanonicalHeaders] diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 4c5358e2e9..7d3bd9488d 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -18,7 +18,7 @@ use reth_primitives::{ Address, Block, BlockHash, BlockHashOrNumber, BlockNumber, BlockWithSenders, ChainInfo, ChainSpec, Header, PruneCheckpoint, PruneSegment, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, - Withdrawal, B256, U256, + Withdrawal, Withdrawals, B256, U256, }; use revm::primitives::{BlockEnv, CfgEnv}; use std::{ @@ -418,7 +418,7 @@ impl WithdrawalsProvider for ProviderFactory { &self, id: BlockHashOrNumber, timestamp: u64, - ) -> ProviderResult>> { + ) -> ProviderResult> { self.provider()?.withdrawals_by_block(id, timestamp) } diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index eef70b2b83..d5e5b6fc6d 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -41,7 +41,7 @@ use reth_primitives::{ ChainInfo, ChainSpec, GotExpected, Hardfork, Head, Header, PruneCheckpoint, PruneModes, PruneSegment, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, SnapshotSegment, StorageEntry, TransactionMeta, TransactionSigned, TransactionSignedEcRecovered, - TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, B256, U256, + TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256, }; use reth_trie::{prefix_set::PrefixSetMut, updates::TrieUpdates, HashedPostState, StateRoot}; use revm::primitives::{BlockEnv, CfgEnv, SpecId}; @@ -770,7 +770,7 @@ impl DatabaseProvider { // withdrawal can be missing let shanghai_is_active = chain_spec.fork(Hardfork::Shanghai).active_at_timestamp(header.timestamp); - let mut withdrawals = Some(Vec::new()); + let mut withdrawals = Some(Withdrawals::default()); if shanghai_is_active { if let Some((block_number, _)) = block_withdrawals.as_ref() { if *block_number == main_block_number { @@ -1703,7 +1703,7 @@ impl WithdrawalsProvider for DatabaseProvider { &self, id: BlockHashOrNumber, timestamp: u64, - ) -> ProviderResult>> { + ) -> ProviderResult> { if self.chain_spec.is_shanghai_active_at_timestamp(timestamp) { if let Some(number) = self.convert_hash_or_number(id)? { // If we are past shanghai, then all blocks should have a withdrawal list, even if diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index a3696f37fe..b7055d81da 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -19,7 +19,8 @@ use reth_primitives::{ Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag, BlockWithSenders, ChainInfo, ChainSpec, Header, PruneCheckpoint, PruneSegment, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, TransactionMeta, - TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, B256, U256, + TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, + U256, }; use revm::primitives::{BlockEnv, CfgEnv}; use std::{ @@ -429,7 +430,7 @@ where &self, id: BlockHashOrNumber, timestamp: u64, - ) -> ProviderResult>> { + ) -> ProviderResult> { self.database.provider()?.withdrawals_by_block(id, timestamp) } diff --git a/crates/storage/provider/src/providers/snapshot/manager.rs b/crates/storage/provider/src/providers/snapshot/manager.rs index 5ed22ecf28..6bf1b24246 100644 --- a/crates/storage/provider/src/providers/snapshot/manager.rs +++ b/crates/storage/provider/src/providers/snapshot/manager.rs @@ -17,7 +17,7 @@ use reth_primitives::{ snapshot::HighestSnapshots, Address, Block, BlockHash, BlockHashOrNumber, BlockNumber, BlockWithSenders, ChainInfo, Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, SnapshotSegment, TransactionMeta, TransactionSigned, TransactionSignedNoHash, - TxHash, TxNumber, Withdrawal, B256, U256, + TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256, }; use std::{ collections::{hash_map::Entry, BTreeMap, HashMap}, @@ -674,7 +674,7 @@ impl WithdrawalsProvider for SnapshotProvider { &self, _id: BlockHashOrNumber, _timestamp: u64, - ) -> ProviderResult>> { + ) -> ProviderResult> { // Required data not present in snapshots Err(ProviderError::UnsupportedProvider) } diff --git a/crates/storage/provider/src/test_utils/blocks.rs b/crates/storage/provider/src/test_utils/blocks.rs index 10d170421c..7d54c80ff0 100644 --- a/crates/storage/provider/src/test_utils/blocks.rs +++ b/crates/storage/provider/src/test_utils/blocks.rs @@ -8,7 +8,7 @@ use reth_primitives::{ proofs::{state_root_unhashed, storage_root_unhashed}, revm::compat::into_reth_acc, Address, BlockNumber, Bytes, Header, Log, Receipt, Receipts, SealedBlock, - SealedBlockWithSenders, TxType, Withdrawal, B256, U256, + SealedBlockWithSenders, TxType, Withdrawal, Withdrawals, B256, U256, }; use revm::{ db::BundleState, @@ -89,7 +89,7 @@ pub fn genesis() -> SealedBlock { .seal(B256::ZERO), body: vec![], ommers: vec![], - withdrawals: Some(vec![]), + withdrawals: Some(Withdrawals::default()), } } @@ -152,7 +152,7 @@ fn block1(number: BlockNumber) -> (SealedBlockWithSenders, BundleStateWithReceip ); let mut block = SealedBlock::decode(&mut BLOCK_RLP.as_slice()).unwrap(); - block.withdrawals = Some(vec![Withdrawal::default()]); + block.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); let mut header = block.header.clone().unseal(); header.number = number; header.state_root = state_root; @@ -212,7 +212,7 @@ fn block2( ); let mut block = SealedBlock::decode(&mut BLOCK_RLP.as_slice()).unwrap(); - block.withdrawals = Some(vec![Withdrawal::default()]); + block.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); let mut header = block.header.clone().unseal(); header.number = number; header.state_root = state_root; diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 3f4a4b20ae..1b68e32e0c 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -14,7 +14,8 @@ use reth_primitives::{ keccak256, trie::AccountProof, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, BlockWithSenders, Bytecode, Bytes, ChainInfo, ChainSpec, Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, StorageKey, StorageValue, TransactionMeta, - TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, B256, U256, + TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, + U256, }; use reth_trie::updates::TrieUpdates; use revm::primitives::{BlockEnv, CfgEnv}; @@ -689,14 +690,14 @@ impl StateProviderFactory for Arc { } impl WithdrawalsProvider for MockEthProvider { - fn latest_withdrawal(&self) -> ProviderResult> { + fn latest_withdrawal(&self) -> ProviderResult> { Ok(None) } fn withdrawals_by_block( &self, _id: BlockHashOrNumber, _timestamp: u64, - ) -> ProviderResult>> { + ) -> ProviderResult> { Ok(None) } } diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index cdd3e93b96..dfb0391fda 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -16,7 +16,8 @@ use reth_primitives::{ Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, Bytecode, ChainInfo, ChainSpec, Header, PruneCheckpoint, PruneSegment, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, StorageKey, StorageValue, TransactionMeta, - TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, B256, MAINNET, U256, + TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, + MAINNET, U256, }; use reth_trie::updates::TrieUpdates; use revm::primitives::{BlockEnv, CfgEnv}; @@ -426,14 +427,14 @@ impl StageCheckpointReader for NoopProvider { } impl WithdrawalsProvider for NoopProvider { - fn latest_withdrawal(&self) -> ProviderResult> { + fn latest_withdrawal(&self) -> ProviderResult> { Ok(None) } fn withdrawals_by_block( &self, _id: BlockHashOrNumber, _timestamp: u64, - ) -> ProviderResult>> { + ) -> ProviderResult> { Ok(None) } } diff --git a/crates/storage/provider/src/traits/withdrawals.rs b/crates/storage/provider/src/traits/withdrawals.rs index 419c1453d2..a54dc7db81 100644 --- a/crates/storage/provider/src/traits/withdrawals.rs +++ b/crates/storage/provider/src/traits/withdrawals.rs @@ -1,5 +1,5 @@ use reth_interfaces::provider::ProviderResult; -use reth_primitives::{BlockHashOrNumber, Withdrawal}; +use reth_primitives::{BlockHashOrNumber, Withdrawal, Withdrawals}; /// Client trait for fetching [Withdrawal] related data. #[auto_impl::auto_impl(&, Arc)] @@ -9,7 +9,7 @@ pub trait WithdrawalsProvider: Send + Sync { &self, id: BlockHashOrNumber, timestamp: u64, - ) -> ProviderResult>>; + ) -> ProviderResult>; /// Get latest withdrawal from this block or earlier . fn latest_withdrawal(&self) -> ProviderResult>; diff --git a/testing/ef-tests/src/models.rs b/testing/ef-tests/src/models.rs index 049facbe44..e213bdb5b3 100644 --- a/testing/ef-tests/src/models.rs +++ b/testing/ef-tests/src/models.rs @@ -8,8 +8,8 @@ use reth_db::{ }; use reth_primitives::{ keccak256, Account as RethAccount, Address, Bloom, Bytecode, Bytes, ChainSpec, - ChainSpecBuilder, Header as RethHeader, JsonU256, SealedHeader, StorageEntry, Withdrawal, B256, - B64, U256, + ChainSpecBuilder, Header as RethHeader, JsonU256, SealedHeader, StorageEntry, Withdrawals, + B256, B64, U256, }; use serde::{self, Deserialize}; use std::{collections::BTreeMap, ops::Deref}; @@ -131,7 +131,7 @@ pub struct Block { /// Transaction Sequence pub transaction_sequence: Option>, /// Withdrawals - pub withdrawals: Option>, + pub withdrawals: Option, } /// Transaction sequence in block