From a2e238036c26335a82caec830d8c676e26e4e91b Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 18 Aug 2023 15:49:34 +0200 Subject: [PATCH 1/3] feat: add recovered wrapper type and eth pool conversions --- crates/primitives/src/lib.rs | 8 +- crates/primitives/src/transaction/mod.rs | 2 +- crates/primitives/src/transaction/pooled.rs | 85 ++++++++++++++++++++- crates/transaction-pool/src/traits.rs | 55 +++++++++++-- 4 files changed, 136 insertions(+), 14 deletions(-) diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 8d0ffb023615..fd973ff74191 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -92,10 +92,10 @@ pub use transaction::{ util::secp256k1::{public_key_to_address, recover_signer, sign_message}, AccessList, AccessListItem, AccessListWithGasUsed, BlobTransaction, BlobTransactionSidecar, FromRecoveredTransaction, IntoRecoveredTransaction, InvalidTransactionError, - PooledTransactionsElement, 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, + 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, }; pub use withdrawal::Withdrawal; diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 962bd7e5bcdc..57056b5bbdb9 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -24,7 +24,7 @@ pub use eip1559::TxEip1559; pub use eip2930::TxEip2930; pub use eip4844::{BlobTransaction, BlobTransactionSidecar, TxEip4844}; pub use legacy::TxLegacy; -pub use pooled::PooledTransactionsElement; +pub use pooled::{PooledTransactionsElement, PooledTransactionsElementEcRecovered}; mod access_list; mod eip1559; diff --git a/crates/primitives/src/transaction/pooled.rs b/crates/primitives/src/transaction/pooled.rs index ebaf5ce144de..dce0293a6975 100644 --- a/crates/primitives/src/transaction/pooled.rs +++ b/crates/primitives/src/transaction/pooled.rs @@ -1,10 +1,11 @@ //! Defines the types for blob transactions, legacy, and other EIP-2718 transactions included in a //! response to `GetPooledTransactions`. use crate::{ - BlobTransaction, Bytes, Signature, Transaction, TransactionSigned, TxEip1559, TxEip2930, - TxHash, TxLegacy, EIP4844_TX_TYPE_ID, + Address, BlobTransaction, Bytes, Signature, Transaction, TransactionSigned, + TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxHash, TxLegacy, EIP4844_TX_TYPE_ID, H256, }; use bytes::Buf; +use derive_more::{AsRef, Deref}; use reth_rlp::{Decodable, DecodeError, Encodable, Header, EMPTY_LIST_CODE}; use serde::{Deserialize, Serialize}; @@ -45,6 +46,41 @@ pub enum PooledTransactionsElement { } impl PooledTransactionsElement { + /// Heavy operation that return signature hash over rlp encoded transaction. + /// It is only for signature signing or signer recovery. + pub fn signature_hash(&self) -> H256 { + todo!() + } + + /// Returns the signature of the transaction. + pub fn signature(&self) -> &Signature { + match self { + Self::Legacy { signature, .. } => signature, + Self::Eip2930 { signature, .. } => signature, + Self::Eip1559 { signature, .. } => signature, + Self::BlobTransaction(blob_tx) => &blob_tx.signature, + } + } + + /// Recover signer from signature and hash. + /// + /// Returns `None` if the transaction's signature is invalid, see also [Self::recover_signer]. + pub fn recover_signer(&self) -> Option
{ + let signature_hash = self.signature_hash(); + self.signature().recover_signer(signature_hash) + } + + /// Tries to recover signer and return [`PooledTransactionsElementEcRecovered`]. + /// + /// Returns `Err(Self)` if the transaction's signature is invalid, see also + /// [Self::recover_signer]. + pub fn try_into_ecrecovered(self) -> Result { + match self.recover_signer() { + None => Err(self), + Some(signer) => Ok(PooledTransactionsElementEcRecovered { transaction: self, signer }), + } + } + /// Decodes the "raw" format of transaction (e.g. `eth_sendRawTransaction`). /// /// The raw transaction is either a legacy transaction or EIP-2718 typed transaction @@ -117,6 +153,12 @@ impl PooledTransactionsElement { } } + /// Create [`TransactionSignedEcRecovered`] by converting this transaction into + /// [`TransactionSigned`] and [`Address`] of the signer. + pub fn into_ecrecovered_transaction(self, signer: Address) -> TransactionSignedEcRecovered { + TransactionSignedEcRecovered::from_signed_transaction(self.into_transaction(), signer) + } + /// Returns the inner [TransactionSigned]. pub fn into_transaction(self) -> TransactionSigned { match self { @@ -301,3 +343,42 @@ impl From for PooledTransactionsElement { } } } + +/// A signed pooled transaction with recovered signer. +#[derive(Debug, Clone, PartialEq, Eq, AsRef, Deref)] +pub struct PooledTransactionsElementEcRecovered { + /// Signer of the transaction + signer: Address, + /// Signed transaction + #[deref] + #[as_ref] + transaction: PooledTransactionsElement, +} + +// === impl PooledTransactionsElementEcRecovered === + +impl PooledTransactionsElementEcRecovered { + /// Signer of transaction recovered from signature + pub fn signer(&self) -> Address { + self.signer + } + + /// Transform back to [`PooledTransactionsElement`] + pub fn into_transaction(self) -> PooledTransactionsElement { + self.transaction + } + + /// Desolve Self to its component + pub fn into_components(self) -> (PooledTransactionsElement, Address) { + (self.transaction, self.signer) + } + + /// Create [`TransactionSignedEcRecovered`] from [`PooledTransactionsElement`] and [`Address`] + /// of the signer. + pub fn from_signed_transaction( + transaction: PooledTransactionsElement, + signer: Address, + ) -> Self { + Self { transaction, signer } + } +} diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index 4d740da9ab53..2169c700391f 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -6,9 +6,9 @@ use crate::{ }; use futures_util::{ready, Stream}; use reth_primitives::{ - Address, FromRecoveredTransaction, IntoRecoveredTransaction, PeerId, Transaction, - TransactionKind, TransactionSignedEcRecovered, TxHash, EIP1559_TX_TYPE_ID, EIP4844_TX_TYPE_ID, - H256, U256, + Address, BlobTransactionSidecar, FromRecoveredTransaction, IntoRecoveredTransaction, PeerId, + PooledTransactionsElement, PooledTransactionsElementEcRecovered, Transaction, TransactionKind, + TransactionSignedEcRecovered, TxHash, EIP1559_TX_TYPE_ID, EIP4844_TX_TYPE_ID, H256, U256, }; use reth_rlp::Encodable; use std::{ @@ -569,7 +569,7 @@ pub trait PoolTransaction: /// /// This type is essentially a wrapper around [TransactionSignedEcRecovered] with additional fields /// derived from the transaction that are frequently used by the pools for ordering. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct EthPooledTransaction { /// EcRecovered transaction info pub(crate) transaction: TransactionSignedEcRecovered, @@ -577,21 +577,41 @@ pub struct EthPooledTransaction { /// For EIP-1559 transactions: `max_fee_per_gas * gas_limit + tx_value`. /// For legacy transactions: `gas_price * gas_limit + tx_value`. pub(crate) cost: U256, - // TODO optional sidecar + + /// The blob side car this transaction + pub(crate) blob_sidecar: EthBlobTransactionSidecar, +} + +/// Represents the blob sidecar of the [EthPooledTransaction]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) enum EthBlobTransactionSidecar { + /// This transaction does not have a blob sidecar + None, + /// This transaction has a blob sidecar (EIP-4844) but it is missing + /// + /// It was either extracted after being inserted into the pool or re-injected after reorg + /// without the blob sidecar + Missing, + /// The eip-4844 transaction was pulled from the network and still has its blob sidecar + Present(BlobTransactionSidecar), } impl EthPooledTransaction { /// Create new instance of [Self]. pub fn new(transaction: TransactionSignedEcRecovered) -> Self { + let mut blob_sidecar = EthBlobTransactionSidecar::None; let gas_cost = match &transaction.transaction { Transaction::Legacy(t) => U256::from(t.gas_price) * U256::from(t.gas_limit), Transaction::Eip2930(t) => U256::from(t.gas_price) * U256::from(t.gas_limit), Transaction::Eip1559(t) => U256::from(t.max_fee_per_gas) * U256::from(t.gas_limit), - Transaction::Eip4844(t) => U256::from(t.max_fee_per_gas) * U256::from(t.gas_limit), + Transaction::Eip4844(t) => { + blob_sidecar = EthBlobTransactionSidecar::Missing; + U256::from(t.max_fee_per_gas) * U256::from(t.gas_limit) + } }; let cost = gas_cost + U256::from(transaction.value()); - Self { transaction, cost } + Self { transaction, cost, blob_sidecar } } /// Return the reference to the underlying transaction. @@ -600,6 +620,27 @@ impl EthPooledTransaction { } } +/// Conversion from the network transaction type to the pool transaction type. +impl From for EthPooledTransaction { + fn from(tx: PooledTransactionsElementEcRecovered) -> Self { + let (tx, signer) = tx.into_components(); + match tx { + PooledTransactionsElement::BlobTransaction(tx) => { + // include the blob sidecar + let (tx, blob) = tx.into_parts(); + let tx = TransactionSignedEcRecovered::from_signed_transaction(tx, signer); + let mut pooled = EthPooledTransaction::new(tx); + pooled.blob_sidecar = EthBlobTransactionSidecar::Present(blob); + pooled + } + tx => { + // no blob sidecar + EthPooledTransaction::new(tx.into_ecrecovered_transaction(signer)) + } + } + } +} + impl PoolTransaction for EthPooledTransaction { /// Returns hash of the transaction. fn hash(&self) -> &TxHash { From 329c9beb503242f76baad404ca3bd4e14fbe57d1 Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Fri, 18 Aug 2023 13:35:56 -0400 Subject: [PATCH 2/3] implement PooledTransactionsElement::signature_hash * refactors out the relevant encoding and payload length methods into the individual transaction types * implements Transaction::signature_hash with the methods on individual types * finally implements PooledTransactionsElement::signature_hash using these individual methods --- crates/primitives/src/transaction/eip1559.rs | 25 +++++- crates/primitives/src/transaction/eip2930.rs | 25 +++++- crates/primitives/src/transaction/eip4844.rs | 23 +++++ crates/primitives/src/transaction/legacy.rs | 56 +++++++++++- crates/primitives/src/transaction/mod.rs | 94 +++++--------------- crates/primitives/src/transaction/pooled.rs | 7 +- 6 files changed, 153 insertions(+), 77 deletions(-) diff --git a/crates/primitives/src/transaction/eip1559.rs b/crates/primitives/src/transaction/eip1559.rs index c446da2e1607..4bc5cc4754b8 100644 --- a/crates/primitives/src/transaction/eip1559.rs +++ b/crates/primitives/src/transaction/eip1559.rs @@ -1,5 +1,6 @@ use super::access_list::AccessList; -use crate::{Bytes, ChainId, Signature, TransactionKind, TxType}; +use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, H256}; +use bytes::BytesMut; use reth_codecs::{main_codec, Compact}; use reth_rlp::{length_of_length, Decodable, DecodeError, Encodable, Header}; use std::mem; @@ -188,6 +189,28 @@ impl TxEip1559 { self.access_list.size() + // access_list self.input.len() // input } + + /// Encodes the legacy transaction in RLP for signing. + pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { + out.put_u8(self.tx_type() as u8); + Header { list: true, payload_length: self.fields_len() }.encode(out); + self.encode_fields(out); + } + + /// Outputs the length of the signature RLP encoding for the transaction. + pub(crate) fn payload_len_for_signature(&self) -> usize { + let payload_length = self.fields_len(); + // 'transaction type byte length' + 'header length' + 'payload length' + 1 + length_of_length(payload_length) + payload_length + } + + /// Outputs the signature hash of the transaction by first encoding without a signature, then + /// hashing. + pub(crate) fn signature_hash(&self) -> H256 { + let mut buf = BytesMut::with_capacity(self.payload_len_for_signature()); + self.encode_for_signing(&mut buf); + keccak256(&buf) + } } #[cfg(test)] diff --git a/crates/primitives/src/transaction/eip2930.rs b/crates/primitives/src/transaction/eip2930.rs index 3f2a8f8fa6b7..78e187889105 100644 --- a/crates/primitives/src/transaction/eip2930.rs +++ b/crates/primitives/src/transaction/eip2930.rs @@ -1,5 +1,6 @@ use super::access_list::AccessList; -use crate::{Bytes, ChainId, Signature, TransactionKind, TxType}; +use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, H256}; +use bytes::BytesMut; use reth_codecs::{main_codec, Compact}; use reth_rlp::{length_of_length, Decodable, DecodeError, Encodable, Header}; use std::mem; @@ -153,6 +154,28 @@ impl TxEip2930 { pub(crate) fn tx_type(&self) -> TxType { TxType::EIP2930 } + + /// Encodes the legacy transaction in RLP for signing. + pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { + out.put_u8(self.tx_type() as u8); + Header { list: true, payload_length: self.fields_len() }.encode(out); + self.encode_fields(out); + } + + /// Outputs the length of the signature RLP encoding for the transaction. + pub(crate) fn payload_len_for_signature(&self) -> usize { + let payload_length = self.fields_len(); + // 'transaction type byte length' + 'header length' + 'payload length' + 1 + length_of_length(payload_length) + payload_length + } + + /// Outputs the signature hash of the transaction by first encoding without a signature, then + /// hashing. + pub(crate) fn signature_hash(&self) -> H256 { + let mut buf = BytesMut::with_capacity(self.payload_len_for_signature()); + self.encode_for_signing(&mut buf); + keccak256(&buf) + } } #[cfg(test)] diff --git a/crates/primitives/src/transaction/eip4844.rs b/crates/primitives/src/transaction/eip4844.rs index 90246031e500..3092f284f171 100644 --- a/crates/primitives/src/transaction/eip4844.rs +++ b/crates/primitives/src/transaction/eip4844.rs @@ -9,6 +9,7 @@ use crate::{ kzg_to_versioned_hash, Bytes, ChainId, Signature, Transaction, TransactionKind, TransactionSigned, TxHash, TxType, EIP4844_TX_TYPE_ID, H256, }; +use bytes::BytesMut; use reth_codecs::{main_codec, Compact}; use reth_rlp::{length_of_length, Decodable, DecodeError, Encodable, Header}; use serde::{Deserialize, Serialize}; @@ -226,6 +227,28 @@ impl TxEip4844 { pub(crate) fn tx_type(&self) -> TxType { TxType::EIP4844 } + + /// Encodes the legacy transaction in RLP for signing. + pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { + out.put_u8(self.tx_type() as u8); + Header { list: true, payload_length: self.fields_len() }.encode(out); + self.encode_fields(out); + } + + /// Outputs the length of the signature RLP encoding for the transaction. + pub(crate) fn payload_len_for_signature(&self) -> usize { + let payload_length = self.fields_len(); + // 'transaction type byte length' + 'header length' + 'payload length' + 1 + length_of_length(payload_length) + payload_length + } + + /// Outputs the signature hash of the transaction by first encoding without a signature, then + /// hashing. + pub(crate) fn signature_hash(&self) -> H256 { + let mut buf = BytesMut::with_capacity(self.payload_len_for_signature()); + self.encode_for_signing(&mut buf); + keccak256(&buf) + } } /// An error that can occur when validating a [BlobTransaction]. diff --git a/crates/primitives/src/transaction/legacy.rs b/crates/primitives/src/transaction/legacy.rs index fcbb627268b4..9fa6fb7fc115 100644 --- a/crates/primitives/src/transaction/legacy.rs +++ b/crates/primitives/src/transaction/legacy.rs @@ -1,4 +1,5 @@ -use crate::{Bytes, ChainId, Signature, TransactionKind, TxType}; +use crate::{keccak256, Bytes, ChainId, Signature, TransactionKind, TxType, H256}; +use bytes::BytesMut; use reth_codecs::{main_codec, Compact}; use reth_rlp::{length_of_length, Encodable, Header}; use std::mem; @@ -105,6 +106,59 @@ impl TxLegacy { pub(crate) fn tx_type(&self) -> TxType { TxType::Legacy } + + /// Encodes EIP-155 arguments into the desired buffer. Only encodes values for legacy + /// transactions. + pub(crate) fn encode_eip155_fields(&self, out: &mut dyn bytes::BufMut) { + // if this is a legacy transaction without a chain ID, it must be pre-EIP-155 + // and does not need to encode the chain ID for the signature hash encoding + if let Some(id) = self.chain_id { + // EIP-155 encodes the chain ID and two zeroes + id.encode(out); + 0x00u8.encode(out); + 0x00u8.encode(out); + } + } + + /// Outputs the length of EIP-155 fields. Only outputs a non-zero value for EIP-155 legacy + /// transactions. + pub(crate) fn eip155_fields_len(&self) -> usize { + if let Some(id) = self.chain_id { + // EIP-155 encodes the chain ID and two zeroes, so we add 2 to the length of the chain + // ID to get the length of all 3 fields + // len(chain_id) + (0x00) + (0x00) + id.length() + 2 + } else { + // this is either a pre-EIP-155 legacy transaction or a typed transaction + 0 + } + } + + /// Encodes the legacy transaction in RLP for signing, including the EIP-155 fields if possible. + pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) { + Header { list: true, payload_length: self.fields_len() + self.eip155_fields_len() } + .encode(out); + self.encode_fields(out); + self.encode_eip155_fields(out); + } + + /// Outputs the length of the signature RLP encoding for the transaction, including the length + /// of the EIP-155 fields if possible. + pub(crate) fn payload_len_for_signature(&self) -> usize { + let payload_length = self.fields_len() + self.eip155_fields_len(); + // 'header length' + 'payload length' + length_of_length(payload_length) + payload_length + } + + /// Outputs the signature hash of the transaction by first encoding without a signature, then + /// hashing. + /// + /// See [LegacyTx::encode_for_signing] for more information on the encoding format. + pub(crate) fn signature_hash(&self) -> H256 { + let mut buf = BytesMut::with_capacity(self.payload_len_for_signature()); + self.encode_for_signing(&mut buf); + keccak256(&buf) + } } #[cfg(test)] diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 57056b5bbdb9..115bc83aea1f 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -10,9 +10,7 @@ pub use meta::TransactionMeta; use once_cell::sync::Lazy; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use reth_codecs::{add_arbitrary_tests, derive_arbitrary, Compact}; -use reth_rlp::{ - length_of_length, Decodable, DecodeError, Encodable, Header, EMPTY_LIST_CODE, EMPTY_STRING_CODE, -}; +use reth_rlp::{Decodable, DecodeError, Encodable, Header, EMPTY_LIST_CODE, EMPTY_STRING_CODE}; use serde::{Deserialize, Serialize}; pub use signature::Signature; use std::mem; @@ -100,9 +98,12 @@ impl Transaction { /// Heavy operation that return signature hash over rlp encoded transaction. /// It is only for signature signing or signer recovery. pub fn signature_hash(&self) -> H256 { - let mut buf = BytesMut::new(); - self.encode(&mut buf); - keccak256(&buf) + match self { + Transaction::Legacy(tx) => tx.signature_hash(), + Transaction::Eip2930(tx) => tx.signature_hash(), + Transaction::Eip1559(tx) => tx.signature_hash(), + Transaction::Eip4844(tx) => tx.signature_hash(), + } } /// Get chain_id. @@ -316,54 +317,6 @@ impl Transaction { } } - /// Encodes EIP-155 arguments into the desired buffer. Only encodes values for legacy - /// transactions. - pub(crate) fn encode_eip155_fields(&self, out: &mut dyn bytes::BufMut) { - // if this is a legacy transaction without a chain ID, it must be pre-EIP-155 - // and does not need to encode the chain ID for the signature hash encoding - if let Transaction::Legacy(TxLegacy { chain_id: Some(id), .. }) = self { - // EIP-155 encodes the chain ID and two zeroes - id.encode(out); - 0x00u8.encode(out); - 0x00u8.encode(out); - } - } - - /// Outputs the length of EIP-155 fields. Only outputs a non-zero value for EIP-155 legacy - /// transactions. - pub(crate) fn eip155_fields_len(&self) -> usize { - if let Transaction::Legacy(TxLegacy { chain_id: Some(id), .. }) = self { - // EIP-155 encodes the chain ID and two zeroes, so we add 2 to the length of the chain - // ID to get the length of all 3 fields - // len(chain_id) + (0x00) + (0x00) - id.length() + 2 - } else { - // this is either a pre-EIP-155 legacy transaction or a typed transaction - 0 - } - } - - /// Outputs the length of the transaction's fields, without a RLP header or length of the - /// eip155 fields. - pub(crate) fn fields_len(&self) -> usize { - match self { - Transaction::Legacy(legacy_tx) => legacy_tx.fields_len(), - Transaction::Eip2930(access_list_tx) => access_list_tx.fields_len(), - Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.fields_len(), - Transaction::Eip4844(blob_tx) => blob_tx.fields_len(), - } - } - - /// Encodes only the transaction's fields into the desired buffer, without a RLP header. - pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) { - match self { - Transaction::Legacy(legacy_tx) => legacy_tx.encode_fields(out), - Transaction::Eip2930(access_list_tx) => access_list_tx.encode_fields(out), - Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encode_fields(out), - Transaction::Eip4844(blob_tx) => blob_tx.encode_fields(out), - } - } - /// This encodes the transaction _without_ the signature, and is only suitable for creating a /// hash intended for signing. pub fn encode_without_signature(&self, out: &mut dyn bytes::BufMut) { @@ -496,32 +449,27 @@ impl Default for Transaction { impl Encodable for Transaction { fn encode(&self, out: &mut dyn bytes::BufMut) { match self { - Transaction::Legacy { .. } => { - Header { list: true, payload_length: self.fields_len() + self.eip155_fields_len() } - .encode(out); - self.encode_fields(out); - self.encode_eip155_fields(out); + Transaction::Legacy(legacy_tx) => { + legacy_tx.encode_for_signing(out); } - _ => { - out.put_u8(self.tx_type() as u8); - Header { list: true, payload_length: self.fields_len() }.encode(out); - self.encode_fields(out); + Transaction::Eip2930(access_list_tx) => { + access_list_tx.encode_for_signing(out); + } + Transaction::Eip1559(dynamic_fee_tx) => { + dynamic_fee_tx.encode_for_signing(out); + } + Transaction::Eip4844(blob_tx) => { + blob_tx.encode_for_signing(out); } } } fn length(&self) -> usize { match self { - Transaction::Legacy { .. } => { - let payload_length = self.fields_len() + self.eip155_fields_len(); - // 'header length' + 'payload length' - length_of_length(payload_length) + payload_length - } - _ => { - let payload_length = self.fields_len(); - // 'transaction type byte length' + 'header length' + 'payload length' - 1 + length_of_length(payload_length) + payload_length - } + Transaction::Legacy(legacy_tx) => legacy_tx.payload_len_for_signature(), + Transaction::Eip2930(access_list_tx) => access_list_tx.payload_len_for_signature(), + Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.payload_len_for_signature(), + Transaction::Eip4844(blob_tx) => blob_tx.payload_len_for_signature(), } } } diff --git a/crates/primitives/src/transaction/pooled.rs b/crates/primitives/src/transaction/pooled.rs index dce0293a6975..bcc870a2c0f2 100644 --- a/crates/primitives/src/transaction/pooled.rs +++ b/crates/primitives/src/transaction/pooled.rs @@ -49,7 +49,12 @@ impl PooledTransactionsElement { /// Heavy operation that return signature hash over rlp encoded transaction. /// It is only for signature signing or signer recovery. pub fn signature_hash(&self) -> H256 { - todo!() + match self { + Self::Legacy { transaction, .. } => transaction.signature_hash(), + Self::Eip2930 { transaction, .. } => transaction.signature_hash(), + Self::Eip1559 { transaction, .. } => transaction.signature_hash(), + Self::BlobTransaction(blob_tx) => blob_tx.transaction.signature_hash(), + } } /// Returns the signature of the transaction. From 9af77dd151ea4089f35e68bdece316bcc92ef32e Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 18 Aug 2023 19:49:13 +0200 Subject: [PATCH 3/3] fix docs link --- crates/primitives/src/transaction/legacy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/src/transaction/legacy.rs b/crates/primitives/src/transaction/legacy.rs index 9fa6fb7fc115..ec61490a54c5 100644 --- a/crates/primitives/src/transaction/legacy.rs +++ b/crates/primitives/src/transaction/legacy.rs @@ -153,7 +153,7 @@ impl TxLegacy { /// Outputs the signature hash of the transaction by first encoding without a signature, then /// hashing. /// - /// See [LegacyTx::encode_for_signing] for more information on the encoding format. + /// See [Self::encode_for_signing] for more information on the encoding format. pub(crate) fn signature_hash(&self) -> H256 { let mut buf = BytesMut::with_capacity(self.payload_len_for_signature()); self.encode_for_signing(&mut buf);