chore(sdk): improve usability tx primitive traits (#12437)

This commit is contained in:
Emilia Hane
2024-11-13 14:35:59 +01:00
committed by GitHub
parent 9313737dbb
commit 9e77d916e1
7 changed files with 124 additions and 61 deletions

View File

@ -27,7 +27,7 @@ pub use receipt::{FullReceipt, Receipt};
pub mod transaction; pub mod transaction;
pub use transaction::{ pub use transaction::{
signed::{FullSignedTx, SignedTransaction}, signed::{FullSignedTx, SignedTransaction},
FullTransaction, Transaction, FullTransaction, Transaction, TransactionExt,
}; };
mod integer_list; mod integer_list;
@ -80,3 +80,15 @@ pub use size::InMemorySize;
/// Node traits /// Node traits
pub mod node; pub mod node;
pub use node::{FullNodePrimitives, NodePrimitives}; pub use node::{FullNodePrimitives, NodePrimitives};
/// Helper trait that requires arbitrary implementation if the feature is enabled.
#[cfg(any(feature = "test-utils", feature = "arbitrary"))]
pub trait MaybeArbitrary: for<'a> arbitrary::Arbitrary<'a> {}
/// Helper trait that requires arbitrary implementation if the feature is enabled.
#[cfg(not(any(feature = "test-utils", feature = "arbitrary")))]
pub trait MaybeArbitrary {}
#[cfg(any(feature = "test-utils", feature = "arbitrary"))]
impl<T> MaybeArbitrary for T where T: for<'a> arbitrary::Arbitrary<'a> {}
#[cfg(not(any(feature = "test-utils", feature = "arbitrary")))]
impl<T> MaybeArbitrary for T {}

View File

@ -1,17 +1,20 @@
//! Transaction abstraction //! Transaction abstraction
use core::{fmt, hash::Hash};
use alloy_primitives::{TxKind, B256};
use reth_codecs::Compact;
use serde::{Deserialize, Serialize};
use crate::InMemorySize;
pub mod signed; pub mod signed;
#[allow(dead_code)] use core::{fmt, hash::Hash};
use alloy_primitives::B256;
use reth_codecs::Compact;
use serde::{Deserialize, Serialize};
use crate::{InMemorySize, MaybeArbitrary, TxType};
/// Helper trait that unifies all behaviour required by transaction to support full node operations.
pub trait FullTransaction: Transaction + Compact {}
impl<T> FullTransaction for T where T: Transaction + Compact {}
/// Abstraction of a transaction. /// Abstraction of a transaction.
pub trait Transaction: pub trait Transaction:
Send Send
@ -24,41 +27,42 @@ pub trait Transaction:
+ PartialEq + PartialEq
+ Hash + Hash
+ Serialize + Serialize
+ alloy_rlp::Encodable
+ alloy_rlp::Decodable
+ for<'de> Deserialize<'de> + for<'de> Deserialize<'de>
+ alloy_consensus::Transaction + TransactionExt
+ InMemorySize + InMemorySize
+ MaybeArbitrary + MaybeArbitrary
{ {
}
impl<T> Transaction for T where
T: Send
+ Sync
+ Unpin
+ Clone
+ Default
+ fmt::Debug
+ Eq
+ PartialEq
+ Hash
+ Serialize
+ for<'de> Deserialize<'de>
+ TransactionExt
+ InMemorySize
+ MaybeArbitrary
{
}
/// Extension trait of [`alloy_consensus::Transaction`].
pub trait TransactionExt: alloy_consensus::Transaction {
/// Transaction envelope type ID.
type Type: TxType;
/// Heavy operation that return signature hash over rlp encoded transaction. /// Heavy operation that return signature hash over rlp encoded transaction.
/// It is only for signature signing or signer recovery. /// It is only for signature signing or signer recovery.
fn signature_hash(&self) -> B256; fn signature_hash(&self) -> B256;
/// Gets the transaction's [`TxKind`], which is the address of the recipient or /// Returns the transaction type.
/// [`TxKind::Create`] if the transaction is a contract creation. fn tx_type(&self) -> Self::Type {
fn kind(&self) -> TxKind; Self::Type::try_from(self.ty()).expect("should decode tx type id")
}
/// Returns true if the tx supports dynamic fees
fn is_dynamic_fee(&self) -> bool;
/// Returns the effective gas price for the given base fee.
fn effective_gas_price(&self, base_fee: Option<u64>) -> u128;
/// This encodes the transaction _without_ the signature, and is only suitable for creating a
/// hash intended for signing.
fn encode_without_signature(&self, out: &mut dyn bytes::BufMut);
} }
#[cfg(not(feature = "arbitrary"))]
/// Helper trait that requires arbitrary implementation if the feature is enabled.
pub trait MaybeArbitrary {}
#[cfg(feature = "arbitrary")]
/// Helper trait that requires arbitrary implementation if the feature is enabled.
pub trait MaybeArbitrary: for<'a> arbitrary::Arbitrary<'a> {}
/// Helper trait that unifies all behaviour required by transaction to support full node operations.
pub trait FullTransaction: Transaction + Compact {}
impl<T> FullTransaction for T where T: Transaction + Compact {}

