diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs
index 92d55b8d82b0..426607583221 100644
--- a/crates/primitives/src/transaction/mod.rs
+++ b/crates/primitives/src/transaction/mod.rs
@@ -856,10 +856,39 @@ impl TransactionSignedNoHash {
///
/// Returns `None` if the transaction's signature is invalid, see also [Self::recover_signer].
pub fn recover_signer(&self) -> Option
{
+ // Optimism's Deposit transaction does not have a signature. Directly return the
+ // `from` address.
+ #[cfg(feature = "optimism")]
+ if let Transaction::Deposit(TxDeposit { from, .. }) = self.transaction {
+ return Some(from)
+ }
+
let signature_hash = self.signature_hash();
self.signature.recover_signer(signature_hash)
}
+ /// Recover signer from signature and hash _without ensuring that the signature has a low `s`
+ /// value_.
+ ///
+ /// Re-uses a given buffer to avoid numerous reallocations when recovering batches. **Clears the
+ /// buffer before use.**
+ ///
+ /// Returns `None` if the transaction's signature is invalid, see also
+ /// [Signature::recover_signer_unchecked].
+ pub fn encode_and_recover_unchecked(&self, buffer: &mut Vec) -> Option {
+ buffer.clear();
+ self.transaction.encode_without_signature(buffer);
+
+ // Optimism's Deposit transaction does not have a signature. Directly return the
+ // `from` address.
+ #[cfg(feature = "optimism")]
+ if let Transaction::Deposit(TxDeposit { from, .. }) = self.transaction {
+ return Some(from)
+ }
+
+ self.signature.recover_signer_unchecked(keccak256(buffer))
+ }
+
/// Converts into a transaction type with its hash: [`TransactionSigned`].
///
/// Note: This will recalculate the hash of the transaction.
diff --git a/crates/stages/src/stages/sender_recovery.rs b/crates/stages/src/stages/sender_recovery.rs
index 4648f9732443..afb65c560605 100644
--- a/crates/stages/src/stages/sender_recovery.rs
+++ b/crates/stages/src/stages/sender_recovery.rs
@@ -9,7 +9,6 @@ use reth_db::{
};
use reth_interfaces::consensus;
use reth_primitives::{
- keccak256,
stage::{EntitiesCheckpoint, StageCheckpoint, StageId},
Address, PruneSegment, StaticFileSegment, TransactionSignedNoHash, TxNumber,
};
@@ -229,16 +228,13 @@ fn recover_sender(
(tx_id, tx): (TxNumber, TransactionSignedNoHash),
rlp_buf: &mut Vec,
) -> Result<(u64, Address), Box> {
- tx.transaction.encode_without_signature(rlp_buf);
-
// We call [Signature::recover_signer_unchecked] because transactions run in the pipeline are
// known to be valid - this means that we do not need to check whether or not the `s` value is
// greater than `secp256k1n / 2` if past EIP-2. There are transactions pre-homestead which have
// large `s` values, so using [Signature::recover_signer] here would not be
// backwards-compatible.
let sender = tx
- .signature
- .recover_signer_unchecked(keccak256(rlp_buf))
+ .encode_and_recover_unchecked(rlp_buf)
.ok_or(SenderRecoveryStageError::FailedRecovery(FailedSenderRecoveryError { tx: tx_id }))?;
Ok((tx_id, sender))