refactor(tx_wrapper): Use derive(TransactionEnvelope)

This commit is contained in:
sprites0
2025-07-03 04:01:42 +00:00
parent 0bdd9080d1
commit 12d7d5a8b4
5 changed files with 100 additions and 200 deletions

View File

@ -130,7 +130,7 @@ impl FromRecoveredTx<TransactionSigned> for HlTxEnv<TxEnv> {
impl FromTxWithEncoded<TransactionSigned> for HlTxEnv<TxEnv> {
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),

View File

@ -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,

View File

@ -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<TxEip4844>;
#[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<Address, RecoveryError> {
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for TransactionSigned {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self(InnerType::deserialize(deserializer)?))
}
}
macro_rules! impl_from_signed {
($($tx:ident),*) => {
$(
impl From<Signed<$tx>> 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<Self> {
Ok(Self(TxEnvelope::decode(buf)?.into()))
}
}
impl Encodable2718 for TransactionSigned {
fn type_flag(&self) -> Option<u8> {
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<Self> {
Ok(Self(TxEnvelope::typed_decode(ty, buf)?.into()))
}
fn fallback_decode(buf: &mut &[u8]) -> Eip2718Result<Self> {
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<H: Hasher>(&self, state: &mut H) {
core::hash::Hash::hash(&self.0, state);
}
}
impl TransactionTrait for TransactionSigned {
fn chain_id(&self) -> Option<u64> {
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<u128> {
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<u128> {
self.0.max_priority_fee_per_gas()
}
fn max_fee_per_blob_gas(&self) -> Option<u128> {
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<u64>) -> u128 {
self.0.effective_gas_price(base_fee)
}
fn effective_tip_per_gas(&self, base_fee: u64) -> Option<u128> {
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<TransactionSigned>) -> Recovered<InnerType> {
let (tx, signer) = value.into_parts();
Recovered::new_unchecked(tx.0, signer)
Recovered::new_unchecked(tx.into_inner(), signer)
}
impl FromRecoveredTx<TransactionSigned> 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<TransactionSigned>;
impl From<TransactionSigned> for EthereumTxEnvelope<TxEip4844> {
fn from(value: TransactionSigned) -> Self {
value.0
value.into_inner()
}
}
@ -337,7 +204,7 @@ impl TryFrom<TransactionSigned> for EthereumTxEnvelope<TxEip4844WithSidecar> {
type Error = <InnerType as TryInto<EthereumTxEnvelope<TxEip4844WithSidecar>>>::Error;
fn try_from(value: TransactionSigned) -> Result<Self, Self::Error> {
value.0.try_into()
value.into_inner().try_into()
}
}
@ -349,7 +216,7 @@ impl TryFrom<TransactionSigned>
>>::Error;
fn try_from(value: TransactionSigned) -> Result<Self, Self::Error> {
value.0.try_into()
value.into_inner().try_into()
}
}
@ -359,7 +226,7 @@ impl From<EthereumTxEnvelope<TxEip4844WithSidecar<BlobTransactionSidecarVariant>
fn from(
value: EthereumTxEnvelope<TxEip4844WithSidecar<BlobTransactionSidecarVariant>>,
) -> Self {
Self(value.into())
Self::Default(value.into())
}
}
@ -367,23 +234,23 @@ impl Compress for TransactionSigned {
type Compressed = Vec<u8>;
fn compress(self) -> Self::Compressed {
self.0.compress()
self.into_inner().compress()
}
fn compress_to_buf<B: bytes::BufMut + AsMut<[u8]>>(&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<Self, DatabaseError> {
Ok(Self(InnerType::decompress(value)?))
Ok(Self::Default(InnerType::decompress(value)?))
}
}
pub fn convert_to_eth_block_body(value: BlockBody) -> alloy_consensus::BlockBody<InnerType> {
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<InnerType>) -> 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<TransactionSigned> for TransactionRequest {
fn try_into_sim_tx(self) -> Result<TransactionSigned, ValueError<Self>> {
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<HlTxEnv<TxEnv>> for TransactionRequest {
type Err = EthTxEnvError;
fn try_into_tx_env<Spec>(
self,
cfg_env: &CfgEnv<Spec>,
block_env: &BlockEnv,
) -> Result<HlTxEnv<TxEnv>, Self::Err> {
Ok(HlTxEnv::new(self.clone().try_into_tx_env(cfg_env, block_env)?))
}
}
impl FromConsensusTx<TransactionSigned> 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)
}
}

View File

@ -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(),
)?;

View File

@ -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)))
}
}