View File

@ -2,17 +2,18 @@
use alloc::fmt; use alloc::fmt;
use core::hash::Hash; use core::hash::Hash;
use reth_codecs::Compact;
use alloy_consensus::Transaction;
use alloy_eips::eip2718::{Decodable2718, Encodable2718}; use alloy_eips::eip2718::{Decodable2718, Encodable2718};
use alloy_primitives::{keccak256, Address, PrimitiveSignature as Signature, TxHash, B256}; use alloy_primitives::{keccak256, Address, PrimitiveSignature, TxHash, B256};
use reth_codecs::Compact;
use revm_primitives::TxEnv; use revm_primitives::TxEnv;
/// Helper trait that unifies all behaviour required by block to support full node operations. use crate::{transaction::TransactionExt, FullTransaction, MaybeArbitrary, Transaction};
pub trait FullSignedTx: SignedTransaction<Transaction: Compact> + Compact {}
impl<T> FullSignedTx for T where T: SignedTransaction<Transaction: Compact> + Compact {} /// Helper trait that unifies all behaviour required by block to support full node operations.
pub trait FullSignedTx: SignedTransaction<Transaction: FullTransaction> + Compact {}
impl<T> FullSignedTx for T where T: SignedTransaction<Transaction: FullTransaction> + Compact {}
/// A signed transaction. /// A signed transaction.
pub trait SignedTransaction: pub trait SignedTransaction:
@ -31,6 +32,8 @@ pub trait SignedTransaction:
+ alloy_rlp::Decodable + alloy_rlp::Decodable
+ Encodable2718 + Encodable2718
+ Decodable2718 + Decodable2718
+ TransactionExt
+ MaybeArbitrary
{ {
/// Transaction type that is signed. /// Transaction type that is signed.
type Transaction: Transaction; type Transaction: Transaction;
@ -42,7 +45,7 @@ pub trait SignedTransaction:
fn transaction(&self) -> &Self::Transaction; fn transaction(&self) -> &Self::Transaction;
/// Returns reference to signature. /// Returns reference to signature.
fn signature(&self) -> &Signature; fn signature(&self) -> &PrimitiveSignature;
/// Recover signer from signature and hash. /// Recover signer from signature and hash.
/// ///
@ -65,8 +68,10 @@ pub trait SignedTransaction:
/// Create a new signed transaction from a transaction and its signature. /// Create a new signed transaction from a transaction and its signature.
/// ///
/// This will also calculate the transaction hash using its encoding. /// This will also calculate the transaction hash using its encoding.
fn from_transaction_and_signature(transaction: Self::Transaction, signature: Signature) fn from_transaction_and_signature(
-> Self; transaction: Self::Transaction,
signature: PrimitiveSignature,
) -> Self;
/// Calculate transaction hash, eip2728 transaction does not contain rlp header and start with /// Calculate transaction hash, eip2728 transaction does not contain rlp header and start with
/// tx type. /// tx type.
@ -77,3 +82,11 @@ pub trait SignedTransaction:
/// Fills [`TxEnv`] with an [`Address`] and transaction. /// Fills [`TxEnv`] with an [`Address`] and transaction.
fn fill_tx_env(&self, tx_env: &mut TxEnv, sender: Address); fn fill_tx_env(&self, tx_env: &mut TxEnv, sender: Address);
} }
impl<T: SignedTransaction> TransactionExt for T {
type Type = <T::Transaction as TransactionExt>::Type;
fn signature_hash(&self) -> B256 {
self.transaction().signature_hash()
}
}

View File

@ -1,8 +1,6 @@
use core::fmt; use core::fmt;
use alloy_eips::eip2718::Eip2718Error;
use alloy_primitives::{U64, U8}; use alloy_primitives::{U64, U8};
use alloy_rlp::{Decodable, Encodable};
use reth_codecs::Compact; use reth_codecs::Compact;
/// Helper trait that unifies all behaviour required by transaction type ID to support full node /// Helper trait that unifies all behaviour required by transaction type ID to support full node
@ -26,11 +24,11 @@ pub trait TxType:
+ PartialEq<u8> + PartialEq<u8>
+ Into<u8> + Into<u8>
+ Into<U8> + Into<U8>
+ TryFrom<u8, Error = Eip2718Error> + TryFrom<u8, Error: fmt::Debug>
+ TryFrom<u64> + TryFrom<u64, Error: fmt::Debug>
+ TryFrom<U64> + TryFrom<U64>
+ Encodable + alloy_rlp::Encodable
+ Decodable + alloy_rlp::Decodable
{ {
} }
@ -48,10 +46,10 @@ impl<T> TxType for T where
+ PartialEq<u8> + PartialEq<u8>
+ Into<u8> + Into<u8>
+ Into<U8> + Into<U8>
+ TryFrom<u8, Error = Eip2718Error> + TryFrom<u8, Error: fmt::Debug>
+ TryFrom<u64> + TryFrom<u64, Error: fmt::Debug>
+ TryFrom<U64> + TryFrom<U64>
+ Encodable + alloy_rlp::Encodable
+ Decodable + alloy_rlp::Decodable
{ {
} }

