fix: handle optimism deposit transactions on SenderRecovery stage (#7376)

This commit is contained in:
joshieDo
2024-03-29 13:13:27 +01:00
committed by GitHub
parent 79e15b1956
commit 8b88306907
2 changed files with 30 additions and 5 deletions

View File

@ -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<Address> {
// 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<u8>) -> Option<Address> {
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.

View File

@ -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<u8>,
) -> Result<(u64, Address), Box<SenderRecoveryStageError>> {
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))