Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -501,11 +501,11 @@ alloy-transport-ws = { version = "0.15.11", default-features = false }
# op
alloy-op-evm = { version = "0.7.1", default-features = false }
alloy-op-hardforks = "0.2.0"
op-alloy-rpc-types = { version = "0.15.4", default-features = false }
op-alloy-rpc-types-engine = { version = "0.15.4", default-features = false }
op-alloy-network = { version = "0.15.4", default-features = false }
op-alloy-consensus = { version = "0.15.4", default-features = false }
op-alloy-rpc-jsonrpsee = { version = "0.15.4", default-features = false }
op-alloy-rpc-types = { version = "0.15.6", default-features = false }
op-alloy-rpc-types-engine = { version = "0.15.6", default-features = false }
op-alloy-network = { version = "0.15.6", default-features = false }
op-alloy-consensus = { version = "0.15.6", default-features = false }
op-alloy-rpc-jsonrpsee = { version = "0.15.6", default-features = false }
op-alloy-flz = { version = "0.13.0", default-features = false }

# misc
Expand Down
19 changes: 13 additions & 6 deletions crates/ethereum/primitives/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use alloc::vec::Vec;
use alloy_consensus::{
transaction::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx},
transaction::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx, SignerRecoverable},
EthereumTxEnvelope, SignableTransaction, Signed, TxEip1559, TxEip2930, TxEip4844, TxEip7702,
TxLegacy, TxType, Typed2718,
};
Expand Down Expand Up @@ -640,16 +640,23 @@ impl reth_codecs::Compact for TransactionSigned {
}
}

impl SignedTransaction for TransactionSigned {
fn tx_hash(&self) -> &TxHash {
self.hash.get_or_init(|| self.recalculate_hash())
}

impl SignerRecoverable for TransactionSigned {
fn recover_signer(&self) -> Result<Address, RecoveryError> {
let signature_hash = self.signature_hash();
recover_signer(&self.signature, signature_hash)
}

fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
let signature_hash = self.signature_hash();
recover_signer_unchecked(&self.signature, signature_hash)
}
}

impl SignedTransaction for TransactionSigned {
fn tx_hash(&self) -> &TxHash {
self.hash.get_or_init(|| self.recalculate_hash())
}

fn recover_signer_unchecked_with_buf(
&self,
buf: &mut Vec<u8>,
Expand Down
14 changes: 8 additions & 6 deletions crates/optimism/primitives/src/transaction/signed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::transaction::OpTransaction;
use alloc::vec::Vec;
use alloy_consensus::{
transaction::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx},
transaction::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx, SignerRecoverable},
Sealed, SignableTransaction, Signed, Transaction, TxEip1559, TxEip2930, TxEip7702, TxLegacy,
Typed2718,
};
Expand Down Expand Up @@ -103,11 +103,7 @@ impl OpTransactionSigned {
}
}