View File

@ -150,6 +150,7 @@ test-utils = [
"reth-chainspec/test-utils", "reth-chainspec/test-utils",
"reth-codecs?/test-utils", "reth-codecs?/test-utils",
"reth-trie-common/test-utils", "reth-trie-common/test-utils",
"arbitrary",
] ]
serde-bincode-compat = [ serde-bincode-compat = [
"alloy-consensus/serde-bincode-compat", "alloy-consensus/serde-bincode-compat",

View File

@ -68,7 +68,7 @@ use tx_type::{
}; };
use alloc::vec::Vec; use alloc::vec::Vec;
use reth_primitives_traits::SignedTransaction; use reth_primitives_traits::{transaction::TransactionExt, SignedTransaction};
use revm_primitives::{AuthorizationList, TxEnv}; use revm_primitives::{AuthorizationList, TxEnv};
/// Either a transaction hash or number. /// Either a transaction hash or number.
@ -846,6 +846,22 @@ impl alloy_consensus::Transaction for Transaction {
} }
} }
impl TransactionExt for Transaction {
type Type = TxType;
fn signature_hash(&self) -> B256 {
match self {
Self::Legacy(tx) => tx.signature_hash(),
Self::Eip2930(tx) => tx.signature_hash(),
Self::Eip1559(tx) => tx.signature_hash(),
Self::Eip4844(tx) => tx.signature_hash(),
Self::Eip7702(tx) => tx.signature_hash(),
#[cfg(feature = "optimism")]
_ => todo!("use op type for op"),
}
}
}
/// Signed transaction without its Hash. Used type for inserting into the DB. /// Signed transaction without its Hash. Used type for inserting into the DB.
/// ///
/// This can by converted to [`TransactionSigned`] by calling [`TransactionSignedNoHash::hash`]. /// This can by converted to [`TransactionSigned`] by calling [`TransactionSignedNoHash::hash`].

View File

@ -4,6 +4,7 @@ use alloy_consensus::constants::{
}; };
use alloy_primitives::{U64, U8}; use alloy_primitives::{U64, U8};
use alloy_rlp::{Decodable, Encodable}; use alloy_rlp::{Decodable, Encodable};
use derive_more::Display;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// Identifier parameter for legacy transaction /// Identifier parameter for legacy transaction
@ -36,24 +37,42 @@ pub const DEPOSIT_TX_TYPE_ID: u8 = 126;
/// ///
/// Other required changes when adding a new type can be seen on [PR#3953](https://github.com/paradigmxyz/reth/pull/3953/files). /// Other required changes when adding a new type can be seen on [PR#3953](https://github.com/paradigmxyz/reth/pull/3953/files).
#[derive( #[derive(
Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, Hash, Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Default,
Serialize,
Deserialize,
Hash,
Display,
)] )]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))] #[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
#[display("tx type: {_variant}")]
pub enum TxType { pub enum TxType {
/// Legacy transaction pre EIP-2929 /// Legacy transaction pre EIP-2929
#[default] #[default]
#[display("legacy (0)")]
Legacy = 0_isize, Legacy = 0_isize,
/// AccessList transaction /// AccessList transaction
#[display("eip2930 (1)")]
Eip2930 = 1_isize, Eip2930 = 1_isize,
/// Transaction with Priority fee /// Transaction with Priority fee
#[display("eip1559 (2)")]
Eip1559 = 2_isize, Eip1559 = 2_isize,
/// Shard Blob Transactions - EIP-4844 /// Shard Blob Transactions - EIP-4844
#[display("eip4844 (3)")]
Eip4844 = 3_isize, Eip4844 = 3_isize,
/// EOA Contract Code Transactions - EIP-7702 /// EOA Contract Code Transactions - EIP-7702
#[display("eip7702 (4)")]
Eip7702 = 4_isize, Eip7702 = 4_isize,
/// Optimism Deposit transaction. /// Optimism Deposit transaction.
#[cfg(feature = "optimism")] #[cfg(feature = "optimism")]
#[display("deposit (126)")]
Deposit = 126_isize, Deposit = 126_isize,
} }