feat: Support read precompiles

This commit is contained in:
sprites0
2025-06-23 22:48:47 +00:00
parent fa66c97f57
commit b525f47218
2 changed files with 68 additions and 7 deletions

View File

@ -16,6 +16,7 @@ use reth_evm::{
block::{BlockExecutionError, BlockExecutorFactory, BlockExecutorFor}, block::{BlockExecutionError, BlockExecutorFactory, BlockExecutorFor},
eth::{receipt_builder::ReceiptBuilder, EthBlockExecutionCtx}, eth::{receipt_builder::ReceiptBuilder, EthBlockExecutionCtx},
execute::{BlockAssembler, BlockAssemblerInput}, execute::{BlockAssembler, BlockAssemblerInput},
precompiles::PrecompilesMap,
ConfigureEvm, EvmEnv, EvmFactory, ExecutionCtxFor, FromRecoveredTx, FromTxWithEncoded, ConfigureEvm, EvmEnv, EvmFactory, ExecutionCtxFor, FromRecoveredTx, FromTxWithEncoded,
IntoTxEnv, NextBlockEnvAttributes, IntoTxEnv, NextBlockEnvAttributes,
}; };
@ -260,14 +261,17 @@ impl<R, Spec, EvmFactory> HlBlockExecutorFactory<R, Spec, EvmFactory> {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct HlBlockExecutionCtx<'a> { pub struct HlBlockExecutionCtx<'a> {
ctx: EthBlockExecutionCtx<'a>, ctx: EthBlockExecutionCtx<'a>,
read_precompile_calls: ReadPrecompileMap, pub read_precompile_calls: ReadPrecompileMap,
} }
impl<R, Spec, EvmF> BlockExecutorFactory for HlBlockExecutorFactory<R, Spec, EvmF> impl<R, Spec, EvmF> BlockExecutorFactory for HlBlockExecutorFactory<R, Spec, EvmF>
where where
R: ReceiptBuilder<Transaction = TransactionSigned, Receipt: TxReceipt<Log = Log>>, R: ReceiptBuilder<Transaction = TransactionSigned, Receipt: TxReceipt<Log = Log>>,
Spec: EthereumHardforks + HlHardforks + EthChainSpec + Hardforks + Clone, Spec: EthereumHardforks + HlHardforks + EthChainSpec + Hardforks + Clone,
EvmF: EvmFactory<Tx: FromRecoveredTx<TransactionSigned> + FromTxWithEncoded<TransactionSigned>>, EvmF: EvmFactory<
Tx: FromRecoveredTx<TransactionSigned> + FromTxWithEncoded<TransactionSigned>,
Precompiles = PrecompilesMap,
>,
R::Transaction: From<TransactionSigned> + Clone, R::Transaction: From<TransactionSigned> + Clone,
Self: 'static, Self: 'static,
HlTxEnv<TxEnv>: IntoTxEnv<<EvmF as EvmFactory>::Tx>, HlTxEnv<TxEnv>: IntoTxEnv<<EvmF as EvmFactory>::Tx>,

View File

