From 081d71e1a2f6ae3731c9207a7533beb98861ca8c Mon Sep 17 00:00:00 2001 From: Roberto Bayardo Date: Wed, 4 Oct 2023 05:07:44 -0700 Subject: [PATCH] change transaction value fields from u128 to a wrapper-type of U256 (#4439) Co-authored-by: Matthias Seitz --- Cargo.lock | 1 + bin/reth/src/main.rs | 3 + crates/consensus/common/src/validation.rs | 4 +- .../interfaces/src/test_utils/generators.rs | 6 +- crates/net/network/tests/it/requests.rs | 2 +- crates/primitives/Cargo.toml | 6 + crates/primitives/src/lib.rs | 6 +- crates/primitives/src/precaution.rs | 24 ++++ crates/primitives/src/transaction/eip1559.rs | 12 +- crates/primitives/src/transaction/eip2930.rs | 14 +-- crates/primitives/src/transaction/eip4844.rs | 10 +- crates/primitives/src/transaction/legacy.rs | 10 +- crates/primitives/src/transaction/mod.rs | 16 +-- crates/primitives/src/transaction/tx_value.rs | 111 ++++++++++++++++++ crates/revm/revm-primitives/src/env.rs | 8 +- .../rpc-types-compat/src/transaction/mod.rs | 2 +- .../rpc-types/src/eth/transaction/typed.rs | 6 +- crates/rpc/rpc/src/txpool.rs | 2 +- crates/storage/codecs/Cargo.toml | 1 + crates/storage/codecs/derive/Cargo.toml | 1 + .../storage/codecs/derive/src/compact/mod.rs | 5 + .../transaction-pool/src/test_utils/mock.rs | 14 +-- crates/transaction-pool/src/traits.rs | 3 +- 23 files changed, 204 insertions(+), 63 deletions(-) create mode 100644 crates/primitives/src/precaution.rs create mode 100644 crates/primitives/src/transaction/tx_value.rs diff --git a/Cargo.lock b/Cargo.lock index 9deda66ff..a5a0f8ace 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6043,6 +6043,7 @@ dependencies = [ "rand 0.8.5", "rayon", "reth-codecs", + "reth-primitives", "revm-primitives", "secp256k1", "serde", diff --git a/bin/reth/src/main.rs b/bin/reth/src/main.rs index 220b04d9d..3b1811f11 100644 --- a/bin/reth/src/main.rs +++ b/bin/reth/src/main.rs @@ -4,6 +4,9 @@ static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; fn main() { + // ensure we have the correct features enabled + reth::primitives::ensure_ethereum!(); + if let Err(err) = reth::cli::run() { eprintln!("Error: {err:?}"); std::process::exit(1); diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index 715e7333a..9d731d25b 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -576,7 +576,7 @@ mod tests { gas_price: 0x28f000fff, gas_limit: 10, to: TransactionKind::Call(Address::default()), - value: 3, + value: 3_u64.into(), input: Bytes::from(vec![1, 2]), access_list: Default::default(), }); @@ -598,7 +598,7 @@ mod tests { max_fee_per_blob_gas: 0x7, gas_limit: 10, to: TransactionKind::Call(Address::default()), - value: 3, + value: 3_u64.into(), input: Bytes::from(vec![1, 2]), access_list: Default::default(), blob_versioned_hashes: std::iter::repeat_with(|| rng.gen()).take(num_blobs).collect(), diff --git a/crates/interfaces/src/test_utils/generators.rs b/crates/interfaces/src/test_utils/generators.rs index daaabc52f..a4848dbee 100644 --- a/crates/interfaces/src/test_utils/generators.rs +++ b/crates/interfaces/src/test_utils/generators.rs @@ -80,7 +80,7 @@ pub fn random_tx(rng: &mut R) -> Transaction { gas_price: rng.gen::().into(), gas_limit: rng.gen::().into(), to: TransactionKind::Call(rng.gen()), - value: rng.gen::().into(), + value: U256::from(rng.gen::()).into(), input: Bytes::default(), }) } @@ -398,7 +398,7 @@ mod test { nonce: 0x42, gas_limit: 44386, to: TransactionKind::Call(hex!("6069a6c32cf691f5982febae4faf8a6f3ab2f0f6").into()), - value: 0_u128, + value: 0_u64.into(), input: hex!("a22cb4650000000000000000000000005eee75727d804a2b13038928d36f8b188945a57a0000000000000000000000000000000000000000000000000000000000000000").into(), max_fee_per_gas: 0x4a817c800, max_priority_fee_per_gas: 0x3b9aca00, @@ -430,7 +430,7 @@ mod test { gas_price: 20 * 10_u128.pow(9), gas_limit: 21000, to: TransactionKind::Call(hex!("3535353535353535353535353535353535353535").into()), - value: 10_u128.pow(18), + value: 10_u128.pow(18).into(), input: Bytes::default(), }); diff --git a/crates/net/network/tests/it/requests.rs b/crates/net/network/tests/it/requests.rs index cb35e93b9..cfe7df275 100644 --- a/crates/net/network/tests/it/requests.rs +++ b/crates/net/network/tests/it/requests.rs @@ -22,7 +22,7 @@ pub fn rng_transaction(rng: &mut impl rand::RngCore) -> TransactionSigned { gas_price: rng.gen(), gas_limit: rng.gen(), to: TransactionKind::Create, - value: rng.gen(), + value: rng.gen::().into(), input: Bytes::from(vec![1, 2]), access_list: Default::default(), }); diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 7ca606c63..69bf1bfc8 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -79,6 +79,9 @@ triehash = "0.8" plain_hasher = "0.2" hash-db = "~0.15" +# value-256 is needed for the main_codec proptests to pass +reth-primitives = { path = ".", features = ["value-256"] } + # necessary so we don't hit a "undeclared 'std'": # https://github.com/paradigmxyz/reth/pull/177#discussion_r1021172198 @@ -90,6 +93,9 @@ pprof = { version = "0.12", features = ["flamegraph", "frame-pointer", "criterio default = [] arbitrary = ["revm-primitives/arbitrary", "dep:arbitrary", "dep:proptest", "dep:proptest-derive"] test-utils = ["dep:plain_hasher", "dep:hash-db", "dep:ethers-core"] +# value-256 controls whether transaction Value fields are DB-encoded as 256 bits instead of the +# default of 128 bits. +value-256 = ["reth-codecs/value-256"] [[bench]] name = "recover_ecdsa_crit" diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index a6244451d..693aacc43 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -45,6 +45,8 @@ mod transaction; pub mod trie; mod withdrawal; +mod precaution; + pub use account::{Account, Bytecode}; pub use block::{ Block, BlockBody, BlockBodyRoots, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag, @@ -87,8 +89,8 @@ pub use transaction::{ IntoRecoveredTransaction, InvalidTransactionError, PooledTransactionsElement, PooledTransactionsElementEcRecovered, Signature, Transaction, TransactionKind, TransactionMeta, TransactionSigned, TransactionSignedEcRecovered, TransactionSignedNoHash, TxEip1559, TxEip2930, - TxEip4844, TxLegacy, TxType, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, - LEGACY_TX_TYPE_ID, + TxEip4844, TxLegacy, TxType, TxValue, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, + EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID, }; pub use withdrawal::Withdrawal; diff --git a/crates/primitives/src/precaution.rs b/crates/primitives/src/precaution.rs new file mode 100644 index 000000000..0750f65ec --- /dev/null +++ b/crates/primitives/src/precaution.rs @@ -0,0 +1,24 @@ +//! Helpers to ensure certain features are enabled or disabled. +//! +//! The motivation for this is to prevent that a binary is accidentally built with a feature that is +//! not intended to be used. +//! +//! Currently conflicting features are: `value-u256` which is required by optimism. + +/// A macro to ensure that the crate's features are compatible with ethereum +#[macro_export] +macro_rules! ensure_ethereum { + () => { + #[cfg(feature = "value-256")] + compile_error!("The `value-256` feature is enabled but for `ethereum` it must be disabled: https://github.com/paradigmxyz/reth/issues/4891"); + }; +} + +/// A macro to ensure that the crate's features are compatible with optimism +#[macro_export] +macro_rules! ensure_optimism { + () => { + #[cfg(not(feature = "value-256"))] + compile_error!("The `value-256` feature is disabled but for `optimism` it must be enabled: https://github.com/paradigmxyz/reth/issues/4891"); + }; +} diff --git a/crates/primitives/src/transaction/eip1559.rs b/crates/primitives/src/transaction/eip1559.rs index 5a9e07fa7..bb2092be8 100644 --- a/crates/primitives/src/transaction/eip1559.rs +++ b/crates/primitives/src/transaction/eip1559.rs @@ -1,5 +1,5 @@ use super::access_list::AccessList; -use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, B256}; +use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, TxValue, B256}; use alloy_rlp::{length_of_length, Decodable, Encodable, Header}; use bytes::BytesMut; use reth_codecs::{main_codec, Compact}; @@ -46,11 +46,7 @@ pub struct TxEip1559 { /// 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. - /// - /// 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 value: u128, + pub value: TxValue, /// 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). @@ -185,7 +181,7 @@ impl TxEip1559 { mem::size_of::() + // max_fee_per_gas mem::size_of::() + // max_priority_fee_per_gas self.to.size() + // to - mem::size_of::() + // value + mem::size_of::() + // value self.access_list.size() + // access_list self.input.len() // input } @@ -235,7 +231,7 @@ mod tests { nonce: 0x42, gas_limit: 44386, to: TransactionKind::Call( hex!("6069a6c32cf691f5982febae4faf8a6f3ab2f0f6").into()), - value: 0, + value: 0_u64.into(), input: hex!("a22cb4650000000000000000000000005eee75727d804a2b13038928d36f8b188945a57a0000000000000000000000000000000000000000000000000000000000000000").into(), max_fee_per_gas: 0x4a817c800, max_priority_fee_per_gas: 0x3b9aca00, diff --git a/crates/primitives/src/transaction/eip2930.rs b/crates/primitives/src/transaction/eip2930.rs index afafa0de0..e490d7bff 100644 --- a/crates/primitives/src/transaction/eip2930.rs +++ b/crates/primitives/src/transaction/eip2930.rs @@ -1,5 +1,5 @@ use super::access_list::AccessList; -use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, B256}; +use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, TxValue, B256}; use alloy_rlp::{length_of_length, Decodable, Encodable, Header}; use bytes::BytesMut; use reth_codecs::{main_codec, Compact}; @@ -34,11 +34,7 @@ pub struct TxEip2930 { /// 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. - /// - /// 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 value: u128, + pub value: TxValue, /// 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). @@ -62,7 +58,7 @@ impl TxEip2930 { mem::size_of::() + // gas_price mem::size_of::() + // gas_limit self.to.size() + // to - mem::size_of::() + // value + mem::size_of::() + // value self.access_list.size() + // access_list self.input.len() // input } @@ -197,7 +193,7 @@ mod tests { gas_price: 1, gas_limit: 2, to: TransactionKind::Create, - value: 3, + value: 3_u64.into(), input: Bytes::from(vec![1, 2]), access_list: Default::default(), }); @@ -220,7 +216,7 @@ mod tests { gas_price: 1, gas_limit: 2, to: TransactionKind::Call(Address::default()), - value: 3, + value: 3_u64.into(), input: Bytes::from(vec![1, 2]), access_list: Default::default(), }); diff --git a/crates/primitives/src/transaction/eip4844.rs b/crates/primitives/src/transaction/eip4844.rs index f7ee8c0d4..1ce0be764 100644 --- a/crates/primitives/src/transaction/eip4844.rs +++ b/crates/primitives/src/transaction/eip4844.rs @@ -7,7 +7,7 @@ use crate::{ BYTES_PER_COMMITMENT, BYTES_PER_PROOF, }, kzg_to_versioned_hash, Bytes, ChainId, Signature, Transaction, TransactionKind, - TransactionSigned, TxHash, TxType, B256, EIP4844_TX_TYPE_ID, + TransactionSigned, TxHash, TxType, TxValue, B256, EIP4844_TX_TYPE_ID, }; use alloy_rlp::{length_of_length, Decodable, Encodable, Error as RlpError, Header}; use bytes::BytesMut; @@ -58,11 +58,7 @@ pub struct TxEip4844 { /// 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. - /// - /// 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 value: u128, + pub value: TxValue, /// 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). @@ -247,7 +243,7 @@ impl TxEip4844 { mem::size_of::() + // max_fee_per_gas mem::size_of::() + // max_priority_fee_per_gas self.to.size() + // to - mem::size_of::() + // value + 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 diff --git a/crates/primitives/src/transaction/legacy.rs b/crates/primitives/src/transaction/legacy.rs index 90bce9128..98153c6bd 100644 --- a/crates/primitives/src/transaction/legacy.rs +++ b/crates/primitives/src/transaction/legacy.rs @@ -1,4 +1,4 @@ -use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, B256}; +use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, TxValue, B256}; use alloy_rlp::{length_of_length, Encodable, Header}; use bytes::BytesMut; use reth_codecs::{main_codec, Compact}; @@ -33,11 +33,7 @@ pub struct TxLegacy { /// 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. - /// - /// 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 value: u128, + pub value: TxValue, /// 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, @@ -55,7 +51,7 @@ impl TxLegacy { mem::size_of::() + // gas_price mem::size_of::() + // gas_limit self.to.size() + // to - mem::size_of::() + // value + mem::size_of::() + // value self.input.len() // input } diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index f111ee0ff..740d44510 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -27,6 +27,7 @@ pub use signature::Signature; pub use tx_type::{ TxType, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID, }; +pub use tx_value::TxValue; mod access_list; mod eip1559; @@ -38,6 +39,7 @@ mod meta; mod pooled; mod signature; mod tx_type; +mod tx_value; pub(crate) mod util; // Expected number of transactions where we can expect a speed-up by recovering the senders in @@ -157,7 +159,7 @@ impl Transaction { } /// Gets the transaction's value field. - pub fn value(&self) -> u128 { + pub fn value(&self) -> TxValue { *match self { Transaction::Legacy(TxLegacy { value, .. }) => value, Transaction::Eip2930(TxEip2930 { value, .. }) => value, @@ -372,7 +374,7 @@ impl Transaction { } /// This sets the transaction's value. - pub fn set_value(&mut self, value: u128) { + pub fn set_value(&mut self, value: TxValue) { match self { Transaction::Legacy(tx) => tx.value = value, Transaction::Eip2930(tx) => tx.value = value, @@ -1242,7 +1244,7 @@ mod tests { to: TransactionKind::Call( Address::from_str("d3e8763675e4c425df46cc3b5c0f6cbdac396046").unwrap(), ), - value: 1000000000000000, + value: 1000000000000000_u64.into(), input: Bytes::default(), }); let signature = Signature { @@ -1264,7 +1266,7 @@ mod tests { to: TransactionKind::Call(Address::from_slice( &hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046")[..], )), - value: 693361000000000u64.into(), + value: 693361000000000_u64.into(), input: Default::default(), }); let signature = Signature { @@ -1285,7 +1287,7 @@ mod tests { to: TransactionKind::Call(Address::from_slice( &hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046")[..], )), - value: 1000000000000000u64.into(), + value: 1000000000000000_u64.into(), input: Bytes::default(), }); let signature = Signature { @@ -1307,7 +1309,7 @@ mod tests { to: TransactionKind::Call(Address::from_slice( &hex!("61815774383099e24810ab832a5b2a5425c154d5")[..], )), - value: 3000000000000000000u64.into(), + value: 3000000000000000000_u64.into(), input: Default::default(), access_list: Default::default(), }); @@ -1329,7 +1331,7 @@ mod tests { to: TransactionKind::Call(Address::from_slice( &hex!("cf7f9e66af820a19257a2108375b180b0ec49167")[..], )), - value: 1234u64.into(), + value: 1234_u64.into(), input: Bytes::default(), }); let signature = Signature { diff --git a/crates/primitives/src/transaction/tx_value.rs b/crates/primitives/src/transaction/tx_value.rs new file mode 100644 index 000000000..b4ed61d96 --- /dev/null +++ b/crates/primitives/src/transaction/tx_value.rs @@ -0,0 +1,111 @@ +#[allow(unused_imports)] +// suppress warning for UIntTryTo, which is required only when value-256 feature is disabled +use crate::{ + ruint::{ToUintError, UintTryFrom, UintTryTo}, + U256, +}; +use alloy_rlp::{Decodable, Encodable, Error}; +use reth_codecs::{derive_arbitrary, Compact}; +use serde::{Deserialize, Serialize}; + +/// TxValue is the type of the `value` field in the various Ethereum transactions structs. +/// While the field is 256 bits, for many chains it's not possible for the field to use +/// this full precision, hence we use a wrapper type to allow for overriding of encoding. +#[derive_arbitrary(compact, rlp)] +#[derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +pub struct TxValue(U256); + +impl From for U256 { + /// unwrap Value to U256 + fn from(value: TxValue) -> U256 { + value.0 + } +} + +impl From for TxValue +where + Self: UintTryFrom, +{ + /// construct a Value from misc. other uint types + fn from(value: T) -> Self { + match Self::uint_try_from(value) { + Ok(n) => n, + Err(e) => panic!("Uint conversion error: {e}"), + } + } +} + +impl UintTryFrom for TxValue { + #[inline] + fn uint_try_from(value: U256) -> Result> { + Ok(Self(value)) + } +} + +impl UintTryFrom for TxValue { + #[inline] + fn uint_try_from(value: u128) -> Result> { + Ok(Self(U256::from(value))) + } +} + +impl UintTryFrom for TxValue { + #[inline] + fn uint_try_from(value: u64) -> Result> { + Ok(Self(U256::from(value))) + } +} + +impl Encodable for TxValue { + fn encode(&self, out: &mut dyn bytes::BufMut) { + self.0.encode(out) + } + fn length(&self) -> usize { + self.0.length() + } +} + +impl Decodable for TxValue { + fn decode(buf: &mut &[u8]) -> Result { + Ok(TxValue(U256::decode(buf)?)) + } +} + +/// As ethereum circulation on mainnet is around 120mil eth as of 2022 that is around +/// 120000000000000000000000000 wei we are safe to use u128 for TxValue's encoding +/// as its max number is 340282366920938463463374607431768211455. +/// This optimization should be disabled for chains such as Optimism, where +/// some tx values may require more than 128-bit precision. +impl Compact for TxValue { + #[allow(unreachable_code)] + fn to_compact(self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + #[cfg(feature = "value-256")] + { + self.0.to_compact(buf) + } + #[cfg(not(feature = "value-256"))] + { + // SAFETY: For ethereum mainnet this is safe as the max value is + // 120000000000000000000000000 wei + let i: u128 = self.0.uint_try_to().expect("value could not be converted to u128"); + i.to_compact(buf) + } + } + + #[allow(unreachable_code)] + fn from_compact(buf: &[u8], identifier: usize) -> (Self, &[u8]) { + #[cfg(feature = "value-256")] + { + let (i, buf) = U256::from_compact(buf, identifier); + (TxValue(i), buf) + } + #[cfg(not(feature = "value-256"))] + { + let (i, buf) = u128::from_compact(buf, identifier); + (TxValue::from(i), buf) + } + } +} diff --git a/crates/revm/revm-primitives/src/env.rs b/crates/revm/revm-primitives/src/env.rs index 1ebb9e1f6..3ad3a9475 100644 --- a/crates/revm/revm-primitives/src/env.rs +++ b/crates/revm/revm-primitives/src/env.rs @@ -186,7 +186,7 @@ where TransactionKind::Call(to) => TransactTo::Call(*to), TransactionKind::Create => TransactTo::create(), }; - tx_env.value = U256::from(*value); + tx_env.value = (*value).into(); tx_env.data = input.clone(); tx_env.chain_id = *chain_id; tx_env.nonce = Some(*nonce); @@ -211,7 +211,7 @@ where TransactionKind::Call(to) => TransactTo::Call(*to), TransactionKind::Create => TransactTo::create(), }; - tx_env.value = U256::from(*value); + tx_env.value = (*value).into(); tx_env.data = input.clone(); tx_env.chain_id = Some(*chain_id); tx_env.nonce = Some(*nonce); @@ -243,7 +243,7 @@ where TransactionKind::Call(to) => TransactTo::Call(*to), TransactionKind::Create => TransactTo::create(), }; - tx_env.value = U256::from(*value); + tx_env.value = (*value).into(); tx_env.data = input.clone(); tx_env.chain_id = Some(*chain_id); tx_env.nonce = Some(*nonce); @@ -277,7 +277,7 @@ where TransactionKind::Call(to) => TransactTo::Call(*to), TransactionKind::Create => TransactTo::create(), }; - tx_env.value = U256::from(*value); + tx_env.value = (*value).into(); tx_env.data = input.clone(); tx_env.chain_id = Some(*chain_id); tx_env.nonce = Some(*nonce); diff --git a/crates/rpc/rpc-types-compat/src/transaction/mod.rs b/crates/rpc/rpc-types-compat/src/transaction/mod.rs index 07a6f5ff2..e4149c7ec 100644 --- a/crates/rpc/rpc-types-compat/src/transaction/mod.rs +++ b/crates/rpc/rpc-types-compat/src/transaction/mod.rs @@ -111,7 +111,7 @@ fn fill( nonce: U64::from(signed_tx.nonce()), from: signer, to, - value: U256::from(signed_tx.value()), + value: signed_tx.value().into(), gas_price, max_fee_per_gas, max_priority_fee_per_gas: signed_tx.max_priority_fee_per_gas().map(U128::from), diff --git a/crates/rpc/rpc-types/src/eth/transaction/typed.rs b/crates/rpc/rpc-types/src/eth/transaction/typed.rs index 8b3689493..b05ab570b 100644 --- a/crates/rpc/rpc-types/src/eth/transaction/typed.rs +++ b/crates/rpc/rpc-types/src/eth/transaction/typed.rs @@ -37,7 +37,7 @@ impl TypedTransactionRequest { gas_price: tx.gas_price.to(), gas_limit: tx.gas_limit.try_into().ok()?, to: tx.kind.into(), - value: tx.value.try_into().ok()?, + value: tx.value.into(), input: tx.input, }), TypedTransactionRequest::EIP2930(tx) => Transaction::Eip2930(TxEip2930 { @@ -46,7 +46,7 @@ impl TypedTransactionRequest { gas_price: tx.gas_price.to(), gas_limit: tx.gas_limit.try_into().ok()?, to: tx.kind.into(), - value: tx.value.try_into().ok()?, + value: tx.value.into(), input: tx.input, access_list: tx.access_list, }), @@ -56,7 +56,7 @@ impl TypedTransactionRequest { max_fee_per_gas: tx.max_fee_per_gas.to(), gas_limit: tx.gas_limit.try_into().ok()?, to: tx.kind.into(), - value: tx.value.try_into().ok()?, + value: tx.value.into(), input: tx.input, access_list: tx.access_list, max_priority_fee_per_gas: tx.max_priority_fee_per_gas.to(), diff --git a/crates/rpc/rpc/src/txpool.rs b/crates/rpc/rpc/src/txpool.rs index 6458b015f..b3d4cf267 100644 --- a/crates/rpc/rpc/src/txpool.rs +++ b/crates/rpc/rpc/src/txpool.rs @@ -99,7 +99,7 @@ where let gas = tx.gas_limit(); let summary = TxpoolInspectSummary { to, - value: U256::from(value), + value: value.into(), gas: U256::from(gas), gas_price: U256::from(gas_price), }; diff --git a/crates/storage/codecs/Cargo.toml b/crates/storage/codecs/Cargo.toml index 80bdefe2b..e00ba69d8 100644 --- a/crates/storage/codecs/Cargo.toml +++ b/crates/storage/codecs/Cargo.toml @@ -14,6 +14,7 @@ scale = ["codecs-derive/scale"] postcard = ["codecs-derive/postcard"] no_codec = ["codecs-derive/no_codec"] arbitrary = ["revm-primitives/arbitrary", "dep:arbitrary", "dep:proptest", "dep:proptest-derive"] +value-256 = ["codecs-derive/value-256"] [dependencies] bytes.workspace = true diff --git a/crates/storage/codecs/derive/Cargo.toml b/crates/storage/codecs/derive/Cargo.toml index 4a3cea714..6d5f8be7c 100644 --- a/crates/storage/codecs/derive/Cargo.toml +++ b/crates/storage/codecs/derive/Cargo.toml @@ -38,3 +38,4 @@ compact = [] scale = [] postcard = [] no_codec = [] +value-256 = [] \ No newline at end of file diff --git a/crates/storage/codecs/derive/src/compact/mod.rs b/crates/storage/codecs/derive/src/compact/mod.rs index 4bec0cce0..9f6ee1062 100644 --- a/crates/storage/codecs/derive/src/compact/mod.rs +++ b/crates/storage/codecs/derive/src/compact/mod.rs @@ -164,6 +164,11 @@ pub fn get_bit_size(ftype: &str) -> u8 { "u64" | "BlockNumber" | "TxNumber" | "ChainId" | "NumTransactions" => 4, "u128" => 5, "U256" => 6, + #[cfg(not(feature = "value-256"))] + "TxValue" => 5, // u128 for ethereum chains assuming high order bits are not used + #[cfg(feature = "value-256")] + // for fuzz/prop testing and chains that may require full 256 bits + "TxValue" => 6, _ => 0, } } diff --git a/crates/transaction-pool/src/test_utils/mock.rs b/crates/transaction-pool/src/test_utils/mock.rs index 547fe093d..666035f0f 100644 --- a/crates/transaction-pool/src/test_utils/mock.rs +++ b/crates/transaction-pool/src/test_utils/mock.rs @@ -16,7 +16,7 @@ use reth_primitives::{ hex, Address, FromRecoveredPooledTransaction, FromRecoveredTransaction, IntoRecoveredTransaction, PooledTransactionsElementEcRecovered, Signature, Transaction, TransactionKind, TransactionSigned, TransactionSignedEcRecovered, TxEip1559, TxEip2930, - TxEip4844, TxHash, TxLegacy, TxType, B256, EIP1559_TX_TYPE_ID, EIP4844_TX_TYPE_ID, + TxEip4844, TxHash, TxLegacy, TxType, TxValue, B256, EIP1559_TX_TYPE_ID, EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID, U128, U256, }; use std::{ops::Range, sync::Arc, time::Instant}; @@ -512,7 +512,7 @@ impl FromRecoveredTransaction for MockTransaction { gas_price, gas_limit, to, - value: U256::from(value), + value: value.into(), }, Transaction::Eip1559(TxEip1559 { chain_id: _, @@ -532,7 +532,7 @@ impl FromRecoveredTransaction for MockTransaction { max_priority_fee_per_gas, gas_limit, to, - value: U256::from(value), + value: value.into(), }, Transaction::Eip4844(TxEip4844 { chain_id: _, @@ -555,7 +555,7 @@ impl FromRecoveredTransaction for MockTransaction { max_fee_per_blob_gas, gas_limit, to, - value: U256::from(value), + value: value.into(), }, Transaction::Eip2930 { .. } => { unimplemented!() @@ -626,7 +626,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { gas_price: *gas_price, gas_limit: *gas_limit, to: *to, - value: U256::from(*value), + value: (*value).into(), }, Transaction::Eip1559(TxEip1559 { nonce, @@ -645,7 +645,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { max_priority_fee_per_gas: *max_priority_fee_per_gas, gas_limit: *gas_limit, to: *to, - value: U256::from(*value), + value: (*value).into(), }, Transaction::Eip4844(TxEip4844 { nonce, @@ -666,7 +666,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { max_fee_per_blob_gas: *max_fee_per_blob_gas, gas_limit: *gas_limit, to: *to, - value: U256::from(*value), + value: (*value).into(), }, }) .boxed() diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index 94ec8c7ed..5aaec28f7 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -811,7 +811,8 @@ impl EthPooledTransaction { U256::from(t.max_fee_per_gas) * U256::from(t.gas_limit) } }; - let mut cost = gas_cost + U256::from(transaction.value()); + let mut cost: U256 = transaction.value().into(); + cost += gas_cost; if let Some(blob_tx) = transaction.as_eip4844() { // add max blob cost