mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: Support read precompiles
This commit is contained in:
@ -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>,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user