@ -1,14 +1,20 @@
use super::config::HlBlockExecutionCtx; use super::config::HlBlockExecutionCtx;
use super::patch::patch_mainnet_after_tx; use super::patch::patch_mainnet_after_tx;
use crate::{evm::transaction::HlTxEnv, hardforks::HlHardforks, node::types::ReadPrecompileCalls}; use crate::{
evm::transaction::HlTxEnv,
hardforks::HlHardforks,
node::types::{ReadPrecompileCalls, ReadPrecompileInput, ReadPrecompileResult},
};
use alloy_consensus::{Transaction, TxReceipt}; use alloy_consensus::{Transaction, TxReceipt};
use alloy_eips::{eip7685::Requests, Encodable2718}; use alloy_eips::{eip7685::Requests, Encodable2718};
use alloy_evm::{block::ExecutableTx, eth::receipt_builder::ReceiptBuilderCtx}; use alloy_evm::{block::ExecutableTx, eth::receipt_builder::ReceiptBuilderCtx};
use alloy_primitives::Bytes;
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks}; use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
use reth_evm::{ use reth_evm::{
block::{BlockValidationError, CommitChanges}, block::{BlockValidationError, CommitChanges},
eth::receipt_builder::ReceiptBuilder, eth::receipt_builder::ReceiptBuilder,
execute::{BlockExecutionError, BlockExecutor}, execute::{BlockExecutionError, BlockExecutor},
precompiles::{DynPrecompile, PrecompilesMap},
Database, Evm, FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, OnStateHook, RecoveredTx, Database, Evm, FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, OnStateHook, RecoveredTx,
}; };
use reth_primitives::TransactionSigned; use reth_primitives::TransactionSigned;
@ -18,8 +24,7 @@ use revm::{
context::{ context::{
result::{ExecutionResult, ResultAndState}, result::{ExecutionResult, ResultAndState},
TxEnv, TxEnv,
}, }, precompile::{PrecompileError, PrecompileOutput, PrecompileResult}, primitives::HashMap, DatabaseCommit
DatabaseCommit,
}; };
pub fn is_system_transaction(tx: &TransactionSigned) -> bool { pub fn is_system_transaction(tx: &TransactionSigned) -> bool {
@ -51,11 +56,46 @@ where
ctx: HlBlockExecutionCtx<'a>, ctx: HlBlockExecutionCtx<'a>,
} }
fn run_precompile(
precompile_calls: &HashMap<ReadPrecompileInput, ReadPrecompileResult>,
data: &[u8],
gas_limit: u64,
) -> PrecompileResult {
let input = ReadPrecompileInput {
input: Bytes::copy_from_slice(data),
gas_limit,
};
let Some(get) = precompile_calls.get(&input) else {
return Err(PrecompileError::OutOfGas);
};
return match *get {
ReadPrecompileResult::Ok {
gas_used,
ref bytes,
} => {
Ok(PrecompileOutput {
gas_used,
bytes: bytes.clone(),
})
}
ReadPrecompileResult::OutOfGas => {
// Use all the gas passed to this precompile
Err(PrecompileError::OutOfGas)
}
ReadPrecompileResult::Error => {
Err(PrecompileError::OutOfGas)
}
ReadPrecompileResult::UnexpectedError => panic!("unexpected precompile error"),
};
}
impl<'a, DB, EVM, Spec, R: ReceiptBuilder> HlBlockExecutor<'a, EVM, Spec, R> impl<'a, DB, EVM, Spec, R: ReceiptBuilder> HlBlockExecutor<'a, EVM, Spec, R>
where where
DB: Database + 'a, DB: Database + 'a,
EVM: Evm< EVM: Evm<
DB = &'a mut State<DB>, DB = &'a mut State<DB>,
Precompiles = PrecompilesMap,
Tx: FromRecoveredTx<R::Transaction> Tx: FromRecoveredTx<R::Transaction>
+ FromRecoveredTx<TransactionSigned> + FromRecoveredTx<TransactionSigned>
+ FromTxWithEncoded<TransactionSigned>, + FromTxWithEncoded<TransactionSigned>,
@ -68,14 +108,31 @@ where
R::Transaction: Into<TransactionSigned>, R::Transaction: Into<TransactionSigned>,
{ {
/// Creates a new HlBlockExecutor. /// Creates a new HlBlockExecutor.
pub fn new(evm: EVM, ctx: HlBlockExecutionCtx<'a>, spec: Spec, receipt_builder: R) -> Self { 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)
}))
});
}
Self { Self {
spec, spec,
evm, evm,
gas_used: 0, gas_used: 0,
receipts: vec![], receipts: vec![],
system_txs: vec![], system_txs: vec![],
read_precompile_calls: ReadPrecompileCalls::default(), read_precompile_calls: ctx.read_precompile_calls.clone().into(),
receipt_builder, receipt_builder,
// system_contracts, // system_contracts,
ctx, ctx,