From 2f782a9cbbdc5073e3eabb8b1b67a70d19968de4 Mon Sep 17 00:00:00 2001 From: DvirYo-starkware <115620476+DvirYo-starkware@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:29:00 +0300 Subject: [PATCH 01/18] feat(storage): add `opt_sync_bytes` and `opt_sync_period` options to MDBX (#10612) --- crates/storage/libmdbx-rs/src/environment.rs | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/crates/storage/libmdbx-rs/src/environment.rs b/crates/storage/libmdbx-rs/src/environment.rs index 1549d42e1866..f243c7da18ec 100644 --- a/crates/storage/libmdbx-rs/src/environment.rs +++ b/crates/storage/libmdbx-rs/src/environment.rs @@ -41,6 +41,8 @@ impl Environment { flags: EnvironmentFlags::default(), max_readers: None, max_dbs: None, + sync_bytes: None, + sync_period: None, rp_augment_limit: None, loose_limit: None, dp_reserve_limit: None, @@ -566,6 +568,8 @@ pub struct EnvironmentBuilder { flags: EnvironmentFlags, max_readers: Option, max_dbs: Option, + sync_bytes: Option, + sync_period: Option, rp_augment_limit: Option, loose_limit: Option, dp_reserve_limit: Option, @@ -639,6 +643,8 @@ impl EnvironmentBuilder { } for (opt, v) in [ (ffi::MDBX_opt_max_db, self.max_dbs), + (ffi::MDBX_opt_sync_bytes, self.sync_bytes), + (ffi::MDBX_opt_sync_period, self.sync_period), (ffi::MDBX_opt_rp_augment_limit, self.rp_augment_limit), (ffi::MDBX_opt_loose_limit, self.loose_limit), (ffi::MDBX_opt_dp_reserve_limit, self.dp_reserve_limit), @@ -767,6 +773,23 @@ impl EnvironmentBuilder { self } + /// Sets the interprocess/shared threshold to force flush the data buffers to disk, if + /// [`SyncMode::SafeNoSync`](crate::flags::SyncMode::SafeNoSync) is used. + pub fn set_sync_bytes(&mut self, v: usize) -> &mut Self { + self.sync_bytes = Some(v as u64); + self + } + + /// Sets the interprocess/shared relative period since the last unsteady commit to force flush + /// the data buffers to disk, if [`SyncMode::SafeNoSync`](crate::flags::SyncMode::SafeNoSync) is + /// used. + pub fn set_sync_period(&mut self, v: Duration) -> &mut Self { + // For this option, mdbx uses units of 1/65536 of a second. + let as_mdbx_units = (v.as_secs_f64() * 65536f64) as u64; + self.sync_period = Some(as_mdbx_units); + self + } + pub fn set_rp_augment_limit(&mut self, v: u64) -> &mut Self { self.rp_augment_limit = Some(v); self From 71e0178f71c308562907b0e2ff36caeb4a5326bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien?= <3535019+leruaa@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:35:15 +0200 Subject: [PATCH 02/18] feat: migrate to alloy TxLegacy (#9593) Co-authored-by: Arsenii Kulikov --- crates/net/eth-wire-types/src/blocks.rs | 8 +- crates/net/eth-wire-types/src/transactions.rs | 24 +-- crates/primitives/Cargo.toml | 3 +- crates/primitives/src/alloy_compat.rs | 5 +- crates/primitives/src/transaction/compat.rs | 2 +- crates/primitives/src/transaction/legacy.rs | 178 +----------------- crates/primitives/src/transaction/mod.rs | 44 ++++- crates/primitives/src/transaction/pooled.rs | 25 ++- .../primitives/src/transaction/signature.rs | 175 +++++++++-------- .../src/transaction/signature.rs | 2 +- crates/storage/codecs/Cargo.toml | 6 +- crates/storage/codecs/derive/src/arbitrary.rs | 2 +- crates/storage/codecs/src/alloy/mod.rs | 1 + .../storage/codecs/src/alloy/transaction.rs | 94 +++++++++ crates/storage/db-api/src/models/mod.rs | 4 +- crates/transaction-pool/src/test_utils/gen.rs | 2 +- .../transaction-pool/src/test_utils/mock.rs | 14 +- 17 files changed, 280 insertions(+), 309 deletions(-) create mode 100644 crates/storage/codecs/src/alloy/transaction.rs diff --git a/crates/net/eth-wire-types/src/blocks.rs b/crates/net/eth-wire-types/src/blocks.rs index 9cf1ee00283b..b0a0d4a747b1 100644 --- a/crates/net/eth-wire-types/src/blocks.rs +++ b/crates/net/eth-wire-types/src/blocks.rs @@ -364,7 +364,7 @@ mod tests { chain_id: Some(1), nonce: 0x8u64, gas_price: 0x4a817c808, - gas_limit: 0x2e248u64, + gas_limit: 0x2e248, to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()), value: U256::from(0x200u64), input: Default::default(), @@ -379,7 +379,7 @@ mod tests { chain_id: Some(1), nonce: 0x9u64, gas_price: 0x4a817c809, - gas_limit: 0x33450u64, + gas_limit: 0x33450, to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()), value: U256::from(0x2d9u64), input: Default::default(), @@ -438,7 +438,7 @@ mod tests { chain_id: Some(1), nonce: 0x8u64, gas_price: 0x4a817c808, - gas_limit: 0x2e248u64, + gas_limit: 0x2e248, to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()), value: U256::from(0x200u64), input: Default::default(), @@ -454,7 +454,7 @@ mod tests { chain_id: Some(1), nonce: 0x9u64, gas_price: 0x4a817c809, - gas_limit: 0x33450u64, + gas_limit: 0x33450, to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()), value: U256::from(0x2d9u64), input: Default::default(), diff --git a/crates/net/eth-wire-types/src/transactions.rs b/crates/net/eth-wire-types/src/transactions.rs index b4c7bc8b2b57..2e3a6015d20a 100644 --- a/crates/net/eth-wire-types/src/transactions.rs +++ b/crates/net/eth-wire-types/src/transactions.rs @@ -127,7 +127,7 @@ mod tests { chain_id: Some(1), nonce: 0x8u64, gas_price: 0x4a817c808, - gas_limit: 0x2e248u64, + gas_limit: 0x2e248, to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()), value: U256::from(0x200u64), input: Default::default(), @@ -149,7 +149,7 @@ mod tests { chain_id: Some(1), nonce: 0x09u64, gas_price: 0x4a817c809, - gas_limit: 0x33450u64, + gas_limit: 0x33450, to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()), value: U256::from(0x2d9u64), input: Default::default(), @@ -193,7 +193,7 @@ mod tests { chain_id: Some(1), nonce: 0x8u64, gas_price: 0x4a817c808, - gas_limit: 0x2e248u64, + gas_limit: 0x2e248, to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()), value: U256::from(0x200u64), input: Default::default(), @@ -215,7 +215,7 @@ mod tests { chain_id: Some(1), nonce: 0x09u64, gas_price: 0x4a817c809, - gas_limit: 0x33450u64, + gas_limit: 0x33450, to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()), value: U256::from(0x2d9u64), input: Default::default(), @@ -260,7 +260,7 @@ mod tests { chain_id: Some(4), nonce: 15u64, gas_price: 2200000000, - gas_limit: 34811u64, + gas_limit: 34811, to: TxKind::Call(hex!("cf7f9e66af820a19257a2108375b180b0ec49167").into()), value: U256::from(1234u64), input: Default::default(), @@ -306,7 +306,7 @@ mod tests { chain_id: Some(4), nonce: 3u64, gas_price: 2000000000, - gas_limit: 10000000u64, + gas_limit: 10000000, to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()), value: U256::from(1000000000000000u64), input: Default::default(), @@ -328,7 +328,7 @@ mod tests { chain_id: Some(4), nonce: 1u64, gas_price: 1000000000, - gas_limit: 100000u64, + gas_limit: 100000, to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()), value: U256::from(693361000000000u64), input: Default::default(), @@ -350,7 +350,7 @@ mod tests { chain_id: Some(4), nonce: 2u64, gas_price: 1000000000, - gas_limit: 100000u64, + gas_limit: 100000, to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()), value: U256::from(1000000000000000u64), input: Default::default(), @@ -399,7 +399,7 @@ mod tests { chain_id: Some(4), nonce: 15u64, gas_price: 2200000000, - gas_limit: 34811u64, + gas_limit: 34811, to: TxKind::Call(hex!("cf7f9e66af820a19257a2108375b180b0ec49167").into()), value: U256::from(1234u64), input: Default::default(), @@ -445,7 +445,7 @@ mod tests { chain_id: Some(4), nonce: 3u64, gas_price: 2000000000, - gas_limit: 10000000u64, + gas_limit: 10000000, to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()), value: U256::from(1000000000000000u64), input: Default::default(), @@ -467,7 +467,7 @@ mod tests { chain_id: Some(4), nonce: 1u64, gas_price: 1000000000, - gas_limit: 100000u64, + gas_limit: 100000, to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()), value: U256::from(693361000000000u64), input: Default::default(), @@ -489,7 +489,7 @@ mod tests { chain_id: Some(4), nonce: 2u64, gas_price: 1000000000, - gas_limit: 100000u64, + gas_limit: 100000, to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()), value: U256::from(1000000000000000u64), input: Default::default(), diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 2da37359c023..ff6e8d59c378 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -23,13 +23,13 @@ reth-codecs = { workspace = true, optional = true } reth-optimism-chainspec = { workspace = true, optional = true } # ethereum +alloy-consensus.workspace = true alloy-primitives = { workspace = true, features = ["rand", "rlp"] } alloy-rlp = { workspace = true, features = ["arrayvec"] } alloy-rpc-types = { workspace = true, optional = true } alloy-serde = { workspace = true, optional = true } alloy-genesis.workspace = true alloy-eips = { workspace = true, features = ["serde"] } -alloy-consensus.workspace = true # optimism op-alloy-rpc-types = { workspace = true, optional = true } @@ -118,4 +118,3 @@ harness = false name = "validate_blob_tx" required-features = ["arbitrary", "c-kzg"] harness = false - diff --git a/crates/primitives/src/alloy_compat.rs b/crates/primitives/src/alloy_compat.rs index ee5843b1e849..d63bac7c0045 100644 --- a/crates/primitives/src/alloy_compat.rs +++ b/crates/primitives/src/alloy_compat.rs @@ -102,10 +102,7 @@ impl TryFrom> for Transaction { chain_id, nonce: tx.nonce, gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - gas_limit: tx - .gas - .try_into() - .map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?, + gas_limit: tx.gas, to: tx.to.map_or(TxKind::Create, TxKind::Call), value: tx.value, input: tx.input, diff --git a/crates/primitives/src/transaction/compat.rs b/crates/primitives/src/transaction/compat.rs index 7f47aa7e6655..a58277374ecb 100644 --- a/crates/primitives/src/transaction/compat.rs +++ b/crates/primitives/src/transaction/compat.rs @@ -22,7 +22,7 @@ impl FillTxEnv for TransactionSigned { tx_env.caller = sender; match self.as_ref() { Transaction::Legacy(tx) => { - tx_env.gas_limit = tx.gas_limit; + tx_env.gas_limit = tx.gas_limit as u64; tx_env.gas_price = U256::from(tx.gas_price); tx_env.gas_priority_fee = None; tx_env.transact_to = tx.to; diff --git a/crates/primitives/src/transaction/legacy.rs b/crates/primitives/src/transaction/legacy.rs index 181c543803e5..7154f73cc9ef 100644 --- a/crates/primitives/src/transaction/legacy.rs +++ b/crates/primitives/src/transaction/legacy.rs @@ -1,180 +1,4 @@ -use crate::{keccak256, Bytes, ChainId, Signature, TxKind, TxType, B256, U256}; -use alloy_rlp::{length_of_length, Encodable, Header}; -use core::mem; - -#[cfg(any(test, feature = "reth-codec"))] -use reth_codecs::Compact; - -#[cfg(not(feature = "std"))] -use alloc::vec::Vec; -use serde::{Deserialize, Serialize}; - -/// Legacy transaction. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] -#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] -#[cfg_attr(any(test, feature = "reth-codec"), derive(Compact))] -#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))] -pub struct TxLegacy { - /// Added as EIP-155: Simple replay attack protection - pub chain_id: Option, - /// A scalar value equal to the number of transactions sent by the sender; formally Tn. - pub nonce: u64, - /// A scalar value equal to the number of - /// Wei to be paid per unit of gas for all computation - /// costs incurred as a result of the execution of this transaction; formally Tp. - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - pub gas_price: u128, - /// A scalar value equal to the maximum - /// amount of gas that should be used in executing - /// this transaction. This is paid up-front, before any - /// computation is done and may not be increased - /// later; formally Tg. - pub gas_limit: u64, - /// The 160-bit address of the message call’s recipient or, for a contract creation - /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. - pub to: TxKind, - /// A scalar value equal to the number of Wei to - /// be transferred to the message call’s recipient or, - /// in the case of contract creation, as an endowment - /// to the newly created account; formally Tv. - pub value: U256, - /// Input has two uses depending if transaction is Create or Call (if `to` field is None or - /// Some). pub init: An unlimited size byte array specifying the - /// EVM-code for the account initialisation procedure CREATE, - /// data: An unlimited size byte array specifying the - /// input data of the message call, formally Td. - pub input: Bytes, -} - -impl TxLegacy { - /// Calculates a heuristic for the in-memory size of the [`TxLegacy`] transaction. - #[inline] - pub fn size(&self) -> usize { - mem::size_of::>() + // chain_id - mem::size_of::() + // nonce - mem::size_of::() + // gas_price - mem::size_of::() + // gas_limit - self.to.size() + // to - mem::size_of::() + // value - self.input.len() // input - } - - /// Outputs the length of the transaction's fields, without a RLP header or length of the - /// eip155 fields. - pub(crate) fn fields_len(&self) -> usize { - self.nonce.length() + - self.gas_price.length() + - self.gas_limit.length() + - self.to.length() + - self.value.length() + - self.input.0.length() - } - - /// Encodes only the transaction's fields into the desired buffer, without a RLP header or - /// eip155 fields. - pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) { - self.nonce.encode(out); - self.gas_price.encode(out); - self.gas_limit.encode(out); - self.to.encode(out); - self.value.encode(out); - self.input.0.encode(out); - } - - /// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating - /// hash. - /// - /// This encodes the transaction as: - /// `rlp(nonce, gas_price, gas_limit, to, value, input, v, r, s)` - /// - /// The `v` value is encoded according to EIP-155 if the `chain_id` is not `None`. - pub(crate) fn encode_with_signature(&self, signature: &Signature, out: &mut dyn bytes::BufMut) { - let payload_length = - self.fields_len() + signature.payload_len_with_eip155_chain_id(self.chain_id); - let header = Header { list: true, payload_length }; - header.encode(out); - self.encode_fields(out); - signature.encode_with_eip155_chain_id(out, self.chain_id); - } - - /// Output the length of the RLP signed transaction encoding. - pub(crate) fn payload_len_with_signature(&self, signature: &Signature) -> usize { - let payload_length = - self.fields_len() + signature.payload_len_with_eip155_chain_id(self.chain_id); - // 'header length' + 'payload length' - length_of_length(payload_length) + payload_length - } - - /// Get transaction type - pub(crate) const fn tx_type(&self) -> TxType { - TxType::Legacy - } - - /// Encodes EIP-155 arguments into the desired buffer. Only encodes values for legacy - /// transactions. - /// - /// If a `chain_id` is `Some`, this encodes the `chain_id`, followed by two zeroes, as defined - /// by [EIP-155](https://eips.ethereum.org/EIPS/eip-155). - pub(crate) fn encode_eip155_fields(&self, out: &mut dyn bytes::BufMut) { - // if this is a legacy transaction without a chain ID, it must be pre-EIP-155 - // and does not need to encode the chain ID for the signature hash encoding - if let Some(id) = self.chain_id { - // EIP-155 encodes the chain ID and two zeroes - id.encode(out); - 0x00u8.encode(out); - 0x00u8.encode(out); - } - } - - /// Outputs the length of EIP-155 fields. Only outputs a non-zero value for EIP-155 legacy - /// transactions. - pub(crate) fn eip155_fields_len(&self) -> usize { - if let Some(id) = self.chain_id { - // EIP-155 encodes the chain ID and two zeroes, so we add 2 to the length of the chain - // ID to get the length of all 3 fields - // len(chain_id) + (0x00) + (0x00) - id.length() + 2 - } else { - // this is either a pre-EIP-155 legacy transaction or a typed transaction - 0 - } - } - - /// Encodes the legacy transaction in RLP for signing, including the EIP-155 fields if possible. - /// - /// If a `chain_id` is `Some`, this encodes the transaction as: - /// `rlp(nonce, gas_price, gas_limit, to, value, input, chain_id, 0, 0)` - /// - /// Otherwise, this encodes the transaction as: - /// `rlp(nonce, gas_price, gas_limit, to, value, input)` - pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { - Header { list: true, payload_length: self.fields_len() + self.eip155_fields_len() } - .encode(out); - self.encode_fields(out); - self.encode_eip155_fields(out); - } - - /// Outputs the length of the signature RLP encoding for the transaction, including the length - /// of the EIP-155 fields if possible. - pub(crate) fn payload_len_for_signature(&self) -> usize { - let payload_length = self.fields_len() + self.eip155_fields_len(); - // 'header length' + 'payload length' - length_of_length(payload_length) + payload_length - } - - /// Outputs the signature hash of the transaction by first encoding without a signature, then - /// hashing. - /// - /// See [`Self::encode_for_signing`] for more information on the encoding format. - pub(crate) fn signature_hash(&self) -> B256 { - let mut buf = Vec::with_capacity(self.payload_len_for_signature()); - self.encode_for_signing(&mut buf); - keccak256(&buf) - } -} +pub use alloy_consensus::TxLegacy; #[cfg(test)] mod tests { diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index c1bdcc964824..a9f80a23012b 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -5,6 +5,7 @@ use crate::{ B256, U256, }; +use alloy_consensus::SignableTransaction; use alloy_rlp::{ Decodable, Encodable, Error as RlpError, Header, EMPTY_LIST_CODE, EMPTY_STRING_CODE, }; @@ -87,7 +88,6 @@ pub(crate) static PARALLEL_SENDER_RECOVERY_THRESHOLD: Lazy = /// /// Transaction types were introduced in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))] pub enum Transaction { /// Legacy transaction (type `0x0`). @@ -140,6 +140,27 @@ pub enum Transaction { Deposit(TxDeposit), } +#[cfg(any(test, feature = "arbitrary"))] +impl<'a> arbitrary::Arbitrary<'a> for Transaction { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + let mut tx = match TxType::arbitrary(u)? { + TxType::Legacy => Self::Legacy(TxLegacy::arbitrary(u)?), + TxType::Eip2930 => Self::Eip2930(TxEip2930::arbitrary(u)?), + TxType::Eip1559 => Self::Eip1559(TxEip1559::arbitrary(u)?), + TxType::Eip4844 => Self::Eip4844(TxEip4844::arbitrary(u)?), + TxType::Eip7702 => Self::Eip7702(TxEip7702::arbitrary(u)?), + #[cfg(feature = "optimism")] + TxType::Deposit => Self::Deposit(TxDeposit::arbitrary(u)?), + }; + + if let Self::Legacy(tx) = &mut tx { + tx.gas_limit = (tx.gas_limit as u64).into(); + }; + + Ok(tx) + } +} + // === impl Transaction === impl Transaction { @@ -208,7 +229,7 @@ impl Transaction { /// Get the transaction's type pub const fn tx_type(&self) -> TxType { match self { - Self::Legacy(legacy_tx) => legacy_tx.tx_type(), + Self::Legacy(_) => TxType::Legacy, Self::Eip2930(access_list_tx) => access_list_tx.tx_type(), Self::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.tx_type(), Self::Eip4844(blob_tx) => blob_tx.tx_type(), @@ -273,7 +294,7 @@ impl Transaction { /// Get the gas limit of the transaction. pub const fn gas_limit(&self) -> u64 { match self { - Self::Legacy(TxLegacy { gas_limit, .. }) | + Self::Legacy(TxLegacy { gas_limit, .. }) => *gas_limit as u64, Self::Eip2930(TxEip2930 { gas_limit, .. }) | Self::Eip1559(TxEip1559 { gas_limit, .. }) | Self::Eip4844(TxEip4844 { gas_limit, .. }) | @@ -494,7 +515,10 @@ impl Transaction { match self { Self::Legacy(legacy_tx) => { // do nothing w/ with_header - legacy_tx.encode_with_signature(signature, out) + legacy_tx.encode_with_signature_fields( + &signature.as_signature_with_eip155_parity(legacy_tx.chain_id), + out, + ) } Self::Eip2930(access_list_tx) => { access_list_tx.encode_with_signature(signature, out, with_header) @@ -514,7 +538,7 @@ impl Transaction { /// This sets the transaction's gas limit. pub fn set_gas_limit(&mut self, gas_limit: u64) { match self { - Self::Legacy(tx) => tx.gas_limit = gas_limit, + Self::Legacy(tx) => tx.gas_limit = gas_limit.into(), Self::Eip2930(tx) => tx.gas_limit = gas_limit, Self::Eip1559(tx) => tx.gas_limit = gas_limit, Self::Eip4844(tx) => tx.gas_limit = gas_limit, @@ -1174,7 +1198,9 @@ impl TransactionSigned { /// only `true`. pub(crate) fn payload_len_inner(&self) -> usize { match &self.transaction { - Transaction::Legacy(legacy_tx) => legacy_tx.payload_len_with_signature(&self.signature), + Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature( + &self.signature.as_signature_with_eip155_parity(legacy_tx.chain_id), + ), Transaction::Eip2930(access_list_tx) => { access_list_tx.payload_len_with_signature(&self.signature) } @@ -1378,7 +1404,9 @@ impl TransactionSigned { pub fn length_without_header(&self) -> usize { // method computes the payload len without a RLP header match &self.transaction { - Transaction::Legacy(legacy_tx) => legacy_tx.payload_len_with_signature(&self.signature), + Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature( + &self.signature.as_signature_with_eip155_parity(legacy_tx.chain_id), + ), Transaction::Eip2930(access_list_tx) => { access_list_tx.payload_len_with_signature_without_header(&self.signature) } @@ -1770,7 +1798,7 @@ mod tests { chain_id: Some(4), nonce: 1u64, gas_price: 1000000000, - gas_limit: 100000u64, + gas_limit: 100000, to: Address::from_slice(&hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046")[..]).into(), value: U256::from(693361000000000u64), input: Default::default(), diff --git a/crates/primitives/src/transaction/pooled.rs b/crates/primitives/src/transaction/pooled.rs index ff6284d3758f..3f6739bfd609 100644 --- a/crates/primitives/src/transaction/pooled.rs +++ b/crates/primitives/src/transaction/pooled.rs @@ -7,6 +7,7 @@ use crate::{ TransactionSigned, TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxEip4844, TxHash, TxLegacy, B256, EIP4844_TX_TYPE_ID, }; +use alloy_consensus::SignableTransaction; use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header, EMPTY_LIST_CODE}; use bytes::Buf; use derive_more::{AsRef, Deref}; @@ -301,7 +302,9 @@ impl PooledTransactionsElement { match self { Self::Legacy { transaction, signature, .. } => { // method computes the payload len with a RLP header - transaction.payload_len_with_signature(signature) + transaction.encoded_len_with_signature( + &signature.as_signature_with_eip155_parity(transaction.chain_id), + ) } Self::Eip2930 { transaction, signature, .. } => { // method computes the payload len without a RLP header @@ -347,9 +350,11 @@ impl PooledTransactionsElement { // - EIP-4844: BlobTransaction::encode_with_type_inner // - EIP-7702: TxEip7702::encode_with_signature match self { - Self::Legacy { transaction, signature, .. } => { - transaction.encode_with_signature(signature, out) - } + Self::Legacy { transaction, signature, .. } => transaction + .encode_with_signature_fields( + &signature.as_signature_with_eip155_parity(transaction.chain_id), + out, + ), Self::Eip2930 { transaction, signature, .. } => { transaction.encode_with_signature(signature, out, false) } @@ -478,9 +483,11 @@ impl Encodable for PooledTransactionsElement { // - EIP-4844: BlobTransaction::encode_with_type_inner // - EIP-7702: TxEip7702::encode_with_signature match self { - Self::Legacy { transaction, signature, .. } => { - transaction.encode_with_signature(signature, out) - } + Self::Legacy { transaction, signature, .. } => transaction + .encode_with_signature_fields( + &signature.as_signature_with_eip155_parity(transaction.chain_id), + out, + ), Self::Eip2930 { transaction, signature, .. } => { // encodes with string header transaction.encode_with_signature(signature, out, true) @@ -506,7 +513,9 @@ impl Encodable for PooledTransactionsElement { match self { Self::Legacy { transaction, signature, .. } => { // method computes the payload len with a RLP header - transaction.payload_len_with_signature(signature) + transaction.encoded_len_with_signature( + &signature.as_signature_with_eip155_parity(transaction.chain_id), + ) } Self::Eip2930 { transaction, signature, .. } => { // method computes the payload len with a RLP header diff --git a/crates/primitives/src/transaction/signature.rs b/crates/primitives/src/transaction/signature.rs index 69fbd6ab1cb1..dad5ef522dbf 100644 --- a/crates/primitives/src/transaction/signature.rs +++ b/crates/primitives/src/transaction/signature.rs @@ -1,5 +1,8 @@ +use core::fmt::Debug; + use crate::{transaction::util::secp256k1, Address, B256, U256}; -use alloy_primitives::Bytes; +use alloy_consensus::EncodableSignature; +use alloy_primitives::{Bytes, Parity}; use alloy_rlp::{Decodable, Encodable, Error as RlpError}; use serde::{Deserialize, Serialize}; @@ -18,6 +21,9 @@ const SECP256K1N_HALF: U256 = U256::from_be_bytes([ /// r, s: Values corresponding to the signature of the /// transaction and used to determine the sender of /// the transaction; formally Tr and Ts. This is expanded in Appendix F of yellow paper. +/// +/// This type is unaware of the chain id, and thus shouldn't be used when encoding or decoding +/// legacy transactions. Use `SignatureWithParity` instead. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))] @@ -33,15 +39,6 @@ pub struct Signature { pub odd_y_parity: bool, } -impl Signature { - /// Returns the signature for the optimism deposit transactions, which don't include a - /// signature. - #[cfg(feature = "optimism")] - pub const fn optimism_deposit_tx_signature() -> Self { - Self { r: U256::ZERO, s: U256::ZERO, odd_y_parity: false } - } -} - #[cfg(any(test, feature = "reth-codec"))] impl reth_codecs::Compact for Signature { fn to_compact(&self, buf: &mut B) -> usize @@ -64,44 +61,6 @@ impl reth_codecs::Compact for Signature { } impl Signature { - /// Output the length of the signature without the length of the RLP header, using the legacy - /// scheme with EIP-155 support depends on `chain_id`. - pub(crate) fn payload_len_with_eip155_chain_id(&self, chain_id: Option) -> usize { - self.v(chain_id).length() + self.r.length() + self.s.length() - } - - /// Encode the `v`, `r`, `s` values without a RLP header. - /// Encodes the `v` value using the legacy scheme with EIP-155 support depends on `chain_id`. - pub(crate) fn encode_with_eip155_chain_id( - &self, - out: &mut dyn alloy_rlp::BufMut, - chain_id: Option, - ) { - self.v(chain_id).encode(out); - self.r.encode(out); - self.s.encode(out); - } - - /// Output the `v` of the signature depends on `chain_id` - #[inline] - #[allow(clippy::missing_const_for_fn)] - pub fn v(&self, chain_id: Option) -> u64 { - if let Some(chain_id) = chain_id { - // EIP-155: v = {0, 1} + CHAIN_ID * 2 + 35 - self.odd_y_parity as u64 + chain_id * 2 + 35 - } else { - #[cfg(feature = "optimism")] - // pre bedrock system transactions were sent from the zero address as legacy - // transactions with an empty signature - // - // NOTE: this is very hacky and only relevant for op-mainnet pre bedrock - if *self == Self::optimism_deposit_tx_signature() { - return 0 - } - self.odd_y_parity as u64 + 27 - } - } - /// Decodes the `v`, `r`, `s` values without a RLP header. /// This will return a chain ID if the `v` value is [EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) compatible. pub(crate) fn decode_with_eip155_chain_id( @@ -202,6 +161,39 @@ impl Signature { pub const fn size(&self) -> usize { core::mem::size_of::() } + + /// Returns [Parity] value based on `chain_id` for legacy transaction signature. + #[allow(clippy::missing_const_for_fn)] + pub fn legacy_parity(&self, chain_id: Option) -> Parity { + if let Some(chain_id) = chain_id { + Parity::Parity(self.odd_y_parity).with_chain_id(chain_id) + } else { + #[cfg(feature = "optimism")] + // pre bedrock system transactions were sent from the zero address as legacy + // transactions with an empty signature + // + // NOTE: this is very hacky and only relevant for op-mainnet pre bedrock + if *self == Self::optimism_deposit_tx_signature() { + return Parity::Parity(false) + } + Parity::NonEip155(self.odd_y_parity) + } + } + + /// Returns a signature with the given chain ID applied to the `v` value. + pub(crate) fn as_signature_with_eip155_parity( + &self, + chain_id: Option, + ) -> SignatureWithParity { + SignatureWithParity::new(self.r, self.s, self.legacy_parity(chain_id)) + } + + /// Returns the signature for the optimism deposit transactions, which don't include a + /// signature. + #[cfg(feature = "optimism")] + pub const fn optimism_deposit_tx_signature() -> Self { + Self { r: U256::ZERO, s: U256::ZERO, odd_y_parity: false } + } } impl From for Signature { @@ -228,52 +220,69 @@ pub const fn extract_chain_id(v: u64) -> alloy_rlp::Result<(bool, Option)> } } -#[cfg(test)] -mod tests { - use crate::{transaction::signature::SECP256K1N_HALF, Address, Signature, B256, U256}; - use alloy_primitives::{hex, hex::FromHex, Bytes}; - use std::str::FromStr; +/// A signature with full parity included. +// TODO: replace by alloy Signature when there will be an easy way to instantiate them. +pub(crate) struct SignatureWithParity { + /// The R field of the signature; the point on the curve. + r: U256, + /// The S field of the signature; the point on the curve. + s: U256, + /// Signature parity + parity: Parity, +} - #[test] - fn test_payload_len_with_eip155_chain_id() { - // Select 1 as an arbitrary nonzero value for R and S, as v() always returns 0 for (0, 0). - let signature = Signature { r: U256::from(1), s: U256::from(1), odd_y_parity: false }; +impl SignatureWithParity { + /// Creates a new [`SignatureWithParity`]. + pub(crate) const fn new(r: U256, s: U256, parity: Parity) -> Self { + Self { r, s, parity } + } +} - assert_eq!(3, signature.payload_len_with_eip155_chain_id(None)); - assert_eq!(3, signature.payload_len_with_eip155_chain_id(Some(1))); - assert_eq!(4, signature.payload_len_with_eip155_chain_id(Some(47))); +impl EncodableSignature for SignatureWithParity { + fn from_rs_and_parity< + P: TryInto, + E: Into, + >( + r: U256, + s: U256, + parity: P, + ) -> Result { + Ok(Self { r, s, parity: parity.try_into().map_err(Into::into)? }) } - #[test] - fn test_v() { - // Select 1 as an arbitrary nonzero value for R and S, as v() always returns 0 for (0, 0). - let signature = Signature { r: U256::from(1), s: U256::from(1), odd_y_parity: false }; - assert_eq!(27, signature.v(None)); - assert_eq!(37, signature.v(Some(1))); + fn r(&self) -> U256 { + self.r + } - let signature = Signature { r: U256::from(1), s: U256::from(1), odd_y_parity: true }; - assert_eq!(28, signature.v(None)); - assert_eq!(38, signature.v(Some(1))); + fn s(&self) -> U256 { + self.s + } + + fn v(&self) -> Parity { + self.parity + } + + fn with_parity>(self, parity: T) -> Self { + Self { r: self.r, s: self.s, parity: parity.into() } } +} + +#[cfg(test)] +mod tests { + use crate::{hex, transaction::signature::SECP256K1N_HALF, Address, Signature, B256, U256}; + use alloy_primitives::{hex::FromHex, Bytes, Parity}; + use std::str::FromStr; #[test] - fn test_encode_and_decode_with_eip155_chain_id() { + fn test_legacy_parity() { // Select 1 as an arbitrary nonzero value for R and S, as v() always returns 0 for (0, 0). let signature = Signature { r: U256::from(1), s: U256::from(1), odd_y_parity: false }; + assert_eq!(Parity::NonEip155(false), signature.legacy_parity(None)); + assert_eq!(Parity::Eip155(37), signature.legacy_parity(Some(1))); - let mut encoded = Vec::new(); - signature.encode_with_eip155_chain_id(&mut encoded, None); - assert_eq!(encoded.len(), signature.payload_len_with_eip155_chain_id(None)); - let (decoded, chain_id) = Signature::decode_with_eip155_chain_id(&mut &*encoded).unwrap(); - assert_eq!(signature, decoded); - assert_eq!(None, chain_id); - - let mut encoded = Vec::new(); - signature.encode_with_eip155_chain_id(&mut encoded, Some(1)); - assert_eq!(encoded.len(), signature.payload_len_with_eip155_chain_id(Some(1))); - let (decoded, chain_id) = Signature::decode_with_eip155_chain_id(&mut &*encoded).unwrap(); - assert_eq!(signature, decoded); - assert_eq!(Some(1), chain_id); + let signature = Signature { r: U256::from(1), s: U256::from(1), odd_y_parity: true }; + assert_eq!(Parity::NonEip155(true), signature.legacy_parity(None)); + assert_eq!(Parity::Eip155(38), signature.legacy_parity(Some(1))); } #[test] diff --git a/crates/rpc/rpc-types-compat/src/transaction/signature.rs b/crates/rpc/rpc-types-compat/src/transaction/signature.rs index 0e7fe5f5876a..fb41f517d533 100644 --- a/crates/rpc/rpc-types-compat/src/transaction/signature.rs +++ b/crates/rpc/rpc-types-compat/src/transaction/signature.rs @@ -13,7 +13,7 @@ pub(crate) fn from_legacy_primitive_signature( Signature { r: signature.r, s: signature.s, - v: U256::from(signature.v(chain_id)), + v: U256::from(signature.legacy_parity(chain_id).to_u64()), y_parity: None, } } diff --git a/crates/storage/codecs/Cargo.toml b/crates/storage/codecs/Cargo.toml index 7ecf75208ac1..13292c680c6f 100644 --- a/crates/storage/codecs/Cargo.toml +++ b/crates/storage/codecs/Cargo.toml @@ -31,7 +31,11 @@ alloy-eips = { workspace = true, default-features = false, features = [ "arbitrary", "serde", ] } -alloy-primitives = { workspace = true, features = ["arbitrary", "serde", "rand"] } +alloy-primitives = { workspace = true, features = [ + "arbitrary", + "serde", + "rand", +] } alloy-consensus = { workspace = true, features = ["arbitrary"] } test-fuzz.workspace = true serde_json.workspace = true diff --git a/crates/storage/codecs/derive/src/arbitrary.rs b/crates/storage/codecs/derive/src/arbitrary.rs index 4feae63c4f8f..8aa44062e21f 100644 --- a/crates/storage/codecs/derive/src/arbitrary.rs +++ b/crates/storage/codecs/derive/src/arbitrary.rs @@ -27,7 +27,7 @@ pub fn maybe_generate_tests( let mut buf = vec![]; let len = field.clone().to_compact(&mut buf); let (decoded, _): (super::#type_ident, _) = Compact::from_compact(&buf, len); - assert!(field == decoded, "maybe_generate_tests::compact"); + assert_eq!(field, decoded, "maybe_generate_tests::compact"); } }); } else if arg.to_string() == "rlp" { diff --git a/crates/storage/codecs/src/alloy/mod.rs b/crates/storage/codecs/src/alloy/mod.rs index 41a5ba20e2a9..efd76b1075dd 100644 --- a/crates/storage/codecs/src/alloy/mod.rs +++ b/crates/storage/codecs/src/alloy/mod.rs @@ -3,6 +3,7 @@ mod authorization_list; mod genesis_account; mod log; mod request; +mod transaction; mod trie; mod txkind; mod withdrawal; diff --git a/crates/storage/codecs/src/alloy/transaction.rs b/crates/storage/codecs/src/alloy/transaction.rs new file mode 100644 index 000000000000..389fef8ac2d3 --- /dev/null +++ b/crates/storage/codecs/src/alloy/transaction.rs @@ -0,0 +1,94 @@ +use crate::Compact; +use alloy_consensus::TxLegacy as AlloyTxLegacy; +use alloy_primitives::{Bytes, ChainId, TxKind, U256}; +use serde::{Deserialize, Serialize}; + +/// Legacy transaction. +#[derive(Debug, Clone, PartialEq, Eq, Default, Compact, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +#[cfg_attr(test, crate::add_arbitrary_tests(compact))] +struct TxLegacy { + /// Added as EIP-155: Simple replay attack protection + chain_id: Option, + /// A scalar value equal to the number of transactions sent by the sender; formally Tn. + nonce: u64, + /// A scalar value equal to the number of + /// Wei to be paid per unit of gas for all computation + /// costs incurred as a result of the execution of this transaction; formally Tp. + /// + /// As ethereum circulation is around 120mil eth as of 2022 that is around + /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: + /// 340282366920938463463374607431768211455 + gas_price: u128, + /// A scalar value equal to the maximum + /// amount of gas that should be used in executing + /// this transaction. This is paid up-front, before any + /// computation is done and may not be increased + /// later; formally Tg. + gas_limit: u64, + /// The 160-bit address of the message call’s recipient or, for a contract creation + /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. + to: TxKind, + /// A scalar value equal to the number of Wei to + /// be transferred to the message call’s recipient or, + /// in the case of contract creation, as an endowment + /// to the newly created account; formally Tv. + value: U256, + /// Input has two uses depending if transaction is Create or Call (if `to` field is None or + /// Some). pub init: An unlimited size byte array specifying the + /// EVM-code for the account initialisation procedure CREATE, + /// data: An unlimited size byte array specifying the + /// input data of the message call, formally Td. + input: Bytes, +} + +impl Compact for AlloyTxLegacy { + fn to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + let tx = TxLegacy { + chain_id: self.chain_id, + nonce: self.nonce, + gas_price: self.gas_price, + gas_limit: self.gas_limit as u64, + to: self.to, + value: self.value, + input: self.input.clone(), + }; + + tx.to_compact(buf) + } + + fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { + let (tx, _) = TxLegacy::from_compact(buf, len); + + let alloy_tx = Self { + chain_id: tx.chain_id, + nonce: tx.nonce, + gas_price: tx.gas_price, + gas_limit: tx.gas_limit as u128, + to: tx.to, + value: tx.value, + input: tx.input, + }; + + (alloy_tx, buf) + } +} + +#[cfg(test)] +mod tests { + use crate::alloy::transaction::TxLegacy; + + // each value in the database has an extra field named flags that encodes metadata about other + // fields in the value, e.g. offset and length. + // + // this check is to ensure we do not inadvertently add too many fields to a struct which would + // expand the flags field and break backwards compatibility + + #[test] + fn test_ensure_backwards_compatibility() { + assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3); + } +} diff --git a/crates/storage/db-api/src/models/mod.rs b/crates/storage/db-api/src/models/mod.rs index c177ca80b33f..ede53d4b9bfe 100644 --- a/crates/storage/db-api/src/models/mod.rs +++ b/crates/storage/db-api/src/models/mod.rs @@ -303,7 +303,7 @@ mod tests { use super::*; use reth_primitives::{ Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip1559, TxEip2930, TxEip4844, - TxLegacy, Withdrawals, + Withdrawals, }; use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment}; use reth_stages_types::{ @@ -346,7 +346,6 @@ mod tests { assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4); assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3); assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); - assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3); assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0); } @@ -379,7 +378,6 @@ mod tests { assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4); assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3); assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); - assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3); assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0); } } diff --git a/crates/transaction-pool/src/test_utils/gen.rs b/crates/transaction-pool/src/test_utils/gen.rs index 81314caa1bfb..c4069382d780 100644 --- a/crates/transaction-pool/src/test_utils/gen.rs +++ b/crates/transaction-pool/src/test_utils/gen.rs @@ -143,7 +143,7 @@ impl TransactionBuilder { TxLegacy { chain_id: Some(self.chain_id), nonce: self.nonce, - gas_limit: self.gas_limit, + gas_limit: self.gas_limit.into(), gas_price: self.max_fee_per_gas, to: self.to, value: self.value, diff --git a/crates/transaction-pool/src/test_utils/mock.rs b/crates/transaction-pool/src/test_utils/mock.rs index e7679eff888c..6a0c2f8b59a2 100644 --- a/crates/transaction-pool/src/test_utils/mock.rs +++ b/crates/transaction-pool/src/test_utils/mock.rs @@ -798,7 +798,7 @@ impl TryFrom for MockTransaction { sender, nonce, gas_price, - gas_limit, + gas_limit: gas_limit as u64, to, value, input, @@ -919,7 +919,15 @@ impl From for Transaction { value, input, size: _, - } => Self::Legacy(TxLegacy { chain_id, nonce, gas_price, gas_limit, to, value, input }), + } => Self::Legacy(TxLegacy { + chain_id, + nonce, + gas_price, + gas_limit: gas_limit.into(), + to, + value, + input, + }), MockTransaction::Eip2930 { chain_id, hash: _, @@ -1023,7 +1031,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { hash: tx_hash, nonce: *nonce, gas_price: *gas_price, - gas_limit: *gas_limit, + gas_limit: *gas_limit as u64, to: *to, value: *value, input: input.clone(), From e18a46d0a59f776464c0c6905c5e7ef371bc06e3 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Fri, 30 Aug 2024 21:00:59 +0800 Subject: [PATCH 03/18] docs: rm unused file (#10626) --- book/cli/reth/db/clear/static_file.md | 127 ------------------- book/cli/reth/db/get/static_file.md | 133 -------------------- book/cli/reth/db/static_file.md | 174 -------------------------- 3 files changed, 434 deletions(-) delete mode 100644 book/cli/reth/db/clear/static_file.md delete mode 100644 book/cli/reth/db/get/static_file.md delete mode 100644 book/cli/reth/db/static_file.md diff --git a/book/cli/reth/db/clear/static_file.md b/book/cli/reth/db/clear/static_file.md deleted file mode 100644 index 363da79674c3..000000000000 --- a/book/cli/reth/db/clear/static_file.md +++ /dev/null @@ -1,127 +0,0 @@ -# reth db clear static-file - -Deletes all static_file segment entries - -```bash -$ reth db clear static-file --help -Usage: reth db clear static-file [OPTIONS] - -Arguments: - - Possible values: - - headers: StaticFile segment responsible for the `CanonicalHeaders`, `Headers`, `HeaderTerminalDifficulties` tables - - transactions: StaticFile segment responsible for the `Transactions` table - - receipts: StaticFile segment responsible for the `Receipts` table - -Options: - --datadir - The path to the data dir for all reth files and subdirectories. - - Defaults to the OS-specific data directory: - - - Linux: `$XDG_DATA_HOME/reth/` or `$HOME/.local/share/reth/` - - Windows: `{FOLDERID_RoamingAppData}/reth/` - - macOS: `$HOME/Library/Application Support/reth/` - - [default: default] - - --chain - The chain this node is running. - Possible values are either a built-in chain or the path to a chain specification file. - - Built-in chains: - mainnet, sepolia, goerli, holesky, dev - - [default: mainnet] - - --instance - Add a new instance of a node. - - Configures the ports of the node to avoid conflicts with the defaults. This is useful for running multiple nodes on the same machine. - - Max number of instances is 200. It is chosen in a way so that it's not possible to have port numbers that conflict with each other. - - Changes to the following port numbers: - `DISCOVERY_PORT`: default + `instance` - 1 - `AUTH_PORT`: default + `instance` * 100 - 100 - `HTTP_RPC_PORT`: default - `instance` + 1 - `WS_RPC_PORT`: default + `instance` * 2 - 2 - - [default: 1] - - -h, --help - Print help (see a summary with '-h') - -Logging: - --log.stdout.format - The format to use for logs written to stdout - - [default: terminal] - - Possible values: - - json: Represents JSON formatting for logs. This format outputs log records as JSON objects, making it suitable for structured logging - - log-fmt: Represents logfmt (key=value) formatting for logs. This format is concise and human-readable, typically used in command-line applications - - terminal: Represents terminal-friendly formatting for logs - - --log.stdout.filter - The filter to use for logs written to stdout - - [default: ] - - --log.file.format - The format to use for logs written to the log file - - [default: terminal] - - Possible values: - - json: Represents JSON formatting for logs. This format outputs log records as JSON objects, making it suitable for structured logging - - log-fmt: Represents logfmt (key=value) formatting for logs. This format is concise and human-readable, typically used in command-line applications - - terminal: Represents terminal-friendly formatting for logs - - --log.file.filter - The filter to use for logs written to the log file - - [default: debug] - - --log.file.directory - The path to put log files in - - [default: /logs] - - --log.file.max-size - The maximum size (in MB) of one log file - - [default: 200] - - --log.file.max-files - The maximum amount of log files that will be stored. If set to 0, background file logging is disabled - - [default: 5] - - --log.journald - Write logs to journald - - --log.journald.filter - The filter to use for logs written to journald - - [default: error] - - --color - Sets whether or not the formatter emits ANSI terminal escape codes for colors and other text formatting - - [default: always] - - Possible values: - - always: Colors on - - auto: Colors on - - never: Colors off - -Display: - -v, --verbosity... - Set the minimum log level. - - -v Errors - -vv Warnings - -vvv Info - -vvvv Debug - -vvvvv Traces (warning: very verbose!) - - -q, --quiet - Silence all log output -``` \ No newline at end of file diff --git a/book/cli/reth/db/get/static_file.md b/book/cli/reth/db/get/static_file.md deleted file mode 100644 index 51071116c737..000000000000 --- a/book/cli/reth/db/get/static_file.md +++ /dev/null @@ -1,133 +0,0 @@ -# reth db get static-file - -Gets the content of a static_file segment for the given key - -```bash -$ reth db get static-file --help -Usage: reth db get static-file [OPTIONS] - -Arguments: - - Possible values: - - headers: StaticFile segment responsible for the `CanonicalHeaders`, `Headers`, `HeaderTerminalDifficulties` tables - - transactions: StaticFile segment responsible for the `Transactions` table - - receipts: StaticFile segment responsible for the `Receipts` table - - - The key to get content for - -Options: - --datadir - The path to the data dir for all reth files and subdirectories. - - Defaults to the OS-specific data directory: - - - Linux: `$XDG_DATA_HOME/reth/` or `$HOME/.local/share/reth/` - - Windows: `{FOLDERID_RoamingAppData}/reth/` - - macOS: `$HOME/Library/Application Support/reth/` - - [default: default] - - --raw - Output bytes instead of human-readable decoded value - - --chain - The chain this node is running. - Possible values are either a built-in chain or the path to a chain specification file. - - Built-in chains: - mainnet, sepolia, goerli, holesky, dev - - [default: mainnet] - - --instance - Add a new instance of a node. - - Configures the ports of the node to avoid conflicts with the defaults. This is useful for running multiple nodes on the same machine. - - Max number of instances is 200. It is chosen in a way so that it's not possible to have port numbers that conflict with each other. - - Changes to the following port numbers: - `DISCOVERY_PORT`: default + `instance` - 1 - `AUTH_PORT`: default + `instance` * 100 - 100 - `HTTP_RPC_PORT`: default - `instance` + 1 - `WS_RPC_PORT`: default + `instance` * 2 - 2 - - [default: 1] - - -h, --help - Print help (see a summary with '-h') - -Logging: - --log.stdout.format - The format to use for logs written to stdout - - [default: terminal] - - Possible values: - - json: Represents JSON formatting for logs. This format outputs log records as JSON objects, making it suitable for structured logging - - log-fmt: Represents logfmt (key=value) formatting for logs. This format is concise and human-readable, typically used in command-line applications - - terminal: Represents terminal-friendly formatting for logs - - --log.stdout.filter - The filter to use for logs written to stdout - - [default: ] - - --log.file.format - The format to use for logs written to the log file - - [default: terminal] - - Possible values: - - json: Represents JSON formatting for logs. This format outputs log records as JSON objects, making it suitable for structured logging - - log-fmt: Represents logfmt (key=value) formatting for logs. This format is concise and human-readable, typically used in command-line applications - - terminal: Represents terminal-friendly formatting for logs - - --log.file.filter - The filter to use for logs written to the log file - - [default: debug] - - --log.file.directory - The path to put log files in - - [default: /logs] - - --log.file.max-size - The maximum size (in MB) of one log file - - [default: 200] - - --log.file.max-files - The maximum amount of log files that will be stored. If set to 0, background file logging is disabled - - [default: 5] - - --log.journald - Write logs to journald - - --log.journald.filter - The filter to use for logs written to journald - - [default: error] - - --color - Sets whether or not the formatter emits ANSI terminal escape codes for colors and other text formatting - - [default: always] - - Possible values: - - always: Colors on - - auto: Colors on - - never: Colors off - -Display: - -v, --verbosity... - Set the minimum log level. - - -v Errors - -vv Warnings - -vvv Info - -vvvv Debug - -vvvvv Traces (warning: very verbose!) - - -q, --quiet - Silence all log output -``` \ No newline at end of file diff --git a/book/cli/reth/db/static_file.md b/book/cli/reth/db/static_file.md deleted file mode 100644 index 16246c8d47ed..000000000000 --- a/book/cli/reth/db/static_file.md +++ /dev/null @@ -1,174 +0,0 @@ -# reth db static-file - -StaticFiles tables from database - -```bash -$ reth db static-file --help -Usage: reth db static-file [OPTIONS] [SEGMENTS]... - -Arguments: - [SEGMENTS]... - StaticFile segments to generate - - Possible values: - - headers: StaticFile segment responsible for the `CanonicalHeaders`, `Headers`, `HeaderTerminalDifficulties` tables - - transactions: StaticFile segment responsible for the `Transactions` table - - receipts: StaticFile segment responsible for the `Receipts` table - -Options: - --datadir - The path to the data dir for all reth files and subdirectories. - - Defaults to the OS-specific data directory: - - - Linux: `$XDG_DATA_HOME/reth/` or `$HOME/.local/share/reth/` - - Windows: `{FOLDERID_RoamingAppData}/reth/` - - macOS: `$HOME/Library/Application Support/reth/` - - [default: default] - - -f, --from - Starting block for the static_file - - [default: 0] - - -b, --block-interval - Number of blocks in the static_file - - [default: 500000] - - --chain - The chain this node is running. - Possible values are either a built-in chain or the path to a chain specification file. - - Built-in chains: - mainnet, sepolia, goerli, holesky, dev - - [default: mainnet] - - -p, --parallel - Sets the number of static files built in parallel. Note: Each parallel build is memory-intensive - - [default: 1] - - --only-stats - Flag to skip static_file creation and print static_file files stats - - --bench - Flag to enable database-to-static_file benchmarking - - --only-bench - Flag to skip static_file creation and only run benchmarks on existing static files - - -c, --compression - Compression algorithms to use - - [default: uncompressed] - - Possible values: - - lz4: LZ4 compression algorithm - - zstd: Zstandard (Zstd) compression algorithm - - zstd-with-dictionary: Zstandard (Zstd) compression algorithm with a dictionary - - uncompressed: No compression, uncompressed static_file - - --with-filters - Flag to enable inclusion list filters and PHFs - - --phf - Specifies the perfect hashing function to use - - Possible values: - - fmph: Fingerprint-Based Minimal Perfect Hash Function - - go-fmph: Fingerprint-Based Minimal Perfect Hash Function with Group Optimization - - --instance - Add a new instance of a node. - - Configures the ports of the node to avoid conflicts with the defaults. This is useful for running multiple nodes on the same machine. - - Max number of instances is 200. It is chosen in a way so that it's not possible to have port numbers that conflict with each other. - - Changes to the following port numbers: - `DISCOVERY_PORT`: default + `instance` - 1 - `AUTH_PORT`: default + `instance` * 100 - 100 - `HTTP_RPC_PORT`: default - `instance` + 1 - `WS_RPC_PORT`: default + `instance` * 2 - 2 - - [default: 1] - - -h, --help - Print help (see a summary with '-h') - -Logging: - --log.stdout.format - The format to use for logs written to stdout - - [default: terminal] - - Possible values: - - json: Represents JSON formatting for logs. This format outputs log records as JSON objects, making it suitable for structured logging - - log-fmt: Represents logfmt (key=value) formatting for logs. This format is concise and human-readable, typically used in command-line applications - - terminal: Represents terminal-friendly formatting for logs - - --log.stdout.filter - The filter to use for logs written to stdout - - [default: ] - - --log.file.format - The format to use for logs written to the log file - - [default: terminal] - - Possible values: - - json: Represents JSON formatting for logs. This format outputs log records as JSON objects, making it suitable for structured logging - - log-fmt: Represents logfmt (key=value) formatting for logs. This format is concise and human-readable, typically used in command-line applications - - terminal: Represents terminal-friendly formatting for logs - - --log.file.filter - The filter to use for logs written to the log file - - [default: debug] - - --log.file.directory - The path to put log files in - - [default: /logs] - - --log.file.max-size - The maximum size (in MB) of one log file - - [default: 200] - - --log.file.max-files - The maximum amount of log files that will be stored. If set to 0, background file logging is disabled - - [default: 5] - - --log.journald - Write logs to journald - - --log.journald.filter - The filter to use for logs written to journald - - [default: error] - - --color - Sets whether or not the formatter emits ANSI terminal escape codes for colors and other text formatting - - [default: always] - - Possible values: - - always: Colors on - - auto: Colors on - - never: Colors off - -Display: - -v, --verbosity... - Set the minimum log level. - - -v Errors - -vv Warnings - -vvv Info - -vvvv Debug - -vvvvv Traces (warning: very verbose!) - - -q, --quiet - Silence all log output -``` From 237c22f234ea888c7004da2e2fe52eeb20de7720 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Sat, 31 Aug 2024 00:06:47 +0800 Subject: [PATCH 04/18] feat: use alloy_network::Network::BlockResponse instead of reth_rpc_types::Block in RPC (#10613) --- crates/rpc/rpc-eth-api/src/types.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/rpc/rpc-eth-api/src/types.rs b/crates/rpc/rpc-eth-api/src/types.rs index 3f0d526b01ce..55f137300761 100644 --- a/crates/rpc/rpc-eth-api/src/types.rs +++ b/crates/rpc/rpc-eth-api/src/types.rs @@ -20,7 +20,10 @@ pub trait EthApiTypes: Send + Sync + Clone { + Sync; /// Blockchain primitive types, specific to network, e.g. block and transaction. // todo: remove restriction `reth_rpc_types::Transaction` - type NetworkTypes: Network>; + type NetworkTypes: Network< + TransactionResponse = WithOtherFields, + HeaderResponse = reth_rpc_types::Header, + >; } impl EthApiTypes for () { @@ -32,4 +35,4 @@ impl EthApiTypes for () { pub type RpcTransaction = ::TransactionResponse; /// Adapter for network specific block type. -pub type RpcBlock = Block>; +pub type RpcBlock = Block, ::HeaderResponse>; From b4a18ccd93f243281a2819d5097c0d5b75dde610 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Sat, 31 Aug 2024 00:46:33 +0800 Subject: [PATCH 05/18] chore(op): rename file_codec_ovm_receipt.rs to receipt_file_codec.rs (#10622) --- crates/net/downloaders/src/receipt_file_client.rs | 12 ++++++------ crates/optimism/cli/src/commands/import_receipts.rs | 4 ++-- crates/optimism/cli/src/lib.rs | 4 ++-- ...le_codec_ovm_receipt.rs => receipt_file_codec.rs} | 0 4 files changed, 10 insertions(+), 10 deletions(-) rename crates/optimism/cli/src/{file_codec_ovm_receipt.rs => receipt_file_codec.rs} (100%) diff --git a/crates/net/downloaders/src/receipt_file_client.rs b/crates/net/downloaders/src/receipt_file_client.rs index fd0bb0901689..3776886dbc1f 100644 --- a/crates/net/downloaders/src/receipt_file_client.rs +++ b/crates/net/downloaders/src/receipt_file_client.rs @@ -381,14 +381,14 @@ mod test { .unwrap(), }; + // #[allow(clippy::needless_update)] not recognised, ..Default::default() needed so optimism + // feature must not be brought into scope let mut receipt = Receipt { tx_type: TxType::Legacy, success: true, cumulative_gas_used: 202819, ..Default::default() }; - // #[allow(clippy::needless_update)] not recognised, ..Default::default() needed so optimism - // feature must not be brought into scope receipt.logs = vec![log_1, log_2, log_3]; ReceiptWithBlockNumber { receipt, number: 1 } @@ -433,14 +433,14 @@ mod test { .unwrap(), }; + // #[allow(clippy::needless_update)] not recognised, ..Default::default() needed so optimism + // feature must not be brought into scope let mut receipt = Receipt { tx_type: TxType::Legacy, success: true, cumulative_gas_used: 116237, ..Default::default() }; - // #[allow(clippy::needless_update)] not recognised, ..Default::default() needed so optimism - // feature must not be brought into scope receipt.logs = vec![log_1, log_2]; ReceiptWithBlockNumber { receipt, number: 2 } @@ -485,14 +485,14 @@ mod test { .unwrap(), }; + // #[allow(clippy::needless_update)] not recognised, ..Default::default() needed so optimism + // feature must not be brought into scope let mut receipt = Receipt { tx_type: TxType::Legacy, success: true, cumulative_gas_used: 116237, ..Default::default() }; - // #[allow(clippy::needless_update)] not recognised, ..Default::default() needed so optimism - // feature must not be brought into scope receipt.logs = vec![log_1, log_2]; ReceiptWithBlockNumber { receipt, number: 3 } diff --git a/crates/optimism/cli/src/commands/import_receipts.rs b/crates/optimism/cli/src/commands/import_receipts.rs index ada06d47f52c..bebc35c08bf9 100644 --- a/crates/optimism/cli/src/commands/import_receipts.rs +++ b/crates/optimism/cli/src/commands/import_receipts.rs @@ -25,7 +25,7 @@ use reth_stages::StageId; use reth_static_file_types::StaticFileSegment; use tracing::{debug, error, info, trace}; -use crate::file_codec_ovm_receipt::HackReceiptFileCodec; +use crate::receipt_file_codec::HackReceiptFileCodec; /// Initializes the database with the genesis block. #[derive(Debug, Parser)] @@ -259,7 +259,7 @@ mod test { io::{AsyncSeekExt, AsyncWriteExt, SeekFrom}, }; - use crate::file_codec_ovm_receipt::test::{ + use crate::receipt_file_codec::test::{ HACK_RECEIPT_ENCODED_BLOCK_1, HACK_RECEIPT_ENCODED_BLOCK_2, HACK_RECEIPT_ENCODED_BLOCK_3, }; diff --git a/crates/optimism/cli/src/lib.rs b/crates/optimism/cli/src/lib.rs index 48abdde8dce0..2314fe36466c 100644 --- a/crates/optimism/cli/src/lib.rs +++ b/crates/optimism/cli/src/lib.rs @@ -18,14 +18,14 @@ pub mod commands; /// /// Enables decoding and encoding `HackReceipt` type. See . /// -/// Currently configured to use codec [`HackReceipt`](file_codec_ovm_receipt::HackReceipt) based on +/// Currently configured to use codec [`HackReceipt`](receipt_file_codec::HackReceipt) based on /// export of below Bedrock data using . Codec can /// be replaced with regular encoding of receipts for export. /// /// NOTE: receipts can be exported using regular op-geth encoding for `Receipt` type, to fit /// reth's needs for importing. However, this would require patching the diff in to export the `Receipt` and not `HackReceipt` type (originally /// made for op-erigon's import needs). -pub mod file_codec_ovm_receipt; +pub mod receipt_file_codec; pub use commands::{import::ImportOpCommand, import_receipts::ImportReceiptsOpCommand}; diff --git a/crates/optimism/cli/src/file_codec_ovm_receipt.rs b/crates/optimism/cli/src/receipt_file_codec.rs similarity index 100% rename from crates/optimism/cli/src/file_codec_ovm_receipt.rs rename to crates/optimism/cli/src/receipt_file_codec.rs From 24f04710c0d94bb61db65f90d166ef1c8d39a5d6 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Sat, 31 Aug 2024 00:58:59 +0800 Subject: [PATCH 06/18] feat: use alloy_network::Network::ReceiptResponse instead of AnyTransactionReceipt in RPC (#10621) --- crates/rpc/rpc-builder/src/lib.rs | 8 +- crates/rpc/rpc-builder/tests/it/http.rs | 114 ++++++++++++------ crates/rpc/rpc-builder/tests/it/middleware.rs | 4 +- crates/rpc/rpc-eth-api/src/core.rs | 43 ++++--- crates/rpc/rpc-eth-api/src/lib.rs | 2 +- crates/rpc/rpc-eth-api/src/types.rs | 9 +- crates/rpc/rpc-testing-util/src/debug.rs | 4 +- crates/rpc/rpc-testing-util/tests/it/trace.rs | 3 +- crates/rpc/rpc/src/engine.rs | 9 +- crates/rpc/rpc/src/eth/core.rs | 8 +- crates/rpc/rpc/src/otterscan.rs | 9 +- 11 files changed, 139 insertions(+), 74 deletions(-) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index 6c454bff6b57..58f2d9b8fe13 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -791,7 +791,11 @@ where /// If called outside of the tokio runtime. See also [`Self::eth_api`] pub fn register_eth(&mut self) -> &mut Self where - EthApi: EthApiServer, + EthApi: EthApiServer< + reth_rpc_types::Transaction, + reth_rpc_types::Block, + reth_rpc_types::AnyTransactionReceipt, + >, { let eth_api = self.eth_api().clone(); self.modules.insert(RethRpcModule::Eth, eth_api.into_rpc().into()); @@ -808,6 +812,7 @@ where EthApi: EthApiServer< WithOtherFields, reth_rpc_types::Block>, + reth_rpc_types::AnyTransactionReceipt, > + TraceExt, { let otterscan_api = self.otterscan_api(); @@ -911,6 +916,7 @@ where EthApi: EthApiServer< WithOtherFields, reth_rpc_types::Block>, + reth_rpc_types::AnyTransactionReceipt, > + TraceExt, { let eth_api = self.eth_api().clone(); diff --git a/crates/rpc/rpc-builder/tests/it/http.rs b/crates/rpc/rpc-builder/tests/it/http.rs index 8e9c7ce60835..659f9dc70ac5 100644 --- a/crates/rpc/rpc-builder/tests/it/http.rs +++ b/crates/rpc/rpc-builder/tests/it/http.rs @@ -13,7 +13,8 @@ use jsonrpsee::{ }; use reth_network_peers::NodeRecord; use reth_primitives::{ - hex_literal::hex, Address, BlockId, BlockNumberOrTag, Bytes, TxHash, B256, B64, U256, U64, + hex_literal::hex, Address, BlockId, BlockNumberOrTag, Bytes, Receipt, TxHash, B256, B64, U256, + U64, }; use reth_rpc_api::{ clients::{AdminApiClient, EthApiClient}, @@ -173,68 +174,93 @@ where .unwrap(); // Implemented - EthApiClient::::protocol_version(client).await.unwrap(); - EthApiClient::::chain_id(client).await.unwrap(); - EthApiClient::::accounts(client).await.unwrap(); - EthApiClient::::get_account(client, address, block_number.into()) + EthApiClient::::protocol_version(client).await.unwrap(); + EthApiClient::::chain_id(client).await.unwrap(); + EthApiClient::::accounts(client).await.unwrap(); + EthApiClient::::get_account(client, address, block_number.into()) .await .unwrap(); - EthApiClient::::block_number(client).await.unwrap(); - EthApiClient::::get_code(client, address, None).await.unwrap(); - EthApiClient::::send_raw_transaction(client, tx).await.unwrap(); - EthApiClient::::fee_history(client, U64::from(0), block_number, None) + EthApiClient::::block_number(client).await.unwrap(); + EthApiClient::::get_code(client, address, None).await.unwrap(); + EthApiClient::::send_raw_transaction(client, tx).await.unwrap(); + EthApiClient::::fee_history( + client, + U64::from(0), + block_number, + None, + ) + .await + .unwrap(); + EthApiClient::::balance(client, address, None).await.unwrap(); + EthApiClient::::transaction_count(client, address, None) .await .unwrap(); - EthApiClient::::balance(client, address, None).await.unwrap(); - EthApiClient::::transaction_count(client, address, None).await.unwrap(); - EthApiClient::::storage_at(client, address, U256::default().into(), None) + EthApiClient::::storage_at( + client, + address, + U256::default().into(), + None, + ) + .await + .unwrap(); + EthApiClient::::block_by_hash(client, hash, false).await.unwrap(); + EthApiClient::::block_by_number(client, block_number, false) .await .unwrap(); - EthApiClient::::block_by_hash(client, hash, false).await.unwrap(); - EthApiClient::::block_by_number(client, block_number, false).await.unwrap(); - EthApiClient::::block_transaction_count_by_number(client, block_number) + EthApiClient::::block_transaction_count_by_number( + client, + block_number, + ) + .await + .unwrap(); + EthApiClient::::block_transaction_count_by_hash(client, hash) .await .unwrap(); - EthApiClient::::block_transaction_count_by_hash(client, hash) + EthApiClient::::block_uncles_count_by_hash(client, hash) .await .unwrap(); - EthApiClient::::block_uncles_count_by_hash(client, hash).await.unwrap(); - EthApiClient::::block_uncles_count_by_number(client, block_number) + EthApiClient::::block_uncles_count_by_number(client, block_number) .await .unwrap(); - EthApiClient::::uncle_by_block_hash_and_index(client, hash, index) + EthApiClient::::uncle_by_block_hash_and_index(client, hash, index) .await .unwrap(); - EthApiClient::::uncle_by_block_number_and_index( + EthApiClient::::uncle_by_block_number_and_index( client, block_number, index, ) .await .unwrap(); - EthApiClient::::sign(client, address, bytes.clone()).await.unwrap_err(); - EthApiClient::::sign_typed_data(client, address, typed_data) + EthApiClient::::sign(client, address, bytes.clone()) + .await + .unwrap_err(); + EthApiClient::::sign_typed_data(client, address, typed_data) .await .unwrap_err(); - EthApiClient::::transaction_by_hash(client, tx_hash).await.unwrap(); - EthApiClient::::transaction_by_block_hash_and_index(client, hash, index) + EthApiClient::::transaction_by_hash(client, tx_hash) .await .unwrap(); - EthApiClient::::transaction_by_block_number_and_index( + EthApiClient::::transaction_by_block_hash_and_index( + client, hash, index, + ) + .await + .unwrap(); + EthApiClient::::transaction_by_block_number_and_index( client, block_number, index, ) .await .unwrap(); - EthApiClient::::create_access_list( + EthApiClient::::create_access_list( client, call_request.clone(), Some(block_number.into()), ) .await .unwrap(); - EthApiClient::::estimate_gas( + EthApiClient::::estimate_gas( client, call_request.clone(), Some(block_number.into()), @@ -242,7 +268,7 @@ where ) .await .unwrap(); - EthApiClient::::call( + EthApiClient::::call( client, call_request.clone(), Some(block_number.into()), @@ -251,30 +277,38 @@ where ) .await .unwrap(); - EthApiClient::::syncing(client).await.unwrap(); - EthApiClient::::send_transaction(client, transaction_request) + EthApiClient::::syncing(client).await.unwrap(); + EthApiClient::::send_transaction(client, transaction_request) + .await + .unwrap_err(); + EthApiClient::::hashrate(client).await.unwrap(); + EthApiClient::::submit_hashrate( + client, + U256::default(), + B256::default(), + ) + .await + .unwrap(); + EthApiClient::::gas_price(client).await.unwrap_err(); + EthApiClient::::max_priority_fee_per_gas(client) .await .unwrap_err(); - EthApiClient::::hashrate(client).await.unwrap(); - EthApiClient::::submit_hashrate(client, U256::default(), B256::default()) + EthApiClient::::get_proof(client, address, vec![], None) .await .unwrap(); - EthApiClient::::gas_price(client).await.unwrap_err(); - EthApiClient::::max_priority_fee_per_gas(client).await.unwrap_err(); - EthApiClient::::get_proof(client, address, vec![], None).await.unwrap(); // Unimplemented assert!(is_unimplemented( - EthApiClient::::author(client).await.err().unwrap() + EthApiClient::::author(client).await.err().unwrap() )); assert!(is_unimplemented( - EthApiClient::::is_mining(client).await.err().unwrap() + EthApiClient::::is_mining(client).await.err().unwrap() )); assert!(is_unimplemented( - EthApiClient::::get_work(client).await.err().unwrap() + EthApiClient::::get_work(client).await.err().unwrap() )); assert!(is_unimplemented( - EthApiClient::::submit_work( + EthApiClient::::submit_work( client, B64::default(), B256::default(), @@ -285,7 +319,7 @@ where .unwrap() )); assert!(is_unimplemented( - EthApiClient::::sign_transaction(client, call_request.clone()) + EthApiClient::::sign_transaction(client, call_request.clone()) .await .err() .unwrap() diff --git a/crates/rpc/rpc-builder/tests/it/middleware.rs b/crates/rpc/rpc-builder/tests/it/middleware.rs index 6ef6c7f67797..e95ee07642c7 100644 --- a/crates/rpc/rpc-builder/tests/it/middleware.rs +++ b/crates/rpc/rpc-builder/tests/it/middleware.rs @@ -8,7 +8,7 @@ use reth_rpc::EthApi; use reth_rpc_builder::{RpcServerConfig, TransportRpcModuleConfig}; use reth_rpc_eth_api::EthApiClient; use reth_rpc_server_types::RpcModuleSelection; -use reth_rpc_types::{Block, Transaction}; +use reth_rpc_types::{Block, Receipt, Transaction}; use std::{ future::Future, pin::Pin, @@ -75,7 +75,7 @@ async fn test_rpc_middleware() { .unwrap(); let client = handle.http_client().unwrap(); - EthApiClient::::protocol_version(&client).await.unwrap(); + EthApiClient::::protocol_version(&client).await.unwrap(); let count = mylayer.count.load(Ordering::Relaxed); assert_eq!(count, 1); } diff --git a/crates/rpc/rpc-eth-api/src/core.rs b/crates/rpc/rpc-eth-api/src/core.rs index 409dc0076791..9a19307ce990 100644 --- a/crates/rpc/rpc-eth-api/src/core.rs +++ b/crates/rpc/rpc-eth-api/src/core.rs @@ -13,8 +13,8 @@ use reth_rpc_types::{ serde_helpers::JsonStorageKey, simulate::{SimBlock, SimulatedBlock}, state::{EvmOverrides, StateOverride}, - AnyTransactionReceipt, BlockOverrides, BlockTransactions, Bundle, EIP1186AccountProofResponse, - EthCallResponse, FeeHistory, Header, Index, StateContext, SyncStatus, TransactionRequest, Work, + BlockOverrides, BlockTransactions, Bundle, EIP1186AccountProofResponse, EthCallResponse, + FeeHistory, Header, Index, StateContext, SyncStatus, TransactionRequest, Work, }; use reth_transaction_pool::{PoolTransaction, TransactionPool}; use tracing::trace; @@ -23,19 +23,27 @@ use crate::{ helpers::{ EthApiSpec, EthBlocks, EthCall, EthFees, EthState, EthTransactions, FullEthApi, LoadState, }, - RpcBlock, RpcTransaction, + RpcBlock, RpcReceipt, RpcTransaction, }; /// Helper trait, unifies functionality that must be supported to implement all RPC methods for /// server. pub trait FullEthApiServer: - EthApiServer, RpcBlock> + FullEthApi + Clone + EthApiServer< + RpcTransaction, + RpcBlock, + RpcReceipt, + > + FullEthApi + + Clone { } impl FullEthApiServer for T where - T: EthApiServer, RpcBlock> - + FullEthApi + T: EthApiServer< + RpcTransaction, + RpcBlock, + RpcReceipt, + > + FullEthApi + Clone { } @@ -43,7 +51,7 @@ impl FullEthApiServer for T where /// Eth rpc interface: #[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))] #[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))] -pub trait EthApi { +pub trait EthApi { /// Returns the protocol version encoded as a string. #[method(name = "protocolVersion")] async fn protocol_version(&self) -> RpcResult; @@ -100,10 +108,7 @@ pub trait EthApi { /// Returns all transaction receipts for a given block. #[method(name = "getBlockReceipts")] - async fn block_receipts( - &self, - block_id: BlockId, - ) -> RpcResult>>; + async fn block_receipts(&self, block_id: BlockId) -> RpcResult>>; /// Returns an uncle block of the given block and index. #[method(name = "getUncleByBlockHashAndIndex")] @@ -171,7 +176,7 @@ pub trait EthApi { /// Returns the receipt of a transaction by transaction hash. #[method(name = "getTransactionReceipt")] - async fn transaction_receipt(&self, hash: B256) -> RpcResult>; + async fn transaction_receipt(&self, hash: B256) -> RpcResult>; /// Returns the balance of the account of given address. #[method(name = "getBalance")] @@ -361,7 +366,12 @@ pub trait EthApi { } #[async_trait::async_trait] -impl EthApiServer, RpcBlock> for T +impl + EthApiServer< + RpcTransaction, + RpcBlock, + RpcReceipt, + > for T where T: FullEthApi, jsonrpsee_types::error::ErrorObject<'static>: From, @@ -457,7 +467,7 @@ where async fn block_receipts( &self, block_id: BlockId, - ) -> RpcResult>> { + ) -> RpcResult>>> { trace!(target: "rpc::eth", ?block_id, "Serving eth_getBlockReceipts"); Ok(EthBlocks::block_receipts(self, block_id).await?) } @@ -604,7 +614,10 @@ where } /// Handler for: `eth_getTransactionReceipt` - async fn transaction_receipt(&self, hash: B256) -> RpcResult> { + async fn transaction_receipt( + &self, + hash: B256, + ) -> RpcResult>> { trace!(target: "rpc::eth", ?hash, "Serving eth_getTransactionReceipt"); Ok(EthTransactions::transaction_receipt(self, hash).await?) } diff --git a/crates/rpc/rpc-eth-api/src/lib.rs b/crates/rpc/rpc-eth-api/src/lib.rs index 30623d6b8e2f..ec6490917c33 100644 --- a/crates/rpc/rpc-eth-api/src/lib.rs +++ b/crates/rpc/rpc-eth-api/src/lib.rs @@ -24,7 +24,7 @@ pub use core::{EthApiServer, FullEthApiServer}; pub use filter::EthFilterApiServer; pub use helpers::error::{AsEthApiError, FromEthApiError, FromEvmError, IntoEthApiError}; pub use pubsub::EthPubSubApiServer; -pub use types::{EthApiTypes, RpcBlock, RpcTransaction}; +pub use types::{EthApiTypes, RpcBlock, RpcReceipt, RpcTransaction}; #[cfg(feature = "client")] pub use bundle::{EthBundleApiClient, EthCallBundleApiClient}; diff --git a/crates/rpc/rpc-eth-api/src/types.rs b/crates/rpc/rpc-eth-api/src/types.rs index 55f137300761..e1d83095adaa 100644 --- a/crates/rpc/rpc-eth-api/src/types.rs +++ b/crates/rpc/rpc-eth-api/src/types.rs @@ -4,7 +4,7 @@ use std::error::Error; use alloy_network::{AnyNetwork, Network}; use reth_rpc_eth_types::EthApiError; -use reth_rpc_types::{Block, Transaction, WithOtherFields}; +use reth_rpc_types::{AnyTransactionReceipt, Block, Transaction, WithOtherFields}; use crate::{AsEthApiError, FromEthApiError, FromEvmError}; @@ -19,10 +19,12 @@ pub trait EthApiTypes: Send + Sync + Clone { + Send + Sync; /// Blockchain primitive types, specific to network, e.g. block and transaction. - // todo: remove restriction `reth_rpc_types::Transaction` + // todo: remove restriction [`reth_rpc_types::Transaction`] + // todo: remove restriction [`reth_rpc_types::AnyTransactionReceipt`] type NetworkTypes: Network< TransactionResponse = WithOtherFields, HeaderResponse = reth_rpc_types::Header, + ReceiptResponse = AnyTransactionReceipt, >; } @@ -36,3 +38,6 @@ pub type RpcTransaction = ::TransactionResponse; /// Adapter for network specific block type. pub type RpcBlock = Block, ::HeaderResponse>; + +/// Adapter for network specific receipt type. +pub type RpcReceipt = ::ReceiptResponse; diff --git a/crates/rpc/rpc-testing-util/src/debug.rs b/crates/rpc/rpc-testing-util/src/debug.rs index 5bb003dac8e7..9bbccaa2a43d 100644 --- a/crates/rpc/rpc-testing-util/src/debug.rs +++ b/crates/rpc/rpc-testing-util/src/debug.rs @@ -8,7 +8,7 @@ use std::{ use futures::{Stream, StreamExt}; use jsonrpsee::core::client::Error as RpcError; -use reth_primitives::{BlockId, TxHash, B256}; +use reth_primitives::{BlockId, Receipt, TxHash, B256}; use reth_rpc_api::{clients::DebugApiClient, EthApiClient}; use reth_rpc_types::{ trace::{ @@ -77,7 +77,7 @@ pub trait DebugApiExt { impl DebugApiExt for T where - T: EthApiClient + DebugApiClient + Sync, + T: EthApiClient + DebugApiClient + Sync, { type Provider = T; diff --git a/crates/rpc/rpc-testing-util/tests/it/trace.rs b/crates/rpc/rpc-testing-util/tests/it/trace.rs index 619c1ed43374..46d17e40b2ee 100644 --- a/crates/rpc/rpc-testing-util/tests/it/trace.rs +++ b/crates/rpc/rpc-testing-util/tests/it/trace.rs @@ -3,6 +3,7 @@ use std::{collections::HashSet, time::Instant}; use futures::StreamExt; use jsonrpsee::http_client::HttpClientBuilder; use jsonrpsee_http_client::HttpClient; +use reth_primitives::Receipt; use reth_rpc_api_testing_util::{debug::DebugApiExt, trace::TraceApiExt, utils::parse_env_url}; use reth_rpc_eth_api::EthApiClient; use reth_rpc_types::{ @@ -110,7 +111,7 @@ async fn debug_trace_block_entire_chain() { let client = HttpClientBuilder::default().build(url).unwrap(); let current_block: u64 = - >::block_number(&client) + >::block_number(&client) .await .unwrap() .try_into() diff --git a/crates/rpc/rpc/src/engine.rs b/crates/rpc/rpc/src/engine.rs index d21834213716..50bd33545b68 100644 --- a/crates/rpc/rpc/src/engine.rs +++ b/crates/rpc/rpc/src/engine.rs @@ -4,7 +4,7 @@ use reth_primitives::{Address, BlockId, BlockNumberOrTag, Bytes, B256, U256, U64 use reth_rpc_api::{EngineEthApiServer, EthApiServer, EthFilterApiServer}; /// Re-export for convenience pub use reth_rpc_engine_api::EngineApi; -use reth_rpc_eth_api::{EthApiTypes, RpcBlock, RpcTransaction}; +use reth_rpc_eth_api::{EthApiTypes, RpcBlock, RpcReceipt, RpcTransaction}; use reth_rpc_types::{ state::StateOverride, BlockOverrides, EIP1186AccountProofResponse, Filter, JsonStorageKey, Log, SyncStatus, TransactionRequest, WithOtherFields, @@ -36,8 +36,11 @@ impl EngineEthApi { impl EngineEthApiServer> for EngineEthApi where - Eth: EthApiServer, RpcBlock> - + EthApiTypes< + Eth: EthApiServer< + RpcTransaction, + RpcBlock, + RpcReceipt, + > + EthApiTypes< NetworkTypes: Network< TransactionResponse = WithOtherFields, >, diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index c79007fe3d4d..06e1be121374 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -490,7 +490,7 @@ mod tests { /// Invalid block range #[tokio::test] async fn test_fee_history_empty() { - let response = as EthApiServer<_, _>>::fee_history( + let response = as EthApiServer<_, _, _>>::fee_history( &build_test_eth_api(NoopProvider::default()), U64::from(1), BlockNumberOrTag::Latest, @@ -512,7 +512,7 @@ mod tests { let (eth_api, _, _) = prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default()); - let response = as EthApiServer<_, _>>::fee_history( + let response = as EthApiServer<_, _, _>>::fee_history( ð_api, U64::from(newest_block + 1), newest_block.into(), @@ -535,7 +535,7 @@ mod tests { let (eth_api, _, _) = prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default()); - let response = as EthApiServer<_, _>>::fee_history( + let response = as EthApiServer<_, _, _>>::fee_history( ð_api, U64::from(1), (newest_block + 1000).into(), @@ -558,7 +558,7 @@ mod tests { let (eth_api, _, _) = prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default()); - let response = as EthApiServer<_, _>>::fee_history( + let response = as EthApiServer<_, _, _>>::fee_history( ð_api, U64::from(0), newest_block.into(), diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index 06b95c2e1498..dd9a539563bf 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use jsonrpsee::{core::RpcResult, types::ErrorObjectOwned}; use reth_primitives::{Address, BlockNumberOrTag, TxHash, B256, U256}; use reth_rpc_api::{EthApiServer, OtterscanServer}; -use reth_rpc_eth_api::{helpers::TraceExt, EthApiTypes, RpcBlock, RpcTransaction}; +use reth_rpc_eth_api::{helpers::TraceExt, EthApiTypes, RpcBlock, RpcReceipt, RpcTransaction}; use reth_rpc_eth_types::{utils::binary_search, EthApiError}; use reth_rpc_server_types::result::internal_rpc_err; use reth_rpc_types::{ @@ -66,8 +66,11 @@ where #[async_trait] impl OtterscanServer for OtterscanApi where - Eth: EthApiServer, RpcBlock> - + EthApiTypes< + Eth: EthApiServer< + RpcTransaction, + RpcBlock, + RpcReceipt, + > + EthApiTypes< NetworkTypes: Network< TransactionResponse = WithOtherFields, >, From 3efe22eae7d4b976cf9a8065fd10920a33f1de9c Mon Sep 17 00:00:00 2001 From: Delweng Date: Sun, 1 Sep 2024 00:57:34 +0800 Subject: [PATCH 07/18] feat(rpc): dedup rpc getTxBySenderAndNonce (#10600) Signed-off-by: jsvisa --- crates/rpc/rpc-builder/src/lib.rs | 6 +- crates/rpc/rpc-eth-api/src/core.rs | 63 ++------------ crates/rpc/rpc-eth-api/src/helpers/state.rs | 28 ++++-- .../rpc-eth-api/src/helpers/transaction.rs | 85 ++++++++++++++++++- crates/rpc/rpc/src/otterscan.rs | 64 ++++---------- 5 files changed, 127 insertions(+), 119 deletions(-) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index 58f2d9b8fe13..f82532432291 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -813,7 +813,8 @@ where WithOtherFields, reth_rpc_types::Block>, reth_rpc_types::AnyTransactionReceipt, - > + TraceExt, + > + TraceExt + + EthTransactions, { let otterscan_api = self.otterscan_api(); self.modules.insert(RethRpcModule::Ots, otterscan_api.into_rpc().into()); @@ -917,7 +918,8 @@ where WithOtherFields, reth_rpc_types::Block>, reth_rpc_types::AnyTransactionReceipt, - > + TraceExt, + > + TraceExt + + EthTransactions, { let eth_api = self.eth_api().clone(); OtterscanApi::new(eth_api) diff --git a/crates/rpc/rpc-eth-api/src/core.rs b/crates/rpc/rpc-eth-api/src/core.rs index 9a19307ce990..b9d22a7221e1 100644 --- a/crates/rpc/rpc-eth-api/src/core.rs +++ b/crates/rpc/rpc-eth-api/src/core.rs @@ -3,26 +3,22 @@ use alloy_dyn_abi::TypedData; use alloy_json_rpc::RpcObject; -use jsonrpsee::{core::RpcResult, proc_macros::rpc, types::ErrorObjectOwned}; +use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_primitives::{ transaction::AccessListResult, Address, BlockId, BlockNumberOrTag, Bytes, B256, B64, U256, U64, }; -use reth_rpc_eth_types::{utils::binary_search, EthApiError}; use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult}; use reth_rpc_types::{ serde_helpers::JsonStorageKey, simulate::{SimBlock, SimulatedBlock}, state::{EvmOverrides, StateOverride}, - BlockOverrides, BlockTransactions, Bundle, EIP1186AccountProofResponse, EthCallResponse, - FeeHistory, Header, Index, StateContext, SyncStatus, TransactionRequest, Work, + BlockOverrides, Bundle, EIP1186AccountProofResponse, EthCallResponse, FeeHistory, Header, + Index, StateContext, SyncStatus, TransactionRequest, Work, }; -use reth_transaction_pool::{PoolTransaction, TransactionPool}; use tracing::trace; use crate::{ - helpers::{ - EthApiSpec, EthBlocks, EthCall, EthFees, EthState, EthTransactions, FullEthApi, LoadState, - }, + helpers::{EthApiSpec, EthBlocks, EthCall, EthFees, EthState, EthTransactions, FullEthApi}, RpcBlock, RpcReceipt, RpcTransaction, }; @@ -562,55 +558,8 @@ where nonce: U64, ) -> RpcResult>> { trace!(target: "rpc::eth", ?sender, ?nonce, "Serving eth_getTransactionBySenderAndNonce"); - let nonce = nonce.to::(); - - // Check the pool first - if let Some(tx) = LoadState::pool(self).get_transaction_by_sender_and_nonce(sender, nonce) { - let transaction = tx.transaction.clone().into_consensus(); - return Ok(Some(reth_rpc_types_compat::transaction::from_recovered(transaction))) - } - - // Check if the sender is a contract - if self.get_code(sender, None).await?.len() > 0 { - return Ok(None) - } - - let highest = EthState::transaction_count(self, sender, None).await?.saturating_to::(); - - // If the nonce is higher or equal to the highest nonce, the transaction is pending or not - // exists. - if nonce >= highest { - return Ok(None) - } - - // perform a binary search over the block range to find the block in which the sender's - // nonce reached the requested nonce. - let num = binary_search::<_, _, ErrorObjectOwned>( - 1, - self.block_number()?.saturating_to(), - |mid| { - async move { - let mid_nonce = EthState::transaction_count(self, sender, Some(mid.into())) - .await? - .saturating_to::(); - - // The `transaction_count` returns the `nonce` after the transaction was - // executed, which is the state of the account after the block, and we need to - // find the transaction whose nonce is the pre-state, so - // need to compare with `nonce`(no equal). - Ok(mid_nonce > nonce) - } - }, - ) - .await?; - - let Some(BlockTransactions::Full(transactions)) = - self.block_by_number(num.into(), true).await?.map(|block| block.transactions) - else { - return Err(EthApiError::UnknownBlockNumber.into()); - }; - - Ok(transactions.into_iter().find(|tx| *tx.from == *sender && tx.nonce == nonce)) + Ok(EthTransactions::get_transaction_by_sender_and_nonce(self, sender, nonce.to(), true) + .await?) } /// Handler for: `eth_getTransactionReceipt` diff --git a/crates/rpc/rpc-eth-api/src/helpers/state.rs b/crates/rpc/rpc-eth-api/src/helpers/state.rs index 5145bbade648..06c3f9b5b8b1 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/state.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/state.rs @@ -42,14 +42,7 @@ pub trait EthState: LoadState + SpawnBlocking { address: Address, block_id: Option, ) -> impl Future> + Send { - self.spawn_blocking_io(move |this| { - Ok(this - .state_at_block_id_or_latest(block_id)? - .account_code(address) - .map_err(Self::Error::from_eth_err)? - .unwrap_or_default() - .original_bytes()) - }) + LoadState::get_code(self, address, block_id) } /// Returns balance of given account, at given blocknumber. @@ -295,4 +288,23 @@ pub trait LoadState: EthApiTypes { )) }) } + + /// Returns code of given account, at the given identifier. + fn get_code( + &self, + address: Address, + block_id: Option, + ) -> impl Future> + Send + where + Self: SpawnBlocking, + { + self.spawn_blocking_io(move |this| { + Ok(this + .state_at_block_id_or_latest(block_id)? + .account_code(address) + .map_err(Self::Error::from_eth_err)? + .unwrap_or_default() + .original_bytes()) + }) + } } diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index cf7bbf025b05..5e9fd24d785d 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -7,9 +7,10 @@ use reth_primitives::{ Address, BlockId, Bytes, Receipt, SealedBlockWithSenders, TransactionMeta, TransactionSigned, TxHash, TxKind, B256, U256, }; -use reth_provider::{BlockReaderIdExt, ReceiptProvider, TransactionsProvider}; +use reth_provider::{BlockNumReader, BlockReaderIdExt, ReceiptProvider, TransactionsProvider}; use reth_rpc_eth_types::{ - utils::recover_raw_transaction, EthApiError, EthStateCache, SignError, TransactionSource, + utils::{binary_search, recover_raw_transaction}, + EthApiError, EthStateCache, SignError, TransactionSource, }; use reth_rpc_types::{ transaction::{ @@ -18,13 +19,14 @@ use reth_rpc_types::{ }, AnyTransactionReceipt, TransactionInfo, TransactionRequest, TypedTransactionRequest, }; -use reth_rpc_types_compat::transaction::from_recovered_with_block_context; +use reth_rpc_types_compat::transaction::{from_recovered, from_recovered_with_block_context}; use reth_transaction_pool::{PoolTransaction, TransactionOrigin, TransactionPool}; use crate::{FromEthApiError, IntoEthApiError, RpcTransaction}; use super::{ - Call, EthApiSpec, EthSigner, LoadBlock, LoadFee, LoadPendingBlock, LoadReceipt, SpawnBlocking, + Call, EthApiSpec, EthSigner, LoadBlock, LoadFee, LoadPendingBlock, LoadReceipt, LoadState, + SpawnBlocking, }; /// Transaction related functions for the [`EthApiServer`](crate::EthApiServer) trait in @@ -212,6 +214,81 @@ pub trait EthTransactions: LoadTransaction { } } + /// Find a transaction by sender's address and nonce. + fn get_transaction_by_sender_and_nonce( + &self, + sender: Address, + nonce: u64, + include_pending: bool, + ) -> impl Future>, Self::Error>> + Send + where + Self: LoadBlock + LoadState, + { + async move { + // Check the pool first + if include_pending { + if let Some(tx) = + LoadState::pool(self).get_transaction_by_sender_and_nonce(sender, nonce) + { + let transaction = tx.transaction.clone().into_consensus(); + return Ok(Some(from_recovered(transaction))); + } + } + + // Check if the sender is a contract + if self.get_code(sender, None).await?.len() > 0 { + return Ok(None); + } + + let highest = self.transaction_count(sender, None).await?.saturating_to::(); + + // If the nonce is higher or equal to the highest nonce, the transaction is pending or + // not exists. + if nonce >= highest { + return Ok(None); + } + + let Ok(high) = LoadBlock::provider(self).best_block_number() else { + return Err(EthApiError::UnknownBlockNumber.into()); + }; + + // Perform a binary search over the block range to find the block in which the sender's + // nonce reached the requested nonce. + let num = binary_search::<_, _, Self::Error>(1, high, |mid| async move { + let mid_nonce = + self.transaction_count(sender, Some(mid.into())).await?.saturating_to::(); + + Ok(mid_nonce > nonce) + }) + .await?; + + self.block_with_senders(num.into()) + .await? + .and_then(|block| { + let block_hash = block.hash(); + let block_number = block.number; + let base_fee_per_gas = block.base_fee_per_gas; + + block + .into_transactions_ecrecovered() + .enumerate() + .find(|(_, tx)| tx.signer() == sender && tx.nonce() == nonce) + .map(|(index, tx)| { + let tx_info = TransactionInfo { + hash: Some(tx.hash()), + block_hash: Some(block_hash), + block_number: Some(block_number), + base_fee: base_fee_per_gas.map(u128::from), + index: Some(index as u64), + }; + from_recovered_with_block_context(tx, tx_info) + }) + }) + .ok_or(EthApiError::UnknownBlockNumber.into()) + .map(Some) + } + } + /// Get transaction, as raw bytes, by [`BlockId`] and index of transaction within that block. /// /// Returns `Ok(None)` if the block does not exist, or index is out of range. diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index dd9a539563bf..d151f783f8c5 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -4,7 +4,10 @@ use async_trait::async_trait; use jsonrpsee::{core::RpcResult, types::ErrorObjectOwned}; use reth_primitives::{Address, BlockNumberOrTag, TxHash, B256, U256}; use reth_rpc_api::{EthApiServer, OtterscanServer}; -use reth_rpc_eth_api::{helpers::TraceExt, EthApiTypes, RpcBlock, RpcReceipt, RpcTransaction}; +use reth_rpc_eth_api::{ + helpers::{EthTransactions, TraceExt}, + EthApiTypes, RpcBlock, RpcReceipt, RpcTransaction, +}; use reth_rpc_eth_types::{utils::binary_search, EthApiError}; use reth_rpc_server_types::result::internal_rpc_err; use reth_rpc_types::{ @@ -75,6 +78,7 @@ where TransactionResponse = WithOtherFields, >, > + TraceExt + + EthTransactions + 'static, { /// Handler for `{ots,erigon}_getHeaderByNumber` @@ -84,7 +88,9 @@ where /// Handler for `ots_hasCode` async fn has_code(&self, address: Address, block_number: Option) -> RpcResult { - self.eth.get_code(address, block_number.map(Into::into)).await.map(|code| !code.is_empty()) + EthApiServer::get_code(&self.eth, address, block_number.map(Into::into)) + .await + .map(|code| !code.is_empty()) } /// Handler for `ots_getApiLevel` @@ -282,51 +288,11 @@ where sender: Address, nonce: u64, ) -> RpcResult> { - // Check if the sender is a contract - if self.has_code(sender, None).await? { - return Ok(None) - } - - let highest = - EthApiServer::transaction_count(&self.eth, sender, None).await?.saturating_to::(); - - // If the nonce is higher or equal to the highest nonce, the transaction is pending or not - // exists. - if nonce >= highest { - return Ok(None) - } - - // perform a binary search over the block range to find the block in which the sender's - // nonce reached the requested nonce. - let num = binary_search::<_, _, ErrorObjectOwned>( - 1, - self.eth.block_number()?.saturating_to(), - |mid| { - async move { - let mid_nonce = - EthApiServer::transaction_count(&self.eth, sender, Some(mid.into())) - .await? - .saturating_to::(); - - // The `transaction_count` returns the `nonce` after the transaction was - // executed, which is the state of the account after the block, and we need to - // find the transaction whose nonce is the pre-state, so - // need to compare with `nonce`(no equal). - Ok(mid_nonce > nonce) - } - }, - ) - .await?; - - let Some(BlockTransactions::Full(transactions)) = - self.eth.block_by_number(num.into(), true).await?.map(|block| block.transactions) - else { - return Err(EthApiError::UnknownBlockNumber.into()); - }; - - Ok(transactions - .into_iter() - .find(|tx| *tx.from == *sender && tx.nonce == nonce) + Ok(self + .eth + .get_transaction_by_sender_and_nonce(sender, nonce, false) + .await + .map_err(|e| e.into())? .map(|tx| tx.hash)) } @@ -341,7 +307,9 @@ where self.eth.block_number()?.saturating_to(), |mid| { Box::pin(async move { - Ok(!self.eth.get_code(address, Some(mid.into())).await?.is_empty()) + Ok(!EthApiServer::get_code(&self.eth, address, Some(mid.into())) + .await? + .is_empty()) }) }, ) From 17f6225fa5e603fe5bb89f8ab356bf7d1e77ec59 Mon Sep 17 00:00:00 2001 From: malik Date: Sat, 31 Aug 2024 18:27:12 +0100 Subject: [PATCH 08/18] Feat: Extend BuiltPayload type (#10583) Co-authored-by: Oliver --- .../ethereum/engine-primitives/src/payload.rs | 21 ++++++++++++--- crates/ethereum/payload/src/lib.rs | 8 +++--- crates/optimism/payload/src/builder.rs | 13 ++++++++-- crates/optimism/payload/src/payload.rs | 26 ++++++++++++++++--- crates/payload/builder/src/lib.rs | 2 +- crates/payload/builder/src/test_utils.rs | 7 ++++- crates/payload/primitives/src/traits.rs | 5 +++- 7 files changed, 68 insertions(+), 14 deletions(-) diff --git a/crates/ethereum/engine-primitives/src/payload.rs b/crates/ethereum/engine-primitives/src/payload.rs index 45514d4d4415..7de120530482 100644 --- a/crates/ethereum/engine-primitives/src/payload.rs +++ b/crates/ethereum/engine-primitives/src/payload.rs @@ -6,7 +6,7 @@ use reth_evm_ethereum::revm_spec_by_timestamp_after_merge; use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes}; use reth_primitives::{ constants::EIP1559_INITIAL_BASE_FEE, Address, BlobTransactionSidecar, EthereumHardfork, Header, - SealedBlock, Withdrawals, B256, U256, + Receipt, SealedBlock, Withdrawals, B256, U256, }; use reth_rpc_types::engine::{ ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, @@ -35,14 +35,21 @@ pub struct EthBuiltPayload { /// The blobs, proofs, and commitments in the block. If the block is pre-cancun, this will be /// empty. pub(crate) sidecars: Vec, + /// The receipts of the block + pub(crate) receipts: Vec, } // === impl BuiltPayload === impl EthBuiltPayload { /// Initializes the payload with the given initial block. - pub const fn new(id: PayloadId, block: SealedBlock, fees: U256) -> Self { - Self { id, block, fees, sidecars: Vec::new() } + pub const fn new( + id: PayloadId, + block: SealedBlock, + fees: U256, + receipts: Vec, + ) -> Self { + Self { id, block, fees, sidecars: Vec::new(), receipts } } /// Returns the identifier of the payload. @@ -79,6 +86,10 @@ impl BuiltPayload for EthBuiltPayload { fn fees(&self) -> U256 { self.fees } + + fn receipts(&self) -> &[Receipt] { + &self.receipts + } } impl<'a> BuiltPayload for &'a EthBuiltPayload { @@ -89,6 +100,10 @@ impl<'a> BuiltPayload for &'a EthBuiltPayload { fn fees(&self) -> U256 { (**self).fees() } + + fn receipts(&self) -> &[Receipt] { + &self.receipts + } } // V1 engine_getPayloadV1 response diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 2e9a2fdaeda9..5707d97ddefb 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -109,6 +109,7 @@ where ); err })?; + let mut db = State::builder() .with_database(StateProviderDatabase::new(state)) .with_bundle_update() @@ -254,7 +255,7 @@ where let block = Block { header, body: vec![], ommers: vec![], withdrawals, requests }; let sealed_block = block.seal_slow(); - Ok(EthBuiltPayload::new(attributes.payload_id(), sealed_block, U256::ZERO)) + Ok(EthBuiltPayload::new(attributes.payload_id(), sealed_block, U256::ZERO, Vec::new())) } } @@ -490,7 +491,7 @@ where let execution_outcome = ExecutionOutcome::new( db.take_bundle(), - vec![receipts].into(), + vec![receipts.clone()].into(), block_number, vec![requests.clone().unwrap_or_default()], ); @@ -564,7 +565,8 @@ where let sealed_block = block.seal_slow(); debug!(target: "payload_builder", ?sealed_block, "sealed built block"); - let mut payload = EthBuiltPayload::new(attributes.id, sealed_block, total_fees); + let receipts_pay: Vec = receipts.into_iter().flatten().collect(); + let mut payload = EthBuiltPayload::new(attributes.id, sealed_block, total_fees, receipts_pay); // extend the payload with the blob sidecars from the executed txs payload.extend_sidecars(blob_sidecars); diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index db9ffc29eb0f..c985ae845354 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -209,6 +209,8 @@ where let block = Block { header, body: vec![], ommers: vec![], withdrawals, requests: None }; let sealed_block = block.seal_slow(); + let receipts = Vec::new(); + Ok(OptimismBuiltPayload::new( attributes.payload_attributes.payload_id(), sealed_block, @@ -216,6 +218,7 @@ where chain_spec, attributes, None, + receipts, )) } } @@ -515,8 +518,12 @@ where // and 4788 contract call db.merge_transitions(BundleRetention::PlainState); - let execution_outcome = - ExecutionOutcome::new(db.take_bundle(), vec![receipts].into(), block_number, Vec::new()); + let execution_outcome = ExecutionOutcome::new( + db.take_bundle(), + vec![receipts.clone()].into(), + block_number, + Vec::new(), + ); let receipts_root = execution_outcome .optimism_receipts_root_slow( block_number, @@ -601,6 +608,7 @@ where trie: Arc::new(trie_output), }; + let receipts_pay: Vec = receipts.into_iter().flatten().collect(); let mut payload = OptimismBuiltPayload::new( attributes.payload_attributes.id, sealed_block, @@ -608,6 +616,7 @@ where chain_spec, attributes, Some(executed), + receipts_pay, ); // extend the payload with the blob sidecars from the executed txs diff --git a/crates/optimism/payload/src/payload.rs b/crates/optimism/payload/src/payload.rs index 1746b66493ee..df38c60ea9fc 100644 --- a/crates/optimism/payload/src/payload.rs +++ b/crates/optimism/payload/src/payload.rs @@ -11,8 +11,8 @@ use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes}; use reth_primitives::{ revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId}, transaction::WithEncoded, - Address, BlobTransactionSidecar, Header, SealedBlock, TransactionSigned, Withdrawals, B256, - U256, + Address, BlobTransactionSidecar, Header, Receipt, SealedBlock, TransactionSigned, Withdrawals, + B256, U256, }; /// Re-export for use in downstream arguments. pub use reth_rpc_types::optimism::OptimismPayloadAttributes; @@ -179,6 +179,8 @@ pub struct OptimismBuiltPayload { pub(crate) chain_spec: Arc, /// The payload attributes. pub(crate) attributes: OptimismPayloadBuilderAttributes, + /// The receipts of the block + pub(crate) receipts: Vec, } // === impl BuiltPayload === @@ -192,8 +194,18 @@ impl OptimismBuiltPayload { chain_spec: Arc, attributes: OptimismPayloadBuilderAttributes, executed_block: Option, + receipts: Vec, ) -> Self { - Self { id, block, executed_block, fees, sidecars: Vec::new(), chain_spec, attributes } + Self { + id, + block, + executed_block, + fees, + sidecars: Vec::new(), + chain_spec, + attributes, + receipts, + } } /// Returns the identifier of the payload. @@ -229,6 +241,10 @@ impl BuiltPayload for OptimismBuiltPayload { fn executed_block(&self) -> Option { self.executed_block.clone() } + + fn receipts(&self) -> &[Receipt] { + &self.receipts + } } impl<'a> BuiltPayload for &'a OptimismBuiltPayload { @@ -243,6 +259,10 @@ impl<'a> BuiltPayload for &'a OptimismBuiltPayload { fn executed_block(&self) -> Option { self.executed_block.clone() } + + fn receipts(&self) -> &[Receipt] { + &self.receipts + } } // V1 engine_getPayloadV1 response diff --git a/crates/payload/builder/src/lib.rs b/crates/payload/builder/src/lib.rs index 2a29fe916ead..fc74c21a1502 100644 --- a/crates/payload/builder/src/lib.rs +++ b/crates/payload/builder/src/lib.rs @@ -65,7 +65,7 @@ //! }, //! ..Default::default() //! }; -//! let payload = EthBuiltPayload::new(self.attributes.id, payload.seal_slow(), U256::ZERO); +//! let payload = EthBuiltPayload::new(self.attributes.id, payload.seal_slow(), U256::ZERO, Vec::new()); //! Ok(payload) //! } //! diff --git a/crates/payload/builder/src/test_utils.rs b/crates/payload/builder/src/test_utils.rs index 62f697ddd6cb..c854fce738c3 100644 --- a/crates/payload/builder/src/test_utils.rs +++ b/crates/payload/builder/src/test_utils.rs @@ -82,7 +82,12 @@ impl PayloadJob for TestPayloadJob { type BuiltPayload = EthBuiltPayload; fn best_payload(&self) -> Result { - Ok(EthBuiltPayload::new(self.attr.payload_id(), Block::default().seal_slow(), U256::ZERO)) + Ok(EthBuiltPayload::new( + self.attr.payload_id(), + Block::default().seal_slow(), + U256::ZERO, + Vec::new(), + )) } fn payload_attributes(&self) -> Result { diff --git a/crates/payload/primitives/src/traits.rs b/crates/payload/primitives/src/traits.rs index 80ae38127e8a..c3d011f7ef8c 100644 --- a/crates/payload/primitives/src/traits.rs +++ b/crates/payload/primitives/src/traits.rs @@ -2,7 +2,7 @@ use reth_chain_state::ExecutedBlock; use reth_chainspec::ChainSpec; use reth_primitives::{ revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg}, - Address, Header, SealedBlock, Withdrawals, B256, U256, + Address, Header, Receipt, SealedBlock, Withdrawals, B256, U256, }; use reth_rpc_types::{ engine::{PayloadAttributes as EthPayloadAttributes, PayloadId}, @@ -23,6 +23,9 @@ pub trait BuiltPayload: Send + Sync + std::fmt::Debug { /// Returns the fees collected for the built block fn fees(&self) -> U256; + /// Returns the Receipts + fn receipts(&self) -> &[Receipt]; + /// Returns the entire execution data for the built block, if available. fn executed_block(&self) -> Option { None From 3a49a552c73d1036bd1abba533e339648768a096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien?= <3535019+leruaa@users.noreply.github.com> Date: Sat, 31 Aug 2024 19:36:28 +0200 Subject: [PATCH 09/18] feat: migrate to alloy TxEip1559 (#10262) Co-authored-by: Arsenii Kulikov --- crates/net/eth-wire-types/src/transactions.rs | 4 +- crates/primitives/src/alloy_compat.rs | 5 +- crates/primitives/src/transaction/compat.rs | 2 +- crates/primitives/src/transaction/eip1559.rs | 243 +----------------- crates/primitives/src/transaction/mod.rs | 44 ++-- crates/primitives/src/transaction/pooled.rs | 22 +- .../primitives/src/transaction/signature.rs | 6 + crates/storage/codecs/Cargo.toml | 2 +- .../codecs/src/alloy/transaction/eip1559.rs | 67 +++++ .../{transaction.rs => transaction/legacy.rs} | 20 +- .../codecs/src/alloy/transaction/mod.rs | 20 ++ crates/storage/db-api/src/models/mod.rs | 5 +- crates/transaction-pool/src/test_utils/gen.rs | 2 +- .../transaction-pool/src/test_utils/mock.rs | 6 +- 14 files changed, 149 insertions(+), 299 deletions(-) create mode 100644 crates/storage/codecs/src/alloy/transaction/eip1559.rs rename crates/storage/codecs/src/alloy/{transaction.rs => transaction/legacy.rs} (83%) create mode 100644 crates/storage/codecs/src/alloy/transaction/mod.rs diff --git a/crates/net/eth-wire-types/src/transactions.rs b/crates/net/eth-wire-types/src/transactions.rs index 2e3a6015d20a..8d837f824ffe 100644 --- a/crates/net/eth-wire-types/src/transactions.rs +++ b/crates/net/eth-wire-types/src/transactions.rs @@ -283,7 +283,7 @@ mod tests { nonce: 26u64, max_priority_fee_per_gas: 1500000000, max_fee_per_gas: 1500000013, - gas_limit: 21000u64, + gas_limit: 21000, to: TxKind::Call(hex!("61815774383099e24810ab832a5b2a5425c154d5").into()), value: U256::from(3000000000000000000u64), input: Default::default(), @@ -422,7 +422,7 @@ mod tests { nonce: 26u64, max_priority_fee_per_gas: 1500000000, max_fee_per_gas: 1500000013, - gas_limit: 21000u64, + gas_limit: 21000, to: TxKind::Call(hex!("61815774383099e24810ab832a5b2a5425c154d5").into()), value: U256::from(3000000000000000000u64), input: Default::default(), diff --git a/crates/primitives/src/alloy_compat.rs b/crates/primitives/src/alloy_compat.rs index d63bac7c0045..8d0cb853f556 100644 --- a/crates/primitives/src/alloy_compat.rs +++ b/crates/primitives/src/alloy_compat.rs @@ -135,10 +135,7 @@ impl TryFrom> for Transaction { max_fee_per_gas: tx .max_fee_per_gas .ok_or(ConversionError::MissingMaxFeePerGas)?, - gas_limit: tx - .gas - .try_into() - .map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?, + gas_limit: tx.gas, to: tx.to.map_or(TxKind::Create, TxKind::Call), value: tx.value, access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, diff --git a/crates/primitives/src/transaction/compat.rs b/crates/primitives/src/transaction/compat.rs index a58277374ecb..4845283f52f0 100644 --- a/crates/primitives/src/transaction/compat.rs +++ b/crates/primitives/src/transaction/compat.rs @@ -50,7 +50,7 @@ impl FillTxEnv for TransactionSigned { tx_env.authorization_list = None; } Transaction::Eip1559(tx) => { - tx_env.gas_limit = tx.gas_limit; + tx_env.gas_limit = tx.gas_limit as u64; tx_env.gas_price = U256::from(tx.max_fee_per_gas); tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); tx_env.transact_to = tx.to; diff --git a/crates/primitives/src/transaction/eip1559.rs b/crates/primitives/src/transaction/eip1559.rs index f95f84cc418e..cbdea1496d3d 100644 --- a/crates/primitives/src/transaction/eip1559.rs +++ b/crates/primitives/src/transaction/eip1559.rs @@ -1,245 +1,4 @@ -use super::access_list::AccessList; -use crate::{keccak256, Bytes, ChainId, Signature, TxKind, TxType, B256, U256}; -use alloy_rlp::{length_of_length, Decodable, Encodable, Header}; -use core::mem; - -#[cfg(any(test, feature = "reth-codec"))] -use reth_codecs::Compact; - -#[cfg(not(feature = "std"))] -use alloc::vec::Vec; -use serde::{Deserialize, Serialize}; - -/// A transaction with a priority fee ([EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)). -#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] -#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] -#[cfg_attr(any(test, feature = "reth-codec"), derive(Compact))] -#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))] -pub struct TxEip1559 { - /// Added as EIP-155: Simple replay attack protection - pub chain_id: ChainId, - - /// A scalar value equal to the number of transactions sent by the sender; formally Tn. - pub nonce: u64, - - /// A scalar value equal to the maximum - /// amount of gas that should be used in executing - /// this transaction. This is paid up-front, before any - /// computation is done and may not be increased - /// later; formally Tg. - pub gas_limit: u64, - - /// A scalar value equal to the maximum - /// amount of gas that should be used in executing - /// this transaction. This is paid up-front, before any - /// computation is done and may not be increased - /// later; formally Tg. - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - /// - /// This is also known as `GasFeeCap` - pub max_fee_per_gas: u128, - - /// Max Priority fee that transaction is paying - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - /// - /// This is also known as `GasTipCap` - pub max_priority_fee_per_gas: u128, - - /// The 160-bit address of the message call’s recipient or, for a contract creation - /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. - pub to: TxKind, - - /// A scalar value equal to the number of Wei to - /// be transferred to the message call’s recipient or, - /// in the case of contract creation, as an endowment - /// to the newly created account; formally Tv. - pub value: U256, - - /// The accessList specifies a list of addresses and storage keys; - /// these addresses and storage keys are added into the `accessed_addresses` - /// and `accessed_storage_keys` global sets (introduced in EIP-2929). - /// A gas cost is charged, though at a discount relative to the cost of - /// accessing outside the list. - pub access_list: AccessList, - - /// Input has two uses depending if the transaction `to` field is [`TxKind::Create`] or - /// [`TxKind::Call`]. - /// - /// Input as init code, or if `to` is [`TxKind::Create`]: An unlimited size byte array - /// specifying the EVM-code for the account initialisation procedure `CREATE` - /// - /// Input as data, or if `to` is [`TxKind::Call`]: An unlimited size byte array specifying the - /// input data of the message call, formally Td. - pub input: Bytes, -} - -impl TxEip1559 { - /// Returns the effective gas price for the given `base_fee`. - pub const fn effective_gas_price(&self, base_fee: Option) -> u128 { - match base_fee { - None => self.max_fee_per_gas, - Some(base_fee) => { - // if the tip is greater than the max priority fee per gas, set it to the max - // priority fee per gas + base fee - let tip = self.max_fee_per_gas.saturating_sub(base_fee as u128); - if tip > self.max_priority_fee_per_gas { - self.max_priority_fee_per_gas + base_fee as u128 - } else { - // otherwise return the max fee per gas - self.max_fee_per_gas - } - } - } - } - - /// Decodes the inner [`TxEip1559`] fields from RLP bytes. - /// - /// NOTE: This assumes a RLP header has already been decoded, and _just_ decodes the following - /// RLP fields in the following order: - /// - /// - `chain_id` - /// - `nonce` - /// - `max_priority_fee_per_gas` - /// - `max_fee_per_gas` - /// - `gas_limit` - /// - `to` - /// - `value` - /// - `data` (`input`) - /// - `access_list` - pub(crate) fn decode_inner(buf: &mut &[u8]) -> alloy_rlp::Result { - Ok(Self { - chain_id: Decodable::decode(buf)?, - nonce: Decodable::decode(buf)?, - max_priority_fee_per_gas: Decodable::decode(buf)?, - max_fee_per_gas: Decodable::decode(buf)?, - gas_limit: Decodable::decode(buf)?, - to: Decodable::decode(buf)?, - value: Decodable::decode(buf)?, - input: Decodable::decode(buf)?, - access_list: Decodable::decode(buf)?, - }) - } - - /// Encodes only the transaction's fields into the desired buffer, without a RLP header. - pub(crate) fn fields_len(&self) -> usize { - self.chain_id.length() + - self.nonce.length() + - self.max_priority_fee_per_gas.length() + - self.max_fee_per_gas.length() + - self.gas_limit.length() + - self.to.length() + - self.value.length() + - self.input.0.length() + - self.access_list.length() - } - - /// Encodes only the transaction's fields into the desired buffer, without a RLP header. - pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) { - self.chain_id.encode(out); - self.nonce.encode(out); - self.max_priority_fee_per_gas.encode(out); - self.max_fee_per_gas.encode(out); - self.gas_limit.encode(out); - self.to.encode(out); - self.value.encode(out); - self.input.0.encode(out); - self.access_list.encode(out); - } - - /// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating - /// hash that for eip2718 does not require rlp header - /// - /// This encodes the transaction as: - /// `rlp(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit to, value, input, - /// access_list, y_parity, r, s)` - pub(crate) fn encode_with_signature( - &self, - signature: &Signature, - out: &mut dyn bytes::BufMut, - with_header: bool, - ) { - let payload_length = self.fields_len() + signature.payload_len(); - if with_header { - Header { - list: false, - payload_length: 1 + length_of_length(payload_length) + payload_length, - } - .encode(out); - } - out.put_u8(self.tx_type() as u8); - let header = Header { list: true, payload_length }; - header.encode(out); - self.encode_fields(out); - signature.encode(out); - } - - /// Output the length of the RLP signed transaction encoding, _without_ a RLP string header. - pub(crate) fn payload_len_with_signature_without_header(&self, signature: &Signature) -> usize { - let payload_length = self.fields_len() + signature.payload_len(); - // 'transaction type byte length' + 'header length' + 'payload length' - 1 + length_of_length(payload_length) + payload_length - } - - /// Output the length of the RLP signed transaction encoding. This encodes with a RLP header. - pub(crate) fn payload_len_with_signature(&self, signature: &Signature) -> usize { - let len = self.payload_len_with_signature_without_header(signature); - length_of_length(len) + len - } - - /// Get transaction type - pub(crate) const fn tx_type(&self) -> TxType { - TxType::Eip1559 - } - - /// Calculates a heuristic for the in-memory size of the [`TxEip1559`] transaction. - #[inline] - pub fn size(&self) -> usize { - mem::size_of::() + // chain_id - mem::size_of::() + // nonce - mem::size_of::() + // gas_limit - mem::size_of::() + // max_fee_per_gas - mem::size_of::() + // max_priority_fee_per_gas - self.to.size() + // to - mem::size_of::() + // value - self.access_list.size() + // access_list - self.input.len() // input - } - - /// Encodes the EIP-1559 transaction in RLP for signing. - /// - /// This encodes the transaction as: - /// `tx_type || rlp(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, - /// value, input, access_list)` - /// - /// Note that there is no rlp header before the transaction type byte. - pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { - out.put_u8(self.tx_type() as u8); - Header { list: true, payload_length: self.fields_len() }.encode(out); - self.encode_fields(out); - } - - /// Outputs the length of the signature RLP encoding for the transaction. - pub(crate) fn payload_len_for_signature(&self) -> usize { - let payload_length = self.fields_len(); - // 'transaction type byte length' + 'header length' + 'payload length' - 1 + length_of_length(payload_length) + payload_length - } - - /// Outputs the signature hash of the transaction by first encoding without a signature, then - /// hashing. - pub(crate) fn signature_hash(&self) -> B256 { - let mut buf = Vec::with_capacity(self.payload_len_for_signature()); - self.encode_for_signing(&mut buf); - keccak256(&buf) - } -} - +pub use alloy_consensus::TxEip1559; #[cfg(test)] mod tests { use super::TxEip1559; diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index a9f80a23012b..f39973e7940d 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -153,9 +153,15 @@ impl<'a> arbitrary::Arbitrary<'a> for Transaction { TxType::Deposit => Self::Deposit(TxDeposit::arbitrary(u)?), }; - if let Self::Legacy(tx) = &mut tx { - tx.gas_limit = (tx.gas_limit as u64).into(); - }; + match &mut tx { + Self::Legacy(tx) => { + tx.gas_limit = (tx.gas_limit as u64).into(); + } + Self::Eip1559(tx) => { + tx.gas_limit = (tx.gas_limit as u64).into(); + } + _ => {} + } Ok(tx) } @@ -231,7 +237,7 @@ impl Transaction { match self { Self::Legacy(_) => TxType::Legacy, Self::Eip2930(access_list_tx) => access_list_tx.tx_type(), - Self::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.tx_type(), + Self::Eip1559(_) => TxType::Eip1559, Self::Eip4844(blob_tx) => blob_tx.tx_type(), Self::Eip7702(set_code_tx) => set_code_tx.tx_type(), #[cfg(feature = "optimism")] @@ -294,9 +300,9 @@ impl Transaction { /// Get the gas limit of the transaction. pub const fn gas_limit(&self) -> u64 { match self { - Self::Legacy(TxLegacy { gas_limit, .. }) => *gas_limit as u64, + Self::Legacy(TxLegacy { gas_limit, .. }) | + Self::Eip1559(TxEip1559 { gas_limit, .. }) => *gas_limit as u64, Self::Eip2930(TxEip2930 { gas_limit, .. }) | - Self::Eip1559(TxEip1559 { gas_limit, .. }) | Self::Eip4844(TxEip4844 { gas_limit, .. }) | Self::Eip7702(TxEip7702 { gas_limit, .. }) => *gas_limit, #[cfg(feature = "optimism")] @@ -523,9 +529,11 @@ impl Transaction { Self::Eip2930(access_list_tx) => { access_list_tx.encode_with_signature(signature, out, with_header) } - Self::Eip1559(dynamic_fee_tx) => { - dynamic_fee_tx.encode_with_signature(signature, out, with_header) - } + Self::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encode_with_signature( + &signature.as_signature_with_boolean_parity(), + out, + with_header, + ), Self::Eip4844(blob_tx) => blob_tx.encode_with_signature(signature, out, with_header), Self::Eip7702(set_code_tx) => { set_code_tx.encode_with_signature(signature, out, with_header) @@ -540,7 +548,7 @@ impl Transaction { match self { Self::Legacy(tx) => tx.gas_limit = gas_limit.into(), Self::Eip2930(tx) => tx.gas_limit = gas_limit, - Self::Eip1559(tx) => tx.gas_limit = gas_limit, + Self::Eip1559(tx) => tx.gas_limit = gas_limit.into(), Self::Eip4844(tx) => tx.gas_limit = gas_limit, Self::Eip7702(tx) => tx.gas_limit = gas_limit, #[cfg(feature = "optimism")] @@ -1204,9 +1212,10 @@ impl TransactionSigned { Transaction::Eip2930(access_list_tx) => { access_list_tx.payload_len_with_signature(&self.signature) } - Transaction::Eip1559(dynamic_fee_tx) => { - dynamic_fee_tx.payload_len_with_signature(&self.signature) - } + Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encoded_len_with_signature( + &self.signature.as_signature_with_boolean_parity(), + true, + ), Transaction::Eip4844(blob_tx) => blob_tx.payload_len_with_signature(&self.signature), Transaction::Eip7702(set_code_tx) => { set_code_tx.payload_len_with_signature(&self.signature) @@ -1335,7 +1344,7 @@ impl TransactionSigned { let transaction = match tx_type { TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_inner(data)?), - TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_inner(data)?), + TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_fields(data)?), TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode_inner(data)?), TxType::Eip7702 => Transaction::Eip7702(TxEip7702::decode_inner(data)?), #[cfg(feature = "optimism")] @@ -1410,9 +1419,10 @@ impl TransactionSigned { Transaction::Eip2930(access_list_tx) => { access_list_tx.payload_len_with_signature_without_header(&self.signature) } - Transaction::Eip1559(dynamic_fee_tx) => { - dynamic_fee_tx.payload_len_with_signature_without_header(&self.signature) - } + Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encoded_len_with_signature( + &self.signature.as_signature_with_boolean_parity(), + false, + ), Transaction::Eip4844(blob_tx) => { blob_tx.payload_len_with_signature_without_header(&self.signature) } diff --git a/crates/primitives/src/transaction/pooled.rs b/crates/primitives/src/transaction/pooled.rs index 3f6739bfd609..f669d9cdd045 100644 --- a/crates/primitives/src/transaction/pooled.rs +++ b/crates/primitives/src/transaction/pooled.rs @@ -312,7 +312,10 @@ impl PooledTransactionsElement { } Self::Eip1559 { transaction, signature, .. } => { // method computes the payload len without a RLP header - transaction.payload_len_with_signature_without_header(signature) + transaction.encoded_len_with_signature( + &signature.as_signature_with_boolean_parity(), + false, + ) } Self::Eip7702 { transaction, signature, .. } => { // method computes the payload len without a RLP header @@ -358,9 +361,11 @@ impl PooledTransactionsElement { Self::Eip2930 { transaction, signature, .. } => { transaction.encode_with_signature(signature, out, false) } - Self::Eip1559 { transaction, signature, .. } => { - transaction.encode_with_signature(signature, out, false) - } + Self::Eip1559 { transaction, signature, .. } => transaction.encode_with_signature( + &signature.as_signature_with_boolean_parity(), + out, + false, + ), Self::Eip7702 { transaction, signature, .. } => { transaction.encode_with_signature(signature, out, false) } @@ -494,7 +499,11 @@ impl Encodable for PooledTransactionsElement { } Self::Eip1559 { transaction, signature, .. } => { // encodes with string header - transaction.encode_with_signature(signature, out, true) + transaction.encode_with_signature( + &signature.as_signature_with_boolean_parity(), + out, + true, + ) } Self::Eip7702 { transaction, signature, .. } => { // encodes with string header @@ -523,7 +532,8 @@ impl Encodable for PooledTransactionsElement { } Self::Eip1559 { transaction, signature, .. } => { // method computes the payload len with a RLP header - transaction.payload_len_with_signature(signature) + transaction + .encoded_len_with_signature(&signature.as_signature_with_boolean_parity(), true) } Self::Eip7702 { transaction, signature, .. } => { // method computes the payload len with a RLP header diff --git a/crates/primitives/src/transaction/signature.rs b/crates/primitives/src/transaction/signature.rs index dad5ef522dbf..fe03d8d71213 100644 --- a/crates/primitives/src/transaction/signature.rs +++ b/crates/primitives/src/transaction/signature.rs @@ -188,6 +188,12 @@ impl Signature { SignatureWithParity::new(self.r, self.s, self.legacy_parity(chain_id)) } + /// Returns a signature with a boolean parity flag. This is useful when we want to encode + /// the `v` value as 0 or 1. + pub(crate) const fn as_signature_with_boolean_parity(&self) -> SignatureWithParity { + SignatureWithParity::new(self.r, self.s, Parity::Parity(self.odd_y_parity)) + } + /// Returns the signature for the optimism deposit transactions, which don't include a /// signature. #[cfg(feature = "optimism")] diff --git a/crates/storage/codecs/Cargo.toml b/crates/storage/codecs/Cargo.toml index 13292c680c6f..d1e0580000fd 100644 --- a/crates/storage/codecs/Cargo.toml +++ b/crates/storage/codecs/Cargo.toml @@ -16,7 +16,7 @@ reth-codecs-derive = { path = "./derive", default-features = false } # eth alloy-consensus = { workspace = true, optional = true } -alloy-eips = { workspace = true, optional = true } +alloy-eips = { workspace = true, optional = true, features = ["serde"] } alloy-genesis = { workspace = true, optional = true } alloy-primitives.workspace = true alloy-trie = { workspace = true, optional = true } diff --git a/crates/storage/codecs/src/alloy/transaction/eip1559.rs b/crates/storage/codecs/src/alloy/transaction/eip1559.rs new file mode 100644 index 000000000000..a0889492589d --- /dev/null +++ b/crates/storage/codecs/src/alloy/transaction/eip1559.rs @@ -0,0 +1,67 @@ +use crate::Compact; +use alloy_consensus::TxEip1559 as AlloyTxEip1559; +use alloy_eips::eip2930::AccessList; +use alloy_primitives::{Bytes, ChainId, TxKind, U256}; +use serde::{Deserialize, Serialize}; + +/// [EIP-1559 Transaction](https://eips.ethereum.org/EIPS/eip-1559) +/// +/// This is a helper type to use derive on it instead of manually managing `bitfield`. +/// +/// By deriving `Compact` here, any future changes or enhancements to the `Compact` derive +/// will automatically apply to this type. +/// +/// Notice: Make sure this struct is 1:1 with [`alloy_consensus::transaction::TxEip1559`] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Compact, Default, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +#[cfg_attr(test, crate::add_arbitrary_tests(compact))] +pub(crate) struct TxEip1559 { + chain_id: ChainId, + nonce: u64, + gas_limit: u64, + max_fee_per_gas: u128, + max_priority_fee_per_gas: u128, + to: TxKind, + value: U256, + access_list: AccessList, + input: Bytes, +} + +impl Compact for AlloyTxEip1559 { + fn to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + let tx = TxEip1559 { + chain_id: self.chain_id, + nonce: self.nonce, + gas_limit: self.gas_limit as u64, + max_fee_per_gas: self.max_fee_per_gas, + max_priority_fee_per_gas: self.max_priority_fee_per_gas, + to: self.to, + value: self.value, + access_list: self.access_list.clone(), + input: self.input.clone(), + }; + + tx.to_compact(buf) + } + + fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { + let (tx, _) = TxEip1559::from_compact(buf, len); + + let alloy_tx = Self { + chain_id: tx.chain_id, + nonce: tx.nonce, + gas_limit: tx.gas_limit.into(), + max_fee_per_gas: tx.max_fee_per_gas, + max_priority_fee_per_gas: tx.max_priority_fee_per_gas, + to: tx.to, + value: tx.value, + access_list: tx.access_list, + input: tx.input, + }; + + (alloy_tx, buf) + } +} diff --git a/crates/storage/codecs/src/alloy/transaction.rs b/crates/storage/codecs/src/alloy/transaction/legacy.rs similarity index 83% rename from crates/storage/codecs/src/alloy/transaction.rs rename to crates/storage/codecs/src/alloy/transaction/legacy.rs index 389fef8ac2d3..641b27bf53b2 100644 --- a/crates/storage/codecs/src/alloy/transaction.rs +++ b/crates/storage/codecs/src/alloy/transaction/legacy.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Eq, Default, Compact, Serialize, Deserialize)] #[cfg_attr(test, derive(arbitrary::Arbitrary))] #[cfg_attr(test, crate::add_arbitrary_tests(compact))] -struct TxLegacy { +pub(crate) struct TxLegacy { /// Added as EIP-155: Simple replay attack protection chain_id: Option, /// A scalar value equal to the number of transactions sent by the sender; formally Tn. @@ -67,7 +67,7 @@ impl Compact for AlloyTxLegacy { chain_id: tx.chain_id, nonce: tx.nonce, gas_price: tx.gas_price, - gas_limit: tx.gas_limit as u128, + gas_limit: tx.gas_limit.into(), to: tx.to, value: tx.value, input: tx.input, @@ -76,19 +76,3 @@ impl Compact for AlloyTxLegacy { (alloy_tx, buf) } } - -#[cfg(test)] -mod tests { - use crate::alloy::transaction::TxLegacy; - - // each value in the database has an extra field named flags that encodes metadata about other - // fields in the value, e.g. offset and length. - // - // this check is to ensure we do not inadvertently add too many fields to a struct which would - // expand the flags field and break backwards compatibility - - #[test] - fn test_ensure_backwards_compatibility() { - assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3); - } -} diff --git a/crates/storage/codecs/src/alloy/transaction/mod.rs b/crates/storage/codecs/src/alloy/transaction/mod.rs new file mode 100644 index 000000000000..4a343c573b6b --- /dev/null +++ b/crates/storage/codecs/src/alloy/transaction/mod.rs @@ -0,0 +1,20 @@ +mod eip1559; +mod legacy; + +#[cfg(test)] +mod tests { + + // each value in the database has an extra field named flags that encodes metadata about other + // fields in the value, e.g. offset and length. + // + // this check is to ensure we do not inadvertently add too many fields to a struct which would + // expand the flags field and break backwards compatibility + + use super::{eip1559::TxEip1559, legacy::TxLegacy}; + + #[test] + fn test_ensure_backwards_compatibility() { + assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3); + assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4); + } +} diff --git a/crates/storage/db-api/src/models/mod.rs b/crates/storage/db-api/src/models/mod.rs index ede53d4b9bfe..58a246fa991c 100644 --- a/crates/storage/db-api/src/models/mod.rs +++ b/crates/storage/db-api/src/models/mod.rs @@ -302,8 +302,7 @@ add_wrapper_struct!((ClientVersion, CompactClientVersion)); mod tests { use super::*; use reth_primitives::{ - Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip1559, TxEip2930, TxEip4844, - Withdrawals, + Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip2930, TxEip4844, Withdrawals, }; use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment}; use reth_stages_types::{ @@ -343,7 +342,6 @@ mod tests { assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0); assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0); assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1); - assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4); assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3); assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0); @@ -375,7 +373,6 @@ mod tests { assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0); assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0); assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1); - assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4); assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3); assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0); diff --git a/crates/transaction-pool/src/test_utils/gen.rs b/crates/transaction-pool/src/test_utils/gen.rs index c4069382d780..e51acbfcbd52 100644 --- a/crates/transaction-pool/src/test_utils/gen.rs +++ b/crates/transaction-pool/src/test_utils/gen.rs @@ -160,7 +160,7 @@ impl TransactionBuilder { TxEip1559 { chain_id: self.chain_id, nonce: self.nonce, - gas_limit: self.gas_limit, + gas_limit: self.gas_limit.into(), max_fee_per_gas: self.max_fee_per_gas, max_priority_fee_per_gas: self.max_priority_fee_per_gas, to: self.to, diff --git a/crates/transaction-pool/src/test_utils/mock.rs b/crates/transaction-pool/src/test_utils/mock.rs index 6a0c2f8b59a2..ed8bc70b72b0 100644 --- a/crates/transaction-pool/src/test_utils/mock.rs +++ b/crates/transaction-pool/src/test_utils/mock.rs @@ -843,7 +843,7 @@ impl TryFrom for MockTransaction { nonce, max_fee_per_gas, max_priority_fee_per_gas, - gas_limit, + gas_limit: gas_limit as u64, to, value, input, @@ -966,7 +966,7 @@ impl From for Transaction { } => Self::Eip1559(TxEip1559 { chain_id, nonce, - gas_limit, + gas_limit: gas_limit.into(), max_fee_per_gas, max_priority_fee_per_gas, to, @@ -1077,7 +1077,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { nonce: *nonce, max_fee_per_gas: *max_fee_per_gas, max_priority_fee_per_gas: *max_priority_fee_per_gas, - gas_limit: *gas_limit, + gas_limit: *gas_limit as u64, to: *to, value: *value, input: input.clone(), From 7269cf28538d25d87bd85bb3594dc8616d674370 Mon Sep 17 00:00:00 2001 From: Roy <42067944+royvardhan@users.noreply.github.com> Date: Sun, 1 Sep 2024 01:34:38 +0530 Subject: [PATCH 10/18] chore: expose TransactionFetcher param in cli (#10635) --- book/cli/reth/debug/execution.md | 5 +++++ book/cli/reth/debug/in-memory-merkle.md | 5 +++++ book/cli/reth/debug/merkle.md | 5 +++++ book/cli/reth/debug/replay-engine.md | 5 +++++ book/cli/reth/node.md | 5 +++++ book/cli/reth/p2p.md | 5 +++++ book/cli/reth/stage/run.md | 5 +++++ book/cli/reth/stage/unwind.md | 5 +++++ crates/net/network/src/transactions/config.rs | 11 +++++++++-- crates/net/network/src/transactions/fetcher.rs | 11 ++++++++++- crates/node/core/src/args/network.rs | 8 +++++++- 11 files changed, 66 insertions(+), 4 deletions(-) diff --git a/book/cli/reth/debug/execution.md b/book/cli/reth/debug/execution.md index a6475535e8c9..2f8732761fed 100644 --- a/book/cli/reth/debug/execution.md +++ b/book/cli/reth/debug/execution.md @@ -221,6 +221,11 @@ Networking: [default: 131072] + --max-tx-pending-fetch + Max capacity of cache of hashes for transactions pending fetch. + + [default: 25600] + --to The maximum block height diff --git a/book/cli/reth/debug/in-memory-merkle.md b/book/cli/reth/debug/in-memory-merkle.md index 2c9b4b4c67d1..112e9a9b0ef3 100644 --- a/book/cli/reth/debug/in-memory-merkle.md +++ b/book/cli/reth/debug/in-memory-merkle.md @@ -221,6 +221,11 @@ Networking: [default: 131072] + --max-tx-pending-fetch + Max capacity of cache of hashes for transactions pending fetch. + + [default: 25600] + --retries The number of retries per request diff --git a/book/cli/reth/debug/merkle.md b/book/cli/reth/debug/merkle.md index be683bca20cc..c891cfc0e5be 100644 --- a/book/cli/reth/debug/merkle.md +++ b/book/cli/reth/debug/merkle.md @@ -221,6 +221,11 @@ Networking: [default: 131072] + --max-tx-pending-fetch + Max capacity of cache of hashes for transactions pending fetch. + + [default: 25600] + --retries The number of retries per request diff --git a/book/cli/reth/debug/replay-engine.md b/book/cli/reth/debug/replay-engine.md index bf9b63896b7f..154f4464c441 100644 --- a/book/cli/reth/debug/replay-engine.md +++ b/book/cli/reth/debug/replay-engine.md @@ -221,6 +221,11 @@ Networking: [default: 131072] + --max-tx-pending-fetch + Max capacity of cache of hashes for transactions pending fetch. + + [default: 25600] + --engine-api-store The path to read engine API messages from diff --git a/book/cli/reth/node.md b/book/cli/reth/node.md index 9217dc14fa24..934318678771 100644 --- a/book/cli/reth/node.md +++ b/book/cli/reth/node.md @@ -213,6 +213,11 @@ Networking: [default: 131072] + --max-tx-pending-fetch + Max capacity of cache of hashes for transactions pending fetch. + + [default: 25600] + RPC: --http Enable the HTTP-RPC server diff --git a/book/cli/reth/p2p.md b/book/cli/reth/p2p.md index 42d6c8415b02..37bec56b8acf 100644 --- a/book/cli/reth/p2p.md +++ b/book/cli/reth/p2p.md @@ -198,6 +198,11 @@ Networking: [default: 131072] + --max-tx-pending-fetch + Max capacity of cache of hashes for transactions pending fetch. + + [default: 25600] + Datadir: --datadir The path to the data dir for all reth files and subdirectories. diff --git a/book/cli/reth/stage/run.md b/book/cli/reth/stage/run.md index 1f42dba7b2c9..8bc87fd97796 100644 --- a/book/cli/reth/stage/run.md +++ b/book/cli/reth/stage/run.md @@ -264,6 +264,11 @@ Networking: [default: 131072] + --max-tx-pending-fetch + Max capacity of cache of hashes for transactions pending fetch. + + [default: 25600] + Logging: --log.stdout.format The format to use for logs written to stdout diff --git a/book/cli/reth/stage/unwind.md b/book/cli/reth/stage/unwind.md index a88883e11b14..41b0a6640914 100644 --- a/book/cli/reth/stage/unwind.md +++ b/book/cli/reth/stage/unwind.md @@ -226,6 +226,11 @@ Networking: [default: 131072] + --max-tx-pending-fetch + Max capacity of cache of hashes for transactions pending fetch. + + [default: 25600] + --offline If this is enabled, then all stages except headers, bodies, and sender recovery will be unwound diff --git a/crates/net/network/src/transactions/config.rs b/crates/net/network/src/transactions/config.rs index 3dd77514da5a..b8023ca7928c 100644 --- a/crates/net/network/src/transactions/config.rs +++ b/crates/net/network/src/transactions/config.rs @@ -6,7 +6,8 @@ use super::{ SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE, }; use crate::transactions::constants::tx_fetcher::{ - DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS, DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS_PER_PEER, + DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH, DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS, + DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS_PER_PEER, }; /// Configuration for managing transactions within the network. @@ -46,6 +47,11 @@ pub struct TransactionFetcherConfig { /// [`PooledTransactions`](reth_eth_wire::PooledTransactions) response on packing a /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) request with hashes. pub soft_limit_byte_size_pooled_transactions_response_on_pack_request: usize, + /// Max capacity of the cache of transaction hashes, for transactions that weren't yet fetched. + /// A transaction is pending fetch if its hash didn't fit into a + /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) yet, or it wasn't returned + /// upon request to peers. + pub max_capacity_cache_txns_pending_fetch: u32, } impl Default for TransactionFetcherConfig { @@ -56,7 +62,8 @@ impl Default for TransactionFetcherConfig { soft_limit_byte_size_pooled_transactions_response: SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE, soft_limit_byte_size_pooled_transactions_response_on_pack_request: - DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESP_ON_PACK_GET_POOLED_TRANSACTIONS_REQ + DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESP_ON_PACK_GET_POOLED_TRANSACTIONS_REQ, + max_capacity_cache_txns_pending_fetch: DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH, } } } diff --git a/crates/net/network/src/transactions/fetcher.rs b/crates/net/network/src/transactions/fetcher.rs index 8a5b2fbadb37..f553cfbfdb90 100644 --- a/crates/net/network/src/transactions/fetcher.rs +++ b/crates/net/network/src/transactions/fetcher.rs @@ -134,6 +134,8 @@ impl TransactionFetcher { .metrics .capacity_inflight_requests .increment(tx_fetcher.info.max_inflight_requests as u64); + tx_fetcher.info.max_capacity_cache_txns_pending_fetch = + config.max_capacity_cache_txns_pending_fetch; tx_fetcher } @@ -1291,6 +1293,10 @@ pub struct TransactionFetcherInfo { /// Soft limit for the byte size of a [`PooledTransactions`] response, upon assembling the /// response. Spec'd at 2 MiB, but can be adjusted for research purpose. pub soft_limit_byte_size_pooled_transactions_response: usize, + /// Max capacity of the cache of transaction hashes, for transactions that weren't yet fetched. + /// A transaction is pending fetch if its hash didn't fit into a [`GetPooledTransactions`] yet, + /// or it wasn't returned upon request to peers. + pub max_capacity_cache_txns_pending_fetch: u32, } impl TransactionFetcherInfo { @@ -1299,11 +1305,13 @@ impl TransactionFetcherInfo { max_inflight_requests: usize, soft_limit_byte_size_pooled_transactions_response_on_pack_request: usize, soft_limit_byte_size_pooled_transactions_response: usize, + max_capacity_cache_txns_pending_fetch: u32, ) -> Self { Self { max_inflight_requests, soft_limit_byte_size_pooled_transactions_response_on_pack_request, soft_limit_byte_size_pooled_transactions_response, + max_capacity_cache_txns_pending_fetch, } } } @@ -1313,7 +1321,8 @@ impl Default for TransactionFetcherInfo { Self::new( DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS as usize * DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS_PER_PEER as usize, DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESP_ON_PACK_GET_POOLED_TRANSACTIONS_REQ, - SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE + SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESPONSE, + DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH, ) } } diff --git a/crates/node/core/src/args/network.rs b/crates/node/core/src/args/network.rs index 53891ff0bdf7..45aef0b2becb 100644 --- a/crates/node/core/src/args/network.rs +++ b/crates/node/core/src/args/network.rs @@ -20,7 +20,7 @@ use reth_network::{ transactions::{ constants::{ tx_fetcher::{ - DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS, + DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH, DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS, DEFAULT_MAX_COUNT_CONCURRENT_REQUESTS_PER_PEER, }, tx_manager::{ @@ -144,6 +144,10 @@ pub struct NetworkArgs { /// Default is 128 KiB. #[arg(long = "pooled-tx-pack-soft-limit", value_name = "BYTES", default_value_t = DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESP_ON_PACK_GET_POOLED_TRANSACTIONS_REQ, verbatim_doc_comment)] pub soft_limit_byte_size_pooled_transactions_response_on_pack_request: usize, + + /// Max capacity of cache of hashes for transactions pending fetch. + #[arg(long = "max-tx-pending-fetch", value_name = "COUNT", default_value_t = DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH, verbatim_doc_comment)] + pub max_capacity_cache_txns_pending_fetch: u32, } impl NetworkArgs { @@ -191,6 +195,7 @@ impl NetworkArgs { self.max_concurrent_tx_requests_per_peer, self.soft_limit_byte_size_pooled_transactions_response, self.soft_limit_byte_size_pooled_transactions_response_on_pack_request, + self.max_capacity_cache_txns_pending_fetch, ), max_transactions_seen_by_peer_history: self.max_seen_tx_history, }; @@ -297,6 +302,7 @@ impl Default for NetworkArgs { soft_limit_byte_size_pooled_transactions_response_on_pack_request: DEFAULT_SOFT_LIMIT_BYTE_SIZE_POOLED_TRANSACTIONS_RESP_ON_PACK_GET_POOLED_TRANSACTIONS_REQ, max_pending_pool_imports: DEFAULT_MAX_COUNT_PENDING_POOL_IMPORTS, max_seen_tx_history: DEFAULT_MAX_COUNT_TRANSACTIONS_SEEN_BY_PEER, + max_capacity_cache_txns_pending_fetch: DEFAULT_MAX_CAPACITY_CACHE_PENDING_FETCH, } } } From 578b52afd080a81915682ec5f17e066d89da57f7 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Sun, 1 Sep 2024 06:53:19 -0700 Subject: [PATCH 11/18] eip2930: use alloy `TxEip2930` (#10623) --- crates/primitives/src/alloy_compat.rs | 5 +- crates/primitives/src/transaction/compat.rs | 2 +- crates/primitives/src/transaction/eip2930.rs | 263 +----------------- crates/primitives/src/transaction/mod.rs | 66 ++--- crates/primitives/src/transaction/pooled.rs | 22 +- .../codecs/src/alloy/transaction/eip2930.rs | 62 +++++ .../codecs/src/alloy/transaction/mod.rs | 4 +- crates/storage/db-api/src/models/mod.rs | 4 +- .../transaction-pool/src/test_utils/mock.rs | 6 +- 9 files changed, 123 insertions(+), 311 deletions(-) create mode 100644 crates/storage/codecs/src/alloy/transaction/eip2930.rs diff --git a/crates/primitives/src/alloy_compat.rs b/crates/primitives/src/alloy_compat.rs index 8d0cb853f556..dfaee697a708 100644 --- a/crates/primitives/src/alloy_compat.rs +++ b/crates/primitives/src/alloy_compat.rs @@ -113,10 +113,7 @@ impl TryFrom> for Transaction { Ok(Self::Eip2930(TxEip2930 { chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, nonce: tx.nonce, - gas_limit: tx - .gas - .try_into() - .map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?, + gas_limit: tx.gas, to: tx.to.map_or(TxKind::Create, TxKind::Call), value: tx.value, input: tx.input, diff --git a/crates/primitives/src/transaction/compat.rs b/crates/primitives/src/transaction/compat.rs index 4845283f52f0..54d29a0370df 100644 --- a/crates/primitives/src/transaction/compat.rs +++ b/crates/primitives/src/transaction/compat.rs @@ -36,7 +36,7 @@ impl FillTxEnv for TransactionSigned { tx_env.authorization_list = None; } Transaction::Eip2930(tx) => { - tx_env.gas_limit = tx.gas_limit; + tx_env.gas_limit = tx.gas_limit as u64; tx_env.gas_price = U256::from(tx.gas_price); tx_env.gas_priority_fee = None; tx_env.transact_to = tx.to; diff --git a/crates/primitives/src/transaction/eip2930.rs b/crates/primitives/src/transaction/eip2930.rs index 44bad8afb96a..b3f123598b0d 100644 --- a/crates/primitives/src/transaction/eip2930.rs +++ b/crates/primitives/src/transaction/eip2930.rs @@ -1,262 +1 @@ -use super::access_list::AccessList; -use crate::{keccak256, Bytes, ChainId, Signature, TxKind, TxType, B256, U256}; -use alloy_rlp::{length_of_length, Decodable, Encodable, Header}; -use core::mem; - -#[cfg(any(test, feature = "reth-codec"))] -use reth_codecs::Compact; - -#[cfg(not(feature = "std"))] -use alloc::vec::Vec; -use serde::{Deserialize, Serialize}; - -/// Transaction with an [`AccessList`] ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)). -#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] -#[cfg_attr(any(test, feature = "reth-codec"), derive(Compact))] -#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] -#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))] -pub struct TxEip2930 { - /// Added as EIP-155: Simple replay attack protection - pub chain_id: ChainId, - - /// A scalar value equal to the number of transactions sent by the sender; formally Tn. - pub nonce: u64, - - /// A scalar value equal to the number of - /// Wei to be paid per unit of gas for all computation - /// costs incurred as a result of the execution of this transaction; formally Tp. - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - pub gas_price: u128, - - /// A scalar value equal to the maximum - /// amount of gas that should be used in executing - /// this transaction. This is paid up-front, before any - /// computation is done and may not be increased - /// later; formally Tg. - pub gas_limit: u64, - - /// The 160-bit address of the message call’s recipient or, for a contract creation - /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. - pub to: TxKind, - - /// A scalar value equal to the number of Wei to - /// be transferred to the message call’s recipient or, - /// in the case of contract creation, as an endowment - /// to the newly created account; formally Tv. - pub value: U256, - - /// The accessList specifies a list of addresses and storage keys; - /// these addresses and storage keys are added into the `accessed_addresses` - /// and `accessed_storage_keys` global sets (introduced in EIP-2929). - /// A gas cost is charged, though at a discount relative to the cost of - /// accessing outside the list. - pub access_list: AccessList, - - /// Input has two uses depending if the transaction `to` field is [`TxKind::Create`] or - /// [`TxKind::Call`]. - /// - /// Input as init code, or if `to` is [`TxKind::Create`]: An unlimited size byte array - /// specifying the EVM-code for the account initialisation procedure `CREATE` - /// - /// Input as data, or if `to` is [`TxKind::Call`]: An unlimited size byte array specifying the - /// input data of the message call, formally Td. - pub input: Bytes, -} - -impl TxEip2930 { - /// Calculates a heuristic for the in-memory size of the [`TxEip2930`] transaction. - #[inline] - pub fn size(&self) -> usize { - mem::size_of::() + // chain_id - mem::size_of::() + // nonce - mem::size_of::() + // gas_price - mem::size_of::() + // gas_limit - self.to.size() + // to - mem::size_of::() + // value - self.access_list.size() + // access_list - self.input.len() // input - } - - /// Decodes the inner [`TxEip2930`] fields from RLP bytes. - /// - /// NOTE: This assumes a RLP header has already been decoded, and _just_ decodes the following - /// RLP fields in the following order: - /// - /// - `chain_id` - /// - `nonce` - /// - `gas_price` - /// - `gas_limit` - /// - `to` - /// - `value` - /// - `data` (`input`) - /// - `access_list` - pub(crate) fn decode_inner(buf: &mut &[u8]) -> alloy_rlp::Result { - Ok(Self { - chain_id: Decodable::decode(buf)?, - nonce: Decodable::decode(buf)?, - gas_price: Decodable::decode(buf)?, - gas_limit: Decodable::decode(buf)?, - to: Decodable::decode(buf)?, - value: Decodable::decode(buf)?, - input: Decodable::decode(buf)?, - access_list: Decodable::decode(buf)?, - }) - } - - /// Outputs the length of the transaction's fields, without a RLP header. - pub(crate) fn fields_len(&self) -> usize { - self.chain_id.length() + - self.nonce.length() + - self.gas_price.length() + - self.gas_limit.length() + - self.to.length() + - self.value.length() + - self.input.0.length() + - self.access_list.length() - } - - /// Encodes only the transaction's fields into the desired buffer, without a RLP header. - pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) { - self.chain_id.encode(out); - self.nonce.encode(out); - self.gas_price.encode(out); - self.gas_limit.encode(out); - self.to.encode(out); - self.value.encode(out); - self.input.0.encode(out); - self.access_list.encode(out); - } - - /// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating - /// hash that for eip2718 does not require rlp header - /// - /// This encodes the transaction as: - /// `rlp(nonce, gas_price, gas_limit, to, value, input, access_list, y_parity, r, s)` - pub(crate) fn encode_with_signature( - &self, - signature: &Signature, - out: &mut dyn bytes::BufMut, - with_header: bool, - ) { - let payload_length = self.fields_len() + signature.payload_len(); - if with_header { - Header { - list: false, - payload_length: 1 + length_of_length(payload_length) + payload_length, - } - .encode(out); - } - out.put_u8(self.tx_type() as u8); - let header = Header { list: true, payload_length }; - header.encode(out); - self.encode_fields(out); - signature.encode(out); - } - - /// Output the length of the RLP signed transaction encoding, _without_ a RLP string header. - pub(crate) fn payload_len_with_signature_without_header(&self, signature: &Signature) -> usize { - let payload_length = self.fields_len() + signature.payload_len(); - // 'transaction type byte length' + 'header length' + 'payload length' - 1 + length_of_length(payload_length) + payload_length - } - - /// Output the length of the RLP signed transaction encoding. This encodes with a RLP header. - pub(crate) fn payload_len_with_signature(&self, signature: &Signature) -> usize { - let len = self.payload_len_with_signature_without_header(signature); - length_of_length(len) + len - } - - /// Get transaction type - pub(crate) const fn tx_type(&self) -> TxType { - TxType::Eip2930 - } - - /// Encodes the EIP-2930 transaction in RLP for signing. - /// - /// This encodes the transaction as: - /// `tx_type || rlp(chain_id, nonce, gas_price, gas_limit, to, value, input, access_list)` - /// - /// Note that there is no rlp header before the transaction type byte. - pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { - out.put_u8(self.tx_type() as u8); - Header { list: true, payload_length: self.fields_len() }.encode(out); - self.encode_fields(out); - } - - /// Outputs the length of the signature RLP encoding for the transaction. - pub(crate) fn payload_len_for_signature(&self) -> usize { - let payload_length = self.fields_len(); - // 'transaction type byte length' + 'header length' + 'payload length' - 1 + length_of_length(payload_length) + payload_length - } - - /// Outputs the signature hash of the transaction by first encoding without a signature, then - /// hashing. - pub(crate) fn signature_hash(&self) -> B256 { - let mut buf = Vec::with_capacity(self.payload_len_for_signature()); - self.encode_for_signing(&mut buf); - keccak256(&buf) - } -} - -#[cfg(test)] -mod tests { - use super::TxEip2930; - use crate::{ - transaction::{signature::Signature, TxKind}, - Address, Bytes, Transaction, TransactionSigned, U256, - }; - use alloy_rlp::{Decodable, Encodable}; - - #[test] - fn test_decode_create() { - // tests that a contract creation tx encodes and decodes properly - let request = Transaction::Eip2930(TxEip2930 { - chain_id: 1u64, - nonce: 0, - gas_price: 1, - gas_limit: 2, - to: TxKind::Create, - value: U256::from(3), - input: Bytes::from(vec![1, 2]), - access_list: Default::default(), - }); - let signature = Signature { odd_y_parity: true, r: U256::default(), s: U256::default() }; - let tx = TransactionSigned::from_transaction_and_signature(request, signature); - - let mut encoded = Vec::new(); - tx.encode(&mut encoded); - assert_eq!(encoded.len(), tx.length()); - - let decoded = TransactionSigned::decode(&mut &*encoded).unwrap(); - assert_eq!(decoded, tx); - } - - #[test] - fn test_decode_call() { - let request = Transaction::Eip2930(TxEip2930 { - chain_id: 1u64, - nonce: 0, - gas_price: 1, - gas_limit: 2, - to: Address::default().into(), - value: U256::from(3), - input: Bytes::from(vec![1, 2]), - access_list: Default::default(), - }); - - let signature = Signature { odd_y_parity: true, r: U256::default(), s: U256::default() }; - - let tx = TransactionSigned::from_transaction_and_signature(request, signature); - - let mut encoded = Vec::new(); - tx.encode(&mut encoded); - assert_eq!(encoded.len(), tx.length()); - - let decoded = TransactionSigned::decode(&mut &*encoded).unwrap(); - assert_eq!(decoded, tx); - } -} +pub use alloy_consensus::transaction::TxEip2930; diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index f39973e7940d..6665100ce7da 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -143,27 +143,27 @@ pub enum Transaction { #[cfg(any(test, feature = "arbitrary"))] impl<'a> arbitrary::Arbitrary<'a> for Transaction { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - let mut tx = match TxType::arbitrary(u)? { - TxType::Legacy => Self::Legacy(TxLegacy::arbitrary(u)?), - TxType::Eip2930 => Self::Eip2930(TxEip2930::arbitrary(u)?), - TxType::Eip1559 => Self::Eip1559(TxEip1559::arbitrary(u)?), - TxType::Eip4844 => Self::Eip4844(TxEip4844::arbitrary(u)?), - TxType::Eip7702 => Self::Eip7702(TxEip7702::arbitrary(u)?), - #[cfg(feature = "optimism")] - TxType::Deposit => Self::Deposit(TxDeposit::arbitrary(u)?), - }; - - match &mut tx { - Self::Legacy(tx) => { + Ok(match TxType::arbitrary(u)? { + TxType::Legacy => { + let mut tx = TxLegacy::arbitrary(u)?; tx.gas_limit = (tx.gas_limit as u64).into(); + Self::Legacy(tx) } - Self::Eip1559(tx) => { + TxType::Eip2930 => { + let mut tx = TxEip2930::arbitrary(u)?; tx.gas_limit = (tx.gas_limit as u64).into(); + Self::Eip2930(tx) } - _ => {} - } - - Ok(tx) + TxType::Eip1559 => { + let mut tx = TxEip1559::arbitrary(u)?; + tx.gas_limit = (tx.gas_limit as u64).into(); + Self::Eip1559(tx) + } + TxType::Eip4844 => Self::Eip4844(TxEip4844::arbitrary(u)?), + TxType::Eip7702 => Self::Eip7702(TxEip7702::arbitrary(u)?), + #[cfg(feature = "optimism")] + TxType::Deposit => Self::Deposit(TxDeposit::arbitrary(u)?), + }) } } @@ -236,7 +236,7 @@ impl Transaction { pub const fn tx_type(&self) -> TxType { match self { Self::Legacy(_) => TxType::Legacy, - Self::Eip2930(access_list_tx) => access_list_tx.tx_type(), + Self::Eip2930(_) => TxType::Eip2930, Self::Eip1559(_) => TxType::Eip1559, Self::Eip4844(blob_tx) => blob_tx.tx_type(), Self::Eip7702(set_code_tx) => set_code_tx.tx_type(), @@ -300,11 +300,11 @@ impl Transaction { /// Get the gas limit of the transaction. pub const fn gas_limit(&self) -> u64 { match self { - Self::Legacy(TxLegacy { gas_limit, .. }) | + Self::Legacy(TxLegacy { gas_limit, .. }) => *gas_limit as u64, Self::Eip1559(TxEip1559 { gas_limit, .. }) => *gas_limit as u64, - Self::Eip2930(TxEip2930 { gas_limit, .. }) | Self::Eip4844(TxEip4844 { gas_limit, .. }) | Self::Eip7702(TxEip7702 { gas_limit, .. }) => *gas_limit, + Self::Eip2930(TxEip2930 { gas_limit, .. }) => *gas_limit as u64, #[cfg(feature = "optimism")] Self::Deposit(TxDeposit { gas_limit, .. }) => *gas_limit, } @@ -526,9 +526,11 @@ impl Transaction { out, ) } - Self::Eip2930(access_list_tx) => { - access_list_tx.encode_with_signature(signature, out, with_header) - } + Self::Eip2930(access_list_tx) => access_list_tx.encode_with_signature( + &signature.as_signature_with_boolean_parity(), + out, + with_header, + ), Self::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encode_with_signature( &signature.as_signature_with_boolean_parity(), out, @@ -547,7 +549,7 @@ impl Transaction { pub fn set_gas_limit(&mut self, gas_limit: u64) { match self { Self::Legacy(tx) => tx.gas_limit = gas_limit.into(), - Self::Eip2930(tx) => tx.gas_limit = gas_limit, + Self::Eip2930(tx) => tx.gas_limit = gas_limit.into(), Self::Eip1559(tx) => tx.gas_limit = gas_limit.into(), Self::Eip4844(tx) => tx.gas_limit = gas_limit, Self::Eip7702(tx) => tx.gas_limit = gas_limit, @@ -1209,9 +1211,10 @@ impl TransactionSigned { Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature( &self.signature.as_signature_with_eip155_parity(legacy_tx.chain_id), ), - Transaction::Eip2930(access_list_tx) => { - access_list_tx.payload_len_with_signature(&self.signature) - } + Transaction::Eip2930(access_list_tx) => access_list_tx.encoded_len_with_signature( + &self.signature.as_signature_with_boolean_parity(), + true, + ), Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encoded_len_with_signature( &self.signature.as_signature_with_boolean_parity(), true, @@ -1343,7 +1346,7 @@ impl TransactionSigned { }; let transaction = match tx_type { - TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_inner(data)?), + TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_fields(data)?), TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_fields(data)?), TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode_inner(data)?), TxType::Eip7702 => Transaction::Eip7702(TxEip7702::decode_inner(data)?), @@ -1416,9 +1419,10 @@ impl TransactionSigned { Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature( &self.signature.as_signature_with_eip155_parity(legacy_tx.chain_id), ), - Transaction::Eip2930(access_list_tx) => { - access_list_tx.payload_len_with_signature_without_header(&self.signature) - } + Transaction::Eip2930(access_list_tx) => access_list_tx.encoded_len_with_signature( + &self.signature.as_signature_with_boolean_parity(), + false, + ), Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encoded_len_with_signature( &self.signature.as_signature_with_boolean_parity(), false, diff --git a/crates/primitives/src/transaction/pooled.rs b/crates/primitives/src/transaction/pooled.rs index f669d9cdd045..32e9a9db544a 100644 --- a/crates/primitives/src/transaction/pooled.rs +++ b/crates/primitives/src/transaction/pooled.rs @@ -308,7 +308,10 @@ impl PooledTransactionsElement { } Self::Eip2930 { transaction, signature, .. } => { // method computes the payload len without a RLP header - transaction.payload_len_with_signature_without_header(signature) + transaction.encoded_len_with_signature( + &signature.as_signature_with_boolean_parity(), + false, + ) } Self::Eip1559 { transaction, signature, .. } => { // method computes the payload len without a RLP header @@ -358,9 +361,11 @@ impl PooledTransactionsElement { &signature.as_signature_with_eip155_parity(transaction.chain_id), out, ), - Self::Eip2930 { transaction, signature, .. } => { - transaction.encode_with_signature(signature, out, false) - } + Self::Eip2930 { transaction, signature, .. } => transaction.encode_with_signature( + &signature.as_signature_with_boolean_parity(), + out, + false, + ), Self::Eip1559 { transaction, signature, .. } => transaction.encode_with_signature( &signature.as_signature_with_boolean_parity(), out, @@ -495,7 +500,11 @@ impl Encodable for PooledTransactionsElement { ), Self::Eip2930 { transaction, signature, .. } => { // encodes with string header - transaction.encode_with_signature(signature, out, true) + transaction.encode_with_signature( + &signature.as_signature_with_boolean_parity(), + out, + true, + ) } Self::Eip1559 { transaction, signature, .. } => { // encodes with string header @@ -528,7 +537,8 @@ impl Encodable for PooledTransactionsElement { } Self::Eip2930 { transaction, signature, .. } => { // method computes the payload len with a RLP header - transaction.payload_len_with_signature(signature) + transaction + .encoded_len_with_signature(&signature.as_signature_with_boolean_parity(), true) } Self::Eip1559 { transaction, signature, .. } => { // method computes the payload len with a RLP header diff --git a/crates/storage/codecs/src/alloy/transaction/eip2930.rs b/crates/storage/codecs/src/alloy/transaction/eip2930.rs new file mode 100644 index 000000000000..33b58dfff739 --- /dev/null +++ b/crates/storage/codecs/src/alloy/transaction/eip2930.rs @@ -0,0 +1,62 @@ +use crate::Compact; +use alloy_consensus::transaction::TxEip2930 as AlloyTxEip2930; +use alloy_eips::eip2930::AccessList; +use alloy_primitives::{Bytes, ChainId, TxKind, U256}; +use reth_codecs_derive::add_arbitrary_tests; +use serde::{Deserialize, Serialize}; + +/// Transaction with an [`AccessList`] ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)). +/// +/// This is a helper type to use derive on it instead of manually managing `bitfield`. +/// +/// By deriving `Compact` here, any future changes or enhancements to the `Compact` derive +/// will automatically apply to this type. +/// +/// Notice: Make sure this struct is 1:1 with [`alloy_consensus::transaction::TxEip2930`] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize, Compact)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +#[add_arbitrary_tests(compact)] +pub(crate) struct TxEip2930 { + chain_id: ChainId, + nonce: u64, + gas_price: u128, + gas_limit: u64, + to: TxKind, + value: U256, + access_list: AccessList, + input: Bytes, +} + +impl Compact for AlloyTxEip2930 { + fn to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + let tx = TxEip2930 { + chain_id: self.chain_id, + nonce: self.nonce, + gas_price: self.gas_price, + gas_limit: self.gas_limit as u64, + to: self.to, + value: self.value, + access_list: self.access_list.clone(), + input: self.input.clone(), + }; + tx.to_compact(buf) + } + + fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { + let (tx, _) = TxEip2930::from_compact(buf, len); + let alloy_tx = Self { + chain_id: tx.chain_id, + nonce: tx.nonce, + gas_price: tx.gas_price, + gas_limit: tx.gas_limit as u128, + to: tx.to, + value: tx.value, + access_list: tx.access_list, + input: tx.input, + }; + (alloy_tx, buf) + } +} diff --git a/crates/storage/codecs/src/alloy/transaction/mod.rs b/crates/storage/codecs/src/alloy/transaction/mod.rs index 4a343c573b6b..af00e90eafac 100644 --- a/crates/storage/codecs/src/alloy/transaction/mod.rs +++ b/crates/storage/codecs/src/alloy/transaction/mod.rs @@ -1,4 +1,5 @@ mod eip1559; +mod eip2930; mod legacy; #[cfg(test)] @@ -10,11 +11,12 @@ mod tests { // this check is to ensure we do not inadvertently add too many fields to a struct which would // expand the flags field and break backwards compatibility - use super::{eip1559::TxEip1559, legacy::TxLegacy}; + use super::{eip1559::TxEip1559, eip2930::TxEip2930, legacy::TxLegacy}; #[test] fn test_ensure_backwards_compatibility() { assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3); assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4); + assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3); } } diff --git a/crates/storage/db-api/src/models/mod.rs b/crates/storage/db-api/src/models/mod.rs index 58a246fa991c..72668354ff2c 100644 --- a/crates/storage/db-api/src/models/mod.rs +++ b/crates/storage/db-api/src/models/mod.rs @@ -302,7 +302,7 @@ add_wrapper_struct!((ClientVersion, CompactClientVersion)); mod tests { use super::*; use reth_primitives::{ - Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip2930, TxEip4844, Withdrawals, + Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip4844, Withdrawals, }; use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment}; use reth_stages_types::{ @@ -342,7 +342,6 @@ mod tests { assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0); assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0); assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1); - assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3); assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0); } @@ -373,7 +372,6 @@ mod tests { assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0); assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0); assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1); - assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3); assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0); } diff --git a/crates/transaction-pool/src/test_utils/mock.rs b/crates/transaction-pool/src/test_utils/mock.rs index ed8bc70b72b0..18597715d3dc 100644 --- a/crates/transaction-pool/src/test_utils/mock.rs +++ b/crates/transaction-pool/src/test_utils/mock.rs @@ -819,7 +819,7 @@ impl TryFrom for MockTransaction { sender, nonce, gas_price, - gas_limit, + gas_limit: gas_limit as u64, to, value, input, @@ -944,7 +944,7 @@ impl From for Transaction { chain_id, nonce, gas_price, - gas_limit, + gas_limit: gas_limit.into(), to, value, access_list, @@ -1053,7 +1053,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { hash: tx_hash, nonce: *nonce, gas_price: *gas_price, - gas_limit: *gas_limit, + gas_limit: *gas_limit as u64, to: *to, value: *value, input: input.clone(), From d4cfb95e68f38a311ce8a044f4623d7ff1283e0f Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Sun, 1 Sep 2024 12:20:00 -0700 Subject: [PATCH 12/18] eip4844: use alloy `TxEip4844` (#10624) Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com> --- crates/consensus/common/src/validation.rs | 1 - crates/primitives/Cargo.toml | 2 +- crates/primitives/src/alloy_compat.rs | 6 +- crates/primitives/src/transaction/compat.rs | 2 +- crates/primitives/src/transaction/eip4844.rs | 325 +----------------- crates/primitives/src/transaction/mod.rs | 38 +- crates/primitives/src/transaction/pooled.rs | 20 +- crates/primitives/src/transaction/sidecar.rs | 68 ++-- .../rpc-types-compat/src/transaction/typed.rs | 1 - crates/rpc/rpc/src/eth/bundle.rs | 2 +- .../codecs/src/alloy/transaction/eip4844.rs | 96 ++++++ .../codecs/src/alloy/transaction/mod.rs | 4 +- crates/storage/db-api/src/models/mod.rs | 6 +- crates/transaction-pool/src/test_utils/gen.rs | 3 +- .../transaction-pool/src/test_utils/mock.rs | 15 +- 15 files changed, 168 insertions(+), 421 deletions(-) create mode 100644 crates/storage/codecs/src/alloy/transaction/eip4844.rs diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index f3654c42ee2c..9646ddf73115 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -419,7 +419,6 @@ mod tests { max_priority_fee_per_gas: 0x28f000fff, max_fee_per_blob_gas: 0x7, gas_limit: 10, - placeholder: Some(()), to: Address::default(), value: U256::from(3_u64), input: Bytes::from(vec![1, 2]), diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index ff6e8d59c378..74b2a0447a92 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -100,7 +100,7 @@ arbitrary = [ "reth-codec", ] secp256k1 = ["dep:secp256k1"] -c-kzg = ["dep:c-kzg", "revm-primitives/c-kzg", "dep:tempfile", "alloy-eips/kzg"] +c-kzg = ["dep:c-kzg", "revm-primitives/c-kzg", "dep:tempfile", "alloy-eips/kzg", "alloy-consensus/kzg"] optimism = [ "reth-chainspec/optimism", "reth-ethereum-forks/optimism", diff --git a/crates/primitives/src/alloy_compat.rs b/crates/primitives/src/alloy_compat.rs index dfaee697a708..ac3d0c551097 100644 --- a/crates/primitives/src/alloy_compat.rs +++ b/crates/primitives/src/alloy_compat.rs @@ -150,11 +150,7 @@ impl TryFrom> for Transaction { max_fee_per_gas: tx .max_fee_per_gas .ok_or(ConversionError::MissingMaxFeePerGas)?, - gas_limit: tx - .gas - .try_into() - .map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?, - placeholder: tx.to.map(drop), + gas_limit: tx.gas, to: tx.to.unwrap_or_default(), value: tx.value, access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, diff --git a/crates/primitives/src/transaction/compat.rs b/crates/primitives/src/transaction/compat.rs index 54d29a0370df..dfe0083e48be 100644 --- a/crates/primitives/src/transaction/compat.rs +++ b/crates/primitives/src/transaction/compat.rs @@ -64,7 +64,7 @@ impl FillTxEnv for TransactionSigned { tx_env.authorization_list = None; } Transaction::Eip4844(tx) => { - tx_env.gas_limit = tx.gas_limit; + tx_env.gas_limit = tx.gas_limit as u64; tx_env.gas_price = U256::from(tx.max_fee_per_gas); tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); tx_env.transact_to = TxKind::Call(tx.to); diff --git a/crates/primitives/src/transaction/eip4844.rs b/crates/primitives/src/transaction/eip4844.rs index a3bad68805ca..e86133d813ef 100644 --- a/crates/primitives/src/transaction/eip4844.rs +++ b/crates/primitives/src/transaction/eip4844.rs @@ -1,324 +1 @@ -use super::access_list::AccessList; -use crate::{ - constants::eip4844::DATA_GAS_PER_BLOB, keccak256, Address, Bytes, ChainId, Signature, TxType, - B256, U256, -}; -use alloy_rlp::{length_of_length, Decodable, Encodable, Header}; -use core::mem; - -#[cfg(any(test, feature = "reth-codec"))] -use reth_codecs::Compact; - -/// To be used with `Option` to place or replace one bit on the bitflag struct. -pub(crate) type CompactPlaceholder = (); - -#[cfg(feature = "c-kzg")] -use crate::kzg::KzgSettings; - -#[cfg(not(feature = "std"))] -use alloc::vec::Vec; -use serde::{Deserialize, Serialize}; - -/// [EIP-4844 Blob Transaction](https://eips.ethereum.org/EIPS/eip-4844#blob-transaction) -/// -/// A transaction with blob hashes and max blob fee -#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] -#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] -#[cfg_attr(any(test, feature = "reth-codec"), derive(Compact))] -#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))] -pub struct TxEip4844 { - /// Added as EIP-155: Simple replay attack protection - pub chain_id: ChainId, - - /// A scalar value equal to the number of transactions sent by the sender; formally Tn. - pub nonce: u64, - - /// A scalar value equal to the maximum - /// amount of gas that should be used in executing - /// this transaction. This is paid up-front, before any - /// computation is done and may not be increased - /// later; formally Tg. - pub gas_limit: u64, - - /// A scalar value equal to the maximum - /// amount of gas that should be used in executing - /// this transaction. This is paid up-front, before any - /// computation is done and may not be increased - /// later; formally Tg. - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - /// - /// This is also known as `GasFeeCap` - pub max_fee_per_gas: u128, - - /// Max Priority fee that transaction is paying - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - /// - /// This is also known as `GasTipCap` - pub max_priority_fee_per_gas: u128, - - /// TODO(debt): this should be removed if we break the DB. - /// Makes sure that the Compact bitflag struct has one bit after the above field: - /// - pub placeholder: Option, - - /// The 160-bit address of the message call’s recipient. - pub to: Address, - - /// A scalar value equal to the number of Wei to - /// be transferred to the message call’s recipient or, - /// in the case of contract creation, as an endowment - /// to the newly created account; formally Tv. - pub value: U256, - - /// The accessList specifies a list of addresses and storage keys; - /// these addresses and storage keys are added into the `accessed_addresses` - /// and `accessed_storage_keys` global sets (introduced in EIP-2929). - /// A gas cost is charged, though at a discount relative to the cost of - /// accessing outside the list. - pub access_list: AccessList, - - /// It contains a vector of fixed size hash(32 bytes) - pub blob_versioned_hashes: Vec, - - /// Max fee per data gas - /// - /// aka BlobFeeCap or blobGasFeeCap - pub max_fee_per_blob_gas: u128, - - /// Unlike other transaction types, where the `input` field has two uses depending on whether - /// or not the `to` field is [`Create`](crate::TxKind::Create) or - /// [`Call`](crate::TxKind::Call), EIP-4844 transactions cannot be - /// [`Create`](crate::TxKind::Create) transactions. - /// - /// This means the `input` field has a single use, as data: An unlimited size byte array - /// specifying the input data of the message call, formally Td. - pub input: Bytes, -} - -impl TxEip4844 { - /// Returns the effective gas price for the given `base_fee`. - pub const fn effective_gas_price(&self, base_fee: Option) -> u128 { - match base_fee { - None => self.max_fee_per_gas, - Some(base_fee) => { - // if the tip is greater than the max priority fee per gas, set it to the max - // priority fee per gas + base fee - let tip = self.max_fee_per_gas.saturating_sub(base_fee as u128); - if tip > self.max_priority_fee_per_gas { - self.max_priority_fee_per_gas + base_fee as u128 - } else { - // otherwise return the max fee per gas - self.max_fee_per_gas - } - } - } - } - - /// Verifies that the given blob data, commitments, and proofs are all valid for this - /// transaction. - /// - /// Takes as input the [`KzgSettings`], which should contain the parameters derived from the - /// KZG trusted setup. - /// - /// This ensures that the blob transaction payload has the same number of blob data elements, - /// commitments, and proofs. Each blob data element is verified against its commitment and - /// proof. - /// - /// Returns `InvalidProof` if any blob KZG proof in the response - /// fails to verify, or if the versioned hashes in the transaction do not match the actual - /// commitment versioned hashes. - #[cfg(feature = "c-kzg")] - pub fn validate_blob( - &self, - sidecar: &crate::BlobTransactionSidecar, - proof_settings: &KzgSettings, - ) -> Result<(), alloy_eips::eip4844::BlobTransactionValidationError> { - sidecar.validate(&self.blob_versioned_hashes, proof_settings) - } - - /// Returns the total gas for all blobs in this transaction. - #[inline] - pub fn blob_gas(&self) -> u64 { - // NOTE: we don't expect u64::MAX / DATA_GAS_PER_BLOB hashes in a single transaction - self.blob_versioned_hashes.len() as u64 * DATA_GAS_PER_BLOB - } - - /// Decodes the inner [`TxEip4844`] fields from RLP bytes. - /// - /// NOTE: This assumes a RLP header has already been decoded, and _just_ decodes the following - /// RLP fields in the following order: - /// - /// - `chain_id` - /// - `nonce` - /// - `max_priority_fee_per_gas` - /// - `max_fee_per_gas` - /// - `gas_limit` - /// - `to` - /// - `value` - /// - `data` (`input`) - /// - `access_list` - /// - `max_fee_per_blob_gas` - /// - `blob_versioned_hashes` - pub fn decode_inner(buf: &mut &[u8]) -> alloy_rlp::Result { - let mut tx = Self { - chain_id: Decodable::decode(buf)?, - nonce: Decodable::decode(buf)?, - max_priority_fee_per_gas: Decodable::decode(buf)?, - max_fee_per_gas: Decodable::decode(buf)?, - gas_limit: Decodable::decode(buf)?, - placeholder: None, - to: Decodable::decode(buf)?, - value: Decodable::decode(buf)?, - input: Decodable::decode(buf)?, - access_list: Decodable::decode(buf)?, - max_fee_per_blob_gas: Decodable::decode(buf)?, - blob_versioned_hashes: Decodable::decode(buf)?, - }; - - // HACK: our arbitrary implementation sets the placeholder this way for backwards - // compatibility, and should be removed once `placeholder` can be removed - if tx.to != Address::default() { - tx.placeholder = Some(()) - } - - Ok(tx) - } - - /// Outputs the length of the transaction's fields, without a RLP header. - pub(crate) fn fields_len(&self) -> usize { - self.chain_id.length() + - self.nonce.length() + - self.gas_limit.length() + - self.max_fee_per_gas.length() + - self.max_priority_fee_per_gas.length() + - self.to.length() + - self.value.length() + - self.access_list.length() + - self.blob_versioned_hashes.length() + - self.max_fee_per_blob_gas.length() + - self.input.0.length() - } - - /// Encodes only the transaction's fields into the desired buffer, without a RLP header. - pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) { - self.chain_id.encode(out); - self.nonce.encode(out); - self.max_priority_fee_per_gas.encode(out); - self.max_fee_per_gas.encode(out); - self.gas_limit.encode(out); - self.to.encode(out); - self.value.encode(out); - self.input.0.encode(out); - self.access_list.encode(out); - self.max_fee_per_blob_gas.encode(out); - self.blob_versioned_hashes.encode(out); - } - - /// Calculates a heuristic for the in-memory size of the [`TxEip4844`] transaction. - #[inline] - pub fn size(&self) -> usize { - mem::size_of::() + // chain_id - mem::size_of::() + // nonce - mem::size_of::() + // gas_limit - mem::size_of::() + // max_fee_per_gas - mem::size_of::() + // max_priority_fee_per_gas - mem::size_of::
() + // to - mem::size_of::() + // value - self.access_list.size() + // access_list - self.input.len() + // input - self.blob_versioned_hashes.capacity() * mem::size_of::() + // blob hashes size - mem::size_of::() // max_fee_per_data_gas - } - - /// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating - /// hash that for eip2718 does not require rlp header - pub(crate) fn encode_with_signature( - &self, - signature: &Signature, - out: &mut dyn bytes::BufMut, - with_header: bool, - ) { - let payload_length = self.fields_len() + signature.payload_len(); - if with_header { - Header { - list: false, - payload_length: 1 + length_of_length(payload_length) + payload_length, - } - .encode(out); - } - out.put_u8(self.tx_type() as u8); - let header = Header { list: true, payload_length }; - header.encode(out); - self.encode_fields(out); - signature.encode(out); - } - - /// Output the length of the RLP signed transaction encoding. This encodes with a RLP header. - pub(crate) fn payload_len_with_signature(&self, signature: &Signature) -> usize { - let len = self.payload_len_with_signature_without_header(signature); - length_of_length(len) + len - } - - /// Output the length of the RLP signed transaction encoding, _without_ a RLP header. - pub(crate) fn payload_len_with_signature_without_header(&self, signature: &Signature) -> usize { - let payload_length = self.fields_len() + signature.payload_len(); - // 'transaction type byte length' + 'header length' + 'payload length' - 1 + length_of_length(payload_length) + payload_length - } - - /// Get transaction type - pub(crate) const fn tx_type(&self) -> TxType { - TxType::Eip4844 - } - - /// Encodes the EIP-4844 transaction in RLP for signing. - /// - /// This encodes the transaction as: - /// `tx_type || rlp(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, - /// value, input, access_list, max_fee_per_blob_gas, blob_versioned_hashes)` - /// - /// Note that there is no rlp header before the transaction type byte. - pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { - out.put_u8(self.tx_type() as u8); - Header { list: true, payload_length: self.fields_len() }.encode(out); - self.encode_fields(out); - } - - /// Outputs the length of the signature RLP encoding for the transaction. - pub(crate) fn payload_len_for_signature(&self) -> usize { - let payload_length = self.fields_len(); - // 'transaction type byte length' + 'header length' + 'payload length' - 1 + length_of_length(payload_length) + payload_length - } - - /// Outputs the signature hash of the transaction by first encoding without a signature, then - /// hashing. - pub(crate) fn signature_hash(&self) -> B256 { - let mut buf = Vec::with_capacity(self.payload_len_for_signature()); - self.encode_for_signing(&mut buf); - keccak256(&buf) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use alloy_primitives::{address, bytes}; - - #[test] - fn backwards_compatible_txkind_test() { - // TxEip4844 encoded with TxKind on to field - // holesky tx hash: <0xa3b1668225bf0fbfdd6c19aa6fd071fa4ff5d09a607c67ccd458b97735f745ac> - let tx = bytes!("224348a100426844cb2dc6c0b2d05e003b9aca0079c9109b764609df928d16fc4a91e9081f7e87db09310001019101fb28118ceccaabca22a47e35b9c3f12eb2dcb25e5c543d5b75e6cd841f0a05328d26ef16e8450000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007b399987d24fc5951f3e94a4cb16e87414bf22290000000000000000000000001670090000000000000000000000000000010001302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000009e640a6aadf4f664cf467b795c31332f44acbe6c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006614c2d1000000000000000000000000000000000000000000000000000000000014012c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f06fd78f4dcdf089263524731620941747b9b93fd8f631557e25b23845a78b685bd82f9d36bce2f4cc812b6e5191df52479d349089461ffe76e9f2fa2848a0fe1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410819f04aba17677807c61ae72afdddf7737f26931ecfa8af05b7c669808b36a2587e32c90bb0ed2100266dd7797c80121a109a2b0fe941ca5a580e438988cac81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let (tx, _) = TxEip4844::from_compact(&tx, tx.len()); - assert_eq!(tx.to, address!("79C9109b764609df928d16fC4a91e9081F7e87DB")); - assert_eq!(tx.placeholder, Some(())); - assert_eq!(tx.input, bytes!("ef16e8450000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007b399987d24fc5951f3e94a4cb16e87414bf22290000000000000000000000001670090000000000000000000000000000010001302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000009e640a6aadf4f664cf467b795c31332f44acbe6c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006614c2d1000000000000000000000000000000000000000000000000000000000014012c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f06fd78f4dcdf089263524731620941747b9b93fd8f631557e25b23845a78b685bd82f9d36bce2f4cc812b6e5191df52479d349089461ffe76e9f2fa2848a0fe1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410819f04aba17677807c61ae72afdddf7737f26931ecfa8af05b7c669808b36a2587e32c90bb0ed2100266dd7797c80121a109a2b0fe941ca5a580e438988cac81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); - } -} +pub use alloy_consensus::transaction::TxEip4844; diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 6665100ce7da..b580258f3622 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -159,7 +159,12 @@ impl<'a> arbitrary::Arbitrary<'a> for Transaction { tx.gas_limit = (tx.gas_limit as u64).into(); Self::Eip1559(tx) } - TxType::Eip4844 => Self::Eip4844(TxEip4844::arbitrary(u)?), + TxType::Eip4844 => { + let mut tx = TxEip4844::arbitrary(u)?; + tx.gas_limit = (tx.gas_limit as u64).into(); + Self::Eip4844(tx) + } + TxType::Eip7702 => Self::Eip7702(TxEip7702::arbitrary(u)?), #[cfg(feature = "optimism")] TxType::Deposit => Self::Deposit(TxDeposit::arbitrary(u)?), @@ -238,7 +243,7 @@ impl Transaction { Self::Legacy(_) => TxType::Legacy, Self::Eip2930(_) => TxType::Eip2930, Self::Eip1559(_) => TxType::Eip1559, - Self::Eip4844(blob_tx) => blob_tx.tx_type(), + Self::Eip4844(_) => TxType::Eip4844, Self::Eip7702(set_code_tx) => set_code_tx.tx_type(), #[cfg(feature = "optimism")] Self::Deposit(deposit_tx) => deposit_tx.tx_type(), @@ -302,7 +307,7 @@ impl Transaction { match self { Self::Legacy(TxLegacy { gas_limit, .. }) => *gas_limit as u64, Self::Eip1559(TxEip1559 { gas_limit, .. }) => *gas_limit as u64, - Self::Eip4844(TxEip4844 { gas_limit, .. }) | + Self::Eip4844(TxEip4844 { gas_limit, .. }) => *gas_limit as u64, Self::Eip7702(TxEip7702 { gas_limit, .. }) => *gas_limit, Self::Eip2930(TxEip2930 { gas_limit, .. }) => *gas_limit as u64, #[cfg(feature = "optimism")] @@ -536,7 +541,11 @@ impl Transaction { out, with_header, ), - Self::Eip4844(blob_tx) => blob_tx.encode_with_signature(signature, out, with_header), + Self::Eip4844(blob_tx) => blob_tx.encode_with_signature( + &signature.as_signature_with_boolean_parity(), + out, + with_header, + ), Self::Eip7702(set_code_tx) => { set_code_tx.encode_with_signature(signature, out, with_header) } @@ -551,7 +560,7 @@ impl Transaction { Self::Legacy(tx) => tx.gas_limit = gas_limit.into(), Self::Eip2930(tx) => tx.gas_limit = gas_limit.into(), Self::Eip1559(tx) => tx.gas_limit = gas_limit.into(), - Self::Eip4844(tx) => tx.gas_limit = gas_limit, + Self::Eip4844(tx) => tx.gas_limit = gas_limit.into(), Self::Eip7702(tx) => tx.gas_limit = gas_limit, #[cfg(feature = "optimism")] Self::Deposit(tx) => tx.gas_limit = gas_limit, @@ -1219,7 +1228,10 @@ impl TransactionSigned { &self.signature.as_signature_with_boolean_parity(), true, ), - Transaction::Eip4844(blob_tx) => blob_tx.payload_len_with_signature(&self.signature), + Transaction::Eip4844(blob_tx) => blob_tx.encoded_len_with_signature( + &self.signature.as_signature_with_boolean_parity(), + true, + ), Transaction::Eip7702(set_code_tx) => { set_code_tx.payload_len_with_signature(&self.signature) } @@ -1348,7 +1360,7 @@ impl TransactionSigned { let transaction = match tx_type { TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_fields(data)?), TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_fields(data)?), - TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode_inner(data)?), + TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode_fields(data)?), TxType::Eip7702 => Transaction::Eip7702(TxEip7702::decode_inner(data)?), #[cfg(feature = "optimism")] TxType::Deposit => Transaction::Deposit(TxDeposit::decode_inner(data)?), @@ -1427,9 +1439,10 @@ impl TransactionSigned { &self.signature.as_signature_with_boolean_parity(), false, ), - Transaction::Eip4844(blob_tx) => { - blob_tx.payload_len_with_signature_without_header(&self.signature) - } + Transaction::Eip4844(blob_tx) => blob_tx.encoded_len_with_signature( + &self.signature.as_signature_with_boolean_parity(), + false, + ), Transaction::Eip7702(set_code_tx) => { set_code_tx.payload_len_with_signature_without_header(&self.signature) } @@ -1533,11 +1546,6 @@ impl<'a> arbitrary::Arbitrary<'a> for TransactionSigned { transaction.set_chain_id(chain_id % (u64::MAX / 2 - 36)); } - if let Transaction::Eip4844(ref mut tx_eip_4844) = transaction { - tx_eip_4844.placeholder = - if tx_eip_4844.to == Address::default() { None } else { Some(()) }; - } - #[cfg(feature = "optimism")] // Both `Some(0)` and `None` values are encoded as empty string byte. This introduces // ambiguity in roundtrip tests. Patch the mint value of deposit transaction here, so that diff --git a/crates/primitives/src/transaction/pooled.rs b/crates/primitives/src/transaction/pooled.rs index 32e9a9db544a..5e0efcbffee3 100644 --- a/crates/primitives/src/transaction/pooled.rs +++ b/crates/primitives/src/transaction/pooled.rs @@ -7,7 +7,7 @@ use crate::{ TransactionSigned, TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxEip4844, TxHash, TxLegacy, B256, EIP4844_TX_TYPE_ID, }; -use alloy_consensus::SignableTransaction; +use alloy_consensus::{SignableTransaction, TxEip4844WithSidecar}; use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header, EMPTY_LIST_CODE}; use bytes::Buf; use derive_more::{AsRef, Deref}; @@ -102,7 +102,11 @@ impl PooledTransactionsElement { // If the transaction is an EIP-4844 transaction... TransactionSigned { transaction: Transaction::Eip4844(tx), signature, hash } => { // Construct a `PooledTransactionsElement::BlobTransaction` with provided sidecar. - Self::BlobTransaction(BlobTransaction { transaction: tx, signature, hash, sidecar }) + Self::BlobTransaction(BlobTransaction { + signature, + hash, + transaction: TxEip4844WithSidecar { tx, sidecar }, + }) } // If the transaction is not EIP-4844, return an error with the original // transaction. @@ -151,7 +155,7 @@ impl PooledTransactionsElement { Self::Eip2930 { transaction, .. } => transaction.nonce, Self::Eip1559 { transaction, .. } => transaction.nonce, Self::Eip7702 { transaction, .. } => transaction.nonce, - Self::BlobTransaction(blob_tx) => blob_tx.transaction.nonce, + Self::BlobTransaction(blob_tx) => blob_tx.transaction.tx.nonce, } } @@ -416,7 +420,7 @@ impl PooledTransactionsElement { /// Returns the [`TxEip4844`] variant if the transaction is an EIP-4844 transaction. pub const fn as_eip4844(&self) -> Option<&TxEip4844> { match self { - Self::BlobTransaction(tx) => Some(&tx.transaction), + Self::BlobTransaction(tx) => Some(&tx.transaction.tx), _ => None, } } @@ -445,7 +449,7 @@ impl PooledTransactionsElement { /// This is also commonly referred to as the "Blob Gas Fee Cap" (`BlobGasFeeCap`). pub const fn max_fee_per_blob_gas(&self) -> Option { match self { - Self::BlobTransaction(tx) => Some(tx.transaction.max_fee_per_blob_gas), + Self::BlobTransaction(tx) => Some(tx.transaction.tx.max_fee_per_blob_gas), _ => None, } } @@ -459,7 +463,7 @@ impl PooledTransactionsElement { Self::Legacy { .. } | Self::Eip2930 { .. } => None, Self::Eip1559 { transaction, .. } => Some(transaction.max_priority_fee_per_gas), Self::Eip7702 { transaction, .. } => Some(transaction.max_priority_fee_per_gas), - Self::BlobTransaction(tx) => Some(tx.transaction.max_priority_fee_per_gas), + Self::BlobTransaction(tx) => Some(tx.transaction.tx.max_priority_fee_per_gas), } } @@ -472,7 +476,7 @@ impl PooledTransactionsElement { Self::Eip2930 { transaction, .. } => transaction.gas_price, Self::Eip1559 { transaction, .. } => transaction.max_fee_per_gas, Self::Eip7702 { transaction, .. } => transaction.max_fee_per_gas, - Self::BlobTransaction(tx) => tx.transaction.max_fee_per_gas, + Self::BlobTransaction(tx) => tx.transaction.tx.max_fee_per_gas, } } } @@ -691,7 +695,7 @@ impl<'a> arbitrary::Arbitrary<'a> for PooledTransactionsElement { match Self::try_from(tx_signed) { Ok(Self::BlobTransaction(mut tx)) => { // Successfully converted to a BlobTransaction, now generate a sidecar. - tx.sidecar = crate::BlobTransactionSidecar::arbitrary(u)?; + tx.transaction.sidecar = crate::BlobTransactionSidecar::arbitrary(u)?; Ok(Self::BlobTransaction(tx)) } Ok(tx) => Ok(tx), // Successfully converted, but not a BlobTransaction. diff --git a/crates/primitives/src/transaction/sidecar.rs b/crates/primitives/src/transaction/sidecar.rs index 2c6f4598a513..b9583a349db3 100644 --- a/crates/primitives/src/transaction/sidecar.rs +++ b/crates/primitives/src/transaction/sidecar.rs @@ -3,7 +3,8 @@ use crate::{ keccak256, Signature, Transaction, TransactionSigned, TxEip4844, TxHash, EIP4844_TX_TYPE_ID, }; -use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header}; +use alloy_consensus::TxEip4844WithSidecar; +use alloy_rlp::{Decodable, Error as RlpError, Header}; use serde::{Deserialize, Serialize}; #[doc(inline)] @@ -24,12 +25,10 @@ use alloc::vec::Vec; pub struct BlobTransaction { /// The transaction hash. pub hash: TxHash, - /// The transaction payload. - pub transaction: TxEip4844, /// The transaction signature. pub signature: Signature, - /// The transaction's blob sidecar. - pub sidecar: BlobTransactionSidecar, + /// The transaction payload with the sidecar. + pub transaction: TxEip4844WithSidecar, } impl BlobTransaction { @@ -43,7 +42,11 @@ impl BlobTransaction { ) -> Result { let TransactionSigned { transaction, signature, hash } = tx; match transaction { - Transaction::Eip4844(transaction) => Ok(Self { hash, transaction, signature, sidecar }), + Transaction::Eip4844(transaction) => Ok(Self { + hash, + transaction: TxEip4844WithSidecar { tx: transaction, sidecar }, + signature, + }), transaction => { let tx = TransactionSigned { transaction, signature, hash }; Err((tx, sidecar)) @@ -59,19 +62,19 @@ impl BlobTransaction { &self, proof_settings: &c_kzg::KzgSettings, ) -> Result<(), BlobTransactionValidationError> { - self.transaction.validate_blob(&self.sidecar, proof_settings) + self.transaction.validate_blob(proof_settings) } /// Splits the [`BlobTransaction`] into its [`TransactionSigned`] and [`BlobTransactionSidecar`] /// components. pub fn into_parts(self) -> (TransactionSigned, BlobTransactionSidecar) { let transaction = TransactionSigned { - transaction: Transaction::Eip4844(self.transaction), + transaction: Transaction::Eip4844(self.transaction.tx), hash: self.hash, signature: self.signature, }; - (transaction, self.sidecar) + (transaction, self.transaction.sidecar) } /// Encodes the [`BlobTransaction`] fields as RLP, with a tx type. If `with_header` is `false`, @@ -111,36 +114,8 @@ impl BlobTransaction { /// Note: this should be used only when implementing other RLP encoding methods, and does not /// represent the full RLP encoding of the blob transaction. pub(crate) fn encode_inner(&self, out: &mut dyn bytes::BufMut) { - // First we construct both required list headers. - // - // The `transaction_payload_body` length is the length of the fields, plus the length of - // its list header. - let tx_header = Header { - list: true, - payload_length: self.transaction.fields_len() + self.signature.payload_len(), - }; - - let tx_length = tx_header.length() + tx_header.payload_length; - - // The payload length is the length of the `tranascation_payload_body` list, plus the - // length of the blobs, commitments, and proofs. - let payload_length = tx_length + self.sidecar.fields_len(); - - // First we use the payload len to construct the first list header - let blob_tx_header = Header { list: true, payload_length }; - - // Encode the blob tx header first - blob_tx_header.encode(out); - - // Encode the inner tx list header, then its fields - tx_header.encode(out); - self.transaction.encode_fields(out); - - // Encode the signature - self.signature.encode(out); - - // Encode the blobs, commitments, and proofs - self.sidecar.encode(out); + self.transaction + .encode_with_signature_fields(&self.signature.as_signature_with_boolean_parity(), out); } /// Outputs the length of the RLP encoding of the blob transaction, including the tx type byte, @@ -181,14 +156,14 @@ impl BlobTransaction { // its list header. let tx_header = Header { list: true, - payload_length: self.transaction.fields_len() + self.signature.payload_len(), + payload_length: self.transaction.tx.fields_len() + self.signature.payload_len(), }; let tx_length = tx_header.length() + tx_header.payload_length; // The payload length is the length of the `tranascation_payload_body` list, plus the // length of the blobs, commitments, and proofs. - let payload_length = tx_length + self.sidecar.fields_len(); + let payload_length = tx_length + self.transaction.sidecar.fields_len(); // We use the calculated payload len to construct the first list header, which encompasses // everything in the tx - the length of the second, inner list header is part of @@ -234,7 +209,7 @@ impl BlobTransaction { let inner_remaining_len = data.len(); // inner transaction - let transaction = TxEip4844::decode_inner(data)?; + let transaction = TxEip4844::decode(data)?; // signature let signature = Signature::decode(data)?; @@ -265,7 +240,11 @@ impl BlobTransaction { // Instead, we use `encode_with_signature`, which RLP encodes the transaction with a // signature for hashing without a header. We then hash the result. let mut buf = Vec::new(); - transaction.encode_with_signature(&signature, &mut buf, false); + transaction.encode_with_signature( + &signature.as_signature_with_boolean_parity(), + &mut buf, + false, + ); let hash = keccak256(&buf); // the outer header is for the entire transaction, so we check the length here @@ -274,7 +253,7 @@ impl BlobTransaction { return Err(RlpError::UnexpectedLength) } - Ok(Self { transaction, hash, signature, sidecar }) + Ok(Self { transaction: TxEip4844WithSidecar { tx: transaction, sidecar }, hash, signature }) } } @@ -311,6 +290,7 @@ mod tests { use super::*; use crate::{hex, kzg::Blob}; use alloy_eips::eip4844::Bytes48; + use alloy_rlp::Encodable; use std::{fs, path::PathBuf, str::FromStr}; #[test] diff --git a/crates/rpc/rpc-types-compat/src/transaction/typed.rs b/crates/rpc/rpc-types-compat/src/transaction/typed.rs index 21e492218a4a..ffed5117e91e 100644 --- a/crates/rpc/rpc-types-compat/src/transaction/typed.rs +++ b/crates/rpc/rpc-types-compat/src/transaction/typed.rs @@ -47,7 +47,6 @@ pub fn to_primitive_transaction( gas_limit: tx.gas_limit.to(), max_fee_per_gas: tx.max_fee_per_gas.to(), max_priority_fee_per_gas: tx.max_priority_fee_per_gas.to(), - placeholder: Some(()), to: tx.to, value: tx.value, access_list: tx.access_list, diff --git a/crates/rpc/rpc/src/eth/bundle.rs b/crates/rpc/rpc/src/eth/bundle.rs index 9cabc1f6f5fd..4731de20d035 100644 --- a/crates/rpc/rpc/src/eth/bundle.rs +++ b/crates/rpc/rpc/src/eth/bundle.rs @@ -87,7 +87,7 @@ where .iter() .filter_map(|(tx, _)| { if let PooledTransactionsElement::BlobTransaction(tx) = tx { - Some(tx.transaction.blob_gas()) + Some(tx.transaction.tx.blob_gas()) } else { None } diff --git a/crates/storage/codecs/src/alloy/transaction/eip4844.rs b/crates/storage/codecs/src/alloy/transaction/eip4844.rs new file mode 100644 index 000000000000..7ac815820dee --- /dev/null +++ b/crates/storage/codecs/src/alloy/transaction/eip4844.rs @@ -0,0 +1,96 @@ +use crate::{Compact, CompactPlaceholder}; +use alloy_consensus::transaction::TxEip4844 as AlloyTxEip4844; +use alloy_eips::eip2930::AccessList; +use alloy_primitives::{Address, Bytes, ChainId, B256, U256}; +use reth_codecs_derive::add_arbitrary_tests; +use serde::{Deserialize, Serialize}; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +/// [EIP-4844 Blob Transaction](https://eips.ethereum.org/EIPS/eip-4844#blob-transaction) +/// +/// This is a helper type to use derive on it instead of manually managing `bitfield`. +/// +/// By deriving `Compact` here, any future changes or enhancements to the `Compact` derive +/// will automatically apply to this type. +/// +/// Notice: Make sure this struct is 1:1 with [`alloy_consensus::transaction::TxEip4844`] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize, Compact)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +#[add_arbitrary_tests(compact)] +pub(crate) struct TxEip4844 { + chain_id: ChainId, + nonce: u64, + gas_limit: u64, + max_fee_per_gas: u128, + max_priority_fee_per_gas: u128, + /// TODO(debt): this should be removed if we break the DB. + /// Makes sure that the Compact bitflag struct has one bit after the above field: + /// + placeholder: Option, + to: Address, + value: U256, + access_list: AccessList, + blob_versioned_hashes: Vec, + max_fee_per_blob_gas: u128, + input: Bytes, +} + +impl Compact for AlloyTxEip4844 { + fn to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + let tx = TxEip4844 { + chain_id: self.chain_id, + nonce: self.nonce, + gas_limit: self.gas_limit as u64, + max_fee_per_gas: self.max_fee_per_gas, + max_priority_fee_per_gas: self.max_priority_fee_per_gas, + placeholder: Some(()), + to: self.to, + value: self.value, + access_list: self.access_list.clone(), + blob_versioned_hashes: self.blob_versioned_hashes.clone(), + max_fee_per_blob_gas: self.max_fee_per_blob_gas, + input: self.input.clone(), + }; + tx.to_compact(buf) + } + + fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) { + let (tx, _) = TxEip4844::from_compact(buf, len); + let alloy_tx = Self { + chain_id: tx.chain_id, + nonce: tx.nonce, + gas_limit: tx.gas_limit as u128, + max_fee_per_gas: tx.max_fee_per_gas, + max_priority_fee_per_gas: tx.max_priority_fee_per_gas, + to: tx.to, + value: tx.value, + access_list: tx.access_list, + blob_versioned_hashes: tx.blob_versioned_hashes, + max_fee_per_blob_gas: tx.max_fee_per_blob_gas, + input: tx.input, + }; + (alloy_tx, buf) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloy_primitives::{address, bytes}; + + #[test] + fn backwards_compatible_txkind_test() { + // TxEip4844 encoded with TxKind on to field + // holesky tx hash: <0xa3b1668225bf0fbfdd6c19aa6fd071fa4ff5d09a607c67ccd458b97735f745ac> + let tx = bytes!("224348a100426844cb2dc6c0b2d05e003b9aca0079c9109b764609df928d16fc4a91e9081f7e87db09310001019101fb28118ceccaabca22a47e35b9c3f12eb2dcb25e5c543d5b75e6cd841f0a05328d26ef16e8450000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007b399987d24fc5951f3e94a4cb16e87414bf22290000000000000000000000001670090000000000000000000000000000010001302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000009e640a6aadf4f664cf467b795c31332f44acbe6c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006614c2d1000000000000000000000000000000000000000000000000000000000014012c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f06fd78f4dcdf089263524731620941747b9b93fd8f631557e25b23845a78b685bd82f9d36bce2f4cc812b6e5191df52479d349089461ffe76e9f2fa2848a0fe1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410819f04aba17677807c61ae72afdddf7737f26931ecfa8af05b7c669808b36a2587e32c90bb0ed2100266dd7797c80121a109a2b0fe941ca5a580e438988cac81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + let (tx, _) = TxEip4844::from_compact(&tx, tx.len()); + assert_eq!(tx.to, address!("79C9109b764609df928d16fC4a91e9081F7e87DB")); + assert_eq!(tx.placeholder, Some(())); + assert_eq!(tx.input, bytes!("ef16e8450000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007b399987d24fc5951f3e94a4cb16e87414bf22290000000000000000000000001670090000000000000000000000000000010001302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000009e640a6aadf4f664cf467b795c31332f44acbe6c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006614c2d1000000000000000000000000000000000000000000000000000000000014012c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f06fd78f4dcdf089263524731620941747b9b93fd8f631557e25b23845a78b685bd82f9d36bce2f4cc812b6e5191df52479d349089461ffe76e9f2fa2848a0fe1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410819f04aba17677807c61ae72afdddf7737f26931ecfa8af05b7c669808b36a2587e32c90bb0ed2100266dd7797c80121a109a2b0fe941ca5a580e438988cac81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); + } +} diff --git a/crates/storage/codecs/src/alloy/transaction/mod.rs b/crates/storage/codecs/src/alloy/transaction/mod.rs index af00e90eafac..65ac7be57e66 100644 --- a/crates/storage/codecs/src/alloy/transaction/mod.rs +++ b/crates/storage/codecs/src/alloy/transaction/mod.rs @@ -1,5 +1,6 @@ mod eip1559; mod eip2930; +mod eip4844; mod legacy; #[cfg(test)] @@ -11,10 +12,11 @@ mod tests { // this check is to ensure we do not inadvertently add too many fields to a struct which would // expand the flags field and break backwards compatibility - use super::{eip1559::TxEip1559, eip2930::TxEip2930, legacy::TxLegacy}; + use super::{eip1559::TxEip1559, eip2930::TxEip2930, eip4844::TxEip4844, legacy::TxLegacy}; #[test] fn test_ensure_backwards_compatibility() { + assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3); assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4); assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3); diff --git a/crates/storage/db-api/src/models/mod.rs b/crates/storage/db-api/src/models/mod.rs index 72668354ff2c..07f69402ef5c 100644 --- a/crates/storage/db-api/src/models/mod.rs +++ b/crates/storage/db-api/src/models/mod.rs @@ -301,9 +301,7 @@ add_wrapper_struct!((ClientVersion, CompactClientVersion)); #[cfg(test)] mod tests { use super::*; - use reth_primitives::{ - Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip4844, Withdrawals, - }; + use reth_primitives::{Account, Header, Receipt, ReceiptWithBloom, SealedHeader, Withdrawals}; use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment}; use reth_stages_types::{ AccountHashingCheckpoint, CheckpointBlockRange, EntitiesCheckpoint, ExecutionCheckpoint, @@ -342,7 +340,6 @@ mod tests { assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0); assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0); assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1); - assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0); } @@ -372,7 +369,6 @@ mod tests { assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0); assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0); assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1); - assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5); assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0); } } diff --git a/crates/transaction-pool/src/test_utils/gen.rs b/crates/transaction-pool/src/test_utils/gen.rs index e51acbfcbd52..72636f2f7b3e 100644 --- a/crates/transaction-pool/src/test_utils/gen.rs +++ b/crates/transaction-pool/src/test_utils/gen.rs @@ -178,10 +178,9 @@ impl TransactionBuilder { TxEip4844 { chain_id: self.chain_id, nonce: self.nonce, - gas_limit: self.gas_limit, + gas_limit: self.gas_limit as u128, max_fee_per_gas: self.max_fee_per_gas, max_priority_fee_per_gas: self.max_priority_fee_per_gas, - placeholder: None, to: match self.to { TxKind::Call(to) => to, TxKind::Create => Address::default(), diff --git a/crates/transaction-pool/src/test_utils/mock.rs b/crates/transaction-pool/src/test_utils/mock.rs index 18597715d3dc..4d030f852fe0 100644 --- a/crates/transaction-pool/src/test_utils/mock.rs +++ b/crates/transaction-pool/src/test_utils/mock.rs @@ -186,8 +186,6 @@ pub enum MockTransaction { max_fee_per_blob_gas: u128, /// The gas limit for the transaction. gas_limit: u64, - /// Placeholder for backwards compatibility. - placeholder: Option<()>, /// The transaction's destination. to: Address, /// The value of the transaction. @@ -278,7 +276,6 @@ impl MockTransaction { max_priority_fee_per_gas: MIN_PROTOCOL_BASE_FEE as u128, max_fee_per_blob_gas: DATA_GAS_PER_BLOB as u128, gas_limit: 0, - placeholder: Some(()), to: Address::random(), value: Default::default(), input: Bytes::new(), @@ -856,7 +853,6 @@ impl TryFrom for MockTransaction { gas_limit, max_fee_per_gas, max_priority_fee_per_gas, - placeholder, to, value, input, @@ -871,8 +867,7 @@ impl TryFrom for MockTransaction { max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas, - gas_limit, - placeholder, + gas_limit: gas_limit as u64, to, value, input, @@ -989,14 +984,12 @@ impl From for Transaction { input, sidecar, size: _, - placeholder, } => Self::Eip4844(TxEip4844 { chain_id, nonce, - gas_limit, + gas_limit: gas_limit.into(), max_fee_per_gas, max_priority_fee_per_gas, - placeholder, to, value, access_list, @@ -1096,7 +1089,6 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { max_fee_per_blob_gas, access_list, blob_versioned_hashes: _, - placeholder, }) => Self::Eip4844 { chain_id: *chain_id, sender, @@ -1105,8 +1097,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { max_fee_per_gas: *max_fee_per_gas, max_priority_fee_per_gas: *max_priority_fee_per_gas, max_fee_per_blob_gas: *max_fee_per_blob_gas, - gas_limit: *gas_limit, - placeholder: *placeholder, + gas_limit: *gas_limit as u64, to: *to, value: *value, input: input.clone(), From 42dc5eea1685385b835edd03029640609f4c4ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9F=A3=20=E2=82=AC=E2=82=A5=E2=84=B5=E2=88=AA=E2=84=93?= =?UTF-8?q?=20=E2=9F=A2?= <34749913+emnul@users.noreply.github.com> Date: Sun, 1 Sep 2024 19:55:57 -0400 Subject: [PATCH 13/18] docs(NodeBuilder): fix broken link (#10644) --- crates/node/builder/src/builder/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/node/builder/src/builder/mod.rs b/crates/node/builder/src/builder/mod.rs index 156ee05ae03b..52af467cb5cd 100644 --- a/crates/node/builder/src/builder/mod.rs +++ b/crates/node/builder/src/builder/mod.rs @@ -48,6 +48,7 @@ use crate::{ // Note: we need to hardcode this because custom components might depend on it in associated types. pub type RethFullAdapter = FullNodeTypesAdapter>; +#[allow(clippy::doc_markdown)] #[cfg_attr(doc, aquamarine::aquamarine)] /// Declaratively construct a node. /// @@ -120,7 +121,7 @@ pub type RethFullAdapter = FullNodeTypesAdapter Date: Mon, 2 Sep 2024 00:50:24 -0700 Subject: [PATCH 14/18] fix: clippy (#10650) --- crates/transaction-pool/src/pool/txpool.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/transaction-pool/src/pool/txpool.rs b/crates/transaction-pool/src/pool/txpool.rs index 892d42b9d4c3..f29d220fe4a8 100644 --- a/crates/transaction-pool/src/pool/txpool.rs +++ b/crates/transaction-pool/src/pool/txpool.rs @@ -1235,7 +1235,7 @@ impl AllTransactions { pub(crate) fn descendant_txs_exclusive<'a, 'b: 'a>( &'a self, id: &'b TransactionId, - ) -> impl Iterator)> + '_ { + ) -> impl Iterator)> + 'a { self.txs.range((Excluded(id), Unbounded)).take_while(|(other, _)| id.sender == other.sender) } @@ -1246,7 +1246,7 @@ impl AllTransactions { pub(crate) fn descendant_txs_inclusive<'a, 'b: 'a>( &'a self, id: &'b TransactionId, - ) -> impl Iterator)> + '_ { + ) -> impl Iterator)> + 'a { self.txs.range(id..).take_while(|(other, _)| id.sender == other.sender) } @@ -1257,7 +1257,7 @@ impl AllTransactions { pub(crate) fn descendant_txs_mut<'a, 'b: 'a>( &'a mut self, id: &'b TransactionId, - ) -> impl Iterator)> + '_ { + ) -> impl Iterator)> + 'a { self.txs.range_mut(id..).take_while(|(other, _)| id.sender == other.sender) } From 61fe0ea4e9b26ae47d067c61a4ac2b6299618053 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 08:19:33 +0000 Subject: [PATCH 15/18] chore(deps): weekly `cargo update` (#10642) Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> --- Cargo.lock | 202 ++++++++++++++++++++++++++--------------------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 329a5e3c08a8..46dceaf62b14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -403,7 +403,7 @@ checksum = "4d0f2d905ebd295e7effec65e5f6868d153936130ae718352771de3e7d03c75c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -614,7 +614,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -626,11 +626,11 @@ dependencies = [ "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap 2.4.0", + "indexmap 2.5.0", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "syn-solidity", "tiny-keccak", ] @@ -646,7 +646,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "syn-solidity", ] @@ -851,7 +851,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -897,7 +897,7 @@ dependencies = [ "num-bigint", "num-traits", "paste", - "rustc_version 0.4.0", + "rustc_version 0.4.1", "zeroize", ] @@ -1071,7 +1071,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1082,7 +1082,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1093,7 +1093,7 @@ checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" dependencies = [ "futures", "pharos", - "rustc_version 0.4.0", + "rustc_version 0.4.1", ] [[package]] @@ -1120,7 +1120,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1230,7 +1230,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1325,7 +1325,7 @@ dependencies = [ "bitflags 2.6.0", "boa_interner", "boa_macros", - "indexmap 2.4.0", + "indexmap 2.5.0", "num-bigint", "rustc-hash 2.0.0", ] @@ -1351,7 +1351,7 @@ dependencies = [ "fast-float", "hashbrown 0.14.5", "icu_normalizer", - "indexmap 2.4.0", + "indexmap 2.5.0", "intrusive-collections", "itertools 0.13.0", "num-bigint", @@ -1397,7 +1397,7 @@ dependencies = [ "boa_gc", "boa_macros", "hashbrown 0.14.5", - "indexmap 2.4.0", + "indexmap 2.5.0", "once_cell", "phf", "rustc-hash 2.0.0", @@ -1412,7 +1412,7 @@ checksum = "25e0097fa69cde4c95f9869654004340fbbe2bcf3ce9189ba2a31a65ac40e0a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "synstructure", ] @@ -1534,7 +1534,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1746,7 +1746,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -1959,9 +1959,9 @@ dependencies = [ [[package]] name = "cpp_demangle" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ "cfg-if", ] @@ -2190,7 +2190,7 @@ dependencies = [ "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "rustc_version 0.4.0", + "rustc_version 0.4.1", "subtle", "zeroize", ] @@ -2203,7 +2203,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -2227,7 +2227,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -2238,7 +2238,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -2358,7 +2358,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -2370,8 +2370,8 @@ dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", - "rustc_version 0.4.0", - "syn 2.0.76", + "rustc_version 0.4.1", + "syn 2.0.77", ] [[package]] @@ -2392,7 +2392,7 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "unicode-xid", ] @@ -2500,7 +2500,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -2651,7 +2651,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -2662,7 +2662,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -3178,7 +3178,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -3353,7 +3353,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.4.0", + "indexmap 2.5.0", "slab", "tokio", "tokio-util", @@ -3682,7 +3682,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -3832,7 +3832,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -3919,9 +3919,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -3941,7 +3941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ "ahash", - "indexmap 2.4.0", + "indexmap 2.5.0", "is-terminal", "itoa", "log", @@ -4216,7 +4216,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -4602,7 +4602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4f0c8427b39666bf970460908b213ec09b3b350f20c0c2eabcbba51704a08e6" dependencies = [ "base64 0.22.1", - "indexmap 2.4.0", + "indexmap 2.5.0", "metrics", "metrics-util", "quanta", @@ -4634,7 +4634,7 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "hashbrown 0.14.5", - "indexmap 2.4.0", + "indexmap 2.5.0", "metrics", "num_cpus", "ordered-float", @@ -4751,7 +4751,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -4989,7 +4989,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5017,9 +5017,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -5279,7 +5279,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" dependencies = [ "futures", - "rustc_version 0.4.0", + "rustc_version 0.4.1", ] [[package]] @@ -5312,7 +5312,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5341,7 +5341,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5503,7 +5503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -5632,7 +5632,7 @@ checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -6455,7 +6455,7 @@ dependencies = [ "proc-macro2", "quote", "similar-asserts", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -7270,7 +7270,7 @@ dependencies = [ "criterion", "dashmap 6.0.1", "derive_more 1.0.0", - "indexmap 2.4.0", + "indexmap 2.5.0", "parking_lot 0.12.3", "pprof", "rand 0.8.5", @@ -7309,7 +7309,7 @@ dependencies = [ "quote", "regex", "serial_test", - "syn 2.0.76", + "syn 2.0.77", "trybuild", ] @@ -8760,9 +8760,9 @@ dependencies = [ [[package]] name = "revm" -version = "14.0.0" +version = "14.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69eae90188e48c81588fe1987b4bd35cd90d69b3602cb0c3a9ab12b882f18d91" +checksum = "1f719e28cc6fdd086f8bc481429e587740d20ad89729cec3f5f5dd7b655474df" dependencies = [ "auto_impl", "cfg-if", @@ -8793,9 +8793,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "10.0.0" +version = "10.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7bad33a4f862ed8e2dc8bb5e7935852990da74f6db986732ef4f47f9021b2e4" +checksum = "959ecbc36802de6126852479844737f20194cf8e6718e0c30697d306a2cca916" dependencies = [ "revm-primitives", "serde", @@ -8803,9 +8803,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "11.0.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24db0f8fb5bc636e18b4d36bdc4c402ea941be79cfbdb096469887b616959a46" +checksum = "6e25f604cb9db593ca3013be8c00f310d6790ccb1b7d8fbbdd4660ec8888043a" dependencies = [ "aurora-engine-modexp", "blst", @@ -8823,9 +8823,9 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "9.0.0" +version = "9.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13132ed599b17fa9057fcfc1d37d2954921958f3b96173fc4f4cf52803b32c3" +checksum = "0ccb981ede47ccf87c68cebf1ba30cdbb7ec935233ea305f3dfff4c1e10ae541" dependencies = [ "alloy-eips", "alloy-primitives 0.8.0", @@ -8853,9 +8853,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f86ae463694029097b846d8f99fd5536740602ae00022c0c50c5600720b2f71" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -9000,9 +9000,9 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver 1.0.23", ] @@ -9037,9 +9037,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -9305,7 +9305,7 @@ checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -9314,7 +9314,7 @@ version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.5.0", "itoa", "memchr", "ryu", @@ -9363,7 +9363,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.4.0", + "indexmap 2.5.0", "serde", "serde_derive", "serde_json", @@ -9380,7 +9380,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -9405,7 +9405,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -9661,7 +9661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -9707,7 +9707,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -9741,9 +9741,9 @@ dependencies = [ [[package]] name = "symbolic-common" -version = "12.10.0" +version = "12.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16629323a4ec5268ad23a575110a724ad4544aae623451de600c747bf87b36cf" +checksum = "b1944ea8afd197111bca0c0edea1e1f56abb3edd030e240c1035cc0e3ff51fec" dependencies = [ "debugid", "memmap2", @@ -9753,9 +9753,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.10.0" +version = "12.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c043a45f08f41187414592b3ceb53fb0687da57209cc77401767fb69d5b596" +checksum = "ddaccaf1bf8e73c4f64f78dbb30aadd6965c71faa4ff3fba33f8d7296cf94a87" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -9775,9 +9775,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.76" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -9793,7 +9793,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -9813,7 +9813,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -9899,7 +9899,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -9938,7 +9938,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -10091,9 +10091,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -10115,7 +10115,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -10199,7 +10199,7 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.5.0", "serde", "serde_spanned", "toml_datetime", @@ -10302,7 +10302,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -10736,7 +10736,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "wasm-bindgen-shared", ] @@ -10770,7 +10770,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10806,9 +10806,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" dependencies = [ "rustls-pki-types", ] @@ -10899,7 +10899,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -10910,7 +10910,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -11142,7 +11142,7 @@ dependencies = [ "js-sys", "log", "pharos", - "rustc_version 0.4.0", + "rustc_version 0.4.1", "send_wrapper 0.6.0", "thiserror", "wasm-bindgen", @@ -11179,7 +11179,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "synstructure", ] @@ -11201,7 +11201,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -11221,7 +11221,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "synstructure", ] @@ -11242,7 +11242,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -11264,7 +11264,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] From c49feffed46bcff454168e1ee0b3ed9be500d3b1 Mon Sep 17 00:00:00 2001 From: GROARK <39087769+GROOOOAAAARK@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:22:12 +0200 Subject: [PATCH 16/18] [#10645] docs(prune): replace prune parts by segments (#10647) Co-authored-by: GROOOOAAAARK Co-authored-by: Roman Krasiuk --- book/run/config.md | 4 ++-- book/run/pruning.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/book/run/config.md b/book/run/config.md index f2da90ea4f95..10fd40ca7630 100644 --- a/book/run/config.md +++ b/book/run/config.md @@ -352,7 +352,7 @@ i.e. keep the data for the last `100_000` blocks # Minimum pruning interval measured in blocks block_interval = 5 -[prune.parts] +[prune.segments] # Sender Recovery pruning configuration sender_recovery = { distance = 100_000 } # Prune all transaction senders before the block `head-100000`, i.e. keep transaction senders for the last 100001 blocks @@ -373,7 +373,7 @@ We can also prune receipts more granular, using the logs filtering: ```toml # Receipts pruning configuration by retaining only those receipts that contain logs emitted # by the specified addresses, discarding all others. This setting is overridden by `receipts`. -[prune.parts.receipts_log_filter] +[prune.segments.receipts_log_filter] # Prune all receipts, leaving only those which: # - Contain logs from address `0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48`, starting from the block 17000000 # - Contain logs from address `0xdac17f958d2ee523a2206206994597c13d831ec7` in the last 1001 blocks diff --git a/book/run/pruning.md b/book/run/pruning.md index b6f23f54459f..da3bb07e2cdf 100644 --- a/book/run/pruning.md +++ b/book/run/pruning.md @@ -80,14 +80,14 @@ Essentially, the full node is the same as following configuration for the pruned [prune] block_interval = 5 -[prune.parts] +[prune.segments] sender_recovery = "full" # transaction_lookup is not pruned receipts = { before = 11052984 } # Beacon Deposit Contract deployment block: https://etherscan.io/tx/0xe75fb554e433e03763a1560646ee22dcb74e5274b34c5ad644e7c0f619a7e1d0 account_history = { distance = 10_064 } storage_history = { distance = 10_064 } -[prune.parts.receipts_log_filter] +[prune.segments.receipts_log_filter] # Prune all receipts, leaving only those which contain logs from address `0x00000000219ab540356cbb839cbe05303d7705fa`, # starting from the block 11052984. This leaves receipts with the logs from the Beacon Deposit Contract. "0x00000000219ab540356cbb839cbe05303d7705fa" = { before = 11052984 } From 0243e039335e8530aca06150849a9e29633f148e Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Mon, 2 Sep 2024 12:24:39 +0400 Subject: [PATCH 17/18] chore(deps): bump op-alloy-rpc-types (#10646) Co-authored-by: Roman Krasiuk --- Cargo.lock | 16 ++++++++++------ Cargo.toml | 2 +- crates/optimism/rpc/src/eth/receipt.rs | 16 +++++++++------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46dceaf62b14..0dbc4a4632de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5038,9 +5038,9 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "op-alloy-consensus" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0db6e3a9bbbcef7cef19d77aa2cc76d61377376e3bb86f89167e7e3f30ea023" +checksum = "f024d4e0aebc67d887600f90b38ef5c410bce74561995abd79bcb2a8139a52eb" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5049,13 +5049,14 @@ dependencies = [ "alloy-serde", "derive_more 1.0.0", "serde", + "spin", ] [[package]] name = "op-alloy-network" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66184e6c92269ba4ef1f80e8566ce11d41b584884ce7476d4b1b5e0e38503ecb" +checksum = "c90477039fba02e655363be5f034da3bbaea03404d6b3fc92cddaee278e3d64b" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5068,9 +5069,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c604cd3b9680d0edd0b7127f3550bcff634c2d2efe27b2b4853e72320186a8" +checksum = "e0a8514b4b8571ef7202c6ad9de623e820952c6356285d928f64d4debbacdc09" dependencies = [ "alloy-network", "alloy-primitives 0.8.0", @@ -9637,6 +9638,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" diff --git a/Cargo.toml b/Cargo.toml index bfe18acbf57a..c7786f8676ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -446,7 +446,7 @@ alloy-transport-ipc = { version = "0.3.0", default-features = false } alloy-transport-ws = { version = "0.3.0", default-features = false } # op -op-alloy-rpc-types = "0.2" +op-alloy-rpc-types = "0.2.5" op-alloy-rpc-types-engine = "0.2" op-alloy-network = "0.2" diff --git a/crates/optimism/rpc/src/eth/receipt.rs b/crates/optimism/rpc/src/eth/receipt.rs index d9f1ffb8236d..881b91c81597 100644 --- a/crates/optimism/rpc/src/eth/receipt.rs +++ b/crates/optimism/rpc/src/eth/receipt.rs @@ -60,9 +60,9 @@ pub fn op_receipt_fields( op_fields.deposit_receipt_version = receipt.deposit_receipt_version; } else if let Some(l1_block_info) = optimism_tx_meta.l1_block_info { // always present - op_fields.l1_fee = optimism_tx_meta.l1_fee; - op_fields.l1_gas_price = Some(l1_block_info.l1_base_fee.saturating_to()); - op_fields.l1_gas_used = optimism_tx_meta.l1_data_gas.map(|dg| { + op_fields.l1_block_info.l1_fee = optimism_tx_meta.l1_fee; + op_fields.l1_block_info.l1_gas_price = Some(l1_block_info.l1_base_fee.saturating_to()); + op_fields.l1_block_info.l1_gas_used = optimism_tx_meta.l1_data_gas.map(|dg| { dg.saturating_add( l1_block_info.l1_fee_overhead.unwrap_or_default().saturating_to::(), ) @@ -72,16 +72,18 @@ pub fn op_receipt_fields( // None if ecotone is active if l1_block_info.l1_fee_overhead.is_some() { // only pre Ecotone - op_fields.l1_fee_scalar = + op_fields.l1_block_info.l1_fee_scalar = Some(f64::from(l1_block_info.l1_base_fee_scalar) / 1_000_000.0); } else { // base fee scalar is enabled post Ecotone - op_fields.l1_base_fee_scalar = Some(l1_block_info.l1_base_fee_scalar.saturating_to()); + op_fields.l1_block_info.l1_base_fee_scalar = + Some(l1_block_info.l1_base_fee_scalar.saturating_to()); } // 4844 post Ecotone - op_fields.l1_blob_base_fee = l1_block_info.l1_blob_base_fee.map(|v| v.saturating_to()); - op_fields.l1_blob_base_fee_scalar = + op_fields.l1_block_info.l1_blob_base_fee = + l1_block_info.l1_blob_base_fee.map(|v| v.saturating_to()); + op_fields.l1_block_info.l1_blob_base_fee_scalar = l1_block_info.l1_blob_base_fee_scalar.map(|v| v.saturating_to()); } From d59854f1dcd66caef32f0eea23440c2532c29611 Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Mon, 2 Sep 2024 04:25:52 -0400 Subject: [PATCH 18/18] fix(tree): replace debug_assert with relaxed removal logic (#10634) Co-authored-by: Roman Krasiuk --- .../hive/expected_failures_experimental.yaml | 2 -- crates/engine/tree/src/persistence.rs | 2 ++ crates/engine/tree/src/tree/mod.rs | 17 +++++++++++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/assets/hive/expected_failures_experimental.yaml b/.github/assets/hive/expected_failures_experimental.yaml index 66a68f0c67e7..50686a9bcb78 100644 --- a/.github/assets/hive/expected_failures_experimental.yaml +++ b/.github/assets/hive/expected_failures_experimental.yaml @@ -38,7 +38,6 @@ engine-withdrawals: # https://github.com/paradigmxyz/reth/issues/8305 # https://github.com/paradigmxyz/reth/issues/6217 engine-api: - - Re-org to Previously Validated Sidechain Payload (Paris) (reth) - Invalid Missing Ancestor ReOrg, StateRoot, EmptyTxs=False, Invalid P9 (Paris) (reth) - Invalid Missing Ancestor ReOrg, StateRoot, EmptyTxs=True, Invalid P9 (Paris) (reth) - Invalid Missing Ancestor ReOrg, StateRoot, EmptyTxs=False, Invalid P10 (Paris) (reth) @@ -54,7 +53,6 @@ engine-cancun: - Invalid NewPayload, BlobGasUsed, Syncing=True, EmptyTxs=False, DynFeeTxs=False (Cancun) (reth) - Invalid NewPayload, Blob Count on BlobGasUsed, Syncing=True, EmptyTxs=False, DynFeeTxs=False (Cancun) (reth) - Invalid NewPayload, ExcessBlobGas, Syncing=True, EmptyTxs=False, DynFeeTxs=False (Cancun) (reth) - - Re-org to Previously Validated Sidechain Payload (Cancun) (reth) - Invalid Missing Ancestor ReOrg, StateRoot, EmptyTxs=False, Invalid P9 (Cancun) (reth) - Invalid Missing Ancestor ReOrg, StateRoot, EmptyTxs=True, Invalid P9 (Cancun) (reth) - Invalid Missing Ancestor ReOrg, StateRoot, EmptyTxs=False, Invalid P10 (Cancun) (reth) diff --git a/crates/engine/tree/src/persistence.rs b/crates/engine/tree/src/persistence.rs index 04943cd9b1c7..8ccfde04b169 100644 --- a/crates/engine/tree/src/persistence.rs +++ b/crates/engine/tree/src/persistence.rs @@ -88,6 +88,7 @@ where } fn on_remove_blocks_above(&self, new_tip_num: u64) -> Result<(), PersistenceError> { + debug!(target: "tree::persistence", ?new_tip_num, "Removing blocks"); let start_time = Instant::now(); let provider_rw = self.provider.provider_rw()?; let sf_provider = self.provider.static_file_provider(); @@ -100,6 +101,7 @@ where } fn on_save_blocks(&self, blocks: Vec) -> Result, PersistenceError> { + debug!(target: "tree::persistence", first=?blocks.first().map(|b| b.block.number), last=?blocks.last().map(|b| b.block.number), "Saving range of blocks"); let start_time = Instant::now(); let last_block_hash = blocks.last().map(|block| block.block().hash()); diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index e9b9ade96305..666760651336 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -221,13 +221,25 @@ impl TreeState { /// /// Canonical blocks below the upper bound will still be removed. /// - /// NOTE: This assumes that the `finalized_num` is below or equal to the `upper_bound` + /// NOTE: if the finalized block is greater than the upper bound, the only blocks that will be + /// removed are canonical blocks and sidechains that fork below the `upper_bound`. This is the + /// same behavior as if the `finalized_num` were `Some(upper_bound)`. pub(crate) fn remove_until( &mut self, upper_bound: BlockNumber, finalized_num: Option, ) { - debug_assert!(Some(upper_bound) >= finalized_num); + debug!(target: "engine", ?upper_bound, ?finalized_num, "Removing blocks from the tree"); + + // If the finalized num is ahead of the upper bound, and exists, we need to instead ensure + // that the only blocks removed, are canonical blocks less than the upper bound + // finalized_num.take_if(|finalized| *finalized > upper_bound); + let finalized_num = finalized_num.map(|finalized| { + let new_finalized_num = finalized.min(upper_bound); + debug!(target: "engine", ?new_finalized_num, "Adjusted upper bound"); + new_finalized_num + }); + // We want to do two things: // * remove canonical blocks that are persisted // * remove forks whose root are below the finalized block @@ -1247,6 +1259,7 @@ where let target_number = canonical_head_number.saturating_sub(self.config.memory_block_buffer_target()); + debug!(target: "engine", ?last_persisted_number, ?canonical_head_number, ?target_number, ?current_hash, "Returning canonical blocks to persist"); while let Some(block) = self.state.tree_state.blocks_by_hash.get(¤t_hash) { if block.block.number <= last_persisted_number { break;