From dbc8766c83493a47afde0057d781592a8aca6282 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 12 Dec 2024 13:57:49 +0100 Subject: [PATCH 1/7] docs: inline mermaid diagrams while aquamarine is fixed (#13302) --- crates/net/network/src/manager.rs | 26 ++++++++++++++- crates/transaction-pool/src/pool/txpool.rs | 38 +++++++++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/crates/net/network/src/manager.rs b/crates/net/network/src/manager.rs index fed3f54408b6..54018676d102 100644 --- a/crates/net/network/src/manager.rs +++ b/crates/net/network/src/manager.rs @@ -70,13 +70,37 @@ use tokio_stream::wrappers::UnboundedReceiverStream; use tracing::{debug, error, trace, warn}; #[cfg_attr(doc, aquamarine::aquamarine)] +// TODO: Inlined diagram due to a bug in aquamarine library, should become an include when it's +// fixed. See https://github.com/mersinvald/aquamarine/issues/50 +// include_mmd!("docs/mermaid/network-manager.mmd") /// Manages the _entire_ state of the network. /// /// This is an endless [`Future`] that consistently drives the state of the entire network forward. /// /// The [`NetworkManager`] is the container type for all parts involved with advancing the network. /// -/// include_mmd!("docs/mermaid/network-manager.mmd") +/// ```mermaid +/// graph TB +/// handle(NetworkHandle) +/// events(NetworkEvents) +/// transactions(Transactions Task) +/// ethrequest(ETH Request Task) +/// discovery(Discovery Task) +/// subgraph NetworkManager +/// direction LR +/// subgraph Swarm +/// direction TB +/// B1[(Session Manager)] +/// B2[(Connection Lister)] +/// B3[(Network State)] +/// end +/// end +/// handle <--> |request response channel| NetworkManager +/// NetworkManager --> |Network events| events +/// transactions <--> |transactions| NetworkManager +/// ethrequest <--> |ETH request handing| NetworkManager +/// discovery --> |Discovered peers| NetworkManager +/// ``` #[derive(Debug)] #[must_use = "The NetworkManager does nothing unless polled"] pub struct NetworkManager { diff --git a/crates/transaction-pool/src/pool/txpool.rs b/crates/transaction-pool/src/pool/txpool.rs index dd6da1d0fef4..a0a1f6a369fe 100644 --- a/crates/transaction-pool/src/pool/txpool.rs +++ b/crates/transaction-pool/src/pool/txpool.rs @@ -39,11 +39,47 @@ use std::{ use tracing::trace; #[cfg_attr(doc, aquamarine::aquamarine)] +// TODO: Inlined diagram due to a bug in aquamarine library, should become an include when it's +// fixed. See https://github.com/mersinvald/aquamarine/issues/50 +// include_mmd!("docs/mermaid/txpool.mmd") /// A pool that manages transactions. /// /// This pool maintains the state of all transactions and stores them accordingly. /// -/// `include_mmd!("docs/mermaid/txpool.mmd`") +/// ```mermaid +/// graph TB +/// subgraph TxPool +/// direction TB +/// pool[(All Transactions)] +/// subgraph Subpools +/// direction TB +/// B3[(Queued)] +/// B1[(Pending)] +/// B2[(Basefee)] +/// B4[(Blob)] +/// end +/// end +/// discard([discard]) +/// production([Block Production]) +/// new([New Block]) +/// A[Incoming Tx] --> B[Validation] -->|ins +/// pool --> |if ready + blobfee too low| B4 +/// pool --> |if ready| B1 +/// pool --> |if ready + basfee too low| B2 +/// pool --> |nonce gap or lack of funds| B3 +/// pool --> |update| pool +/// B1 --> |best| production +/// B2 --> |worst| discard +/// B3 --> |worst| discard +/// B4 --> |worst| discard +/// B1 --> |increased blob fee| B4 +/// B4 --> |decreased blob fee| B1 +/// B1 --> |increased base fee| B2 +/// B2 --> |decreased base fee| B1 +/// B3 --> |promote| B1 +/// B3 --> |promote| B2 +/// new --> |apply state changes| pool +/// ``` pub struct TxPool { /// Contains the currently known information about the senders. sender_info: FxHashMap, From b94a31f6d8c36be03a905cbfd3ba9bc201c2703f Mon Sep 17 00:00:00 2001 From: Federico Gimenez Date: Thu, 12 Dec 2024 14:24:47 +0100 Subject: [PATCH 2/7] feat(trie): replace TrieInput by its components in ParallelProof (#13346) --- crates/trie/parallel/src/proof.rs | 51 ++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/crates/trie/parallel/src/proof.rs b/crates/trie/parallel/src/proof.rs index 6dd4a9a0138a..cabd9c7e0669 100644 --- a/crates/trie/parallel/src/proof.rs +++ b/crates/trie/parallel/src/proof.rs @@ -17,9 +17,10 @@ use reth_trie::{ prefix_set::{PrefixSetMut, TriePrefixSetsMut}, proof::StorageProof, trie_cursor::{InMemoryTrieCursorFactory, TrieCursorFactory}, + updates::TrieUpdatesSorted, walker::TrieWalker, - HashBuilder, MultiProof, MultiProofTargets, Nibbles, StorageMultiProof, TrieAccount, TrieInput, - TRIE_ACCOUNT_RLP_MAX_SIZE, + HashBuilder, HashedPostStateSorted, MultiProof, MultiProofTargets, Nibbles, StorageMultiProof, + TrieAccount, TRIE_ACCOUNT_RLP_MAX_SIZE, }; use reth_trie_common::proof::ProofRetainer; use reth_trie_db::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory}; @@ -34,8 +35,15 @@ use crate::metrics::ParallelStateRootMetrics; pub struct ParallelProof { /// Consistent view of the database. view: ConsistentDbView, - /// Trie input. - input: Arc, + /// The sorted collection of cached in-memory intermediate trie nodes that + /// can be reused for computation. + pub nodes_sorted: Arc, + /// The sorted in-memory overlay hashed state. + pub state_sorted: Arc, + /// The collection of prefix sets for the computation. Since the prefix sets _always_ + /// invalidate the in-memory nodes, not all keys from `state_sorted` might be present here, + /// if we have cached nodes for them. + pub prefix_sets: Arc, /// Flag indicating whether to include branch node hash masks in the proof. collect_branch_node_hash_masks: bool, /// Parallel state root metrics. @@ -45,10 +53,17 @@ pub struct ParallelProof { impl ParallelProof { /// Create new state proof generator. - pub fn new(view: ConsistentDbView, input: Arc) -> Self { + pub fn new( + view: ConsistentDbView, + nodes_sorted: Arc, + state_sorted: Arc, + prefix_sets: Arc, + ) -> Self { Self { view, - input, + nodes_sorted, + state_sorted, + prefix_sets, collect_branch_node_hash_masks: false, #[cfg(feature = "metrics")] metrics: ParallelStateRootMetrics::default(), @@ -78,11 +93,8 @@ where ) -> Result { let mut tracker = ParallelTrieTracker::default(); - let trie_nodes_sorted = self.input.nodes.clone().into_sorted(); - let hashed_state_sorted = self.input.state.clone().into_sorted(); - // Extend prefix sets with targets - let mut prefix_sets = self.input.prefix_sets.clone(); + let mut prefix_sets = (*self.prefix_sets).clone(); prefix_sets.extend(TriePrefixSetsMut { account_prefix_set: PrefixSetMut::from(targets.keys().copied().map(Nibbles::unpack)), storage_prefix_sets: targets @@ -112,8 +124,8 @@ where let view = self.view.clone(); let target_slots = targets.get(&hashed_address).cloned().unwrap_or_default(); - let trie_nodes_sorted = trie_nodes_sorted.clone(); - let hashed_state_sorted = hashed_state_sorted.clone(); + let trie_nodes_sorted = self.nodes_sorted.clone(); + let hashed_state_sorted = self.state_sorted.clone(); let (tx, rx) = std::sync::mpsc::sync_channel(1); @@ -149,11 +161,11 @@ where let provider_ro = self.view.provider_ro()?; let trie_cursor_factory = InMemoryTrieCursorFactory::new( DatabaseTrieCursorFactory::new(provider_ro.tx_ref()), - &trie_nodes_sorted, + &self.nodes_sorted, ); let hashed_cursor_factory = HashedPostStateCursorFactory::new( DatabaseHashedCursorFactory::new(provider_ro.tx_ref()), - &hashed_state_sorted, + &self.state_sorted, ); // Create the walker. @@ -327,9 +339,14 @@ mod tests { let hashed_cursor_factory = DatabaseHashedCursorFactory::new(provider_rw.tx_ref()); assert_eq!( - ParallelProof::new(consistent_view, Default::default()) - .multiproof(targets.clone()) - .unwrap(), + ParallelProof::new( + consistent_view, + Default::default(), + Default::default(), + Default::default() + ) + .multiproof(targets.clone()) + .unwrap(), Proof::new(trie_cursor_factory, hashed_cursor_factory).multiproof(targets).unwrap() ); } From f7dc27f0269bd4c4dfa5b69c84f9b20a1c667251 Mon Sep 17 00:00:00 2001 From: Ayodeji Akinola Date: Thu, 12 Dec 2024 14:27:59 +0100 Subject: [PATCH 3/7] chore: update gas limit on new head block (#13333) --- crates/transaction-pool/src/validate/eth.rs | 28 ++++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/crates/transaction-pool/src/validate/eth.rs b/crates/transaction-pool/src/validate/eth.rs index 1092a2702f7e..3c93b384c734 100644 --- a/crates/transaction-pool/src/validate/eth.rs +++ b/crates/transaction-pool/src/validate/eth.rs @@ -29,7 +29,10 @@ use reth_storage_api::{AccountReader, StateProviderFactory}; use reth_tasks::TaskSpawner; use std::{ marker::PhantomData, - sync::{atomic::AtomicBool, Arc}, + sync::{ + atomic::{AtomicBool, AtomicU64}, + Arc, + }, }; use tokio::sync::Mutex; @@ -141,7 +144,7 @@ pub(crate) struct EthTransactionValidatorInner { /// Fork indicator whether we are using EIP-7702 type transactions. eip7702: bool, /// The current max gas limit - block_gas_limit: u64, + block_gas_limit: AtomicU64, /// Minimum priority fee to enforce for acceptance into the pool. minimum_priority_fee: Option, /// Stores the setup and parameters needed for validating KZG proofs. @@ -245,12 +248,13 @@ where // Checks for gas limit let transaction_gas_limit = transaction.gas_limit(); - if transaction_gas_limit > self.block_gas_limit { + let block_gas_limit = self.max_gas_limit(); + if transaction_gas_limit > block_gas_limit { return TransactionValidationOutcome::Invalid( transaction, InvalidPoolTransactionError::ExceedsGasLimit( transaction_gas_limit, - self.block_gas_limit, + block_gas_limit, ), ) } @@ -484,11 +488,17 @@ where if self.chain_spec.is_prague_active_at_timestamp(new_tip_block.timestamp()) { self.fork_tracker.prague.store(true, std::sync::atomic::Ordering::Relaxed); } + + self.block_gas_limit.store(new_tip_block.gas_limit(), std::sync::atomic::Ordering::Relaxed); + } + + fn max_gas_limit(&self) -> u64 { + self.block_gas_limit.load(std::sync::atomic::Ordering::Relaxed) } } /// A builder for [`TransactionValidationTaskExecutor`] -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct EthTransactionValidatorBuilder { chain_spec: Arc, /// Fork indicator whether we are in the Shanghai stage. @@ -506,7 +516,7 @@ pub struct EthTransactionValidatorBuilder { /// Whether using EIP-7702 type transactions is allowed eip7702: bool, /// The current max gas limit - block_gas_limit: u64, + block_gas_limit: AtomicU64, /// Minimum priority fee to enforce for acceptance into the pool. minimum_priority_fee: Option, /// Determines how many additional tasks to spawn @@ -533,7 +543,7 @@ impl EthTransactionValidatorBuilder { /// - EIP-4844 pub fn new(chain_spec: Arc) -> Self { Self { - block_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT, + block_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT.into(), chain_spec, minimum_priority_fee: None, additional_tasks: 1, @@ -670,8 +680,8 @@ impl EthTransactionValidatorBuilder { /// Sets the block gas limit /// /// Transactions with a gas limit greater than this will be rejected. - pub const fn set_block_gas_limit(mut self, block_gas_limit: u64) -> Self { - self.block_gas_limit = block_gas_limit; + pub fn set_block_gas_limit(self, block_gas_limit: u64) -> Self { + self.block_gas_limit.store(block_gas_limit, std::sync::atomic::Ordering::Relaxed); self } From cdb03ac0b1888fd4b6e9ce12b5c52168bece03ae Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 12 Dec 2024 17:43:35 +0400 Subject: [PATCH 4/7] feat: optimism-specific receipt (#13317) Co-authored-by: Emilia Hane --- Cargo.lock | 30 +- Cargo.toml | 10 +- crates/optimism/primitives/Cargo.toml | 11 +- crates/optimism/primitives/src/lib.rs | 3 + crates/optimism/primitives/src/receipt.rs | 299 ++++++++++++++++++ .../primitives/src/transaction/signed.rs | 2 +- crates/primitives-traits/src/size.rs | 20 ++ crates/primitives/src/receipt.rs | 1 - .../codecs/derive/src/compact/flags.rs | 4 +- .../codecs/derive/src/compact/generator.rs | 16 +- .../storage/codecs/derive/src/compact/mod.rs | 24 +- .../codecs/derive/src/compact/structs.rs | 5 +- crates/storage/codecs/src/lib.rs | 31 +- 13 files changed, 414 insertions(+), 42 deletions(-) create mode 100644 crates/optimism/primitives/src/receipt.rs diff --git a/Cargo.lock b/Cargo.lock index 6c11466404f9..5550c83d24fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5411,9 +5411,9 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "op-alloy-consensus" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d95d0ec6457ad4d3d7fc0ad41db490b219587ed837ada87a26b28e535db15f" +checksum = "e5085cc8be65a2da9c04e9a904eccfe38eb69ecc3bc6c6485ce0f1af879f3abe" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5429,9 +5429,9 @@ dependencies = [ [[package]] name = "op-alloy-genesis" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8692a934265dd0fc68f02e2a1d644a80b76ae07dbc59552aa51d6df06953e9d" +checksum = "64f5aa1201d83af3b0ebffbfc28fdc7e772d7e44f4dea9e41c51162f84412edf" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5444,9 +5444,9 @@ dependencies = [ [[package]] name = "op-alloy-network" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f973f9e396dc53138ef89501875991bb1728ec34bbd9c0e1ab30caa5518abfa3" +checksum = "9d12eafaad5b89792de75f1344d42634dd5271945fd36256e4e5d766cf32107e" dependencies = [ "alloy-consensus", "alloy-network", @@ -5459,9 +5459,9 @@ dependencies = [ [[package]] name = "op-alloy-protocol" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29cb147e6f39d34bd8284b1107bcbca2e4c14e95b5bc49e5498ca6c0068a94c2" +checksum = "2cf8c05e1b7ed20c4af6f72a54cc389225d2c6af6fcf932ef6481cfdfcb540ac" dependencies = [ "alloc-no-stdlib", "alloy-consensus", @@ -5483,9 +5483,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-jsonrpsee" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7e394ccd907c63acc8213c24ebfb1be24f184b75af89cbaa92178b11de34a8" +checksum = "3b6edd6fb56f23ab45c704ad0c598641086e07b3a55d74890acaa01226ffc3e2" dependencies = [ "alloy-eips", "alloy-primitives", @@ -5496,9 +5496,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba1b44e2035ec04cc61762cb9b5457d0ecd29d9af631e1a1c107ef571ce2318" +checksum = "b44194f44faef3db1edd17fc8e0b1309d377c6c7a4ba74a02d78c13d5f2ed90d" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5515,9 +5515,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types-engine" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bcf8a51980231bbcd250a686c9ef41501c9e7aaa348ffe5808aa61dfe14151" +checksum = "c005d0a4431fbd9cd16eb0c2f67306de4245f76f311fa1628a68b79e7ea5aa0e" dependencies = [ "alloy-eips", "alloy-primitives", @@ -8583,6 +8583,7 @@ dependencies = [ "arbitrary", "bytes", "derive_more", + "modular-bitfield", "op-alloy-consensus", "proptest", "proptest-arbitrary-interop", @@ -8590,6 +8591,7 @@ dependencies = [ "reth-codecs", "reth-primitives", "reth-primitives-traits", + "reth-zstd-compressors", "revm-primitives", "rstest", "secp256k1", diff --git a/Cargo.toml b/Cargo.toml index 3d652c5908eb..80233cdb4397 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -477,11 +477,11 @@ alloy-transport-ipc = { version = "0.8.0", default-features = false } alloy-transport-ws = { version = "0.8.0", default-features = false } # op -op-alloy-rpc-types = "0.8.0" -op-alloy-rpc-types-engine = "0.8.0" -op-alloy-rpc-jsonrpsee = "0.8.0" -op-alloy-network = "0.8.0" -op-alloy-consensus = "0.8.0" +op-alloy-rpc-types = "0.8.1" +op-alloy-rpc-types-engine = "0.8.1" +op-alloy-rpc-jsonrpsee = "0.8.1" +op-alloy-network = "0.8.1" +op-alloy-consensus = "0.8.1" # misc aquamarine = "0.6" diff --git a/crates/optimism/primitives/Cargo.toml b/crates/optimism/primitives/Cargo.toml index ed8e9686fa7d..c3bd68deffe6 100644 --- a/crates/optimism/primitives/Cargo.toml +++ b/crates/optimism/primitives/Cargo.toml @@ -16,6 +16,7 @@ workspace = true reth-primitives.workspace = true reth-primitives-traits = { workspace = true, features = ["op"] } reth-codecs = { workspace = true, optional = true, features = ["op"] } +reth-zstd-compressors = { workspace = true, optional = true } # ethereum alloy-primitives.workspace = true @@ -30,6 +31,7 @@ op-alloy-consensus.workspace = true # codec bytes = { workspace = true, optional = true } +modular-bitfield = { workspace = true, optional = true } serde = { workspace = true, optional = true } # misc @@ -59,9 +61,10 @@ std = [ "serde?/std", "bytes?/std", "derive_more/std", - "revm-primitives/std", - "secp256k1?/std", - "alloy-rlp/std", + "revm-primitives/std", + "secp256k1?/std", + "alloy-rlp/std", + "reth-zstd-compressors?/std" ] reth-codec = [ "dep:reth-codecs", @@ -74,6 +77,8 @@ reth-codec = [ "reth-codecs?/op", "reth-primitives/reth-codec", "dep:bytes", + "dep:modular-bitfield", + "dep:reth-zstd-compressors" ] serde = [ "dep:serde", diff --git a/crates/optimism/primitives/src/lib.rs b/crates/optimism/primitives/src/lib.rs index b1f029d20bc2..2eedf2453f2a 100644 --- a/crates/optimism/primitives/src/lib.rs +++ b/crates/optimism/primitives/src/lib.rs @@ -18,6 +18,9 @@ pub mod transaction; pub use transaction::{signed::OpTransactionSigned, tx_type::OpTxType, OpTransaction}; +mod receipt; +pub use receipt::OpReceipt; + /// Optimism primitive types. pub type OpPrimitives = reth_primitives::EthPrimitives; diff --git a/crates/optimism/primitives/src/receipt.rs b/crates/optimism/primitives/src/receipt.rs new file mode 100644 index 000000000000..1c9ca442497c --- /dev/null +++ b/crates/optimism/primitives/src/receipt.rs @@ -0,0 +1,299 @@ +use alloy_consensus::{ + Eip2718EncodableReceipt, Eip658Value, Receipt, ReceiptWithBloom, RlpDecodableReceipt, + RlpEncodableReceipt, TxReceipt, Typed2718, +}; +use alloy_primitives::{Bloom, Log}; +use alloy_rlp::{BufMut, Decodable, Header}; +use op_alloy_consensus::{OpDepositReceipt, OpTxType}; +use reth_primitives_traits::InMemorySize; + +/// Typed ethereum transaction receipt. +/// Receipt containing result of transaction execution. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +pub enum OpReceipt { + /// Legacy receipt + Legacy(Receipt), + /// EIP-2930 receipt + Eip2930(Receipt), + /// EIP-1559 receipt + Eip1559(Receipt), + /// EIP-7702 receipt + Eip7702(Receipt), + /// Deposit receipt + Deposit(OpDepositReceipt), +} + +impl OpReceipt { + /// Returns [`OpTxType`] of the receipt. + pub const fn tx_type(&self) -> OpTxType { + match self { + Self::Legacy(_) => OpTxType::Legacy, + Self::Eip2930(_) => OpTxType::Eip2930, + Self::Eip1559(_) => OpTxType::Eip1559, + Self::Eip7702(_) => OpTxType::Eip7702, + Self::Deposit(_) => OpTxType::Deposit, + } + } + + /// Returns inner [`Receipt`], + pub const fn as_receipt(&self) -> &Receipt { + match self { + Self::Legacy(receipt) | + Self::Eip2930(receipt) | + Self::Eip1559(receipt) | + Self::Eip7702(receipt) => receipt, + Self::Deposit(receipt) => &receipt.inner, + } + } + + /// Returns length of RLP-encoded receipt fields with the given [`Bloom`] without an RLP header. + pub fn rlp_encoded_fields_length(&self, bloom: &Bloom) -> usize { + match self { + Self::Legacy(receipt) | + Self::Eip2930(receipt) | + Self::Eip1559(receipt) | + Self::Eip7702(receipt) => receipt.rlp_encoded_fields_length_with_bloom(bloom), + Self::Deposit(receipt) => receipt.rlp_encoded_fields_length_with_bloom(bloom), + } + } + + /// RLP-encodes receipt fields with the given [`Bloom`] without an RLP header. + pub fn rlp_encode_fields(&self, bloom: &Bloom, out: &mut dyn BufMut) { + match self { + Self::Legacy(receipt) | + Self::Eip2930(receipt) | + Self::Eip1559(receipt) | + Self::Eip7702(receipt) => receipt.rlp_encode_fields_with_bloom(bloom, out), + Self::Deposit(receipt) => receipt.rlp_encode_fields_with_bloom(bloom, out), + } + } + + /// Returns RLP header for inner encoding. + pub fn rlp_header_inner(&self, bloom: &Bloom) -> Header { + Header { list: true, payload_length: self.rlp_encoded_fields_length(bloom) } + } + + /// RLP-decodes the receipt from the provided buffer. This does not expect a type byte or + /// network header. + pub fn rlp_decode_inner( + buf: &mut &[u8], + tx_type: OpTxType, + ) -> alloy_rlp::Result> { + match tx_type { + OpTxType::Legacy => { + let ReceiptWithBloom { receipt, logs_bloom } = + RlpDecodableReceipt::rlp_decode_with_bloom(buf)?; + Ok(ReceiptWithBloom { receipt: Self::Legacy(receipt), logs_bloom }) + } + OpTxType::Eip2930 => { + let ReceiptWithBloom { receipt, logs_bloom } = + RlpDecodableReceipt::rlp_decode_with_bloom(buf)?; + Ok(ReceiptWithBloom { receipt: Self::Eip2930(receipt), logs_bloom }) + } + OpTxType::Eip1559 => { + let ReceiptWithBloom { receipt, logs_bloom } = + RlpDecodableReceipt::rlp_decode_with_bloom(buf)?; + Ok(ReceiptWithBloom { receipt: Self::Eip1559(receipt), logs_bloom }) + } + OpTxType::Eip7702 => { + let ReceiptWithBloom { receipt, logs_bloom } = + RlpDecodableReceipt::rlp_decode_with_bloom(buf)?; + Ok(ReceiptWithBloom { receipt: Self::Eip7702(receipt), logs_bloom }) + } + OpTxType::Deposit => { + let ReceiptWithBloom { receipt, logs_bloom } = + RlpDecodableReceipt::rlp_decode_with_bloom(buf)?; + Ok(ReceiptWithBloom { receipt: Self::Deposit(receipt), logs_bloom }) + } + } + } +} + +impl Eip2718EncodableReceipt for OpReceipt { + fn eip2718_encoded_length_with_bloom(&self, bloom: &Bloom) -> usize { + !self.tx_type().is_legacy() as usize + self.rlp_header_inner(bloom).length_with_payload() + } + + fn eip2718_encode_with_bloom(&self, bloom: &Bloom, out: &mut dyn BufMut) { + if !self.tx_type().is_legacy() { + out.put_u8(self.tx_type() as u8); + } + self.rlp_header_inner(bloom).encode(out); + self.rlp_encode_fields(bloom, out); + } +} + +impl RlpEncodableReceipt for OpReceipt { + fn rlp_encoded_length_with_bloom(&self, bloom: &Bloom) -> usize { + let mut len = self.eip2718_encoded_length_with_bloom(bloom); + if !self.tx_type().is_legacy() { + len += Header { + list: false, + payload_length: self.eip2718_encoded_length_with_bloom(bloom), + } + .length(); + } + + len + } + + fn rlp_encode_with_bloom(&self, bloom: &Bloom, out: &mut dyn BufMut) { + if !self.tx_type().is_legacy() { + Header { list: false, payload_length: self.eip2718_encoded_length_with_bloom(bloom) } + .encode(out); + } + self.eip2718_encode_with_bloom(bloom, out); + } +} + +impl RlpDecodableReceipt for OpReceipt { + fn rlp_decode_with_bloom(buf: &mut &[u8]) -> alloy_rlp::Result> { + let header_buf = &mut &**buf; + let header = Header::decode(header_buf)?; + + // Legacy receipt, reuse initial buffer without advancing + if header.list { + return Self::rlp_decode_inner(buf, OpTxType::Legacy) + } + + // Otherwise, advance the buffer and try decoding type flag followed by receipt + *buf = *header_buf; + + let remaining = buf.len(); + let tx_type = OpTxType::decode(buf)?; + let this = Self::rlp_decode_inner(buf, tx_type)?; + + if buf.len() + header.payload_length != remaining { + return Err(alloy_rlp::Error::UnexpectedLength); + } + + Ok(this) + } +} + +impl TxReceipt for OpReceipt { + type Log = Log; + + fn status_or_post_state(&self) -> Eip658Value { + self.as_receipt().status_or_post_state() + } + + fn status(&self) -> bool { + self.as_receipt().status() + } + + fn bloom(&self) -> Bloom { + self.as_receipt().bloom() + } + + fn cumulative_gas_used(&self) -> u128 { + self.as_receipt().cumulative_gas_used() + } + + fn logs(&self) -> &[Log] { + self.as_receipt().logs() + } +} + +impl Typed2718 for OpReceipt { + fn ty(&self) -> u8 { + self.tx_type().into() + } +} + +impl InMemorySize for OpReceipt { + fn size(&self) -> usize { + self.as_receipt().size() + } +} + +impl reth_primitives_traits::Receipt for OpReceipt {} + +#[cfg(feature = "reth-codec")] +mod compact { + use super::*; + use alloc::borrow::Cow; + use reth_codecs::Compact; + + #[derive(reth_codecs::CompactZstd)] + #[reth_zstd( + compressor = reth_zstd_compressors::RECEIPT_COMPRESSOR, + decompressor = reth_zstd_compressors::RECEIPT_DECOMPRESSOR + )] + struct CompactOpReceipt<'a> { + tx_type: OpTxType, + success: bool, + cumulative_gas_used: u64, + logs: Cow<'a, Vec>, + deposit_nonce: Option, + deposit_receipt_version: Option, + } + + impl<'a> From<&'a OpReceipt> for CompactOpReceipt<'a> { + fn from(receipt: &'a OpReceipt) -> Self { + Self { + tx_type: receipt.tx_type(), + success: receipt.status(), + cumulative_gas_used: receipt.cumulative_gas_used() as u64, + logs: Cow::Borrowed(&receipt.as_receipt().logs), + deposit_nonce: if let OpReceipt::Deposit(receipt) = receipt { + receipt.deposit_nonce + } else { + None + }, + deposit_receipt_version: if let OpReceipt::Deposit(receipt) = receipt { + receipt.deposit_receipt_version + } else { + None + }, + } + } + } + + impl From> for OpReceipt { + fn from(receipt: CompactOpReceipt<'_>) -> Self { + let CompactOpReceipt { + tx_type, + success, + cumulative_gas_used, + logs, + deposit_nonce, + deposit_receipt_version, + } = receipt; + + let inner = Receipt { + status: success.into(), + cumulative_gas_used: cumulative_gas_used as u128, + logs: logs.into_owned(), + }; + + match tx_type { + OpTxType::Legacy => Self::Legacy(inner), + OpTxType::Eip2930 => Self::Eip2930(inner), + OpTxType::Eip1559 => Self::Eip1559(inner), + OpTxType::Eip7702 => Self::Eip7702(inner), + OpTxType::Deposit => Self::Deposit(OpDepositReceipt { + inner, + deposit_nonce, + deposit_receipt_version, + }), + } + } + } + + impl Compact for OpReceipt { + fn to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + CompactOpReceipt::from(self).to_compact(buf) + } + + fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { + let (receipt, buf) = CompactOpReceipt::from_compact(buf, len); + (receipt.into(), buf) + } + } +} diff --git a/crates/optimism/primitives/src/transaction/signed.rs b/crates/optimism/primitives/src/transaction/signed.rs index 5acf9b8a8ca7..796a33cf3614 100644 --- a/crates/optimism/primitives/src/transaction/signed.rs +++ b/crates/optimism/primitives/src/transaction/signed.rs @@ -40,7 +40,7 @@ use std::sync::OnceLock; #[derive(Debug, Clone, Eq, AsRef, Deref)] pub struct OpTransactionSigned { /// Transaction hash - #[serde(skip)] + #[cfg_attr(feature = "serde", serde(skip))] pub hash: OnceLock, /// The transaction signature values pub signature: Signature, diff --git a/crates/primitives-traits/src/size.rs b/crates/primitives-traits/src/size.rs index a1978ff379e0..be19ae81282a 100644 --- a/crates/primitives-traits/src/size.rs +++ b/crates/primitives-traits/src/size.rs @@ -1,5 +1,6 @@ use alloy_consensus::{Header, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxLegacy, TxType}; use alloy_primitives::{PrimitiveSignature as Signature, TxHash}; +use revm_primitives::Log; /// Trait for calculating a heuristic for the in-memory size of a struct. #[auto_impl::auto_impl(&, Arc, Box)] @@ -49,6 +50,25 @@ impl_in_mem_size!(Header, TxLegacy, TxEip2930, TxEip1559, TxEip7702, TxEip4844); #[cfg(feature = "op")] impl_in_mem_size_size_of!(op_alloy_consensus::OpTxType); +impl InMemorySize for alloy_consensus::Receipt { + fn size(&self) -> usize { + let Self { status, cumulative_gas_used, logs } = self; + core::mem::size_of_val(status) + + core::mem::size_of_val(cumulative_gas_used) + + logs.capacity() * core::mem::size_of::() + } +} + +#[cfg(feature = "op")] +impl InMemorySize for op_alloy_consensus::OpDepositReceipt { + fn size(&self) -> usize { + let Self { inner, deposit_nonce, deposit_receipt_version } = self; + inner.size() + + core::mem::size_of_val(deposit_nonce) + + core::mem::size_of_val(deposit_receipt_version) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/primitives/src/receipt.rs b/crates/primitives/src/receipt.rs index b6e7949a3dc8..d4c15fe856aa 100644 --- a/crates/primitives/src/receipt.rs +++ b/crates/primitives/src/receipt.rs @@ -21,7 +21,6 @@ pub use reth_primitives_traits::receipt::gas_spent_by_transactions; Clone, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable, Serialize, Deserialize, )] #[cfg_attr(any(test, feature = "reth-codec"), derive(reth_codecs::CompactZstd))] -#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests)] #[cfg_attr(any(test, feature = "reth-codec"), reth_zstd( compressor = reth_zstd_compressors::RECEIPT_COMPRESSOR, decompressor = reth_zstd_compressors::RECEIPT_DECOMPRESSOR diff --git a/crates/storage/codecs/derive/src/compact/flags.rs b/crates/storage/codecs/derive/src/compact/flags.rs index 798c9ad53b45..622eba60b28b 100644 --- a/crates/storage/codecs/derive/src/compact/flags.rs +++ b/crates/storage/codecs/derive/src/compact/flags.rs @@ -126,7 +126,9 @@ fn build_struct_field_flags( let mut total_bits = 0; // Find out the adequate bit size for the length of each field, if applicable. - for (name, ftype, is_compact, _) in fields { + for field in fields { + let StructFieldDescriptor { name, ftype, is_compact, use_alt_impl: _, is_reference: _ } = + field; // This happens when dealing with a wrapper struct eg. Struct(pub U256). let name = if name.is_empty() { "placeholder" } else { name }; diff --git a/crates/storage/codecs/derive/src/compact/generator.rs b/crates/storage/codecs/derive/src/compact/generator.rs index a84913f59e81..26a1f10127f4 100644 --- a/crates/storage/codecs/derive/src/compact/generator.rs +++ b/crates/storage/codecs/derive/src/compact/generator.rs @@ -41,7 +41,15 @@ pub fn generate_from_to( } }; - let fn_from_compact = if has_lifetime { + let has_ref_fields = fields.iter().any(|field| { + if let FieldTypes::StructField(field) = field { + field.is_reference + } else { + false + } + }); + + let fn_from_compact = if has_ref_fields { quote! { unimplemented!("from_compact not supported with ref structs") } } else { quote! { @@ -100,7 +108,7 @@ fn generate_from_compact( ) -> TokenStream2 { let mut lines = vec![]; let mut known_types = - vec!["B256", "Address", "Bloom", "Vec", "TxHash", "BlockHash", "FixedBytes"]; + vec!["B256", "Address", "Bloom", "Vec", "TxHash", "BlockHash", "FixedBytes", "Cow"]; // Only types without `Bytes` should be added here. It's currently manually added, since // it's hard to figure out with derive_macro which types have Bytes fields. @@ -132,8 +140,8 @@ fn generate_from_compact( }); } else { let fields = fields.iter().filter_map(|field| { - if let FieldTypes::StructField((name, _, _, _)) = field { - let ident = format_ident!("{name}"); + if let FieldTypes::StructField(field) = field { + let ident = format_ident!("{}", field.name); return Some(quote! { #ident: #ident, }) diff --git a/crates/storage/codecs/derive/src/compact/mod.rs b/crates/storage/codecs/derive/src/compact/mod.rs index ab9ed78e164e..e7906bbdb506 100644 --- a/crates/storage/codecs/derive/src/compact/mod.rs +++ b/crates/storage/codecs/derive/src/compact/mod.rs @@ -17,10 +17,6 @@ use structs::*; use crate::ZstdConfig; -// Helper Alias type -type IsCompact = bool; -// Helper Alias type -type FieldName = String; // Helper Alias type type FieldType = String; /// `Compact` has alternative functions that can be used as a workaround for type @@ -30,7 +26,14 @@ type FieldType = String; /// require the len of the element, while the latter one does. type UseAlternative = bool; // Helper Alias type -type StructFieldDescriptor = (FieldName, FieldType, IsCompact, UseAlternative); +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct StructFieldDescriptor { + name: String, + ftype: String, + is_compact: bool, + use_alt_impl: bool, + is_reference: bool, +} // Helper Alias type type FieldList = Vec; @@ -150,12 +153,13 @@ fn load_field_from_segments( attr.path().segments.iter().any(|path| path.ident == "maybe_zero") }); - fields.push(FieldTypes::StructField(( - field.ident.as_ref().map(|i| i.to_string()).unwrap_or_default(), + fields.push(FieldTypes::StructField(StructFieldDescriptor { + name: field.ident.as_ref().map(|i| i.to_string()).unwrap_or_default(), ftype, - should_compact, + is_compact: should_compact, use_alt_impl, - ))); + is_reference: matches!(field.ty, syn::Type::Reference(_)), + })); } } } @@ -196,7 +200,7 @@ fn should_use_alt_impl(ftype: &str, segment: &syn::PathSegment) -> bool { pub fn get_bit_size(ftype: &str) -> u8 { match ftype { "TransactionKind" | "TxKind" | "bool" | "Option" | "Signature" => 1, - "TxType" => 2, + "TxType" | "OpTxType" => 2, "u64" | "BlockNumber" | "TxNumber" | "ChainId" | "NumTransactions" => 4, "u128" => 5, "U256" => 6, diff --git a/crates/storage/codecs/derive/src/compact/structs.rs b/crates/storage/codecs/derive/src/compact/structs.rs index 07d7a3803ade..f8ebda33499e 100644 --- a/crates/storage/codecs/derive/src/compact/structs.rs +++ b/crates/storage/codecs/derive/src/compact/structs.rs @@ -44,7 +44,8 @@ impl<'a> StructHandler<'a> { /// Generates `to_compact` code for a struct field. fn to(&mut self, field_descriptor: &StructFieldDescriptor) { - let (name, ftype, is_compact, use_alt_impl) = field_descriptor; + let StructFieldDescriptor { name, ftype, is_compact, use_alt_impl, is_reference: _ } = + field_descriptor; let to_compact_ident = if *use_alt_impl { format_ident!("specialized_to_compact") @@ -97,7 +98,7 @@ impl<'a> StructHandler<'a> { /// Generates `from_compact` code for a struct field. fn from(&mut self, field_descriptor: &StructFieldDescriptor, known_types: &[&str]) { - let (name, ftype, is_compact, use_alt_impl) = field_descriptor; + let StructFieldDescriptor { name, ftype, is_compact, use_alt_impl, .. } = field_descriptor; let (name, len) = if name.is_empty() { self.is_wrapper = true; diff --git a/crates/storage/codecs/src/lib.rs b/crates/storage/codecs/src/lib.rs index 8c6ba5e4c766..cf18e548bd5d 100644 --- a/crates/storage/codecs/src/lib.rs +++ b/crates/storage/codecs/src/lib.rs @@ -25,7 +25,10 @@ use serde as _; use alloy_primitives::{Address, Bloom, Bytes, FixedBytes, U256}; use bytes::{Buf, BufMut}; -use alloc::vec::Vec; +use alloc::{ + borrow::{Cow, ToOwned}, + vec::Vec, +}; #[cfg(feature = "test-utils")] pub mod alloy; @@ -343,6 +346,32 @@ where } } +impl> Compact for Cow<'_, T> { + fn to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + self.as_ref().to_compact(buf) + } + + fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { + let (element, buf) = T::from_compact(buf, len); + (Cow::Owned(element), buf) + } + + fn specialized_to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + self.as_ref().specialized_to_compact(buf) + } + + fn specialized_from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { + let (element, buf) = T::specialized_from_compact(buf, len); + (Cow::Owned(element), buf) + } +} + impl Compact for U256 { #[inline] fn to_compact(&self, buf: &mut B) -> usize From 59fb0e210de020581d0990a9cc955432f81ea481 Mon Sep 17 00:00:00 2001 From: joshieDo <93316087+joshieDo@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:49:44 +0000 Subject: [PATCH 5/7] chore: add `BlockBodyIndicesProvider` trait (#13347) --- crates/stages/stages/src/stages/mod.rs | 5 +- .../stages/src/stages/sender_recovery.rs | 4 +- crates/stages/stages/src/stages/tx_lookup.rs | 3 +- .../src/providers/blockchain_provider.rs | 28 +++---- .../provider/src/providers/consistent.rs | 74 ++++++++++--------- .../provider/src/providers/database/mod.rs | 19 +++-- .../src/providers/database/provider.rs | 16 ++-- crates/storage/provider/src/providers/mod.rs | 18 +++-- .../src/providers/static_file/manager.rs | 14 ++-- .../storage/provider/src/test_utils/mock.rs | 14 ++-- crates/storage/storage-api/src/block.rs | 17 +---- .../storage/storage-api/src/block_indices.rs | 11 +++ crates/storage/storage-api/src/lib.rs | 3 + crates/storage/storage-api/src/noop.rs | 22 +++--- 14 files changed, 136 insertions(+), 112 deletions(-) create mode 100644 crates/storage/storage-api/src/block_indices.rs diff --git a/crates/stages/stages/src/stages/mod.rs b/crates/stages/stages/src/stages/mod.rs index 9d7cc685a7ef..955d0d01e5e3 100644 --- a/crates/stages/stages/src/stages/mod.rs +++ b/crates/stages/stages/src/stages/mod.rs @@ -60,8 +60,9 @@ mod tests { use reth_provider::{ providers::{StaticFileProvider, StaticFileWriter}, test_utils::MockNodeTypesWithDB, - AccountExtReader, BlockReader, DatabaseProviderFactory, ProviderFactory, ProviderResult, - ReceiptProvider, StageCheckpointWriter, StaticFileProviderFactory, StorageReader, + AccountExtReader, BlockBodyIndicesProvider, DatabaseProviderFactory, ProviderFactory, + ProviderResult, ReceiptProvider, StageCheckpointWriter, StaticFileProviderFactory, + StorageReader, }; use reth_prune_types::{PruneMode, PruneModes}; use reth_stages_api::{ diff --git a/crates/stages/stages/src/stages/sender_recovery.rs b/crates/stages/stages/src/stages/sender_recovery.rs index 2dcce61b90d0..833246b1b020 100644 --- a/crates/stages/stages/src/stages/sender_recovery.rs +++ b/crates/stages/stages/src/stages/sender_recovery.rs @@ -376,8 +376,8 @@ mod tests { use reth_primitives::{SealedBlock, TransactionSigned}; use reth_primitives_traits::SignedTransaction; use reth_provider::{ - providers::StaticFileWriter, DatabaseProviderFactory, PruneCheckpointWriter, - StaticFileProviderFactory, TransactionsProvider, + providers::StaticFileWriter, BlockBodyIndicesProvider, DatabaseProviderFactory, + PruneCheckpointWriter, StaticFileProviderFactory, TransactionsProvider, }; use reth_prune_types::{PruneCheckpoint, PruneMode}; use reth_stages_api::StageUnitCheckpoint; diff --git a/crates/stages/stages/src/stages/tx_lookup.rs b/crates/stages/stages/src/stages/tx_lookup.rs index fab10b0f9535..90f577360980 100644 --- a/crates/stages/stages/src/stages/tx_lookup.rs +++ b/crates/stages/stages/src/stages/tx_lookup.rs @@ -257,7 +257,8 @@ mod tests { use assert_matches::assert_matches; use reth_primitives::SealedBlock; use reth_provider::{ - providers::StaticFileWriter, DatabaseProviderFactory, StaticFileProviderFactory, + providers::StaticFileWriter, BlockBodyIndicesProvider, DatabaseProviderFactory, + StaticFileProviderFactory, }; use reth_stages_api::StageUnitCheckpoint; use reth_testing_utils::generators::{ diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 7d5399897894..14cb8108d692 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -35,8 +35,8 @@ use reth_primitives_traits::BlockBody as _; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DBProvider, NodePrimitivesProvider, OmmersProvider, StateCommitmentProvider, - StorageChangeSetReader, + BlockBodyIndicesProvider, DBProvider, NodePrimitivesProvider, OmmersProvider, + StateCommitmentProvider, StorageChangeSetReader, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; @@ -315,13 +315,6 @@ impl BlockReader for BlockchainProvider2 { Ok(self.canonical_in_memory_state.pending_block_and_receipts()) } - fn block_body_indices( - &self, - number: BlockNumber, - ) -> ProviderResult> { - self.consistent_provider()?.block_body_indices(number) - } - /// Returns the block with senders with matching number or hash from database. /// /// **NOTE: If [`TransactionVariant::NoHash`] is provided then the transactions have invalid @@ -481,6 +474,15 @@ impl OmmersProvider for BlockchainProvider2 { } } +impl BlockBodyIndicesProvider for BlockchainProvider2 { + fn block_body_indices( + &self, + number: BlockNumber, + ) -> ProviderResult> { + self.consistent_provider()?.block_body_indices(number) + } +} + impl StageCheckpointReader for BlockchainProvider2 { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.consistent_provider()?.get_stage_checkpoint(id) @@ -817,10 +819,10 @@ mod tests { use reth_primitives::{BlockExt, Receipt, SealedBlock, StaticFileSegment}; use reth_primitives_traits::{BlockBody as _, SignedTransaction}; use reth_storage_api::{ - BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, BlockSource, - ChangeSetReader, DatabaseProviderFactory, HeaderProvider, OmmersProvider, ReceiptProvider, - ReceiptProviderIdExt, StateProviderFactory, TransactionVariant, TransactionsProvider, - WithdrawalsProvider, + BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, + BlockReaderIdExt, BlockSource, ChangeSetReader, DatabaseProviderFactory, HeaderProvider, + OmmersProvider, ReceiptProvider, ReceiptProviderIdExt, StateProviderFactory, + TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use reth_testing_utils::generators::{ self, random_block, random_block_range, random_changeset_range, random_eoa_accounts, diff --git a/crates/storage/provider/src/providers/consistent.rs b/crates/storage/provider/src/providers/consistent.rs index 643bc2e38984..6d7529d2b4ac 100644 --- a/crates/storage/provider/src/providers/consistent.rs +++ b/crates/storage/provider/src/providers/consistent.rs @@ -28,8 +28,8 @@ use reth_primitives_traits::BlockBody; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, NodePrimitivesProvider, OmmersProvider, StateProvider, - StorageChangeSetReader, + BlockBodyIndicesProvider, DatabaseProviderFactory, NodePrimitivesProvider, OmmersProvider, + StateProvider, StorageChangeSetReader, }; use reth_storage_errors::provider::ProviderResult; use revm::{ @@ -841,40 +841,6 @@ impl BlockReader for ConsistentProvider { Ok(self.canonical_in_memory_state.pending_block_and_receipts()) } - fn block_body_indices( - &self, - number: BlockNumber, - ) -> ProviderResult> { - self.get_in_memory_or_storage_by_block( - number.into(), - |db_provider| db_provider.block_body_indices(number), - |block_state| { - // Find the last block indices on database - let last_storage_block_number = block_state.anchor().number; - let mut stored_indices = self - .storage_provider - .block_body_indices(last_storage_block_number)? - .ok_or(ProviderError::BlockBodyIndicesNotFound(last_storage_block_number))?; - - // Prepare our block indices - stored_indices.first_tx_num = stored_indices.next_tx_num(); - stored_indices.tx_count = 0; - - // Iterate from the lowest block in memory until our target block - for state in block_state.chain().collect::>().into_iter().rev() { - let block_tx_count = state.block_ref().block.body.transactions().len() as u64; - if state.block_ref().block().number() == number { - stored_indices.tx_count = block_tx_count; - } else { - stored_indices.first_tx_num += block_tx_count; - } - } - - Ok(Some(stored_indices)) - }, - ) - } - /// Returns the block with senders with matching number or hash from database. /// /// **NOTE: If [`TransactionVariant::NoHash`] is provided then the transactions have invalid @@ -1219,6 +1185,42 @@ impl OmmersProvider for ConsistentProvider { } } +impl BlockBodyIndicesProvider for ConsistentProvider { + fn block_body_indices( + &self, + number: BlockNumber, + ) -> ProviderResult> { + self.get_in_memory_or_storage_by_block( + number.into(), + |db_provider| db_provider.block_body_indices(number), + |block_state| { + // Find the last block indices on database + let last_storage_block_number = block_state.anchor().number; + let mut stored_indices = self + .storage_provider + .block_body_indices(last_storage_block_number)? + .ok_or(ProviderError::BlockBodyIndicesNotFound(last_storage_block_number))?; + + // Prepare our block indices + stored_indices.first_tx_num = stored_indices.next_tx_num(); + stored_indices.tx_count = 0; + + // Iterate from the lowest block in memory until our target block + for state in block_state.chain().collect::>().into_iter().rev() { + let block_tx_count = state.block_ref().block.body.transactions().len() as u64; + if state.block_ref().block().number() == number { + stored_indices.tx_count = block_tx_count; + } else { + stored_indices.first_tx_num += block_tx_count; + } + } + + Ok(Some(stored_indices)) + }, + ) + } +} + impl StageCheckpointReader for ConsistentProvider { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.storage_provider.get_stage_checkpoint(id) diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index a6195ff8181c..0241c432019d 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -26,7 +26,8 @@ use reth_primitives::{ use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - NodePrimitivesProvider, OmmersProvider, StateCommitmentProvider, TryIntoHistoricalStateProvider, + BlockBodyIndicesProvider, NodePrimitivesProvider, OmmersProvider, StateCommitmentProvider, + TryIntoHistoricalStateProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; @@ -404,13 +405,6 @@ impl BlockReader for ProviderFactory { self.provider()?.pending_block_and_receipts() } - fn block_body_indices( - &self, - number: BlockNumber, - ) -> ProviderResult> { - self.provider()?.block_body_indices(number) - } - fn block_with_senders( &self, id: BlockHashOrNumber, @@ -578,6 +572,15 @@ impl OmmersProvider for ProviderFactory { } } +impl BlockBodyIndicesProvider for ProviderFactory { + fn block_body_indices( + &self, + number: BlockNumber, + ) -> ProviderResult> { + self.provider()?.block_body_indices(number) + } +} + impl StageCheckpointReader for ProviderFactory { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.provider()?.get_stage_checkpoint(id) diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index f21773d12170..03ece42b6047 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -60,8 +60,8 @@ use reth_primitives_traits::{Block as _, BlockBody as _, SignedTransaction}; use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - BlockBodyReader, NodePrimitivesProvider, OmmersProvider, StateProvider, StorageChangeSetReader, - TryIntoHistoricalStateProvider, + BlockBodyIndicesProvider, BlockBodyReader, NodePrimitivesProvider, OmmersProvider, + StateProvider, StorageChangeSetReader, TryIntoHistoricalStateProvider, }; use reth_storage_errors::provider::{ProviderResult, RootMismatch}; use reth_trie::{ @@ -1222,10 +1222,6 @@ impl BlockReader for DatabaseProvid Ok(None) } - fn block_body_indices(&self, num: u64) -> ProviderResult> { - Ok(self.tx.get::(num)?) - } - /// Returns the block with senders with matching number or hash from database. /// /// **NOTE: The transactions have invalid hashes, since they would need to be calculated on the @@ -1637,6 +1633,14 @@ impl OmmersProvider for DatabasePro } } +impl BlockBodyIndicesProvider + for DatabaseProvider +{ + fn block_body_indices(&self, num: u64) -> ProviderResult> { + Ok(self.tx.get::(num)?) + } +} + impl EvmEnvProvider> for DatabaseProvider { diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index 810d6b1c77ad..5a1568d0aca6 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -37,7 +37,7 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::{CanonChainTracker, OmmersProvider}; +use reth_storage_api::{BlockBodyIndicesProvider, CanonChainTracker, OmmersProvider}; use reth_storage_errors::provider::ProviderResult; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use std::{ @@ -402,13 +402,6 @@ impl BlockReader for BlockchainProvider { Ok(self.tree.pending_block_and_receipts()) } - fn block_body_indices( - &self, - number: BlockNumber, - ) -> ProviderResult> { - self.database.block_body_indices(number) - } - /// Returns the block with senders with matching number or hash from database. /// /// **NOTE: If [`TransactionVariant::NoHash`] is provided then the transactions have invalid @@ -586,6 +579,15 @@ impl OmmersProvider for BlockchainProvider { } } +impl BlockBodyIndicesProvider for BlockchainProvider { + fn block_body_indices( + &self, + number: BlockNumber, + ) -> ProviderResult> { + self.database.block_body_indices(number) + } +} + impl StageCheckpointReader for BlockchainProvider { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.database.provider()?.get_stage_checkpoint(id) diff --git a/crates/storage/provider/src/providers/static_file/manager.rs b/crates/storage/provider/src/providers/static_file/manager.rs index 45f22f3780df..ab6b034fd98c 100644 --- a/crates/storage/provider/src/providers/static_file/manager.rs +++ b/crates/storage/provider/src/providers/static_file/manager.rs @@ -43,7 +43,7 @@ use reth_primitives::{ }; use reth_primitives_traits::SignedTransaction; use reth_stages_types::{PipelineTarget, StageId}; -use reth_storage_api::{DBProvider, OmmersProvider}; +use reth_storage_api::{BlockBodyIndicesProvider, DBProvider, OmmersProvider}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use std::{ collections::{hash_map::Entry, BTreeMap, HashMap}, @@ -1628,11 +1628,6 @@ impl> Err(ProviderError::UnsupportedProvider) } - fn block_body_indices(&self, _num: u64) -> ProviderResult> { - // Required data not present in static_files - Err(ProviderError::UnsupportedProvider) - } - fn block_with_senders( &self, _id: BlockHashOrNumber, @@ -1694,6 +1689,13 @@ impl> OmmersProvider for StaticFilePro } } +impl BlockBodyIndicesProvider for StaticFileProvider { + fn block_body_indices(&self, _num: u64) -> ProviderResult> { + // Required data not present in static_files + Err(ProviderError::UnsupportedProvider) + } +} + impl StatsReader for StaticFileProvider { fn count_entries(&self) -> ProviderResult { match T::NAME { diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 7958c4a2d16b..69635a55f63e 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -29,8 +29,8 @@ use reth_primitives::{ use reth_primitives_traits::SignedTransaction; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, HashedPostStateProvider, OmmersProvider, StageCheckpointReader, - StateCommitmentProvider, StateProofProvider, StorageRootProvider, + BlockBodyIndicesProvider, DatabaseProviderFactory, HashedPostStateProvider, OmmersProvider, + StageCheckpointReader, StateCommitmentProvider, StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; use reth_trie::{ @@ -510,10 +510,6 @@ impl BlockReader for MockEthProvider { Ok(None) } - fn block_body_indices(&self, _num: u64) -> ProviderResult> { - Ok(None) - } - fn block_with_senders( &self, _id: BlockHashOrNumber, @@ -796,6 +792,12 @@ impl OmmersProvider for MockEthProvider { } } +impl BlockBodyIndicesProvider for MockEthProvider { + fn block_body_indices(&self, _num: u64) -> ProviderResult> { + Ok(None) + } +} + impl ChangeSetReader for MockEthProvider { fn account_block_changeset( &self, diff --git a/crates/storage/storage-api/src/block.rs b/crates/storage/storage-api/src/block.rs index 794e399cae92..5e55042a76c4 100644 --- a/crates/storage/storage-api/src/block.rs +++ b/crates/storage/storage-api/src/block.rs @@ -1,10 +1,9 @@ use crate::{ - BlockNumReader, HeaderProvider, OmmersProvider, ReceiptProvider, ReceiptProviderIdExt, - TransactionVariant, TransactionsProvider, WithdrawalsProvider, + BlockBodyIndicesProvider, BlockNumReader, HeaderProvider, OmmersProvider, ReceiptProvider, + ReceiptProviderIdExt, TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag}; use alloy_primitives::{BlockNumber, B256}; -use reth_db_models::StoredBlockBodyIndices; use reth_primitives::{BlockWithSenders, SealedBlockFor, SealedBlockWithSenders, SealedHeader}; use reth_storage_errors::provider::ProviderResult; use std::ops::RangeInclusive; @@ -50,6 +49,7 @@ pub type ProviderBlock

=

::Block; pub trait BlockReader: BlockNumReader + HeaderProvider + + BlockBodyIndicesProvider + TransactionsProvider + ReceiptProvider + WithdrawalsProvider @@ -113,11 +113,6 @@ pub trait BlockReader: self.block(num.into()) } - /// Returns the block body indices with matching number from database. - /// - /// Returns `None` if block is not found. - fn block_body_indices(&self, num: u64) -> ProviderResult>; - /// Returns the block with senders with matching number or hash from database. /// /// Returns the block's transactions in the requested variant. @@ -192,9 +187,6 @@ impl BlockReader for std::sync::Arc { fn block_by_number(&self, num: u64) -> ProviderResult> { T::block_by_number(self, num) } - fn block_body_indices(&self, num: u64) -> ProviderResult> { - T::block_body_indices(self, num) - } fn block_with_senders( &self, id: BlockHashOrNumber, @@ -258,9 +250,6 @@ impl BlockReader for &T { fn block_by_number(&self, num: u64) -> ProviderResult> { T::block_by_number(self, num) } - fn block_body_indices(&self, num: u64) -> ProviderResult> { - T::block_body_indices(self, num) - } fn block_with_senders( &self, id: BlockHashOrNumber, diff --git a/crates/storage/storage-api/src/block_indices.rs b/crates/storage/storage-api/src/block_indices.rs new file mode 100644 index 000000000000..25c37bca8e2c --- /dev/null +++ b/crates/storage/storage-api/src/block_indices.rs @@ -0,0 +1,11 @@ +use reth_db_models::StoredBlockBodyIndices; +use reth_storage_errors::provider::ProviderResult; + +/// Client trait for fetching block body indices related data. +#[auto_impl::auto_impl(&, Arc)] +pub trait BlockBodyIndicesProvider: Send + Sync { + /// Returns the block body indices with matching number from database. + /// + /// Returns `None` if block is not found. + fn block_body_indices(&self, num: u64) -> ProviderResult>; +} diff --git a/crates/storage/storage-api/src/lib.rs b/crates/storage/storage-api/src/lib.rs index 3432c0d029bc..150d745e3bfe 100644 --- a/crates/storage/storage-api/src/lib.rs +++ b/crates/storage/storage-api/src/lib.rs @@ -76,3 +76,6 @@ pub use legacy::*; mod primitives; pub use primitives::*; + +mod block_indices; +pub use block_indices::*; diff --git a/crates/storage/storage-api/src/noop.rs b/crates/storage/storage-api/src/noop.rs index fe481d581ad4..e19776c7d964 100644 --- a/crates/storage/storage-api/src/noop.rs +++ b/crates/storage/storage-api/src/noop.rs @@ -1,12 +1,12 @@ //! Various noop implementations for traits. use crate::{ - AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, - BlockSource, ChangeSetReader, HashedPostStateProvider, HeaderProvider, NodePrimitivesProvider, - OmmersProvider, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, - StageCheckpointReader, StateProofProvider, StateProvider, StateProviderBox, - StateProviderFactory, StateRootProvider, StorageRootProvider, TransactionVariant, - TransactionsProvider, WithdrawalsProvider, + AccountReader, BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, + BlockReader, BlockReaderIdExt, BlockSource, ChangeSetReader, HashedPostStateProvider, + HeaderProvider, NodePrimitivesProvider, OmmersProvider, PruneCheckpointReader, ReceiptProvider, + ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider, StateProvider, + StateProviderBox, StateProviderFactory, StateRootProvider, StorageRootProvider, + TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use alloy_eips::{ eip4895::{Withdrawal, Withdrawals}, @@ -185,10 +185,6 @@ impl BlockReader for NoopProvider { Ok(None) } - fn block_body_indices(&self, _num: u64) -> ProviderResult> { - Ok(None) - } - fn block_with_senders( &self, _id: BlockHashOrNumber, @@ -575,3 +571,9 @@ impl PruneCheckpointReader for NoopProvider NodePrimitivesProvider for NoopProvider { type Primitives = N; } + +impl BlockBodyIndicesProvider for NoopProvider { + fn block_body_indices(&self, _num: u64) -> ProviderResult> { + Ok(None) + } +} From aef90237811ee0eed755884e3cb3d751342e6798 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 12 Dec 2024 18:31:37 +0400 Subject: [PATCH 6/7] chore: use `OpTypedTransaction` directly (#13350) --- crates/optimism/primitives/src/lib.rs | 2 +- .../primitives/src/transaction/mod.rs | 199 +----------------- .../primitives/src/transaction/signed.rs | 48 ++--- crates/primitives-traits/src/size.rs | 13 ++ .../codecs/src/alloy/transaction/optimism.rs | 60 +++++- 5 files changed, 93 insertions(+), 229 deletions(-) diff --git a/crates/optimism/primitives/src/lib.rs b/crates/optimism/primitives/src/lib.rs index 2eedf2453f2a..b2b9e60e544f 100644 --- a/crates/optimism/primitives/src/lib.rs +++ b/crates/optimism/primitives/src/lib.rs @@ -16,7 +16,7 @@ extern crate alloc; pub mod bedrock; pub mod transaction; -pub use transaction::{signed::OpTransactionSigned, tx_type::OpTxType, OpTransaction}; +pub use transaction::{signed::OpTransactionSigned, tx_type::OpTxType}; mod receipt; pub use receipt::OpReceipt; diff --git a/crates/optimism/primitives/src/transaction/mod.rs b/crates/optimism/primitives/src/transaction/mod.rs index 214814dd84c1..ab45ec9ea45e 100644 --- a/crates/optimism/primitives/src/transaction/mod.rs +++ b/crates/optimism/primitives/src/transaction/mod.rs @@ -1,201 +1,4 @@ -//! Wrapper of [`OpTypedTransaction`], that implements reth database encoding [`Compact`]. +//! Optimism transaction types pub mod signed; pub mod tx_type; - -use alloy_primitives::{bytes, Bytes, TxKind, Uint, B256}; - -#[cfg(any(test, feature = "reth-codec"))] -use alloy_consensus::constants::EIP7702_TX_TYPE_ID; -use alloy_consensus::{SignableTransaction, TxLegacy, Typed2718}; -use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization}; -use derive_more::{Constructor, Deref, From}; -use op_alloy_consensus::OpTypedTransaction; -#[cfg(any(test, feature = "reth-codec"))] -use op_alloy_consensus::DEPOSIT_TX_TYPE_ID; -#[cfg(any(test, feature = "reth-codec"))] -use reth_codecs::Compact; -#[cfg(any(test, feature = "reth-codec"))] -use reth_primitives::transaction::{ - COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930, - COMPACT_IDENTIFIER_LEGACY, -}; -use reth_primitives_traits::InMemorySize; - -#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[derive(Debug, Clone, PartialEq, Eq, Deref, Hash, From, Constructor)] -/// Optimistic transaction. -pub struct OpTransaction(OpTypedTransaction); - -impl OpTransaction { - /// This encodes the transaction _without_ the signature, and is only suitable for creating a - /// hash intended for signing. - pub fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { - match self.deref() { - OpTypedTransaction::Legacy(tx) => tx.encode_for_signing(out), - OpTypedTransaction::Eip2930(tx) => tx.encode_for_signing(out), - OpTypedTransaction::Eip1559(tx) => tx.encode_for_signing(out), - OpTypedTransaction::Eip7702(tx) => tx.encode_for_signing(out), - OpTypedTransaction::Deposit(_) => {} - } - } -} - -impl Default for OpTransaction { - fn default() -> Self { - Self(OpTypedTransaction::Legacy(TxLegacy::default())) - } -} - -#[cfg(any(test, feature = "reth-codec"))] -impl Compact for OpTransaction { - fn to_compact(&self, out: &mut B) -> usize - where - B: bytes::BufMut + AsMut<[u8]>, - { - match &self.0 { - OpTypedTransaction::Legacy(tx) => tx.to_compact(out), - OpTypedTransaction::Eip2930(tx) => tx.to_compact(out), - OpTypedTransaction::Eip1559(tx) => tx.to_compact(out), - OpTypedTransaction::Eip7702(tx) => tx.to_compact(out), - OpTypedTransaction::Deposit(tx) => tx.to_compact(out), - } - } - - fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) { - use bytes::Buf; - - match identifier { - COMPACT_IDENTIFIER_LEGACY => { - let (tx, buf) = TxLegacy::from_compact(buf, buf.len()); - (Self(OpTypedTransaction::Legacy(tx)), buf) - } - COMPACT_IDENTIFIER_EIP2930 => { - let (tx, buf) = - alloy_consensus::transaction::TxEip2930::from_compact(buf, buf.len()); - (Self(OpTypedTransaction::Eip2930(tx)), buf) - } - COMPACT_IDENTIFIER_EIP1559 => { - let (tx, buf) = - alloy_consensus::transaction::TxEip1559::from_compact(buf, buf.len()); - (Self(OpTypedTransaction::Eip1559(tx)), buf) - } - COMPACT_EXTENDED_IDENTIFIER_FLAG => { - // An identifier of 3 indicates that the transaction type did not fit into - // the backwards compatible 2 bit identifier, their transaction types are - // larger than 2 bits (eg. 4844 and Deposit Transactions). In this case, - // we need to read the concrete transaction type from the buffer by - // reading the full 8 bits (single byte) and match on this transaction type. - let identifier = buf.get_u8(); - match identifier { - EIP7702_TX_TYPE_ID => { - let (tx, buf) = - alloy_consensus::transaction::TxEip7702::from_compact(buf, buf.len()); - (Self(OpTypedTransaction::Eip7702(tx)), buf) - } - DEPOSIT_TX_TYPE_ID => { - let (tx, buf) = op_alloy_consensus::TxDeposit::from_compact(buf, buf.len()); - (Self(OpTypedTransaction::Deposit(tx)), buf) - } - _ => unreachable!( - "Junk data in database: unknown Transaction variant: {identifier}" - ), - } - } - _ => unreachable!("Junk data in database: unknown Transaction variant: {identifier}"), - } - } -} - -impl alloy_consensus::Transaction for OpTransaction { - fn chain_id(&self) -> Option { - self.0.chain_id() - } - - fn nonce(&self) -> u64 { - self.0.nonce() - } - - fn gas_limit(&self) -> u64 { - self.0.gas_limit() - } - - fn gas_price(&self) -> Option { - self.0.gas_price() - } - - fn max_fee_per_gas(&self) -> u128 { - self.0.max_fee_per_gas() - } - - fn max_priority_fee_per_gas(&self) -> Option { - self.0.max_priority_fee_per_gas() - } - - fn max_fee_per_blob_gas(&self) -> Option { - self.0.max_fee_per_blob_gas() - } - - fn priority_fee_or_price(&self) -> u128 { - self.0.priority_fee_or_price() - } - - fn kind(&self) -> TxKind { - self.0.kind() - } - - fn is_create(&self) -> bool { - self.0.is_create() - } - - fn value(&self) -> Uint<256, 4> { - self.0.value() - } - - fn input(&self) -> &Bytes { - self.0.input() - } - - fn access_list(&self) -> Option<&AccessList> { - self.0.access_list() - } - - fn blob_versioned_hashes(&self) -> Option<&[B256]> { - self.0.blob_versioned_hashes() - } - - fn authorization_list(&self) -> Option<&[SignedAuthorization]> { - self.0.authorization_list() - } - - fn is_dynamic_fee(&self) -> bool { - self.0.is_dynamic_fee() - } - - fn effective_gas_price(&self, base_fee: Option) -> u128 { - self.0.effective_gas_price(base_fee) - } - - fn effective_tip_per_gas(&self, base_fee: u64) -> Option { - self.0.effective_tip_per_gas(base_fee) - } -} - -impl InMemorySize for OpTransaction { - fn size(&self) -> usize { - match &self.0 { - OpTypedTransaction::Legacy(tx) => tx.size(), - OpTypedTransaction::Eip2930(tx) => tx.size(), - OpTypedTransaction::Eip1559(tx) => tx.size(), - OpTypedTransaction::Eip7702(tx) => tx.size(), - OpTypedTransaction::Deposit(tx) => tx.size(), - } - } -} - -impl Typed2718 for OpTransaction { - fn ty(&self) -> u8 { - self.0.ty() - } -} diff --git a/crates/optimism/primitives/src/transaction/signed.rs b/crates/optimism/primitives/src/transaction/signed.rs index 796a33cf3614..0d4c20447c57 100644 --- a/crates/optimism/primitives/src/transaction/signed.rs +++ b/crates/optimism/primitives/src/transaction/signed.rs @@ -1,6 +1,6 @@ //! A signed Optimism transaction. -use crate::{OpTransaction, OpTxType}; +use crate::OpTxType; use alloc::vec::Vec; use alloy_consensus::{ transaction::RlpEcdsaTx, SignableTransaction, Transaction, TxEip1559, TxEip2930, TxEip7702, @@ -47,7 +47,7 @@ pub struct OpTransactionSigned { /// Raw transaction info #[deref] #[as_ref] - pub transaction: OpTransaction, + pub transaction: OpTypedTransaction, } impl OpTransactionSigned { @@ -65,7 +65,7 @@ impl OpTransactionSigned { /// /// Note: this only calculates the hash on the first [`TransactionSigned::hash`] call. pub fn new_unhashed(transaction: OpTypedTransaction, signature: Signature) -> Self { - Self { hash: Default::default(), signature, transaction: OpTransaction::new(transaction) } + Self { hash: Default::default(), signature, transaction } } } @@ -81,7 +81,7 @@ impl SignedTransaction for OpTransactionSigned { fn recover_signer(&self) -> Option

