Make it compilable (still bunch to fix!)

This commit is contained in:
sprites0
2025-06-17 18:06:53 -04:00
parent 5e531b7260
commit 821bf7a775
38 changed files with 3652 additions and 31 deletions

316
src/node/evm/config.rs Normal file
View File

@ -0,0 +1,316 @@
use super::{executor::HlBlockExecutor, factory::HlEvmFactory};
use crate::{
chainspec::HlChainSpec,
evm::{spec::HlSpecId, transaction::HlTxEnv},
hardforks::HlHardforks,
HlPrimitives,
};
use alloy_consensus::{BlockHeader, Header, TxReceipt};
use alloy_primitives::{Log, U256};
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
use reth_ethereum_forks::EthereumHardfork;
use reth_evm::{
block::{BlockExecutorFactory, BlockExecutorFor},
eth::{receipt_builder::ReceiptBuilder, EthBlockExecutionCtx},
ConfigureEvm, EvmEnv, EvmFactory, ExecutionCtxFor, FromRecoveredTx, FromTxWithEncoded,
IntoTxEnv, NextBlockEnvAttributes,
};
use reth_evm_ethereum::{EthBlockAssembler, RethReceiptBuilder};
use reth_primitives::{BlockTy, HeaderTy, SealedBlock, SealedHeader, TransactionSigned};
use reth_revm::State;
use revm::{
context::{BlockEnv, CfgEnv, TxEnv},
context_interface::block::BlobExcessGasAndPrice,
primitives::hardfork::SpecId,
Inspector,
};
use std::{borrow::Cow, convert::Infallible, sync::Arc};
/// Ethereum-related EVM configuration.
#[derive(Debug, Clone)]
pub struct HlEvmConfig {
/// Inner [`HlBlockExecutorFactory`].
pub executor_factory:
HlBlockExecutorFactory<RethReceiptBuilder, Arc<HlChainSpec>, HlEvmFactory>,
/// Ethereum block assembler.
pub block_assembler: EthBlockAssembler<HlChainSpec>,
}
impl HlEvmConfig {
/// Creates a new Ethereum EVM configuration with the given chain spec.
pub fn new(chain_spec: Arc<HlChainSpec>) -> Self {
Self::hl(chain_spec)
}
/// Creates a new Ethereum EVM configuration.
pub fn hl(chain_spec: Arc<HlChainSpec>) -> Self {
Self::new_with_evm_factory(chain_spec, HlEvmFactory::default())
}
}
impl HlEvmConfig {
/// 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 {
Self {
block_assembler: EthBlockAssembler::new(chain_spec.clone()),
executor_factory: HlBlockExecutorFactory::new(
RethReceiptBuilder::default(),
chain_spec,
evm_factory,
),
}
}
/// Returns the chain spec associated with this configuration.
pub const fn chain_spec(&self) -> &Arc<HlChainSpec> {
self.executor_factory.spec()
}
}
/// Ethereum block executor factory.
#[derive(Debug, Clone, Default, Copy)]
pub struct HlBlockExecutorFactory<
R = RethReceiptBuilder,
Spec = Arc<HlChainSpec>,
EvmFactory = HlEvmFactory,
> {
/// Receipt builder.
receipt_builder: R,
/// Chain specification.
spec: Spec,
/// EVM factory.
evm_factory: EvmFactory,
}
impl<R, Spec, EvmFactory> HlBlockExecutorFactory<R, Spec, EvmFactory> {
/// Creates a new [`HlBlockExecutorFactory`] with the given spec, [`EvmFactory`], and
/// [`ReceiptBuilder`].
pub const fn new(receipt_builder: R, spec: Spec, evm_factory: EvmFactory) -> Self {
Self {
receipt_builder,
spec,
evm_factory,
}
}
/// Exposes the receipt builder.
pub const fn receipt_builder(&self) -> &R {
&self.receipt_builder
}
/// Exposes the chain specification.
pub const fn spec(&self) -> &Spec {
&self.spec
}
}
impl<R, Spec, EvmF> BlockExecutorFactory for HlBlockExecutorFactory<R, Spec, EvmF>
where
R: ReceiptBuilder<Transaction = TransactionSigned, Receipt: TxReceipt<Log = Log>>,
Spec: EthereumHardforks + HlHardforks + EthChainSpec + Hardforks + Clone,
EvmF: EvmFactory<Tx: FromRecoveredTx<TransactionSigned> + FromTxWithEncoded<TransactionSigned>>,
R::Transaction: From<TransactionSigned> + Clone,
Self: 'static,
HlTxEnv<TxEnv>: IntoTxEnv<<EvmF as EvmFactory>::Tx>,
{
type EvmFactory = EvmF;
type ExecutionCtx<'a> = EthBlockExecutionCtx<'a>;
type Transaction = TransactionSigned;
type Receipt = R::Receipt;
fn evm_factory(&self) -> &Self::EvmFactory {
&self.evm_factory
}
fn create_executor<'a, DB, I>(
&'a self,
evm: <Self::EvmFactory as EvmFactory>::Evm<&'a mut State<DB>, I>,
ctx: Self::ExecutionCtx<'a>,
) -> impl BlockExecutorFor<'a, Self, DB, I>
where
DB: alloy_evm::Database + 'a,
I: Inspector<<Self::EvmFactory as EvmFactory>::Context<&'a mut State<DB>>> + 'a,
{
HlBlockExecutor::new(evm, ctx, self.spec().clone(), self.receipt_builder())
}
}
const EIP1559_INITIAL_BASE_FEE: u64 = 0;
impl ConfigureEvm for HlEvmConfig
where
Self: Send + Sync + Unpin + Clone + 'static,
{
type Primitives = HlPrimitives;
type Error = Infallible;
type NextBlockEnvCtx = NextBlockEnvAttributes;
type BlockExecutorFactory = HlBlockExecutorFactory;
type BlockAssembler = Self;
fn block_executor_factory(&self) -> &Self::BlockExecutorFactory {
&self.executor_factory
}
fn block_assembler(&self) -> &Self::BlockAssembler {
self
}
fn evm_env(&self, header: &Header) -> EvmEnv<HlSpecId> {
let blob_params = self.chain_spec().blob_params_at_timestamp(header.timestamp);
let spec = revm_spec_by_timestamp_and_block_number(
self.chain_spec().clone(),
header.timestamp(),
header.number(),
);
// configure evm env based on parent block
let mut cfg_env = CfgEnv::new()
.with_chain_id(self.chain_spec().chain().id())
.with_spec(spec);
if let Some(blob_params) = &blob_params {
cfg_env.set_blob_max_count(blob_params.max_blob_count);
}
// derive the EIP-4844 blob fees from the header's `excess_blob_gas` and the current
// blobparams
let blob_excess_gas_and_price =
header
.excess_blob_gas
.zip(blob_params)
.map(|(excess_blob_gas, params)| {
let blob_gasprice = params.calc_blob_fee(excess_blob_gas);
BlobExcessGasAndPrice {
excess_blob_gas,
blob_gasprice,
}
});
let eth_spec = spec.into_eth_spec();
let block_env = BlockEnv {
number: header.number(),
beneficiary: header.beneficiary(),
timestamp: header.timestamp(),
difficulty: if eth_spec >= SpecId::MERGE {
U256::ZERO
} else {
header.difficulty()
},
prevrandao: if eth_spec >= SpecId::MERGE {
header.mix_hash()
} else {
None
},
gas_limit: header.gas_limit(),
basefee: header.base_fee_per_gas().unwrap_or_default(),
blob_excess_gas_and_price,
};
EvmEnv { cfg_env, block_env }
}
fn next_evm_env(
&self,
parent: &Header,
attributes: &Self::NextBlockEnvCtx,
) -> Result<EvmEnv<HlSpecId>, Self::Error> {
// ensure we're not missing any timestamp based hardforks
let spec_id = revm_spec_by_timestamp_and_block_number(
self.chain_spec().clone(),
attributes.timestamp,
parent.number() + 1,
);
// configure evm env based on parent block
let cfg_env = CfgEnv::new()
.with_chain_id(self.chain_spec().chain().id())
.with_spec(spec_id);
// if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is
// cancun now, we need to set the excess blob gas to the default value(0)
let blob_excess_gas_and_price = parent
.maybe_next_block_excess_blob_gas(
self.chain_spec()
.blob_params_at_timestamp(attributes.timestamp),
)
.or_else(|| (spec_id.into_eth_spec().is_enabled_in(SpecId::CANCUN)).then_some(0))
.map(|gas| BlobExcessGasAndPrice::new(gas, false));
let mut basefee = parent.next_block_base_fee(
self.chain_spec()
.base_fee_params_at_timestamp(attributes.timestamp),
);
let mut gas_limit = U256::from(parent.gas_limit);
// If we are on the London fork boundary, we need to multiply the parent's gas limit by the
// elasticity multiplier to get the new gas limit.
if self
.chain_spec()
.inner
.fork(EthereumHardfork::London)
.transitions_at_block(parent.number + 1)
{
let elasticity_multiplier = self
.chain_spec()
.base_fee_params_at_timestamp(attributes.timestamp)
.elasticity_multiplier;
// multiply the gas limit by the elasticity multiplier
gas_limit *= U256::from(elasticity_multiplier);
// set the base fee to the initial base fee from the EIP-1559 spec
basefee = Some(EIP1559_INITIAL_BASE_FEE)
}
let block_env = BlockEnv {
number: parent.number() + 1,
beneficiary: attributes.suggested_fee_recipient,
timestamp: attributes.timestamp,
difficulty: U256::ZERO,
prevrandao: Some(attributes.prev_randao),
gas_limit: attributes.gas_limit,
// calculate basefee based on parent block's gas usage
basefee: basefee.unwrap_or_default(),
// calculate excess gas based on parent block's blob gas usage
blob_excess_gas_and_price,
};
Ok(EvmEnv { cfg_env, block_env })
}
fn context_for_block<'a>(
&self,
block: &'a SealedBlock<BlockTy<Self::Primitives>>,
) -> ExecutionCtxFor<'a, Self> {
EthBlockExecutionCtx {
parent_hash: block.header().parent_hash,
parent_beacon_block_root: block.header().parent_beacon_block_root,
ommers: &block.body().ommers,
withdrawals: block.body().withdrawals.as_ref().map(Cow::Borrowed),
}
}
fn context_for_next_block(
&self,
parent: &SealedHeader<HeaderTy<Self::Primitives>>,
attributes: Self::NextBlockEnvCtx,
) -> ExecutionCtxFor<'_, Self> {
EthBlockExecutionCtx {
parent_hash: parent.hash(),
parent_beacon_block_root: attributes.parent_beacon_block_root,
ommers: &[],
withdrawals: attributes.withdrawals.map(Cow::Owned),
}
}
}
/// Map the latest active hardfork at the given timestamp or block number to a [`HlSpecId`].
pub fn revm_spec_by_timestamp_and_block_number(
chain_spec: impl HlHardforks,
timestamp: u64,
block_number: u64,
) -> HlSpecId {
HlSpecId::V1
}