diff --git a/crates/consensus/src/lib.rs b/crates/consensus/src/lib.rs index f1bcd5f169b..ef1699390ef 100644 --- a/crates/consensus/src/lib.rs +++ b/crates/consensus/src/lib.rs @@ -36,7 +36,7 @@ pub mod transaction; #[cfg(feature = "kzg")] pub use transaction::BlobTransactionValidationError; pub use transaction::{ - SignableTransaction, Transaction, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, + Enveloped, SignableTransaction, Transaction, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEip4844WithSidecar, TxEip7702, TxEnvelope, TxLegacy, TxType, TypedTransaction, }; diff --git a/crates/consensus/src/signed.rs b/crates/consensus/src/signed.rs index 47554129beb..96737d9b387 100644 --- a/crates/consensus/src/signed.rs +++ b/crates/consensus/src/signed.rs @@ -10,8 +10,6 @@ pub struct Signed { tx: T, #[cfg_attr(feature = "serde", serde(flatten))] signature: Sig, - #[doc(alias = "tx_hash", alias = "transaction_hash")] - hash: B256, } impl Signed { @@ -26,15 +24,9 @@ impl Signed { &self.signature } - /// Returns a reference to the transaction hash. - #[doc(alias = "tx_hash", alias = "transaction_hash")] - pub const fn hash(&self) -> &B256 { - &self.hash - } - /// Splits the transaction into parts. - pub fn into_parts(self) -> (T, Sig, B256) { - (self.tx, self.signature, self.hash) + pub fn into_parts(self) -> (T, Sig) { + (self.tx, self.signature) } /// Returns the transaction without signature. @@ -45,8 +37,8 @@ impl Signed { impl, Sig> Signed { /// Instantiate from a transaction and signature. Does not verify the signature. - pub const fn new_unchecked(tx: T, signature: Sig, hash: B256) -> Self { - Self { tx, signature, hash } + pub const fn new_unchecked(tx: T, signature: Sig) -> Self { + Self { tx, signature } } /// Calculate the signing hash for the transaction. diff --git a/crates/consensus/src/transaction/eip1559.rs b/crates/consensus/src/transaction/eip1559.rs index fd8d164162e..109c867fee5 100644 --- a/crates/consensus/src/transaction/eip1559.rs +++ b/crates/consensus/src/transaction/eip1559.rs @@ -1,7 +1,6 @@ use crate::{EncodableSignature, SignableTransaction, Signed, Transaction, TxType}; -use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization}; -use alloy_primitives::{keccak256, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; +use alloy_primitives::{Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{BufMut, Decodable, Encodable, Header}; use core::mem; @@ -345,11 +344,7 @@ impl SignableTransaction for TxEip1559 { // signature. let signature = signature.with_parity_bool(); - let mut buf = Vec::with_capacity(self.encoded_len_with_signature(&signature, false)); - self.encode_with_signature(&signature, &mut buf, false); - let hash = keccak256(&buf); - - Signed::new_unchecked(self, signature, hash) + Signed::new_unchecked(self, signature) } } @@ -414,8 +409,8 @@ mod tests { hex!("0d5688ac3897124635b6cf1bc0e29d6dfebceebdc10a54d74f2ef8b56535b682") ); - let signed_tx = tx.into_signed(sig); - assert_eq!(*signed_tx.hash(), hash, "Expected same hash"); + let signed_tx: crate::TxEnvelope = tx.into_signed(sig).into(); + assert_eq!(signed_tx.tx_hash(), hash, "Expected same hash"); assert_eq!(signed_tx.recover_signer().unwrap(), signer, "Recovering signer should pass."); } @@ -446,7 +441,9 @@ mod tests { tx.encode_with_signature_fields(&sig, &mut buf); let decoded = TxEip1559::decode_signed_fields(&mut &buf[..]).unwrap(); assert_eq!(decoded, tx.into_signed(sig)); - assert_eq!(*decoded.hash(), hash); + + let envelope = crate::TxEnvelope::from(decoded); + assert_eq!(envelope.tx_hash(), hash); } } diff --git a/crates/consensus/src/transaction/eip2930.rs b/crates/consensus/src/transaction/eip2930.rs index 3f3b6030f58..a918f15c85d 100644 --- a/crates/consensus/src/transaction/eip2930.rs +++ b/crates/consensus/src/transaction/eip2930.rs @@ -1,7 +1,6 @@ use crate::{EncodableSignature, SignableTransaction, Signed, Transaction, TxType}; -use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization}; -use alloy_primitives::{keccak256, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; +use alloy_primitives::{Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable, Header}; use core::mem; @@ -312,11 +311,7 @@ impl SignableTransaction for TxEip2930 { // signature. let signature = signature.with_parity_bool(); - let mut buf = Vec::with_capacity(self.encoded_len_with_signature(&signature, false)); - self.encode_with_signature(&signature, &mut buf, false); - let hash = keccak256(&buf); - - Signed::new_unchecked(self, signature, hash) + Signed::new_unchecked(self, signature) } } @@ -391,7 +386,7 @@ mod tests { let tx = request.into_signed(signature); - let envelope = TxEnvelope::Eip2930(tx); + let envelope: TxEnvelope = tx.into(); let mut encoded = Vec::new(); envelope.encode(&mut encoded); diff --git a/crates/consensus/src/transaction/eip4844.rs b/crates/consensus/src/transaction/eip4844.rs index 0036666eb97..82421ea34b9 100644 --- a/crates/consensus/src/transaction/eip4844.rs +++ b/crates/consensus/src/transaction/eip4844.rs @@ -2,7 +2,7 @@ use crate::{EncodableSignature, SignableTransaction, Signed, Transaction, TxType use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip4844::DATA_GAS_PER_BLOB, eip7702::SignedAuthorization}; -use alloy_primitives::{keccak256, Address, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; +use alloy_primitives::{Address, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable, Header}; use core::mem; @@ -185,15 +185,15 @@ impl TxEip4844Variant { let header = Header::decode(&mut current_buf)?; if header.list { let tx = TxEip4844WithSidecar::decode_signed_fields(buf)?; - let (tx, signature, hash) = tx.into_parts(); - return Ok(Signed::new_unchecked(tx.into(), signature, hash)); + let (tx, signature) = tx.into_parts(); + return Ok(Signed::new_unchecked(tx.into(), signature)); } // Since there is not a second list header, this is a historical 4844 transaction without a // sidecar. let tx = TxEip4844::decode_signed_fields(buf)?; - let (tx, signature, hash) = tx.into_parts(); - Ok(Signed::new_unchecked(tx.into(), signature, hash)) + let (tx, signature) = tx.into_parts(); + Ok(Signed::new_unchecked(tx.into(), signature)) } } @@ -329,13 +329,7 @@ impl SignableTransaction for TxEip4844Variant { // signature. let signature = signature.with_parity_bool(); - let payload_length = 1 + self.fields_len() + signature.rlp_vrs_len(); - let mut buf = Vec::with_capacity(payload_length); - // we use the inner tx to encode the fields - self.tx().encode_with_signature(&signature, &mut buf, false); - let hash = keccak256(&buf); - - Signed::new_unchecked(self, signature, hash) + Signed::new_unchecked(self, signature) } } @@ -685,11 +679,7 @@ impl SignableTransaction for TxEip4844 { // signature. let signature = signature.with_parity_bool(); - let mut buf = Vec::with_capacity(self.encoded_len_with_signature(&signature, false)); - self.encode_with_signature(&signature, &mut buf, false); - let hash = keccak256(&buf); - - Signed::new_unchecked(self, signature, hash) + Signed::new_unchecked(self, signature) } } @@ -919,11 +909,11 @@ impl TxEip4844WithSidecar { }); } - let (tx, signature, hash) = inner_tx.into_parts(); + let (tx, signature) = inner_tx.into_parts(); // create unchecked signed tx because these checks should have happened during construction // of `Signed` in `TxEip4844::decode_signed_fields` - Ok(Signed::new_unchecked(Self::from_tx_and_sidecar(tx, sidecar), signature, hash)) + Ok(Signed::new_unchecked(Self::from_tx_and_sidecar(tx, sidecar), signature)) } } @@ -953,16 +943,7 @@ impl SignableTransaction for TxEip4844WithSidecar { // signature. let signature = signature.with_parity_bool(); - let mut buf = Vec::with_capacity(self.tx.encoded_len_with_signature(&signature, false)); - // The sidecar is NOT included in the signed payload, only the transaction fields and the - // type byte. Include the type byte. - // - // Include the transaction fields, making sure to __not__ use the sidecar, and __not__ - // encode a header. - self.tx.encode_with_signature(&signature, &mut buf, false); - let hash = keccak256(&buf); - - Signed::new_unchecked(self, signature, hash) + Signed::new_unchecked(self, signature) } } @@ -1075,12 +1056,13 @@ mod tests { let actual_signed = tx.into_signed(signature); // the hashes should be the same - assert_eq!(expected_signed.hash(), actual_signed.hash()); // convert to envelopes let expected_envelope: TxEnvelope = expected_signed.into(); let actual_envelope: TxEnvelope = actual_signed.into(); + assert_eq!(expected_envelope.tx_hash(), actual_envelope.tx_hash()); + // now encode the transaction and check the length let len = expected_envelope.length(); let mut buf = Vec::with_capacity(len); @@ -1124,9 +1106,9 @@ mod tests { ) .unwrap(); - let signed = variant.into_signed(signature); + let signed = TxEnvelope::from(variant.into_signed(signature)); assert_eq!( - *signed.hash(), + signed.tx_hash(), b256!("93fc9daaa0726c3292a2e939df60f7e773c6a6a726a61ce43f4a217c64d85e87") ); } diff --git a/crates/consensus/src/transaction/eip7702.rs b/crates/consensus/src/transaction/eip7702.rs index 50ead9215b9..b2d40300ae9 100644 --- a/crates/consensus/src/transaction/eip7702.rs +++ b/crates/consensus/src/transaction/eip7702.rs @@ -4,7 +4,7 @@ use alloy_eips::{ eip2930::AccessList, eip7702::{constants::EIP7702_TX_TYPE_ID, SignedAuthorization}, }; -use alloy_primitives::{keccak256, Address, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; +use alloy_primitives::{Address, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{BufMut, Decodable, Encodable, Header}; use core::mem; @@ -355,11 +355,7 @@ impl SignableTransaction for TxEip7702 { // signature. let signature = signature.with_parity_bool(); - let mut buf = Vec::with_capacity(self.encoded_len_with_signature(&signature, false)); - self.encode_with_signature(&signature, &mut buf, false); - let hash = keccak256(&buf); - - Signed::new_unchecked(self, signature, hash) + Signed::new_unchecked(self, signature) } } diff --git a/crates/consensus/src/transaction/envelope.rs b/crates/consensus/src/transaction/envelope.rs index 9fb2ab855c5..a77f10bcb35 100644 --- a/crates/consensus/src/transaction/envelope.rs +++ b/crates/consensus/src/transaction/envelope.rs @@ -1,14 +1,22 @@ -use core::fmt; - -use crate::{Signed, Transaction, TxEip1559, TxEip2930, TxEip7702, TxLegacy}; +use crate::{ + transaction::eip4844::{TxEip4844, TxEip4844Variant, TxEip4844WithSidecar}, + Signed, Transaction, TxEip1559, TxEip2930, TxEip7702, TxLegacy, +}; +use alloc::vec::Vec; use alloy_eips::{ eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718}, eip2930::AccessList, }; -use alloy_primitives::{Bytes, TxKind, B256}; +use alloy_primitives::{keccak256, Bytes, Sealed, TxKind, B256}; use alloy_rlp::{Decodable, Encodable, Header}; +use core::fmt; -use crate::transaction::eip4844::{TxEip4844, TxEip4844Variant, TxEip4844WithSidecar}; +/// Enveloped transactions are [`Signed`] and [`Sealed`] (and maybe +/// [delivered]). +/// +/// +/// [delivered]: https://www.youtube.com/watch?v=pUj9frKY46E +pub type Enveloped = alloy_primitives::Sealed>; /// Ethereum `TransactionType` flags as specified in EIPs [2718], [1559], [2930], /// [4844], and [7702]. @@ -95,11 +103,11 @@ impl TryFrom for TxType { #[non_exhaustive] pub enum TxEnvelope { /// An untagged [`TxLegacy`]. - Legacy(Signed), + Legacy(Enveloped), /// A [`TxEip2930`] tagged with type 1. - Eip2930(Signed), + Eip2930(Enveloped), /// A [`TxEip1559`] tagged with type 2. - Eip1559(Signed), + Eip1559(Enveloped), /// A TxEip4844 tagged with type 3. /// An EIP-4844 transaction has two network representations: /// 1 - The transaction itself, which is a regular RLP-encoded transaction and used to retrieve @@ -107,52 +115,78 @@ pub enum TxEnvelope { /// /// 2 - The transaction with a sidecar, which is the form used to /// send transactions to the network. - Eip4844(Signed), + Eip4844(Enveloped), /// A [`TxEip7702`] tagged with type 4. - Eip7702(Signed), + Eip7702(Enveloped), } impl From> for TxEnvelope { fn from(v: Signed) -> Self { - Self::Legacy(v) + let mut buf = Vec::with_capacity(v.tx().encoded_len_with_signature(v.signature())); + v.tx().encode_with_signature_fields(v.signature(), &mut buf); + let h = keccak256(buf); + + Self::Legacy(Sealed::new_unchecked(v, h)) } } impl From> for TxEnvelope { fn from(v: Signed) -> Self { - Self::Eip2930(v) + let mut buf = Vec::with_capacity(v.tx().encoded_len_with_signature(v.signature(), false)); + v.tx().encode_with_signature(v.signature(), &mut buf, false); + let h = keccak256(buf); + + Self::Eip2930(Sealed::new_unchecked(v, h)) } } impl From> for TxEnvelope { fn from(v: Signed) -> Self { - Self::Eip1559(v) + let tx = v.tx(); + let signature = v.signature(); + + let mut buf = Vec::with_capacity(tx.encoded_len_with_signature(signature, false)); + tx.encode_with_signature(signature, &mut buf, false); + let hash = keccak256(&buf); + + Self::Eip1559(Sealed::new_unchecked(v, hash)) } } impl From> for TxEnvelope { fn from(v: Signed) -> Self { - Self::Eip4844(v) + let tx = v.tx().tx(); + let signature = v.signature(); + + let mut buf = Vec::with_capacity(tx.encoded_len_with_signature(signature, false)); + tx.encode_with_signature(signature, &mut buf, false); + let hash = keccak256(&buf); + + Self::Eip4844(Sealed::new_unchecked(v, hash)) } } impl From> for TxEnvelope { fn from(v: Signed) -> Self { - let (tx, signature, hash) = v.into_parts(); - Self::Eip4844(Signed::new_unchecked(tx.into(), signature, hash)) + let (tx, signature) = v.into_parts(); + Signed::new_unchecked(TxEip4844Variant::from(tx), signature).into() } } impl From> for TxEnvelope { fn from(v: Signed) -> Self { - let (tx, signature, hash) = v.into_parts(); - Self::Eip4844(Signed::new_unchecked(tx.into(), signature, hash)) + let (tx, signature) = v.into_parts(); + Signed::new_unchecked(TxEip4844Variant::from(tx), signature).into() } } impl From> for TxEnvelope { fn from(v: Signed) -> Self { - Self::Eip7702(v) + let mut buf = Vec::with_capacity(v.tx().encoded_len_with_signature(v.signature(), false)); + v.tx().encode_with_signature(v.signature(), &mut buf, false); + let h = keccak256(buf); + + Self::Eip7702(Sealed::new_unchecked(v, h)) } } @@ -188,7 +222,7 @@ impl TxEnvelope { } /// Returns the [`TxLegacy`] variant if the transaction is a legacy transaction. - pub const fn as_legacy(&self) -> Option<&Signed> { + pub const fn as_legacy(&self) -> Option<&Enveloped> { match self { Self::Legacy(tx) => Some(tx), _ => None, @@ -196,7 +230,7 @@ impl TxEnvelope { } /// Returns the [`TxEip2930`] variant if the transaction is an EIP-2930 transaction. - pub const fn as_eip2930(&self) -> Option<&Signed> { + pub const fn as_eip2930(&self) -> Option<&Enveloped> { match self { Self::Eip2930(tx) => Some(tx), _ => None, @@ -204,7 +238,7 @@ impl TxEnvelope { } /// Returns the [`TxEip1559`] variant if the transaction is an EIP-1559 transaction. - pub const fn as_eip1559(&self) -> Option<&Signed> { + pub const fn as_eip1559(&self) -> Option<&Enveloped> { match self { Self::Eip1559(tx) => Some(tx), _ => None, @@ -212,7 +246,7 @@ impl TxEnvelope { } /// Returns the [`TxEip4844`] variant if the transaction is an EIP-4844 transaction. - pub const fn as_eip4844(&self) -> Option<&Signed> { + pub const fn as_eip4844(&self) -> Option<&Enveloped> { match self { Self::Eip4844(tx) => Some(tx), _ => None, @@ -220,7 +254,7 @@ impl TxEnvelope { } /// Returns the [`TxEip7702`] variant if the transaction is an EIP-7702 transaction. - pub const fn as_eip7702(&self) -> Option<&Signed> { + pub const fn as_eip7702(&self) -> Option<&Enveloped> { match self { Self::Eip7702(tx) => Some(tx), _ => None, @@ -253,14 +287,14 @@ impl TxEnvelope { } /// Return the hash of the inner Signed. - #[doc(alias = "transaction_hash")] - pub const fn tx_hash(&self) -> &B256 { + #[doc(alias = "transaction_hash", alias = "hash")] + pub const fn tx_hash(&self) -> B256 { match self { - Self::Legacy(tx) => tx.hash(), - Self::Eip2930(tx) => tx.hash(), - Self::Eip1559(tx) => tx.hash(), - Self::Eip4844(tx) => tx.hash(), - Self::Eip7702(tx) => tx.hash(), + Self::Legacy(tx) => tx.seal(), + Self::Eip2930(tx) => tx.seal(), + Self::Eip1559(tx) => tx.seal(), + Self::Eip4844(tx) => tx.seal(), + Self::Eip7702(tx) => tx.seal(), } } @@ -362,6 +396,10 @@ impl Encodable2718 for TxEnvelope { } } } + + fn trie_hash(&self) -> B256 { + self.tx_hash() + } } impl Transaction for TxEnvelope { @@ -527,30 +565,30 @@ mod serde_from { //! //! We serialize via [`TaggedTxEnvelope`] and deserialize via //! [`MaybeTaggedTxEnvelope`]. - use crate::{Signed, TxEip1559, TxEip2930, TxEip4844Variant, TxEip7702, TxLegacy}; - - use super::TxEnvelope; + use crate::{ + Enveloped, TxEip1559, TxEip2930, TxEip4844Variant, TxEip7702, TxEnvelope, TxLegacy, + }; #[derive(Debug, serde::Deserialize)] #[serde(untagged)] pub(crate) enum MaybeTaggedTxEnvelope { Tagged(TaggedTxEnvelope), - Untagged(Signed), + Untagged(Enveloped), } #[derive(Debug, serde::Serialize, serde::Deserialize)] #[serde(tag = "type")] pub(crate) enum TaggedTxEnvelope { #[serde(rename = "0x0", alias = "0x00")] - Legacy(Signed), + Legacy(#[serde(with = "alloy_serde::sealed::flat_hash")] Enveloped), #[serde(rename = "0x1", alias = "0x01")] - Eip2930(Signed), + Eip2930(#[serde(with = "alloy_serde::sealed::flat_hash")] Enveloped), #[serde(rename = "0x2", alias = "0x02")] - Eip1559(Signed), + Eip1559(#[serde(with = "alloy_serde::sealed::flat_hash")] Enveloped), #[serde(rename = "0x3", alias = "0x03")] - Eip4844(Signed), + Eip4844(#[serde(with = "alloy_serde::sealed::flat_hash")] Enveloped), #[serde(rename = "0x4", alias = "0x04")] - Eip7702(Signed), + Eip7702(#[serde(with = "alloy_serde::sealed::flat_hash")] Enveloped), } impl From for TxEnvelope { @@ -635,16 +673,17 @@ mod tests { let res = TxEnvelope::decode(&mut raw_tx.as_slice()).unwrap(); assert_eq!(res.tx_type(), TxType::Legacy); + assert_eq!( + res.tx_hash().to_string(), + "0x280cde7cdefe4b188750e76c888f13bd05ce9a4d7767730feefe8a0e50ca6fc4" + ); + let tx = match res { TxEnvelope::Legacy(tx) => tx, _ => unreachable!(), }; assert_eq!(tx.tx().to, TxKind::Call(address!("7a250d5630B4cF539739dF2C5dAcb4c659F2488D"))); - assert_eq!( - tx.hash().to_string(), - "0x280cde7cdefe4b188750e76c888f13bd05ce9a4d7767730feefe8a0e50ca6fc4" - ); let from = tx.recover_signer().unwrap(); assert_eq!(from, address!("a12e1462d0ceD572f396F58B6E2D03894cD7C8a4")); } @@ -892,20 +931,19 @@ mod tests { #[test] fn test_encode_decode_transaction_list() { let signature = Signature::test_signature(); - let tx = TxEnvelope::Eip1559( - TxEip1559 { - chain_id: 1u64, - nonce: 2, - max_fee_per_gas: 3, - max_priority_fee_per_gas: 4, - gas_limit: 5, - to: Address::left_padding_from(&[6]).into(), - value: U256::from(7_u64), - input: vec![8].into(), - access_list: Default::default(), - } - .into_signed(signature), - ); + let tx: TxEnvelope = TxEip1559 { + chain_id: 1u64, + nonce: 2, + max_fee_per_gas: 3, + max_priority_fee_per_gas: 4, + gas_limit: 5, + to: Address::left_padding_from(&[6]).into(), + value: U256::from(7_u64), + input: vec![8].into(), + access_list: Default::default(), + } + .into_signed(signature) + .into(); let transactions = vec![tx.clone(), tx]; let encoded = alloy_rlp::encode(&transactions); let decoded = Vec::::decode(&mut &encoded[..]).unwrap(); diff --git a/crates/consensus/src/transaction/legacy.rs b/crates/consensus/src/transaction/legacy.rs index 08f3ea492f3..6ea194592c7 100644 --- a/crates/consensus/src/transaction/legacy.rs +++ b/crates/consensus/src/transaction/legacy.rs @@ -1,8 +1,7 @@ use core::mem; -use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization}; -use alloy_primitives::{keccak256, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; +use alloy_primitives::{Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable, Header, Result}; use crate::{EncodableSignature, SignableTransaction, Signed, Transaction, TxType}; @@ -296,10 +295,8 @@ impl SignableTransaction for TxLegacy { } else { signature }; - let mut buf = Vec::with_capacity(self.encoded_len_with_signature(&signature)); - self.encode_with_signature_fields(&signature, &mut buf); - let hash = keccak256(&buf); - Signed::new_unchecked(self, signature, hash) + + Signed::new_unchecked(self, signature) } } @@ -372,9 +369,9 @@ mod tests { ) .unwrap(); - let signed_tx = tx.into_signed(sig); + let signed_tx: crate::TxEnvelope = tx.into_signed(sig).into(); - assert_eq!(*signed_tx.hash(), hash, "Expected same hash"); + assert_eq!(*signed_tx.tx_hash(), hash, "Expected same hash"); assert_eq!(signed_tx.recover_signer().unwrap(), signer, "Recovering signer should pass."); } diff --git a/crates/consensus/src/transaction/mod.rs b/crates/consensus/src/transaction/mod.rs index 3fee674bb33..f1233ae4eba 100644 --- a/crates/consensus/src/transaction/mod.rs +++ b/crates/consensus/src/transaction/mod.rs @@ -27,7 +27,7 @@ pub use eip4844::BlobTransactionValidationError; pub use eip4844::{TxEip4844, TxEip4844Variant, TxEip4844WithSidecar}; mod envelope; -pub use envelope::{TxEnvelope, TxType}; +pub use envelope::{Enveloped, TxEnvelope, TxType}; mod legacy; pub use legacy::TxLegacy; diff --git a/crates/consensus/src/transaction/typed.rs b/crates/consensus/src/transaction/typed.rs index af067e5f55e..437684c2667 100644 --- a/crates/consensus/src/transaction/typed.rs +++ b/crates/consensus/src/transaction/typed.rs @@ -80,11 +80,11 @@ impl From for TypedTransaction { impl From for TypedTransaction { fn from(envelope: TxEnvelope) -> Self { match envelope { - TxEnvelope::Legacy(tx) => Self::Legacy(tx.strip_signature()), - TxEnvelope::Eip2930(tx) => Self::Eip2930(tx.strip_signature()), - TxEnvelope::Eip1559(tx) => Self::Eip1559(tx.strip_signature()), - TxEnvelope::Eip4844(tx) => Self::Eip4844(tx.strip_signature()), - TxEnvelope::Eip7702(tx) => Self::Eip7702(tx.strip_signature()), + TxEnvelope::Legacy(tx) => Self::Legacy(tx.into_inner().strip_signature()), + TxEnvelope::Eip2930(tx) => Self::Eip2930(tx.into_inner().strip_signature()), + TxEnvelope::Eip1559(tx) => Self::Eip1559(tx.into_inner().strip_signature()), + TxEnvelope::Eip4844(tx) => Self::Eip4844(tx.into_inner().strip_signature()), + TxEnvelope::Eip7702(tx) => Self::Eip7702(tx.into_inner().strip_signature()), } } } diff --git a/crates/rpc-types-eth/src/transaction/mod.rs b/crates/rpc-types-eth/src/transaction/mod.rs index 0c6bf437926..0e2ba28e7ae 100644 --- a/crates/rpc-types-eth/src/transaction/mod.rs +++ b/crates/rpc-types-eth/src/transaction/mod.rs @@ -292,7 +292,7 @@ impl TryFrom for Signed { fn try_from(tx: Transaction) -> Result { let tx: Signed = tx.try_into()?; - let (inner, signature, _) = tx.into_parts(); + let (inner, signature) = tx.into_parts(); let tx: TxEip4844Variant = inner.into(); Ok(tx.into_signed(signature)) @@ -329,11 +329,11 @@ impl TryFrom for TxEnvelope { fn try_from(tx: Transaction) -> Result { match tx.transaction_type.unwrap_or_default().try_into()? { - TxType::Legacy => Ok(Self::Legacy(tx.try_into()?)), - TxType::Eip1559 => Ok(Self::Eip1559(tx.try_into()?)), - TxType::Eip2930 => Ok(Self::Eip2930(tx.try_into()?)), - TxType::Eip4844 => Ok(Self::Eip4844(tx.try_into()?)), - TxType::Eip7702 => Ok(Self::Eip7702(tx.try_into()?)), + TxType::Legacy => Ok(Signed::::try_from(tx)?.into()), + TxType::Eip1559 => Ok(Signed::::try_from(tx)?.into()), + TxType::Eip2930 => Ok(Signed::::try_from(tx)?.into()), + TxType::Eip4844 => Ok(Signed::::try_from(tx)?.into()), + TxType::Eip7702 => Ok(Signed::::try_from(tx)?.into()), } } } diff --git a/crates/rpc-types-eth/src/transaction/request.rs b/crates/rpc-types-eth/src/transaction/request.rs index 63b431ae0ed..e5699026892 100644 --- a/crates/rpc-types-eth/src/transaction/request.rs +++ b/crates/rpc-types-eth/src/transaction/request.rs @@ -934,7 +934,7 @@ impl From for TransactionRequest { #[cfg(feature = "k256")] { let from = tx.recover_signer().ok(); - let tx: Self = tx.strip_signature().into(); + let tx: Self = tx.into_inner().strip_signature().into(); if let Some(from) = from { tx.from(from) } else { @@ -944,14 +944,14 @@ impl From for TransactionRequest { #[cfg(not(feature = "k256"))] { - tx.strip_signature().into() + tx.into_inner().strip_signature().into() } } TxEnvelope::Eip2930(tx) => { #[cfg(feature = "k256")] { let from = tx.recover_signer().ok(); - let tx: Self = tx.strip_signature().into(); + let tx: Self = tx.into_inner().strip_signature().into(); if let Some(from) = from { tx.from(from) } else { @@ -961,14 +961,14 @@ impl From for TransactionRequest { #[cfg(not(feature = "k256"))] { - tx.strip_signature().into() + tx.into_inner().strip_signature().into() } } TxEnvelope::Eip1559(tx) => { #[cfg(feature = "k256")] { let from = tx.recover_signer().ok(); - let tx: Self = tx.strip_signature().into(); + let tx: Self = tx.into_inner().strip_signature().into(); if let Some(from) = from { tx.from(from) } else { @@ -978,14 +978,14 @@ impl From for TransactionRequest { #[cfg(not(feature = "k256"))] { - tx.strip_signature().into() + tx.into_inner().strip_signature().into() } } TxEnvelope::Eip4844(tx) => { #[cfg(feature = "k256")] { let from = tx.recover_signer().ok(); - let tx: Self = tx.strip_signature().into(); + let tx: Self = tx.into_inner().strip_signature().into(); if let Some(from) = from { tx.from(from) } else { @@ -995,14 +995,14 @@ impl From for TransactionRequest { #[cfg(not(feature = "k256"))] { - tx.strip_signature().into() + tx.into_inner().strip_signature().into() } } TxEnvelope::Eip7702(tx) => { #[cfg(feature = "k256")] { let from = tx.recover_signer().ok(); - let tx: Self = tx.strip_signature().into(); + let tx: Self = tx.into_inner().strip_signature().into(); if let Some(from) = from { tx.from(from) } else { @@ -1012,7 +1012,7 @@ impl From for TransactionRequest { #[cfg(not(feature = "k256"))] { - tx.strip_signature().into() + tx.into_inner().strip_signature().into() } } _ => Default::default(), diff --git a/crates/serde/src/lib.rs b/crates/serde/src/lib.rs index 603300801fa..9af01f2d3a6 100644 --- a/crates/serde/src/lib.rs +++ b/crates/serde/src/lib.rs @@ -23,6 +23,11 @@ pub use self::optional::*; pub mod quantity; +/// Serialization options for [`Sealed`]. +/// +/// [`Sealed`]: alloy_primitives::Sealed +pub mod sealed; + /// Storage related helpers. pub mod storage; pub use storage::JsonStorageKey; diff --git a/crates/serde/src/sealed.rs b/crates/serde/src/sealed.rs new file mode 100644 index 00000000000..205d6ca205f --- /dev/null +++ b/crates/serde/src/sealed.rs @@ -0,0 +1,82 @@ +/// Serializes and Deserializes [`Sealed`], flattening the struct. +/// +/// [`Sealed`]: alloy_primitives::Sealed +pub mod flat { + use alloy_primitives::{Sealed, B256}; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + #[derive(Serialize)] + struct FlatSer<'a, T> { + seal: B256, + #[serde(flatten)] + t: &'a T, + } + + #[derive(Deserialize)] + struct FlatDeser { + seal: B256, + #[serde(flatten)] + t: T, + } + + /// Serializes a [`Sealed`] with the given serializer. + pub fn serialize(sealed: &Sealed, serializer: S) -> Result + where + S: Serializer, + T: Serialize, + { + FlatSer { seal: sealed.seal(), t: sealed.inner() }.serialize(serializer) + } + + /// Deserializes a [`Sealed`] with the given deserializer. + pub fn deserialize<'de, D, T>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + T: Deserialize<'de>, + { + let FlatDeser { seal, t } = FlatDeser::deserialize(deserializer)?; + Ok(Sealed::new_unchecked(t, seal)) + } +} + +/// Serializes and Deserializes [`Sealed`], flattening the struct and renaming +/// the `seal` key to `hash`. +/// +/// [`Sealed`]: alloy_primitives::Sealed +pub mod flat_hash { + use alloy_primitives::{Sealed, B256}; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + #[derive(Serialize)] + struct FlatSer<'a, T> { + hash: B256, + #[serde(flatten)] + t: &'a T, + } + + #[derive(Deserialize)] + struct FlatDeser { + hash: B256, + #[serde(flatten)] + t: T, + } + + /// Serializes a [`Sealed`] with the given serializer. + pub fn serialize(sealed: &Sealed, serializer: S) -> Result + where + S: Serializer, + T: Serialize, + { + FlatSer { hash: sealed.seal(), t: sealed.inner() }.serialize(serializer) + } + + /// Deserializes a [`Sealed`] with the given deserializer. + pub fn deserialize<'de, D, T>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + T: Deserialize<'de>, + { + let FlatDeser { hash, t } = FlatDeser::deserialize(deserializer)?; + Ok(Sealed::new_unchecked(t, hash)) + } +}