{ // Optimism's Deposit transaction does not have a signature. Directly return the // `from` address. - if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = *self.transaction { + if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = self.transaction { return Some(from) } @@ -93,8 +93,8 @@ impl SignedTransaction for OpTransactionSigned { fn recover_signer_unchecked(&self) -> Option
{ // Optimism's Deposit transaction does not have a signature. Directly return the // `from` address. - if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = *self.transaction { - return Some(from) + if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = &self.transaction { + return Some(*from) } let Self { transaction, signature, .. } = self; @@ -103,14 +103,16 @@ impl SignedTransaction for OpTransactionSigned { } fn recover_signer_unchecked_with_buf(&self, buf: &mut Vec) -> Option
{ - // Optimism's Deposit transaction does not have a signature. Directly return the - // `from` address. - if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = *self.transaction { - return Some(from) - } - self.encode_for_signing(buf); - let signature_hash = keccak256(buf); - recover_signer_unchecked(&self.signature, signature_hash) + match &self.transaction { + // Optimism's Deposit transaction does not have a signature. Directly return the + // `from` address. + OpTypedTransaction::Deposit(tx) => return Some(tx.from), + OpTypedTransaction::Legacy(tx) => tx.encode_for_signing(buf), + OpTypedTransaction::Eip2930(tx) => tx.encode_for_signing(buf), + OpTypedTransaction::Eip1559(tx) => tx.encode_for_signing(buf), + OpTypedTransaction::Eip7702(tx) => tx.encode_for_signing(buf), + }; + recover_signer_unchecked(&self.signature, keccak256(buf)) } fn recalculate_hash(&self) -> B256 { @@ -123,7 +125,7 @@ impl FillTxEnv for OpTransactionSigned { let envelope = self.encoded_2718(); tx_env.caller = sender; - match self.transaction.deref() { + match &self.transaction { OpTypedTransaction::Legacy(tx) => { tx_env.gas_limit = tx.gas_limit; tx_env.gas_price = U256::from(tx.gas_price); @@ -252,7 +254,7 @@ impl Encodable2718 for OpTransactionSigned { } fn encode_2718_len(&self) -> usize { - match self.transaction.deref() { + match &self.transaction { OpTypedTransaction::Legacy(legacy_tx) => { legacy_tx.eip2718_encoded_length(&self.signature) } @@ -272,7 +274,7 @@ impl Encodable2718 for OpTransactionSigned { fn encode_2718(&self, out: &mut dyn alloy_rlp::BufMut) { let Self { transaction, signature, .. } = self; - match transaction.deref() { + match &transaction { OpTypedTransaction::Legacy(legacy_tx) => { // do nothing w/ with_header legacy_tx.eip2718_encode(signature, out) @@ -408,16 +410,6 @@ impl Typed2718 for OpTransactionSigned { } } -impl Default for OpTransactionSigned { - fn default() -> Self { - Self { - hash: Default::default(), - signature: Signature::test_signature(), - transaction: OpTransaction::new(OpTypedTransaction::Legacy(Default::default())), - } - } -} - impl PartialEq for OpTransactionSigned { fn eq(&self, other: &Self) -> bool { self.signature == other.signature && @@ -463,7 +455,7 @@ impl<'a> arbitrary::Arbitrary<'a> for OpTransactionSigned { } /// Calculates the signing hash for the transaction. -pub fn signature_hash(tx: &OpTypedTransaction) -> B256 { +fn signature_hash(tx: &OpTypedTransaction) -> B256 { match tx { OpTypedTransaction::Legacy(tx) => tx.signature_hash(), OpTypedTransaction::Eip2930(tx) => tx.signature_hash(), diff --git a/crates/primitives-traits/src/size.rs b/crates/primitives-traits/src/size.rs index be19ae81282a..c9706aa653e6 100644 --- a/crates/primitives-traits/src/size.rs +++ b/crates/primitives-traits/src/size.rs @@ -69,6 +69,19 @@ impl InMemorySize for op_alloy_consensus::OpDepositReceipt { } } +#[cfg(feature = "op")] +impl InMemorySize for op_alloy_consensus::OpTypedTransaction { + fn size(&self) -> usize { + match self { + Self::Legacy(tx) => tx.size(), + Self::Eip2930(tx) => tx.size(), + Self::Eip1559(tx) => tx.size(), + Self::Eip7702(tx) => tx.size(), + Self::Deposit(tx) => tx.size(), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/storage/codecs/src/alloy/transaction/optimism.rs b/crates/storage/codecs/src/alloy/transaction/optimism.rs index 631f5c406eeb..ea06ae6b0111 100644 --- a/crates/storage/codecs/src/alloy/transaction/optimism.rs +++ b/crates/storage/codecs/src/alloy/transaction/optimism.rs @@ -3,7 +3,7 @@ use alloy_consensus::constants::EIP7702_TX_TYPE_ID; use crate::Compact; use alloy_primitives::{Address, Bytes, TxKind, B256, U256}; -use op_alloy_consensus::{OpTxType, TxDeposit as AlloyTxDeposit}; +use op_alloy_consensus::{OpTxType, OpTypedTransaction, TxDeposit as AlloyTxDeposit, DEPOSIT_TX_TYPE_ID}; use reth_codecs_derive::add_arbitrary_tests; use crate::txtype::{COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930, COMPACT_IDENTIFIER_LEGACY}; @@ -114,4 +114,60 @@ impl crate::Compact for OpTxType { buf, ) } -} \ No newline at end of file +} + +impl Compact for OpTypedTransaction { + fn to_compact(&self, out: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + match self { + Self::Legacy(tx) => tx.to_compact(out), + Self::Eip2930(tx) => tx.to_compact(out), + Self::Eip1559(tx) => tx.to_compact(out), + Self::Eip7702(tx) => tx.to_compact(out), + Self::Deposit(tx) => tx.to_compact(out), + } + } + + fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) { + use bytes::Buf; + + match identifier { + COMPACT_IDENTIFIER_LEGACY => { + let (tx, buf) = Compact::from_compact(buf, buf.len()); + (Self::Legacy(tx), buf) + } + COMPACT_IDENTIFIER_EIP2930 => { + let (tx, buf) = Compact::from_compact(buf, buf.len()); + (Self::Eip2930(tx), buf) + } + COMPACT_IDENTIFIER_EIP1559 => { + let (tx, buf) = Compact::from_compact(buf, buf.len()); + (Self::Eip1559(tx), buf) + } + COMPACT_EXTENDED_IDENTIFIER_FLAG => { + // An identifier of 3 indicates that the transaction type did not fit into + // the backwards compatible 2 bit identifier, their transaction types are + // larger than 2 bits (eg. 4844 and Deposit Transactions). In this case, + // we need to read the concrete transaction type from the buffer by + // reading the full 8 bits (single byte) and match on this transaction type. + let identifier = buf.get_u8(); + match identifier { + EIP7702_TX_TYPE_ID => { + let (tx, buf) = Compact::from_compact(buf, buf.len()); + (Self::Eip7702(tx), buf) + } + DEPOSIT_TX_TYPE_ID => { + let (tx, buf) = Compact::from_compact(buf, buf.len()); + (Self::Deposit(tx), buf) + } + _ => unreachable!( + "Junk data in database: unknown Transaction variant: {identifier}" + ), + } + } + _ => unreachable!("Junk data in database: unknown Transaction variant: {identifier}"), + } + } +} From c339811727547423062616788cf676db7579dcbc Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 12 Dec 2024 15:44:35 +0100 Subject: [PATCH 7/7] chore: rm reth-provider dep from payload crate (#13348) --- Cargo.lock | 2 +- crates/ethereum/payload/Cargo.toml | 2 +- crates/ethereum/payload/src/lib.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5550c83d24fa..6189481cafba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7625,8 +7625,8 @@ dependencies = [ "reth-payload-builder-primitives", "reth-payload-primitives", "reth-primitives", - "reth-provider", "reth-revm", + "reth-storage-api", "reth-transaction-pool", "revm", "tracing", diff --git a/crates/ethereum/payload/Cargo.toml b/crates/ethereum/payload/Cargo.toml index b01f4c5bc74f..bec0b094c077 100644 --- a/crates/ethereum/payload/Cargo.toml +++ b/crates/ethereum/payload/Cargo.toml @@ -16,8 +16,8 @@ workspace = true reth-primitives.workspace = true reth-revm.workspace = true reth-transaction-pool.workspace = true -reth-provider.workspace = true reth-payload-builder.workspace = true +reth-storage-api.workspace = true reth-payload-builder-primitives.workspace = true reth-payload-primitives.workspace = true reth-execution-types.workspace = true diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 575b12659c76..757b75018253 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -20,7 +20,7 @@ use reth_basic_payload_builder::{ PayloadConfig, }; use reth_chain_state::ExecutedBlock; -use reth_chainspec::ChainSpec; +use reth_chainspec::{ChainSpec, ChainSpecProvider}; use reth_errors::RethError; use reth_evm::{system_calls::SystemCaller, ConfigureEvm, NextBlockEnvAttributes}; use reth_evm_ethereum::{eip6110::parse_deposits_from_receipts, EthEvmConfig}; @@ -33,7 +33,6 @@ use reth_primitives::{ Block, BlockBody, BlockExt, EthereumHardforks, InvalidTransactionError, Receipt, TransactionSigned, }; -use reth_provider::{ChainSpecProvider, StateProviderFactory}; use reth_revm::database::StateProviderDatabase; use reth_transaction_pool::{ error::InvalidPoolTransactionError, noop::NoopTransactionPool, BestTransactions, @@ -52,6 +51,7 @@ use tracing::{debug, trace, warn}; mod config; pub use config::*; +use reth_storage_api::StateProviderFactory; type BestTransactionsIter = Box< dyn BestTransactions::Transaction>>>,