diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index 90a59afcc..250422032 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -23,7 +23,7 @@ use reth_execution_types::BlockExecutionResult; use reth_primitives::{ EthPrimitives, Receipt, Recovered, RecoveredBlock, SealedBlock, TransactionSigned, }; -use reth_primitives_traits::{transaction::signed::HL_SYSTEM_TX_FROM_ADDR, NodePrimitives}; +use reth_primitives_traits::{transaction::signed::is_impersonated_tx, NodePrimitives}; use reth_revm::{context_interface::result::ResultAndState, db::State, DatabaseCommit}; /// Factory for [`EthExecutionStrategy`]. @@ -191,7 +191,7 @@ where } let hash = tx.hash(); - let is_system_transaction = tx.signer() == HL_SYSTEM_TX_FROM_ADDR; + let is_system_transaction = is_impersonated_tx(tx.signature(), tx.gas_price()).is_some(); // Execute transaction. let result_and_state = diff --git a/crates/ethereum/primitives/src/transaction.rs b/crates/ethereum/primitives/src/transaction.rs index 9196c6669..bbd71f9de 100644 --- a/crates/ethereum/primitives/src/transaction.rs +++ b/crates/ethereum/primitives/src/transaction.rs @@ -21,7 +21,7 @@ use reth_primitives_traits::{ sync::OnceLock, transaction::{ error::TransactionConversionError, - signed::{is_impersonated_tx, RecoveryError, HL_SYSTEM_TX_FROM_ADDR}, + signed::{is_impersonated_tx, RecoveryError}, }, InMemorySize, SignedTransaction, }; @@ -836,8 +836,8 @@ impl SignedTransaction for TransactionSigned { fn recover_signer(&self) -> Result { let signature = self.signature(); - if is_impersonated_tx(signature, self.gas_price()) { - return Ok(HL_SYSTEM_TX_FROM_ADDR); + if let Some(address) = is_impersonated_tx(signature, self.gas_price()) { + return Ok(address); } let signature_hash = self.signature_hash(); recover_signer(&self.signature, signature_hash) diff --git a/crates/payload/validator/src/lib.rs b/crates/payload/validator/src/lib.rs index 878f1cf21..ae77c25b1 100644 --- a/crates/payload/validator/src/lib.rs +++ b/crates/payload/validator/src/lib.rs @@ -15,7 +15,7 @@ pub mod shanghai; use alloy_rpc_types_engine::{ExecutionData, PayloadError}; use reth_chainspec::EthereumHardforks; use reth_primitives::SealedBlock; -use reth_primitives_traits::transaction::signed::HL_SYSTEM_TX_FROM_ADDR; +use reth_primitives_traits::transaction::signed::is_impersonated_tx; use reth_primitives_traits::{Block, SignedTransaction}; use std::sync::Arc; @@ -94,9 +94,7 @@ impl ExecutionPayloadValidator { let (normal, system) = transactions.into_iter().partition(|tx| { let tx = T::decode_2718(&mut tx.iter().as_slice()); match tx { - Ok(tx) => { - !matches!(tx.recover_signer(), Ok(address) if HL_SYSTEM_TX_FROM_ADDR == address) - } + Ok(tx) => is_impersonated_tx(tx.signature(), tx.gas_price()).is_none(), Err(_) => true, } }); diff --git a/crates/primitives-traits/src/block/body.rs b/crates/primitives-traits/src/block/body.rs index 75131b28c..21af49458 100644 --- a/crates/primitives-traits/src/block/body.rs +++ b/crates/primitives-traits/src/block/body.rs @@ -1,7 +1,7 @@ //! Block body abstraction. use crate::{ - transaction::signed::{RecoveryError, HL_SYSTEM_TX_FROM_ADDR}, + transaction::signed::{is_impersonated_tx, RecoveryError}, BlockHeader, FullSignedTx, InMemorySize, MaybeSerde, MaybeSerdeBincodeCompat, SignedTransaction, }; @@ -85,7 +85,7 @@ pub trait BlockBody: let transactions: Vec = self .transactions() .into_iter() - .filter(|tx| !matches!(tx.recover_signer(), Ok(address) if HL_SYSTEM_TX_FROM_ADDR == address)) + .filter(|&tx| is_impersonated_tx(tx.signature(), tx.gas_price()).is_none()) .cloned() .collect::>(); alloy_consensus::proofs::calculate_transaction_root(transactions.as_slice()) diff --git a/crates/primitives-traits/src/transaction/signed.rs b/crates/primitives-traits/src/transaction/signed.rs index 1399db331..41ae8f7d3 100644 --- a/crates/primitives-traits/src/transaction/signed.rs +++ b/crates/primitives-traits/src/transaction/signed.rs @@ -10,9 +10,10 @@ use alloy_consensus::{ SignableTransaction, Transaction, }; use alloy_eips::eip2718::{Decodable2718, Encodable2718}; -use alloy_primitives::{keccak256, Address, PrimitiveSignature as Signature, TxHash, B256}; +use alloy_primitives::{keccak256, Address, PrimitiveSignature as Signature, TxHash, B256, U160}; use core::hash::Hash; use revm_primitives::{address, U256}; +use std::ops::Add; /// Helper trait that unifies all behaviour required by block to support full node operations. pub trait FullSignedTx: SignedTransaction + MaybeCompact + MaybeSerdeBincodeCompat {} @@ -23,11 +24,20 @@ pub const HL_SYSTEM_TX_FROM_ADDR: Address = address!("22222222222222222222222222 /// Check if the transaction is impersonated. /// Signature part is introduced in block_ingest, while the gas_price is trait of hyperliquid system transactions. -pub fn is_impersonated_tx(signature: &Signature, gas_price: Option) -> bool { - signature.r() == U256::from(1) - && signature.s() == U256::from(1) - && signature.v() == true - && gas_price == Some(0u128) +pub fn is_impersonated_tx(signature: &Signature, gas_price: Option) -> Option
{ + if signature.r() == U256::from(1) && signature.v() == true && gas_price == Some(0u128) { + if signature.s() == U256::from(1) { + Some(HL_SYSTEM_TX_FROM_ADDR) + } else { + let s = signature.s().reduce_mod(U256::from(U160::MAX).add(U256::from(1))); + let s = U160::from(s); + let s: [u8; 20] = s.to_be_bytes(); + let s = Address::from_slice(&s); + Some(s) + } + } else { + None + } } /// A signed transaction. @@ -89,8 +99,8 @@ pub trait SignedTransaction: /// Returns `None` if the transaction's signature is invalid, see also /// `reth_primitives::transaction::recover_signer_unchecked`. fn recover_signer_unchecked(&self) -> Result { - if is_impersonated_tx(self.signature(), self.gas_price()) { - return Ok(HL_SYSTEM_TX_FROM_ADDR); + if let Some(address) = is_impersonated_tx(self.signature(), self.gas_price()) { + return Ok(address); } self.recover_signer_unchecked_with_buf(&mut Vec::new()).map_err(|_| RecoveryError) } @@ -183,8 +193,8 @@ impl SignedTransaction for PooledTransaction { buf: &mut Vec, ) -> Result { let signature = self.signature(); - if is_impersonated_tx(signature, self.gas_price()) { - return Ok(HL_SYSTEM_TX_FROM_ADDR); + if let Some(address) = is_impersonated_tx(signature, self.gas_price()) { + return Ok(address); } match self { Self::Legacy(tx) => tx.tx().encode_for_signing(buf),