diff --git a/crates/primitives/src/transaction/pooled.rs b/crates/primitives/src/transaction/pooled.rs index 00f62c2437..c6ab623829 100644 --- a/crates/primitives/src/transaction/pooled.rs +++ b/crates/primitives/src/transaction/pooled.rs @@ -5,8 +5,8 @@ use super::{error::TransactionConversionError, signature::recover_signer, TxEip7 use crate::{BlobTransaction, Transaction, TransactionSigned, TransactionSignedEcRecovered}; use alloy_consensus::{ constants::EIP4844_TX_TYPE_ID, - transaction::{RlpEcdsaTx, TxEip1559, TxEip2930, TxEip4844, TxLegacy}, - SignableTransaction, Signed, Transaction as _, TxEip4844WithSidecar, + transaction::{TxEip1559, TxEip2930, TxEip4844, TxLegacy}, + Signed, Transaction as _, TxEip4844WithSidecar, }; use alloy_eips::{ eip2718::{Decodable2718, Eip2718Result, Encodable2718}, @@ -78,11 +78,11 @@ impl PooledTransactionsElement { // If the transaction is an EIP-4844 transaction... TransactionSigned { transaction: Transaction::Eip4844(tx), signature, .. } => { // Construct a `PooledTransactionsElement::BlobTransaction` with provided sidecar. - Self::BlobTransaction(BlobTransaction { + Self::BlobTransaction(BlobTransaction(Signed::new_unchecked( + TxEip4844WithSidecar { tx, sidecar }, signature, hash, - transaction: TxEip4844WithSidecar { tx, sidecar }, - }) + ))) } // If the transaction is not EIP-4844, return an error with the original // transaction. @@ -98,7 +98,7 @@ impl PooledTransactionsElement { Self::Eip2930(tx) => tx.signature_hash(), Self::Eip1559(tx) => tx.signature_hash(), Self::Eip7702(tx) => tx.signature_hash(), - Self::BlobTransaction(blob_tx) => blob_tx.transaction.signature_hash(), + Self::BlobTransaction(tx) => tx.signature_hash(), } } @@ -109,7 +109,7 @@ impl PooledTransactionsElement { Self::Eip2930(tx) => tx.hash(), Self::Eip1559(tx) => tx.hash(), Self::Eip7702(tx) => tx.hash(), - Self::BlobTransaction(tx) => &tx.hash, + Self::BlobTransaction(tx) => tx.0.hash(), } } @@ -120,7 +120,7 @@ impl PooledTransactionsElement { Self::Eip2930(tx) => tx.signature(), Self::Eip1559(tx) => tx.signature(), Self::Eip7702(tx) => tx.signature(), - Self::BlobTransaction(blob_tx) => &blob_tx.signature, + Self::BlobTransaction(tx) => tx.0.signature(), } } @@ -131,7 +131,7 @@ impl PooledTransactionsElement { Self::Eip2930(tx) => tx.tx().nonce(), Self::Eip1559(tx) => tx.tx().nonce(), Self::Eip7702(tx) => tx.tx().nonce(), - Self::BlobTransaction(blob_tx) => blob_tx.transaction.tx.nonce, + Self::BlobTransaction(tx) => tx.tx().nonce(), } } @@ -203,7 +203,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.tx), + Self::BlobTransaction(tx) => Some(tx.0.tx().tx()), _ => None, } } @@ -232,7 +232,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.tx.max_fee_per_blob_gas), + Self::BlobTransaction(tx) => Some(tx.0.tx().tx.max_fee_per_blob_gas), _ => None, } } @@ -246,7 +246,7 @@ impl PooledTransactionsElement { Self::Legacy(_) | Self::Eip2930(_) => None, Self::Eip1559(tx) => Some(tx.tx().max_priority_fee_per_gas), Self::Eip7702(tx) => Some(tx.tx().max_priority_fee_per_gas), - Self::BlobTransaction(tx) => Some(tx.transaction.tx.max_priority_fee_per_gas), + Self::BlobTransaction(tx) => Some(tx.0.tx().tx.max_priority_fee_per_gas), } } @@ -259,7 +259,7 @@ impl PooledTransactionsElement { Self::Eip2930(tx) => tx.tx().gas_price, Self::Eip1559(tx) => tx.tx().max_fee_per_gas, Self::Eip7702(tx) => tx.tx().max_fee_per_gas, - Self::BlobTransaction(tx) => tx.transaction.tx.max_fee_per_gas, + Self::BlobTransaction(tx) => tx.0.tx().tx.max_fee_per_gas, } } } @@ -362,9 +362,7 @@ impl Encodable2718 for PooledTransactionsElement { Self::Eip2930(tx) => tx.eip2718_encoded_length(), Self::Eip1559(tx) => tx.eip2718_encoded_length(), Self::Eip7702(tx) => tx.eip2718_encoded_length(), - Self::BlobTransaction(BlobTransaction { transaction, signature, .. }) => { - transaction.eip2718_encoded_length(signature) - } + Self::BlobTransaction(tx) => tx.eip2718_encoded_length(), } } @@ -374,9 +372,7 @@ impl Encodable2718 for PooledTransactionsElement { Self::Eip2930(tx) => tx.eip2718_encode(out), Self::Eip1559(tx) => tx.eip2718_encode(out), Self::Eip7702(tx) => tx.eip2718_encode(out), - Self::BlobTransaction(BlobTransaction { transaction, signature, .. }) => { - transaction.eip2718_encode(signature, out) - } + Self::BlobTransaction(tx) => tx.eip2718_encode(out), } } @@ -457,15 +453,22 @@ impl<'a> arbitrary::Arbitrary<'a> for PooledTransactionsElement { // Attempt to create a `TransactionSigned` with arbitrary data. let tx_signed = TransactionSigned::arbitrary(u)?; // Attempt to create a `PooledTransactionsElement` with arbitrary data, handling the Result. - match Self::try_from(tx_signed) { - Ok(Self::BlobTransaction(mut tx)) => { - // Successfully converted to a BlobTransaction, now generate a sidecar. - tx.transaction.sidecar = alloy_eips::eip4844::BlobTransactionSidecar::arbitrary(u)?; - Ok(Self::BlobTransaction(tx)) + match Self::try_from_broadcast(tx_signed) { + Ok(tx) => Ok(tx), + Err(tx) => { + let (tx, sig, hash) = tx.into_parts(); + match tx { + Transaction::Eip4844(tx) => { + let sidecar = BlobTransactionSidecar::arbitrary(u)?; + Ok(Self::BlobTransaction(BlobTransaction(Signed::new_unchecked( + TxEip4844WithSidecar { tx, sidecar }, + sig, + hash, + )))) + } + _ => Err(arbitrary::Error::IncorrectFormat), + } } - Ok(tx) => Ok(tx), // Successfully converted, but not a BlobTransaction. - Err(_) => Err(arbitrary::Error::IncorrectFormat), /* Conversion failed, return an - * arbitrary error. */ } } } diff --git a/crates/primitives/src/transaction/sidecar.rs b/crates/primitives/src/transaction/sidecar.rs index ec8c9b7f0e..5eeeef09fc 100644 --- a/crates/primitives/src/transaction/sidecar.rs +++ b/crates/primitives/src/transaction/sidecar.rs @@ -1,9 +1,9 @@ #![cfg_attr(docsrs, doc(cfg(feature = "c-kzg")))] use crate::{Transaction, TransactionSigned}; -use alloy_consensus::{transaction::RlpEcdsaTx, TxEip4844WithSidecar}; +use alloy_consensus::{transaction::RlpEcdsaTx, Signed, TxEip4844WithSidecar}; use alloy_eips::eip4844::BlobTransactionSidecar; -use alloy_primitives::{PrimitiveSignature as Signature, TxHash}; +use derive_more::Deref; use serde::{Deserialize, Serialize}; /// A response to `GetPooledTransactions` that includes blob data, their commitments, and their @@ -11,16 +11,8 @@ use serde::{Deserialize, Serialize}; /// /// This is defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#networking) as an element /// of a `PooledTransactions` response. -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct BlobTransaction { - /// The transaction hash. - pub hash: TxHash, - /// The transaction signature. - pub signature: Signature, - /// The transaction payload with the sidecar. - #[serde(flatten)] - pub transaction: TxEip4844WithSidecar, -} +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Deref)] +pub struct BlobTransaction(pub Signed); impl BlobTransaction { /// Constructs a new [`BlobTransaction`] from a [`TransactionSigned`] and a @@ -34,11 +26,11 @@ impl BlobTransaction { let hash = tx.hash(); let TransactionSigned { transaction, signature, .. } = tx; match transaction { - Transaction::Eip4844(transaction) => Ok(Self { - hash, - transaction: TxEip4844WithSidecar { tx: transaction, sidecar }, + Transaction::Eip4844(transaction) => Ok(Self(Signed::new_unchecked( + TxEip4844WithSidecar { tx: transaction, sidecar }, signature, - }), + hash, + ))), transaction => { let tx = TransactionSigned { transaction, signature, hash: hash.into() }; Err((tx, sidecar)) @@ -54,19 +46,16 @@ impl BlobTransaction { &self, proof_settings: &c_kzg::KzgSettings, ) -> Result<(), alloy_eips::eip4844::BlobTransactionValidationError> { - self.transaction.validate_blob(proof_settings) + self.tx().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.tx), - hash: self.hash.into(), - signature: self.signature, - }; - - (transaction, self.transaction.sidecar) + let (transaction, signature, hash) = self.0.into_parts(); + let (transaction, sidecar) = transaction.into_parts(); + let transaction = TransactionSigned::new(transaction.into(), signature, hash); + (transaction, sidecar) } /// Decodes a [`BlobTransaction`] from RLP. This expects the encoding to be: @@ -80,8 +69,7 @@ impl BlobTransaction { pub(crate) fn decode_inner(data: &mut &[u8]) -> alloy_rlp::Result { let (transaction, signature, hash) = TxEip4844WithSidecar::rlp_decode_signed(data)?.into_parts(); - - Ok(Self { transaction, hash, signature }) + Ok(Self(Signed::new_unchecked(transaction, signature, hash))) } } diff --git a/crates/rpc/rpc/src/eth/bundle.rs b/crates/rpc/rpc/src/eth/bundle.rs index f92bd075a3..ee2b3ed5e7 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.tx.blob_gas()) + Some(tx.tx().tx().blob_gas()) } else { None }