mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
precompile attempt
This commit is contained in:
@ -1,5 +1,12 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
|
use crate::node::types::ReadPrecompileResult;
|
||||||
|
use crate::node::types::{ReadPrecompileInput, ReadPrecompileMap};
|
||||||
|
use revm::interpreter::{Gas, InstructionResult};
|
||||||
|
use revm::precompile::PrecompileError;
|
||||||
|
use revm::precompile::PrecompileOutput;
|
||||||
|
use revm::primitives::Bytes;
|
||||||
|
|
||||||
use super::spec::HlSpecId;
|
use super::spec::HlSpecId;
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use once_cell::{race::OnceBox, sync::Lazy};
|
use once_cell::{race::OnceBox, sync::Lazy};
|
||||||
@ -18,15 +25,23 @@ use std::boxed::Box;
|
|||||||
pub struct HlPrecompiles {
|
pub struct HlPrecompiles {
|
||||||
/// Inner precompile provider is same as Ethereums.
|
/// Inner precompile provider is same as Ethereums.
|
||||||
inner: EthPrecompiles,
|
inner: EthPrecompiles,
|
||||||
|
/// Precompile calls
|
||||||
|
precompile_calls: ReadPrecompileMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HlPrecompiles {
|
impl HlPrecompiles {
|
||||||
/// Create a new precompile provider with the given hl spec.
|
/// Create a new precompile provider with the given hl spec.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(spec: HlSpecId) -> Self {
|
pub fn new(spec: HlSpecId, precompile_calls: ReadPrecompileMap) -> Self {
|
||||||
let precompiles = cancun();
|
let precompiles = cancun();
|
||||||
|
|
||||||
Self { inner: EthPrecompiles { precompiles, spec: spec.into_eth_spec() } }
|
Self {
|
||||||
|
inner: EthPrecompiles {
|
||||||
|
precompiles,
|
||||||
|
spec: spec.into_eth_spec(),
|
||||||
|
},
|
||||||
|
precompile_calls,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -53,7 +68,7 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set_spec(&mut self, spec: <CTX::Cfg as Cfg>::Spec) -> bool {
|
fn set_spec(&mut self, spec: <CTX::Cfg as Cfg>::Spec) -> bool {
|
||||||
*self = Self::new(spec);
|
*self = Self::new(spec, self.precompile_calls.clone());
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +81,51 @@ where
|
|||||||
is_static: bool,
|
is_static: bool,
|
||||||
gas_limit: u64,
|
gas_limit: u64,
|
||||||
) -> Result<Option<Self::Output>, String> {
|
) -> Result<Option<Self::Output>, String> {
|
||||||
self.inner.run(context, address, inputs, is_static, gas_limit)
|
let Some(precompile_calls) = self.precompile_calls.get(address) else {
|
||||||
|
return self
|
||||||
|
.inner
|
||||||
|
.run(context, address, inputs, is_static, gas_limit);
|
||||||
|
};
|
||||||
|
|
||||||
|
let input = ReadPrecompileInput {
|
||||||
|
input: inputs.input.bytes(context),
|
||||||
|
gas_limit,
|
||||||
|
};
|
||||||
|
let mut result = InterpreterResult {
|
||||||
|
result: InstructionResult::Return,
|
||||||
|
gas: Gas::new(gas_limit),
|
||||||
|
output: Bytes::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(get) = precompile_calls.get(&input) else {
|
||||||
|
result.gas.spend_all();
|
||||||
|
result.result = InstructionResult::PrecompileError;
|
||||||
|
return Ok(Some(result));
|
||||||
|
};
|
||||||
|
|
||||||
|
return match *get {
|
||||||
|
ReadPrecompileResult::Ok {
|
||||||
|
gas_used,
|
||||||
|
ref bytes,
|
||||||
|
} => {
|
||||||
|
let underflow = result.gas.record_cost(gas_used);
|
||||||
|
assert!(underflow, "Gas underflow is not possible");
|
||||||
|
result.output = bytes.clone();
|
||||||
|
Ok(Some(result))
|
||||||
|
}
|
||||||
|
ReadPrecompileResult::OutOfGas => {
|
||||||
|
// Use all the gas passed to this precompile
|
||||||
|
result.gas.spend_all();
|
||||||
|
result.result = InstructionResult::OutOfGas;
|
||||||
|
Ok(Some(result))
|
||||||
|
}
|
||||||
|
ReadPrecompileResult::Error => {
|
||||||
|
result.gas.spend_all();
|
||||||
|
result.result = InstructionResult::PrecompileError;
|
||||||
|
Ok(Some(result))
|
||||||
|
}
|
||||||
|
ReadPrecompileResult::UnexpectedError => panic!("unexpected precompile error"),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -82,6 +141,6 @@ where
|
|||||||
|
|
||||||
impl Default for HlPrecompiles {
|
impl Default for HlPrecompiles {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(HlSpecId::default())
|
Self::new(HlSpecId::default(), ReadPrecompileMap::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,18 +15,7 @@ impl BlockAssembler<HlBlockExecutorFactory> for HlEvmConfig {
|
|||||||
&self,
|
&self,
|
||||||
input: BlockAssemblerInput<'_, '_, HlBlockExecutorFactory, Header>,
|
input: BlockAssemblerInput<'_, '_, HlBlockExecutorFactory, Header>,
|
||||||
) -> Result<Self::Block, BlockExecutionError> {
|
) -> Result<Self::Block, BlockExecutionError> {
|
||||||
let Block { header, body: inner } = self.block_assembler.assemble_block(input)?;
|
let HlBlock { header, body } = self.block_assembler.assemble_block(input)?;
|
||||||
Ok(HlBlock {
|
Ok(HlBlock { header, body })
|
||||||
header,
|
|
||||||
body: HlBlockBody {
|
|
||||||
inner,
|
|
||||||
// HACK: we're setting sidecars to `None` here but ideally we should somehow get
|
|
||||||
// them from the payload builder.
|
|
||||||
//
|
|
||||||
// Payload building is out of scope of reth-bsc for now, so this is not critical
|
|
||||||
sidecars: None,
|
|
||||||
read_precompile_calls: None,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,20 +3,28 @@ use crate::{
|
|||||||
chainspec::HlChainSpec,
|
chainspec::HlChainSpec,
|
||||||
evm::{spec::HlSpecId, transaction::HlTxEnv},
|
evm::{spec::HlSpecId, transaction::HlTxEnv},
|
||||||
hardforks::HlHardforks,
|
hardforks::HlHardforks,
|
||||||
HlPrimitives,
|
node::types::ReadPrecompileMap,
|
||||||
|
HlBlock, HlBlockBody, HlPrimitives,
|
||||||
};
|
};
|
||||||
use alloy_consensus::{BlockHeader, Header, TxReceipt};
|
use alloy_consensus::{BlockHeader, Header, Transaction as _, TxReceipt, EMPTY_OMMER_ROOT_HASH};
|
||||||
|
use alloy_eips::merge::BEACON_NONCE;
|
||||||
use alloy_primitives::{Log, U256};
|
use alloy_primitives::{Log, U256};
|
||||||
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
|
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
|
||||||
use reth_ethereum_forks::EthereumHardfork;
|
use reth_ethereum_forks::EthereumHardfork;
|
||||||
|
use reth_ethereum_primitives::BlockBody;
|
||||||
use reth_evm::{
|
use reth_evm::{
|
||||||
block::{BlockExecutorFactory, BlockExecutorFor},
|
block::{BlockExecutionError, BlockExecutorFactory, BlockExecutorFor},
|
||||||
eth::{receipt_builder::ReceiptBuilder, EthBlockExecutionCtx},
|
eth::{receipt_builder::ReceiptBuilder, EthBlockExecutionCtx},
|
||||||
|
execute::{BlockAssembler, BlockAssemblerInput},
|
||||||
ConfigureEvm, EvmEnv, EvmFactory, ExecutionCtxFor, FromRecoveredTx, FromTxWithEncoded,
|
ConfigureEvm, EvmEnv, EvmFactory, ExecutionCtxFor, FromRecoveredTx, FromTxWithEncoded,
|
||||||
IntoTxEnv, NextBlockEnvAttributes,
|
IntoTxEnv, NextBlockEnvAttributes,
|
||||||
};
|
};
|
||||||
use reth_evm_ethereum::{EthBlockAssembler, RethReceiptBuilder};
|
use reth_evm_ethereum::{EthBlockAssembler, RethReceiptBuilder};
|
||||||
use reth_primitives::{BlockTy, HeaderTy, SealedBlock, SealedHeader, TransactionSigned};
|
use reth_primitives::{
|
||||||
|
logs_bloom, BlockTy, HeaderTy, Receipt, SealedBlock, SealedHeader, TransactionSigned,
|
||||||
|
};
|
||||||
|
use reth_primitives_traits::proofs;
|
||||||
|
use reth_provider::BlockExecutionResult;
|
||||||
use reth_revm::State;
|
use reth_revm::State;
|
||||||
use revm::{
|
use revm::{
|
||||||
context::{BlockEnv, CfgEnv, TxEnv},
|
context::{BlockEnv, CfgEnv, TxEnv},
|
||||||
@ -26,6 +34,139 @@ use revm::{
|
|||||||
};
|
};
|
||||||
use std::{borrow::Cow, convert::Infallible, sync::Arc};
|
use std::{borrow::Cow, convert::Infallible, sync::Arc};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct HlBlockAssembler {
|
||||||
|
inner: EthBlockAssembler<HlChainSpec>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> BlockAssembler<F> for HlBlockAssembler
|
||||||
|
where
|
||||||
|
F: for<'a> BlockExecutorFactory<
|
||||||
|
ExecutionCtx<'a> = HlBlockExecutionCtx<'a>,
|
||||||
|
Transaction = TransactionSigned,
|
||||||
|
Receipt = Receipt,
|
||||||
|
>,
|
||||||
|
{
|
||||||
|
type Block = HlBlock;
|
||||||
|
|
||||||
|
fn assemble_block(
|
||||||
|
&self,
|
||||||
|
input: BlockAssemblerInput<'_, '_, F>,
|
||||||
|
) -> Result<Self::Block, BlockExecutionError> {
|
||||||
|
// TODO: Copy of EthBlockAssembler::assemble_block
|
||||||
|
let inner = &self.inner;
|
||||||
|
let BlockAssemblerInput {
|
||||||
|
evm_env,
|
||||||
|
execution_ctx: ctx,
|
||||||
|
parent,
|
||||||
|
transactions,
|
||||||
|
output:
|
||||||
|
BlockExecutionResult {
|
||||||
|
receipts,
|
||||||
|
requests,
|
||||||
|
gas_used,
|
||||||
|
},
|
||||||
|
state_root,
|
||||||
|
..
|
||||||
|
} = input;
|
||||||
|
|
||||||
|
let timestamp = evm_env.block_env.timestamp;
|
||||||
|
|
||||||
|
let transactions_root = proofs::calculate_transaction_root(&transactions);
|
||||||
|
let receipts_root = Receipt::calculate_receipt_root_no_memo(receipts);
|
||||||
|
let logs_bloom = logs_bloom(receipts.iter().flat_map(|r| r.logs()));
|
||||||
|
|
||||||
|
let withdrawals = inner
|
||||||
|
.chain_spec
|
||||||
|
.is_shanghai_active_at_timestamp(timestamp)
|
||||||
|
.then(|| {
|
||||||
|
ctx.ctx
|
||||||
|
.withdrawals
|
||||||
|
.map(|w| w.into_owned())
|
||||||
|
.unwrap_or_default()
|
||||||
|
});
|
||||||
|
|
||||||
|
let withdrawals_root = withdrawals
|
||||||
|
.as_deref()
|
||||||
|
.map(|w| proofs::calculate_withdrawals_root(w));
|
||||||
|
let requests_hash = inner
|
||||||
|
.chain_spec
|
||||||
|
.is_prague_active_at_timestamp(timestamp)
|
||||||
|
.then(|| requests.requests_hash());
|
||||||
|
|
||||||
|
let mut excess_blob_gas = None;
|
||||||
|
let mut blob_gas_used = None;
|
||||||
|
|
||||||
|
// only determine cancun fields when active
|
||||||
|
if inner.chain_spec.is_cancun_active_at_timestamp(timestamp) {
|
||||||
|
blob_gas_used = Some(
|
||||||
|
transactions
|
||||||
|
.iter()
|
||||||
|
.map(|tx| tx.blob_gas_used().unwrap_or_default())
|
||||||
|
.sum(),
|
||||||
|
);
|
||||||
|
excess_blob_gas = if inner
|
||||||
|
.chain_spec
|
||||||
|
.is_cancun_active_at_timestamp(parent.timestamp)
|
||||||
|
{
|
||||||
|
parent.maybe_next_block_excess_blob_gas(
|
||||||
|
inner.chain_spec.blob_params_at_timestamp(timestamp),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// for the first post-fork block, both parent.blob_gas_used and
|
||||||
|
// parent.excess_blob_gas are evaluated as 0
|
||||||
|
Some(alloy_eips::eip7840::BlobParams::cancun().next_block_excess_blob_gas(0, 0))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let header = Header {
|
||||||
|
parent_hash: ctx.ctx.parent_hash,
|
||||||
|
ommers_hash: EMPTY_OMMER_ROOT_HASH,
|
||||||
|
beneficiary: evm_env.block_env.beneficiary,
|
||||||
|
state_root,
|
||||||
|
transactions_root,
|
||||||
|
receipts_root,
|
||||||
|
withdrawals_root,
|
||||||
|
logs_bloom,
|
||||||
|
timestamp,
|
||||||
|
mix_hash: evm_env.block_env.prevrandao.unwrap_or_default(),
|
||||||
|
nonce: BEACON_NONCE.into(),
|
||||||
|
base_fee_per_gas: Some(evm_env.block_env.basefee),
|
||||||
|
number: evm_env.block_env.number,
|
||||||
|
gas_limit: evm_env.block_env.gas_limit,
|
||||||
|
difficulty: evm_env.block_env.difficulty,
|
||||||
|
gas_used: *gas_used,
|
||||||
|
extra_data: inner.extra_data.clone(),
|
||||||
|
parent_beacon_block_root: ctx.ctx.parent_beacon_block_root,
|
||||||
|
blob_gas_used,
|
||||||
|
excess_blob_gas,
|
||||||
|
requests_hash,
|
||||||
|
};
|
||||||
|
|
||||||
|
let read_precompile_calls = ctx.read_precompile_calls.clone().into();
|
||||||
|
Ok(Self::Block {
|
||||||
|
header,
|
||||||
|
body: HlBlockBody {
|
||||||
|
inner: BlockBody {
|
||||||
|
transactions,
|
||||||
|
ommers: Default::default(),
|
||||||
|
withdrawals,
|
||||||
|
},
|
||||||
|
sidecars: None,
|
||||||
|
read_precompile_calls: Some(read_precompile_calls),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HlBlockAssembler {
|
||||||
|
pub fn new(chain_spec: Arc<HlChainSpec>) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: EthBlockAssembler::new(chain_spec),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Ethereum-related EVM configuration.
|
/// Ethereum-related EVM configuration.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct HlEvmConfig {
|
pub struct HlEvmConfig {
|
||||||
@ -33,7 +174,7 @@ pub struct HlEvmConfig {
|
|||||||
pub executor_factory:
|
pub executor_factory:
|
||||||
HlBlockExecutorFactory<RethReceiptBuilder, Arc<HlChainSpec>, HlEvmFactory>,
|
HlBlockExecutorFactory<RethReceiptBuilder, Arc<HlChainSpec>, HlEvmFactory>,
|
||||||
/// Ethereum block assembler.
|
/// Ethereum block assembler.
|
||||||
pub block_assembler: EthBlockAssembler<HlChainSpec>,
|
pub block_assembler: HlBlockAssembler,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HlEvmConfig {
|
impl HlEvmConfig {
|
||||||
@ -52,7 +193,7 @@ impl HlEvmConfig {
|
|||||||
/// Creates a new Ethereum EVM configuration with the given chain spec and EVM factory.
|
/// Creates a new Ethereum EVM configuration with the given chain spec and EVM factory.
|
||||||
pub fn new_with_evm_factory(chain_spec: Arc<HlChainSpec>, evm_factory: HlEvmFactory) -> Self {
|
pub fn new_with_evm_factory(chain_spec: Arc<HlChainSpec>, evm_factory: HlEvmFactory) -> Self {
|
||||||
Self {
|
Self {
|
||||||
block_assembler: EthBlockAssembler::new(chain_spec.clone()),
|
block_assembler: HlBlockAssembler::new(chain_spec.clone()),
|
||||||
executor_factory: HlBlockExecutorFactory::new(
|
executor_factory: HlBlockExecutorFactory::new(
|
||||||
RethReceiptBuilder::default(),
|
RethReceiptBuilder::default(),
|
||||||
chain_spec,
|
chain_spec,
|
||||||
@ -104,6 +245,12 @@ impl<R, Spec, EvmFactory> HlBlockExecutorFactory<R, Spec, EvmFactory> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct HlBlockExecutionCtx<'a> {
|
||||||
|
ctx: EthBlockExecutionCtx<'a>,
|
||||||
|
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>>,
|
||||||
@ -114,7 +261,7 @@ where
|
|||||||
HlTxEnv<TxEnv>: IntoTxEnv<<EvmF as EvmFactory>::Tx>,
|
HlTxEnv<TxEnv>: IntoTxEnv<<EvmF as EvmFactory>::Tx>,
|
||||||
{
|
{
|
||||||
type EvmFactory = EvmF;
|
type EvmFactory = EvmF;
|
||||||
type ExecutionCtx<'a> = EthBlockExecutionCtx<'a>;
|
type ExecutionCtx<'a> = HlBlockExecutionCtx<'a>;
|
||||||
type Transaction = TransactionSigned;
|
type Transaction = TransactionSigned;
|
||||||
type Receipt = R::Receipt;
|
type Receipt = R::Receipt;
|
||||||
|
|
||||||
@ -284,11 +431,18 @@ where
|
|||||||
&self,
|
&self,
|
||||||
block: &'a SealedBlock<BlockTy<Self::Primitives>>,
|
block: &'a SealedBlock<BlockTy<Self::Primitives>>,
|
||||||
) -> ExecutionCtxFor<'a, Self> {
|
) -> ExecutionCtxFor<'a, Self> {
|
||||||
EthBlockExecutionCtx {
|
HlBlockExecutionCtx {
|
||||||
parent_hash: block.header().parent_hash,
|
ctx: EthBlockExecutionCtx {
|
||||||
parent_beacon_block_root: block.header().parent_beacon_block_root,
|
parent_hash: block.header().parent_hash,
|
||||||
ommers: &block.body().ommers,
|
parent_beacon_block_root: block.header().parent_beacon_block_root,
|
||||||
withdrawals: block.body().withdrawals.as_ref().map(Cow::Borrowed),
|
ommers: &block.body().ommers,
|
||||||
|
withdrawals: block.body().withdrawals.as_ref().map(Cow::Borrowed),
|
||||||
|
},
|
||||||
|
read_precompile_calls: block
|
||||||
|
.body()
|
||||||
|
.read_precompile_calls
|
||||||
|
.clone()
|
||||||
|
.map_or(ReadPrecompileMap::default(), |calls| calls.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,11 +451,15 @@ where
|
|||||||
parent: &SealedHeader<HeaderTy<Self::Primitives>>,
|
parent: &SealedHeader<HeaderTy<Self::Primitives>>,
|
||||||
attributes: Self::NextBlockEnvCtx,
|
attributes: Self::NextBlockEnvCtx,
|
||||||
) -> ExecutionCtxFor<'_, Self> {
|
) -> ExecutionCtxFor<'_, Self> {
|
||||||
EthBlockExecutionCtx {
|
HlBlockExecutionCtx {
|
||||||
parent_hash: parent.hash(),
|
ctx: EthBlockExecutionCtx {
|
||||||
parent_beacon_block_root: attributes.parent_beacon_block_root,
|
parent_hash: parent.hash(),
|
||||||
ommers: &[],
|
parent_beacon_block_root: attributes.parent_beacon_block_root,
|
||||||
withdrawals: attributes.withdrawals.map(Cow::Owned),
|
ommers: &[],
|
||||||
|
withdrawals: attributes.withdrawals.map(Cow::Owned),
|
||||||
|
},
|
||||||
|
// TODO: hacky, double check if this is correct
|
||||||
|
read_precompile_calls: ReadPrecompileMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
|
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};
|
use crate::{evm::transaction::HlTxEnv, hardforks::HlHardforks, node::types::ReadPrecompileCalls};
|
||||||
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::Address;
|
|
||||||
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, EthBlockExecutionCtx},
|
eth::receipt_builder::ReceiptBuilder,
|
||||||
execute::{BlockExecutionError, BlockExecutor},
|
execute::{BlockExecutionError, BlockExecutor},
|
||||||
Database, Evm, FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, OnStateHook, RecoveredTx,
|
Database, Evm, FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, OnStateHook, RecoveredTx,
|
||||||
};
|
};
|
||||||
@ -19,8 +19,7 @@ use revm::{
|
|||||||
result::{ExecutionResult, ResultAndState},
|
result::{ExecutionResult, ResultAndState},
|
||||||
TxEnv,
|
TxEnv,
|
||||||
},
|
},
|
||||||
state::Bytecode,
|
DatabaseCommit,
|
||||||
Database as _, DatabaseCommit,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn is_system_transaction(tx: &TransactionSigned) -> bool {
|
fn is_system_transaction(tx: &TransactionSigned) -> bool {
|
||||||
@ -44,12 +43,12 @@ where
|
|||||||
receipts: Vec<R::Receipt>,
|
receipts: Vec<R::Receipt>,
|
||||||
/// System txs
|
/// System txs
|
||||||
system_txs: Vec<R::Transaction>,
|
system_txs: Vec<R::Transaction>,
|
||||||
|
/// Read precompile calls
|
||||||
|
read_precompile_calls: ReadPrecompileCalls,
|
||||||
/// Receipt builder.
|
/// Receipt builder.
|
||||||
receipt_builder: R,
|
receipt_builder: R,
|
||||||
/// System contracts used to trigger fork specific logic.
|
|
||||||
// system_contracts: SystemContract<Spec>,
|
|
||||||
/// Context for block execution.
|
/// Context for block execution.
|
||||||
_ctx: EthBlockExecutionCtx<'a>,
|
ctx: HlBlockExecutionCtx<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, DB, EVM, Spec, R: ReceiptBuilder> HlBlockExecutor<'a, EVM, Spec, R>
|
impl<'a, DB, EVM, Spec, R: ReceiptBuilder> HlBlockExecutor<'a, EVM, Spec, R>
|
||||||
@ -69,33 +68,19 @@ where
|
|||||||
R::Transaction: Into<TransactionSigned>,
|
R::Transaction: Into<TransactionSigned>,
|
||||||
{
|
{
|
||||||
/// Creates a new HlBlockExecutor.
|
/// Creates a new HlBlockExecutor.
|
||||||
pub fn new(
|
pub fn new(evm: EVM, ctx: HlBlockExecutionCtx<'a>, spec: Spec, receipt_builder: R) -> Self {
|
||||||
evm: EVM,
|
|
||||||
_ctx: EthBlockExecutionCtx<'a>,
|
|
||||||
spec: Spec,
|
|
||||||
receipt_builder: R,
|
|
||||||
// system_contracts: SystemContract<Spec>,
|
|
||||||
) -> Self {
|
|
||||||
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(),
|
||||||
receipt_builder,
|
receipt_builder,
|
||||||
// system_contracts,
|
// system_contracts,
|
||||||
_ctx,
|
ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes the genesis contracts
|
|
||||||
fn deploy_genesis_contracts(
|
|
||||||
&mut self,
|
|
||||||
beneficiary: Address,
|
|
||||||
) -> Result<(), BlockExecutionError> {
|
|
||||||
todo!("Deploy WETH, System contract");
|
|
||||||
// Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, DB, E, Spec, R> BlockExecutor for HlBlockExecutor<'a, E, Spec, R>
|
impl<'a, DB, E, Spec, R> BlockExecutor for HlBlockExecutor<'a, E, Spec, R>
|
||||||
@ -119,11 +104,6 @@ where
|
|||||||
type Evm = E;
|
type Evm = E;
|
||||||
|
|
||||||
fn apply_pre_execution_changes(&mut self) -> Result<(), BlockExecutionError> {
|
fn apply_pre_execution_changes(&mut self) -> Result<(), BlockExecutionError> {
|
||||||
// If first block deploy genesis contracts
|
|
||||||
if self.evm.block().number == 1 {
|
|
||||||
self.deploy_genesis_contracts(self.evm.block().beneficiary)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,9 +166,7 @@ where
|
|||||||
Ok(gas_used)
|
Ok(gas_used)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(
|
fn finish(self) -> Result<(Self::Evm, BlockExecutionResult<R::Receipt>), BlockExecutionError> {
|
||||||
mut self,
|
|
||||||
) -> Result<(Self::Evm, BlockExecutionResult<R::Receipt>), BlockExecutionError> {
|
|
||||||
Ok((
|
Ok((
|
||||||
self.evm,
|
self.evm,
|
||||||
BlockExecutionResult {
|
BlockExecutionResult {
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
use super::HlEvm;
|
use super::HlEvm;
|
||||||
use crate::evm::{
|
use crate::{
|
||||||
api::{
|
evm::{
|
||||||
builder::HlBuilder,
|
api::{
|
||||||
ctx::{HlContext, DefaultHl},
|
builder::HlBuilder,
|
||||||
|
ctx::{DefaultHl, HlContext},
|
||||||
|
},
|
||||||
|
precompiles::HlPrecompiles,
|
||||||
|
spec::HlSpecId,
|
||||||
|
transaction::HlTxEnv,
|
||||||
},
|
},
|
||||||
precompiles::HlPrecompiles,
|
node::types::ReadPrecompileMap,
|
||||||
spec::HlSpecId,
|
|
||||||
transaction::HlTxEnv,
|
|
||||||
};
|
};
|
||||||
use reth_evm::{precompiles::PrecompilesMap, EvmEnv, EvmFactory};
|
use reth_evm::{precompiles::PrecompilesMap, EvmEnv, EvmFactory};
|
||||||
use reth_revm::{Context, Database};
|
use reth_revm::{Context, Database};
|
||||||
@ -39,7 +42,8 @@ impl EvmFactory for HlEvmFactory {
|
|||||||
db: DB,
|
db: DB,
|
||||||
input: EvmEnv<HlSpecId>,
|
input: EvmEnv<HlSpecId>,
|
||||||
) -> Self::Evm<DB, NoOpInspector> {
|
) -> Self::Evm<DB, NoOpInspector> {
|
||||||
let precompiles = HlPrecompiles::new(input.cfg_env.spec).precompiles();
|
let precompiles =
|
||||||
|
HlPrecompiles::new(input.cfg_env.spec, ReadPrecompileMap::default()).precompiles();
|
||||||
HlEvm {
|
HlEvm {
|
||||||
inner: Context::hl()
|
inner: Context::hl()
|
||||||
.with_block(input.block_env)
|
.with_block(input.block_env)
|
||||||
@ -60,7 +64,8 @@ impl EvmFactory for HlEvmFactory {
|
|||||||
input: EvmEnv<HlSpecId>,
|
input: EvmEnv<HlSpecId>,
|
||||||
inspector: I,
|
inspector: I,
|
||||||
) -> Self::Evm<DB, I> {
|
) -> Self::Evm<DB, I> {
|
||||||
let precompiles = HlPrecompiles::new(input.cfg_env.spec).precompiles();
|
let precompiles =
|
||||||
|
HlPrecompiles::new(input.cfg_env.spec, ReadPrecompileMap::default()).precompiles();
|
||||||
HlEvm {
|
HlEvm {
|
||||||
inner: Context::hl()
|
inner: Context::hl()
|
||||||
.with_block(input.block_env)
|
.with_block(input.block_env)
|
||||||
|
|||||||
@ -121,7 +121,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn finish(self) -> (Self::DB, EvmEnv<Self::Spec>) {
|
fn finish(self) -> (Self::DB, EvmEnv<Self::Spec>) {
|
||||||
let Context { block: block_env, cfg: cfg_env, journaled_state, .. } = self.inner.0.ctx;
|
let Context {
|
||||||
|
block: block_env,
|
||||||
|
cfg: cfg_env,
|
||||||
|
journaled_state,
|
||||||
|
..
|
||||||
|
} = self.inner.0.ctx;
|
||||||
|
|
||||||
(journaled_state.database, EvmEnv { block_env, cfg_env })
|
(journaled_state.database, EvmEnv { block_env, cfg_env })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -379,6 +379,7 @@ mod tests {
|
|||||||
withdrawals: None,
|
withdrawals: None,
|
||||||
},
|
},
|
||||||
sidecars: None,
|
sidecars: None,
|
||||||
|
read_precompile_calls: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let new_block = HlNewBlock(NewBlock { block, td: U128::from(1) });
|
let new_block = HlNewBlock(NewBlock { block, td: U128::from(1) });
|
||||||
|
|||||||
@ -6,12 +6,34 @@ use alloy_primitives::{Address, Bytes, Log};
|
|||||||
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
|
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
use reth_primitives::{SealedBlock, Transaction};
|
use reth_primitives::{SealedBlock, Transaction};
|
||||||
|
use revm::primitives::HashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub type ReadPrecompileCall = (Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>);
|
pub type ReadPrecompileCall = (Address, Vec<(ReadPrecompileInput, ReadPrecompileResult)>);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)]
|
||||||
pub struct ReadPrecompileCalls(pub Vec<ReadPrecompileCall>);
|
pub struct ReadPrecompileCalls(pub Vec<ReadPrecompileCall>);
|
||||||
|
pub type ReadPrecompileMap = HashMap<Address, HashMap<ReadPrecompileInput, ReadPrecompileResult>>;
|
||||||
|
|
||||||
|
impl From<ReadPrecompileCalls> for ReadPrecompileMap {
|
||||||
|
fn from(calls: ReadPrecompileCalls) -> Self {
|
||||||
|
calls
|
||||||
|
.0
|
||||||
|
.into_iter()
|
||||||
|
.map(|(address, calls)| (address, calls.into_iter().collect()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ReadPrecompileMap> for ReadPrecompileCalls {
|
||||||
|
fn from(map: ReadPrecompileMap) -> Self {
|
||||||
|
Self(
|
||||||
|
map.into_iter()
|
||||||
|
.map(|(address, calls)| (address, calls.into_iter().collect()))
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Encodable for ReadPrecompileCalls {
|
impl Encodable for ReadPrecompileCalls {
|
||||||
fn encode(&self, out: &mut dyn BufMut) {
|
fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
|||||||
Reference in New Issue
Block a user