feat: Custom TransactionSigned

Like OpTransactionSigned, introduce a new tx type. Not a trivial change but might be beneficial for potential system tx changes e.g., in case it's separated into another tx type
This commit is contained in:
sprites0
2025-06-27 06:32:39 +00:00
parent b702f3c480
commit 2c6e989ad0
20 changed files with 1102 additions and 198 deletions

View File

@ -3,7 +3,11 @@ use crate::{
chainspec::HlChainSpec,
evm::{spec::HlSpecId, transaction::HlTxEnv},
hardforks::HlHardforks,
node::{evm::executor::is_system_transaction, types::ReadPrecompileMap},
node::{
evm::{executor::is_system_transaction, receipt_builder::RethReceiptBuilder},
primitives::{BlockBody, TransactionSigned},
types::ReadPrecompileMap,
},
HlBlock, HlBlockBody, HlPrimitives,
};
use alloy_consensus::{BlockHeader, Header, Transaction as _, TxReceipt, EMPTY_OMMER_ROOT_HASH};
@ -11,7 +15,6 @@ use alloy_eips::merge::BEACON_NONCE;
use alloy_primitives::{Log, U256};
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
use reth_ethereum_forks::EthereumHardfork;
use reth_ethereum_primitives::BlockBody;
use reth_evm::{
block::{BlockExecutionError, BlockExecutorFactory, BlockExecutorFor},
eth::{receipt_builder::ReceiptBuilder, EthBlockExecutionCtx},
@ -20,10 +23,8 @@ use reth_evm::{
ConfigureEvm, EvmEnv, EvmFactory, ExecutionCtxFor, FromRecoveredTx, FromTxWithEncoded,
IntoTxEnv, NextBlockEnvAttributes,
};
use reth_evm_ethereum::{EthBlockAssembler, RethReceiptBuilder};
use reth_primitives::{
logs_bloom, BlockTy, HeaderTy, Receipt, SealedBlock, SealedHeader, TransactionSigned,
};
use reth_evm_ethereum::EthBlockAssembler;
use reth_primitives::{logs_bloom, BlockTy, HeaderTy, Receipt, SealedBlock, SealedHeader};
use reth_primitives_traits::proofs;
use reth_provider::BlockExecutionResult;
use reth_revm::State;

View File

@ -2,7 +2,10 @@ use super::{config::HlBlockExecutionCtx, patch::patch_mainnet_after_tx};
use crate::{
evm::transaction::HlTxEnv,
hardforks::HlHardforks,
node::types::{ReadPrecompileInput, ReadPrecompileResult},
node::{
primitives::TransactionSigned,
types::{ReadPrecompileInput, ReadPrecompileResult},
},
};
use alloy_consensus::{Transaction, TxReceipt};
use alloy_eips::{eip7685::Requests, Encodable2718};
@ -16,7 +19,6 @@ use reth_evm::{
precompiles::{DynPrecompile, PrecompilesMap},
Database, Evm, FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, OnStateHook, RecoveredTx,
};
use reth_primitives::TransactionSigned;
use reth_provider::BlockExecutionResult;
use reth_revm::State;
use revm::{
@ -98,23 +100,7 @@ where
{
/// Creates a new HlBlockExecutor.
pub fn new(mut evm: EVM, ctx: HlBlockExecutionCtx<'a>, spec: Spec, receipt_builder: R) -> Self {
let precompiles_mut = evm.precompiles_mut();
// For all precompile addresses just in case it's populated and not cleared
// Clear 0x00...08xx addresses
let addresses = precompiles_mut.addresses().cloned().collect::<Vec<_>>();
for address in addresses {
if address.starts_with(&[0u8; 18]) && address[19] == 8 {
precompiles_mut.apply_precompile(&address, |_| None);
}
}
for (address, precompile) in ctx.read_precompile_calls.iter() {
let precompile = precompile.clone();
precompiles_mut.apply_precompile(address, |_| {
Some(DynPrecompile::from(move |data: &[u8], gas: u64| {
run_precompile(&precompile, data, gas)
}))
});
}
apply_precompiles(&mut evm, &ctx);
Self { spec, evm, gas_used: 0, receipts: vec![], receipt_builder, ctx }
}
}
@ -127,6 +113,7 @@ where
Tx: FromRecoveredTx<R::Transaction>
+ FromRecoveredTx<TransactionSigned>
+ FromTxWithEncoded<TransactionSigned>,
Precompiles = PrecompilesMap,
>,
Spec: EthereumHardforks + HlHardforks + EthChainSpec + Hardforks,
R: ReceiptBuilder<Transaction = TransactionSigned, Receipt: TxReceipt>,
@ -140,6 +127,7 @@ where
type Evm = E;
fn apply_pre_execution_changes(&mut self) -> Result<(), BlockExecutionError> {
apply_precompiles(&mut self.evm, &self.ctx);
Ok(())
}
@ -223,3 +211,27 @@ where
&self.evm
}
}
fn apply_precompiles<'a, DB, EVM>(evm: &mut EVM, ctx: &HlBlockExecutionCtx<'a>)
where
EVM: Evm<DB = &'a mut State<DB>, Precompiles = PrecompilesMap>,
DB: Database + 'a,
{
let precompiles_mut = evm.precompiles_mut();
// For all precompile addresses just in case it's populated and not cleared
// Clear 0x00...08xx addresses
let addresses = precompiles_mut.addresses().cloned().collect::<Vec<_>>();
for address in addresses {
if address.starts_with(&[0u8; 18]) && address[19] == 8 {
precompiles_mut.apply_precompile(&address, |_| None);
}
}
for (address, precompile) in ctx.read_precompile_calls.iter() {
let precompile = precompile.clone();
precompiles_mut.apply_precompile(address, |_| {
Some(DynPrecompile::from(move |data: &[u8], gas: u64| {
run_precompile(&precompile, data, gas)
}))
});
}
}

View File

@ -29,6 +29,7 @@ pub mod config;
mod executor;
mod factory;
mod patch;
pub mod receipt_builder;
/// HL EVM implementation.
///

View File

@ -0,0 +1,30 @@
use crate::node::primitives::TransactionSigned;
use alloy_evm::eth::receipt_builder::{ReceiptBuilder, ReceiptBuilderCtx};
use reth_evm::Evm;
use reth_primitives::Receipt;
/// A builder that operates on Reth primitive types, specifically [`TransactionSigned`] and
/// [`Receipt`].
#[derive(Debug, Clone, Copy, Default)]
#[non_exhaustive]
pub struct RethReceiptBuilder;
impl ReceiptBuilder for RethReceiptBuilder {
type Transaction = TransactionSigned;
type Receipt = Receipt;
fn build_receipt<E: Evm>(
&self,
ctx: ReceiptBuilderCtx<'_, Self::Transaction, E>,
) -> Self::Receipt {
let ReceiptBuilderCtx { tx, result, cumulative_gas_used, .. } = ctx;
Receipt {
tx_type: tx.tx_type(),
// Success flag was added in `EIP-658: Embedding transaction status code in
// receipts`.
success: result.is_success(),
cumulative_gas_used,
logs: result.into_logs(),
}
}
}