From 12d7d5a8b420dc6a571ca307a6efbff0555b2064 Mon Sep 17 00:00:00 2001 From: sprites0 <199826320+sprites0@users.noreply.github.com> Date: Thu, 3 Jul 2025 04:01:42 +0000 Subject: [PATCH] refactor(tx_wrapper): Use derive(TransactionEnvelope) --- src/evm/transaction.rs | 2 +- src/node/mod.rs | 2 +- src/node/primitives/tx_wrapper.rs | 282 ++++++++++-------------------- src/node/storage/mod.rs | 2 +- src/node/types/reth_compat.rs | 12 +- 5 files changed, 100 insertions(+), 200 deletions(-) diff --git a/src/evm/transaction.rs b/src/evm/transaction.rs index bd2379dc6..8f1dc6702 100644 --- a/src/evm/transaction.rs +++ b/src/evm/transaction.rs @@ -130,7 +130,7 @@ impl FromRecoveredTx for HlTxEnv { impl FromTxWithEncoded for HlTxEnv { fn from_encoded_tx(tx: &TransactionSigned, sender: Address, _encoded: Bytes) -> Self { - let base = match tx.clone().0.into_typed_transaction() { + let base = match tx.clone().into_inner().into_typed_transaction() { reth_primitives::Transaction::Legacy(tx) => TxEnv::from_recovered_tx(&tx, sender), reth_primitives::Transaction::Eip2930(tx) => TxEnv::from_recovered_tx(&tx, sender), reth_primitives::Transaction::Eip1559(tx) => TxEnv::from_recovered_tx(&tx, sender), diff --git a/src/node/mod.rs b/src/node/mod.rs index 76cf29b15..d59850870 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -139,7 +139,7 @@ where inner: BlockBody { transactions: transactions .into_transactions() - .map(|tx| TransactionSigned(tx.inner.into_inner().into())) + .map(|tx| TransactionSigned::Default(tx.inner.into_inner().into())) .collect(), ommers: Default::default(), withdrawals, diff --git a/src/node/primitives/tx_wrapper.rs b/src/node/primitives/tx_wrapper.rs index 223ba5726..bbc60b23f 100644 --- a/src/node/primitives/tx_wrapper.rs +++ b/src/node/primitives/tx_wrapper.rs @@ -1,18 +1,13 @@ //! HlNodePrimitives::TransactionSigned; it's the same as ethereum transaction type, //! except that it supports pseudo signer for system transactions. -use std::hash::Hasher; - use alloy_consensus::{ - crypto::RecoveryError, EthereumTxEnvelope, Signed, Transaction as TransactionTrait, TxEip1559, - TxEip2930, TxEip4844, TxEip4844WithSidecar, TxEip7702, TxEnvelope, TxLegacy, TxType, - TypedTransaction, + crypto::RecoveryError, error::ValueError, EthereumTxEnvelope, SignableTransaction, Signed, + Transaction as TransactionTrait, TransactionEnvelope, TxEip1559, TxEip2930, TxEip4844, + TxEip4844WithSidecar, TxEip7702, TxLegacy, TxType, TypedTransaction, }; -use alloy_eips::{ - eip2718::Eip2718Result, eip7594::BlobTransactionSidecarVariant, eip7702::SignedAuthorization, - Decodable2718, Encodable2718, Typed2718, -}; -use alloy_primitives::{address, Address, Bytes, TxHash, TxKind, Uint, B256, U256}; -use alloy_rpc_types::AccessList; +use alloy_eips::{eip7594::BlobTransactionSidecarVariant, Encodable2718}; +use alloy_primitives::{address, Address, TxHash, U256}; +use alloy_rpc_types::{Transaction, TransactionInfo, TransactionRequest}; use alloy_signer::Signature; use reth_codecs::alloy::transaction::FromTxCompact; use reth_db::{ @@ -24,13 +19,22 @@ use reth_primitives::Recovered; use reth_primitives_traits::{ serde_bincode_compat::SerdeBincodeCompat, InMemorySize, SignedTransaction, SignerRecoverable, }; -use revm::context::TxEnv; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use reth_rpc_eth_api::{ + transaction::{FromConsensusTx, TryIntoTxEnv}, + EthTxEnvError, TryIntoSimTx, +}; +use revm::context::{BlockEnv, CfgEnv, TxEnv}; + +use crate::evm::transaction::HlTxEnv; type InnerType = alloy_consensus::EthereumTxEnvelope; -#[derive(Debug, Clone, Eq)] -pub struct TransactionSigned(pub InnerType); +#[derive(Debug, Clone, TransactionEnvelope)] +#[envelope(tx_type_name = HlTxType)] +pub enum TransactionSigned { + #[envelope(flatten)] + Default(InnerType), +} fn s_to_address(s: U256) -> Address { if s == U256::ONE { @@ -46,20 +50,20 @@ impl SignerRecoverable for TransactionSigned { if self.is_system_transaction() { return Ok(s_to_address(self.signature().s())); } - self.0.recover_signer() + self.inner().recover_signer() } fn recover_signer_unchecked(&self) -> Result { if self.is_system_transaction() { return Ok(s_to_address(self.signature().s())); } - self.0.recover_signer_unchecked() + self.inner().recover_signer_unchecked() } } impl SignedTransaction for TransactionSigned { fn tx_hash(&self) -> &TxHash { - self.0.tx_hash() + self.inner().tx_hash() } fn recover_signer_unchecked_with_buf( @@ -69,8 +73,7 @@ impl SignedTransaction for TransactionSigned { if self.is_system_transaction() { return Ok(s_to_address(self.signature().s())); } - - self.0.recover_signer_unchecked_with_buf(buf) + self.inner().recover_signer_unchecked_with_buf(buf) } } @@ -78,30 +81,12 @@ impl SignedTransaction for TransactionSigned { // NOTE: All lines below are just wrappers for the inner type. // ------------------------------------------------------------ -impl Serialize for TransactionSigned { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for TransactionSigned { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(Self(InnerType::deserialize(deserializer)?)) - } -} - macro_rules! impl_from_signed { ($($tx:ident),*) => { $( impl From> for TransactionSigned { fn from(value: Signed<$tx>) -> Self { - Self(value.into()) + Self::Default(value.into()) } } )* @@ -113,139 +98,7 @@ impl_from_signed!(TxLegacy, TxEip2930, TxEip1559, TxEip7702, TypedTransaction); impl InMemorySize for TransactionSigned { #[inline] fn size(&self) -> usize { - self.0.size() - } -} - -impl alloy_rlp::Encodable for TransactionSigned { - fn encode(&self, out: &mut dyn alloy_rlp::bytes::BufMut) { - self.0.encode(out); - } - - fn length(&self) -> usize { - self.0.length() - } -} - -impl alloy_rlp::Decodable for TransactionSigned { - fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { - Ok(Self(TxEnvelope::decode(buf)?.into())) - } -} - -impl Encodable2718 for TransactionSigned { - fn type_flag(&self) -> Option { - self.0.type_flag() - } - - fn encode_2718_len(&self) -> usize { - self.0.encode_2718_len() - } - - fn encode_2718(&self, out: &mut dyn alloy_rlp::BufMut) { - self.0.encode_2718(out) - } -} - -impl Decodable2718 for TransactionSigned { - fn typed_decode(ty: u8, buf: &mut &[u8]) -> Eip2718Result { - Ok(Self(TxEnvelope::typed_decode(ty, buf)?.into())) - } - - fn fallback_decode(buf: &mut &[u8]) -> Eip2718Result { - Ok(Self(TxEnvelope::fallback_decode(buf)?.into())) - } -} - -impl Typed2718 for TransactionSigned { - fn ty(&self) -> u8 { - self.0.ty() - } -} - -impl PartialEq for TransactionSigned { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl core::hash::Hash for TransactionSigned { - fn hash(&self, state: &mut H) { - core::hash::Hash::hash(&self.0, state); - } -} - -impl TransactionTrait for TransactionSigned { - fn chain_id(&self) -> Option { - self.0.chain_id() - } - - fn nonce(&self) -> u64 { - self.0.nonce() - } - - fn gas_limit(&self) -> u64 { - self.0.gas_limit() - } - - fn gas_price(&self) -> Option { - self.0.gas_price() - } - - fn max_fee_per_gas(&self) -> u128 { - self.0.max_fee_per_gas() - } - - fn max_priority_fee_per_gas(&self) -> Option { - self.0.max_priority_fee_per_gas() - } - - fn max_fee_per_blob_gas(&self) -> Option { - self.0.max_fee_per_blob_gas() - } - - fn priority_fee_or_price(&self) -> u128 { - self.0.priority_fee_or_price() - } - - fn effective_gas_price(&self, base_fee: Option) -> u128 { - self.0.effective_gas_price(base_fee) - } - - fn effective_tip_per_gas(&self, base_fee: u64) -> Option { - self.0.effective_tip_per_gas(base_fee) - } - - fn is_dynamic_fee(&self) -> bool { - self.0.is_dynamic_fee() - } - - fn kind(&self) -> TxKind { - self.0.kind() - } - - fn is_create(&self) -> bool { - self.0.is_create() - } - - fn value(&self) -> Uint<256, 4> { - self.0.value() - } - - fn input(&self) -> &Bytes { - self.0.input() - } - - fn access_list(&self) -> Option<&AccessList> { - self.0.access_list() - } - - fn blob_versioned_hashes(&self) -> Option<&[B256]> { - self.0.blob_versioned_hashes() - } - - fn authorization_list(&self) -> Option<&[SignedAuthorization]> { - self.0.authorization_list() + self.inner().size() } } @@ -254,23 +107,23 @@ impl reth_codecs::Compact for TransactionSigned { where B: bytes::BufMut + AsMut<[u8]>, { - self.0.to_compact(buf) + self.inner().to_compact(buf) } fn from_compact(buf: &[u8], _len: usize) -> (Self, &[u8]) { let (tx, hash) = InnerType::from_compact(buf, _len); - (Self(tx), hash) + (Self::Default(tx), hash) } } pub fn convert_recovered(value: Recovered) -> Recovered { let (tx, signer) = value.into_parts(); - Recovered::new_unchecked(tx.0, signer) + Recovered::new_unchecked(tx.into_inner(), signer) } impl FromRecoveredTx for TxEnv { fn from_recovered_tx(tx: &TransactionSigned, sender: Address) -> Self { - TxEnv::from_recovered_tx(&tx.0, sender) + TxEnv::from_recovered_tx(&tx.inner(), sender) } } @@ -282,27 +135,41 @@ impl FromTxCompact for TransactionSigned { Self: Sized, { let (tx, buf) = InnerType::from_tx_compact(buf, tx_type, signature); - (Self(tx), buf) + (Self::Default(tx), buf) } } impl reth_codecs::alloy::transaction::Envelope for TransactionSigned { fn signature(&self) -> &Signature { - self.0.signature() + self.inner().signature() } fn tx_type(&self) -> Self::TxType { - self.0.tx_type() + self.inner().tx_type() } } impl TransactionSigned { - pub const fn signature(&self) -> &Signature { - self.0.signature() + #[inline] + pub fn into_inner(self) -> InnerType { + match self { + Self::Default(tx) => tx, + } + } + + #[inline] + pub const fn inner(&self) -> &InnerType { + match self { + Self::Default(tx) => tx, + } + } + + pub fn signature(&self) -> &Signature { + self.inner().signature() } pub const fn tx_type(&self) -> TxType { - self.0.tx_type() + self.inner().tx_type() } pub fn is_system_transaction(&self) -> bool { @@ -329,7 +196,7 @@ pub type BlockBody = alloy_consensus::BlockBody; impl From for EthereumTxEnvelope { fn from(value: TransactionSigned) -> Self { - value.0 + value.into_inner() } } @@ -337,7 +204,7 @@ impl TryFrom for EthereumTxEnvelope { type Error = >>::Error; fn try_from(value: TransactionSigned) -> Result { - value.0.try_into() + value.into_inner().try_into() } } @@ -349,7 +216,7 @@ impl TryFrom >>::Error; fn try_from(value: TransactionSigned) -> Result { - value.0.try_into() + value.into_inner().try_into() } } @@ -359,7 +226,7 @@ impl From fn from( value: EthereumTxEnvelope>, ) -> Self { - Self(value.into()) + Self::Default(value.into()) } } @@ -367,23 +234,23 @@ impl Compress for TransactionSigned { type Compressed = Vec; fn compress(self) -> Self::Compressed { - self.0.compress() + self.into_inner().compress() } fn compress_to_buf>(&self, buf: &mut B) { - self.0.compress_to_buf(buf); + self.inner().compress_to_buf(buf); } } impl Decompress for TransactionSigned { fn decompress(value: &[u8]) -> Result { - Ok(Self(InnerType::decompress(value)?)) + Ok(Self::Default(InnerType::decompress(value)?)) } } pub fn convert_to_eth_block_body(value: BlockBody) -> alloy_consensus::BlockBody { alloy_consensus::BlockBody { - transactions: value.transactions.into_iter().map(|tx| tx.0).collect(), + transactions: value.transactions.into_iter().map(|tx| tx.into_inner()).collect(), ommers: value.ommers, withdrawals: value.withdrawals, } @@ -391,8 +258,41 @@ pub fn convert_to_eth_block_body(value: BlockBody) -> alloy_consensus::BlockBody pub fn convert_to_hl_block_body(value: alloy_consensus::BlockBody) -> BlockBody { BlockBody { - transactions: value.transactions.into_iter().map(TransactionSigned).collect(), + transactions: value.transactions.into_iter().map(TransactionSigned::Default).collect(), ommers: value.ommers, withdrawals: value.withdrawals, } } + +impl TryIntoSimTx for TransactionRequest { + fn try_into_sim_tx(self) -> Result> { + let tx = self + .build_typed_tx() + .map_err(|request| ValueError::new(request, "Required fields missing"))?; + + // Create an empty signature for the transaction. + let signature = Signature::new(Default::default(), Default::default(), false); + + Ok(tx.into_signed(signature).into()) + } +} + +impl TryIntoTxEnv> for TransactionRequest { + type Err = EthTxEnvError; + + fn try_into_tx_env( + self, + cfg_env: &CfgEnv, + block_env: &BlockEnv, + ) -> Result, Self::Err> { + Ok(HlTxEnv::new(self.clone().try_into_tx_env(cfg_env, block_env)?)) + } +} + +impl FromConsensusTx for Transaction { + type TxInfo = TransactionInfo; + + fn from_consensus_tx(tx: TransactionSigned, signer: Address, tx_info: Self::TxInfo) -> Self { + Self::from_transaction(Recovered::new_unchecked(tx.into_inner().into(), signer), tx_info) + } +} diff --git a/src/node/storage/mod.rs b/src/node/storage/mod.rs index eab40d5b5..6540a78e8 100644 --- a/src/node/storage/mod.rs +++ b/src/node/storage/mod.rs @@ -139,7 +139,7 @@ where inputs .into_iter() .map(|(header, transactions)| { - (header, transactions.into_iter().map(|tx| tx.0).collect()) + (header, transactions.into_iter().map(|tx| tx.into_inner()).collect()) }) .collect(), )?; diff --git a/src/node/types/reth_compat.rs b/src/node/types/reth_compat.rs index 9c527783d..1d33472a6 100644 --- a/src/node/types/reth_compat.rs +++ b/src/node/types/reth_compat.rs @@ -47,19 +47,19 @@ impl TransactionSigned { fn to_reth_transaction(&self) -> TxSigned { match self.transaction.clone() { Transaction::Legacy(tx) => { - TxSigned(RethTxSigned::Legacy(Signed::new_unhashed(tx, self.signature))) + TxSigned::Default(RethTxSigned::Legacy(Signed::new_unhashed(tx, self.signature))) } Transaction::Eip2930(tx) => { - TxSigned(RethTxSigned::Eip2930(Signed::new_unhashed(tx, self.signature))) + TxSigned::Default(RethTxSigned::Eip2930(Signed::new_unhashed(tx, self.signature))) } Transaction::Eip1559(tx) => { - TxSigned(RethTxSigned::Eip1559(Signed::new_unhashed(tx, self.signature))) + TxSigned::Default(RethTxSigned::Eip1559(Signed::new_unhashed(tx, self.signature))) } Transaction::Eip4844(tx) => { - TxSigned(RethTxSigned::Eip4844(Signed::new_unhashed(tx, self.signature))) + TxSigned::Default(RethTxSigned::Eip4844(Signed::new_unhashed(tx, self.signature))) } Transaction::Eip7702(tx) => { - TxSigned(RethTxSigned::Eip7702(Signed::new_unhashed(tx, self.signature))) + TxSigned::Default(RethTxSigned::Eip7702(Signed::new_unhashed(tx, self.signature))) } } } @@ -104,7 +104,7 @@ fn system_tx_to_reth_transaction(transaction: &SystemTx, chain_id: u64) -> TxSig } }; let signature = Signature::new(U256::from(0x1), s, true); - TxSigned(RethTxSigned::Legacy(Signed::new_unhashed(tx.clone(), signature))) + TxSigned::Default(RethTxSigned::Legacy(Signed::new_unhashed(tx.clone(), signature))) } }