impl SignedTransaction for OpTransactionSigned {
fn tx_hash(&self) -> &TxHash {
self.hash.get_or_init(|| self.recalculate_hash())
}

impl SignerRecoverable for OpTransactionSigned {
fn recover_signer(&self) -> Result<Address, RecoveryError> {
// Optimism's Deposit transaction does not have a signature. Directly return the
// `from` address.
Expand All @@ -131,6 +127,12 @@ impl SignedTransaction for OpTransactionSigned {
let signature_hash = signature_hash(transaction);
recover_signer_unchecked(signature, signature_hash)
}
}

impl SignedTransaction for OpTransactionSigned {
fn tx_hash(&self) -> &TxHash {
self.hash.get_or_init(|| self.recalculate_hash())
}

fn recover_signer_unchecked_with_buf(
&self,
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives-traits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ revm-bytecode.workspace = true
revm-state.workspace = true

# op
op-alloy-consensus = { workspace = true, optional = true }
op-alloy-consensus = { workspace = true, optional = true, features = ["k256"] }

# crypto
secp256k1 = { workspace = true, features = ["recovery"], optional = true }
Expand Down
24 changes: 15 additions & 9 deletions crates/primitives-traits/src/extended.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
transaction::signed::{RecoveryError, SignedTransaction},
};
use alloc::vec::Vec;
use alloy_consensus::Transaction;
use alloy_consensus::{transaction::SignerRecoverable, Transaction};
use alloy_eips::{
eip2718::{Eip2718Error, Eip2718Result, IsTyped2718},
eip2930::AccessList,
Expand Down Expand Up @@ -136,25 +136,31 @@ where
}
}

impl<B, T> SignedTransaction for ExtendedTxEnvelope<B, T>
impl<B, T> SignerRecoverable for ExtendedTxEnvelope<B, T>
where
B: SignedTransaction + IsTyped2718,
T: SignedTransaction,
{
fn tx_hash(&self) -> &TxHash {
match self {
Self::BuiltIn(tx) => tx.tx_hash(),
Self::Other(tx) => tx.tx_hash(),
}
}

fn recover_signer(&self) -> Result<Address, RecoveryError> {
delegate!(self => tx.recover_signer())
}

fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
delegate!(self => tx.recover_signer_unchecked())
}
}

impl<B, T> SignedTransaction for ExtendedTxEnvelope<B, T>
where
B: SignedTransaction + IsTyped2718,
T: SignedTransaction,
{
fn tx_hash(&self) -> &TxHash {
match self {
Self::BuiltIn(tx) => tx.tx_hash(),
Self::Other(tx) => tx.tx_hash(),
}
}

fn recover_signer_unchecked_with_buf(
&self,
Expand Down
83 changes: 8 additions & 75 deletions crates/primitives-traits/src/transaction/signed.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! API of a signed transaction.

use crate::{
crypto::secp256k1::{recover_signer, recover_signer_unchecked},
InMemorySize, MaybeCompact, MaybeSerde, MaybeSerdeBincodeCompat,
crypto::secp256k1::recover_signer_unchecked, InMemorySize, MaybeCompact, MaybeSerde,
MaybeSerdeBincodeCompat,
};
use alloc::{fmt, vec::Vec};
use alloy_consensus::{
transaction::{Recovered, RlpEcdsaEncodableTx},
transaction::{Recovered, RlpEcdsaEncodableTx, SignerRecoverable},
EthereumTxEnvelope, SignableTransaction,
};
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
Expand Down Expand Up @@ -38,6 +38,7 @@ pub trait SignedTransaction:
+ alloy_consensus::Transaction
+ MaybeSerde
+ InMemorySize
+ SignerRecoverable
{
/// Returns reference to transaction hash.
fn tx_hash(&self) -> &TxHash;
Expand All @@ -52,33 +53,13 @@ pub trait SignedTransaction:
!self.is_eip4844()
}

/// Recover signer from signature and hash.
///
/// Returns `RecoveryError` if the transaction's signature is invalid following [EIP-2](https://eips.ethereum.org/EIPS/eip-2), see also `reth_primitive_traits::crypto::secp256k1::recover_signer`.
///
/// Note:
///
/// This can fail for some early ethereum mainnet transactions pre EIP-2, use
/// [`Self::recover_signer_unchecked`] if you want to recover the signer without ensuring that
/// the signature has a low `s` value.
fn recover_signer(&self) -> Result<Address, RecoveryError>;

/// Recover signer from signature and hash.
///
/// Returns an error if the transaction's signature is invalid.
fn try_recover(&self) -> Result<Address, RecoveryError> {
self.recover_signer()
}

/// Recover signer from signature and hash _without ensuring that the signature has a low `s`
/// value_.
///
/// Returns `RecoveryError` if the transaction's signature is invalid, see also
/// `reth_primitive_traits::crypto::secp256k1::recover_signer_unchecked`.
fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
self.recover_signer_unchecked_with_buf(&mut Vec::new())
}

/// Recover signer from signature and hash _without ensuring that the signature has a low `s`
/// value_.
///
Expand All @@ -87,8 +68,9 @@ pub trait SignedTransaction:
self.recover_signer_unchecked()
}

/// Same as [`Self::recover_signer_unchecked`] but receives a buffer to operate on. This is used
/// during batch recovery to avoid allocating a new buffer for each transaction.
/// Same as [`SignerRecoverable::recover_signer_unchecked`] but receives a buffer to operate on.
/// This is used during batch recovery to avoid allocating a new buffer for each
/// transaction.
fn recover_signer_unchecked_with_buf(
&self,
buf: &mut Vec<u8>,
Expand All @@ -109,7 +91,7 @@ pub trait SignedTransaction:
/// Tries to recover signer and return [`Recovered`].
///
/// Returns `Err(Self)` if the transaction's signature is invalid, see also
/// [`SignedTransaction::recover_signer`].
/// [`SignerRecoverable::recover_signer`].
#[auto_impl(keep_default_for(&, Arc))]
fn try_into_recovered(self) -> Result<Recovered<Self>, Self> {
match self.recover_signer() {
Expand Down Expand Up @@ -151,11 +133,6 @@ where
}
}

fn recover_signer(&self) -> Result<Address, RecoveryError> {
let signature_hash = self.signature_hash();
recover_signer(self.signature(), signature_hash)
}

fn recover_signer_unchecked_with_buf(
&self,
buf: &mut Vec<u8>,
Expand Down Expand Up @@ -187,10 +164,6 @@ mod op {
}
}

fn recover_signer(&self) -> Result<Address, RecoveryError> {
recover_signer(self.signature(), self.signature_hash())
}

fn recover_signer_unchecked_with_buf(
&self,
buf: &mut Vec<u8>,
Expand All @@ -217,46 +190,6 @@ mod op {
}
}

fn recover_signer(&self) -> Result<Address, RecoveryError> {
let signature_hash = match self {
Self::Legacy(tx) => tx.signature_hash(),
Self::Eip2930(tx) => tx.signature_hash(),
Self::Eip1559(tx) => tx.signature_hash(),
Self::Eip7702(tx) => tx.signature_hash(),
// Optimism's Deposit transaction does not have a signature. Directly return the
// `from` address.
Self::Deposit(tx) => return Ok(tx.from),
};
let signature = match self {
Self::Legacy(tx) => tx.signature(),
Self::Eip2930(tx) => tx.signature(),
Self::Eip1559(tx) => tx.signature(),
Self::Eip7702(tx) => tx.signature(),
Self::Deposit(_) => unreachable!("Deposit transactions should not be handled here"),
};
recover_signer(signature, signature_hash)
}

fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
let signature_hash = match self {
Self::Legacy(tx) => tx.signature_hash(),
Self::Eip2930(tx) => tx.signature_hash(),
Self::Eip1559(tx) => tx.signature_hash(),
Self::Eip7702(tx) => tx.signature_hash(),
// Optimism's Deposit transaction does not have a signature. Directly return the
// `from` address.
Self::Deposit(tx) => return Ok(tx.from),
};
let signature = match self {
Self::Legacy(tx) => tx.signature(),
Self::Eip2930(tx) => tx.signature(),
Self::Eip1559(tx) => tx.signature(),
Self::Eip7702(tx) => tx.signature(),
Self::Deposit(_) => unreachable!("Deposit transactions should not be handled here"),
};
recover_signer_unchecked(signature, signature_hash)
}

fn recover_signer_unchecked_with_buf(
&self,
buf: &mut Vec<u8>,
Expand Down
4 changes: 2 additions & 2 deletions crates/primitives/benches/recover_ecdsa_crit.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#![allow(missing_docs)]
use alloy_consensus::transaction::SignerRecoverable;
use alloy_primitives::hex_literal::hex;
use alloy_rlp::Decodable;
use criterion::{criterion_group, criterion_main, Criterion};
use reth_ethereum_primitives::TransactionSigned;
use reth_primitives_traits::SignedTransaction;

/// Benchmarks the recovery of the public key from the ECDSA message using criterion.
pub fn criterion_benchmark(c: &mut Criterion) {
Expand All @@ -12,7 +12,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let raw =hex!("f88b8212b085028fa6ae00830f424094aad593da0c8116ef7d2d594dd6a63241bccfc26c80a48318b64b000000000000000000000000641c5d790f862a58ec7abcfd644c0442e9c201b32aa0a6ef9e170bca5ffb7ac05433b13b7043de667fbb0b4a5e45d3b54fb2d6efcc63a0037ec2c05c3d60c5f5f78244ce0a3859e3a18a36c61efb061b383507d3ce19d2");
let mut pointer = raw.as_ref();
let tx = TransactionSigned::decode(&mut pointer).unwrap();
SignedTransaction::recover_signer(&tx).unwrap();
SignerRecoverable::recover_signer(&tx).unwrap();
}
)
});
Expand Down
Loading
Loading