mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: re-use BlockExecutionStrategy in payload building (#14609)
This commit is contained in:
@ -29,8 +29,6 @@ alloy-evm.workspace = true
|
||||
alloy-sol-types.workspace = true
|
||||
alloy-consensus.workspace = true
|
||||
|
||||
derive_more.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
reth-testing-utils.workspace = true
|
||||
reth-evm = { workspace = true, features = ["test-utils"] }
|
||||
@ -58,5 +56,4 @@ std = [
|
||||
"alloy-evm/std",
|
||||
"reth-execution-types/std",
|
||||
"reth-evm/std",
|
||||
"derive_more/std",
|
||||
]
|
||||
|
||||
@ -5,8 +5,9 @@ use crate::{
|
||||
EthEvmConfig,
|
||||
};
|
||||
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||
use alloy_consensus::{BlockHeader, Transaction};
|
||||
use alloy_eips::{eip6110, eip7685::Requests};
|
||||
use alloy_consensus::{Header, Transaction};
|
||||
use alloy_eips::{eip4895::Withdrawals, eip6110, eip7685::Requests};
|
||||
use alloy_primitives::{Address, B256};
|
||||
use reth_chainspec::{ChainSpec, EthereumHardfork, EthereumHardforks, MAINNET};
|
||||
use reth_evm::{
|
||||
execute::{
|
||||
@ -75,43 +76,83 @@ where
|
||||
DB: Database,
|
||||
{
|
||||
let evm = self.evm_config.evm_for_block(db, block.header());
|
||||
EthExecutionStrategy::new(evm, block.sealed_block(), self)
|
||||
EthExecutionStrategy::new(evm, block.sealed_block(), &self.chain_spec, &self.evm_config)
|
||||
}
|
||||
}
|
||||
|
||||
/// Input for block execution.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct EthBlockExecutionInput<'a> {
|
||||
/// Block number.
|
||||
pub number: u64,
|
||||
/// Block timestamp.
|
||||
pub timestamp: u64,
|
||||
/// Parent block hash.
|
||||
pub parent_hash: B256,
|
||||
/// Block gas limit.
|
||||
pub gas_limit: u64,
|
||||
/// Parent beacon block root.
|
||||
pub parent_beacon_block_root: Option<B256>,
|
||||
/// Block beneficiary.
|
||||
pub beneficiary: Address,
|
||||
/// Block ommers
|
||||
pub ommers: &'a [Header],
|
||||
/// Block withdrawals.
|
||||
pub withdrawals: Option<&'a Withdrawals>,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SealedBlock> for EthBlockExecutionInput<'a> {
|
||||
fn from(block: &'a SealedBlock) -> Self {
|
||||
Self {
|
||||
number: block.header().number,
|
||||
timestamp: block.header().timestamp,
|
||||
parent_hash: block.header().parent_hash,
|
||||
gas_limit: block.header().gas_limit,
|
||||
parent_beacon_block_root: block.header().parent_beacon_block_root,
|
||||
beneficiary: block.header().beneficiary,
|
||||
ommers: &block.body().ommers,
|
||||
withdrawals: block.body().withdrawals.as_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Block execution strategy for Ethereum.
|
||||
#[derive(Debug, derive_more::Deref)]
|
||||
#[derive(Debug)]
|
||||
pub struct EthExecutionStrategy<'a, Evm, EvmConfig> {
|
||||
/// Reference to the parent factory providing access to [`ChainSpec`].
|
||||
#[deref]
|
||||
factory: &'a EthExecutionStrategyFactory<EvmConfig>,
|
||||
/// Reference to the [`ChainSpec`].
|
||||
chain_spec: &'a ChainSpec,
|
||||
/// How to configure the EVM.
|
||||
evm_config: EvmConfig,
|
||||
|
||||
/// Block being executed.
|
||||
block: &'a SealedBlock,
|
||||
/// Input for block execution.
|
||||
input: EthBlockExecutionInput<'a>,
|
||||
/// The EVM used by strategy.
|
||||
evm: Evm,
|
||||
/// Utility to call system smart contracts.
|
||||
system_caller: SystemCaller<&'a ChainSpec>,
|
||||
|
||||
/// Receipts of executed transactions.
|
||||
receipts: Vec<Receipt>,
|
||||
/// Total gas used by transactions in this block.
|
||||
gas_used: u64,
|
||||
/// Utility to call system smart contracts.
|
||||
system_caller: SystemCaller<&'a ChainSpec>,
|
||||
}
|
||||
|
||||
impl<'a, Evm, EvmConfig> EthExecutionStrategy<'a, Evm, EvmConfig> {
|
||||
/// Creates a new [`EthExecutionStrategy`]
|
||||
pub fn new(
|
||||
evm: Evm,
|
||||
block: &'a SealedBlock,
|
||||
factory: &'a EthExecutionStrategyFactory<EvmConfig>,
|
||||
input: impl Into<EthBlockExecutionInput<'a>>,
|
||||
chain_spec: &'a ChainSpec,
|
||||
evm_config: EvmConfig,
|
||||
) -> Self {
|
||||
Self {
|
||||
evm,
|
||||
factory,
|
||||
block,
|
||||
chain_spec,
|
||||
evm_config,
|
||||
input: input.into(),
|
||||
receipts: Vec::new(),
|
||||
gas_used: 0,
|
||||
system_caller: SystemCaller::new(&factory.chain_spec),
|
||||
system_caller: SystemCaller::new(chain_spec),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,9 +169,12 @@ where
|
||||
fn apply_pre_execution_changes(&mut self) -> Result<(), Self::Error> {
|
||||
// Set state clear flag if the block is after the Spurious Dragon hardfork.
|
||||
let state_clear_flag =
|
||||
self.chain_spec.is_spurious_dragon_active_at_block(self.block.number());
|
||||
self.chain_spec.is_spurious_dragon_active_at_block(self.input.number);
|
||||
self.evm.db_mut().set_state_clear_flag(state_clear_flag);
|
||||
self.system_caller.apply_pre_execution_changes(self.block.header(), &mut self.evm)?;
|
||||
self.system_caller
|
||||
.apply_blockhashes_contract_call(self.input.parent_hash, &mut self.evm)?;
|
||||
self.system_caller
|
||||
.apply_beacon_root_contract_call(self.input.parent_beacon_block_root, &mut self.evm)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -138,10 +182,10 @@ where
|
||||
fn execute_transaction(
|
||||
&mut self,
|
||||
tx: Recovered<&TransactionSigned>,
|
||||
) -> Result<(), Self::Error> {
|
||||
) -> Result<u64, Self::Error> {
|
||||
// The sum of the transaction's gas limit, Tg, and the gas utilized in this block prior,
|
||||
// must be no greater than the block's gasLimit.
|
||||
let block_available_gas = self.block.gas_limit() - self.gas_used;
|
||||
let block_available_gas = self.input.gas_limit - self.gas_used;
|
||||
if tx.gas_limit() > block_available_gas {
|
||||
return Err(BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas {
|
||||
transaction_gas_limit: tx.gas_limit(),
|
||||
@ -161,8 +205,10 @@ where
|
||||
let ResultAndState { result, state } = result_and_state;
|
||||
self.evm.db_mut().commit(state);
|
||||
|
||||
let gas_used = result.gas_used();
|
||||
|
||||
// append gas used
|
||||
self.gas_used += result.gas_used();
|
||||
self.gas_used += gas_used;
|
||||
|
||||
// Push transaction changeset and calculate header bloom filter for receipt.
|
||||
self.receipts.push(Receipt {
|
||||
@ -174,16 +220,16 @@ where
|
||||
logs: result.into_logs(),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
Ok(gas_used)
|
||||
}
|
||||
|
||||
fn apply_post_execution_changes(
|
||||
mut self,
|
||||
) -> Result<BlockExecutionResult<Receipt>, Self::Error> {
|
||||
let requests = if self.chain_spec.is_prague_active_at_timestamp(self.block.timestamp) {
|
||||
let requests = if self.chain_spec.is_prague_active_at_timestamp(self.input.timestamp) {
|
||||
// Collect all EIP-6110 deposits
|
||||
let deposit_requests =
|
||||
crate::eip6110::parse_deposits_from_receipts(&self.chain_spec, &self.receipts)?;
|
||||
crate::eip6110::parse_deposits_from_receipts(self.chain_spec, &self.receipts)?;
|
||||
|
||||
let mut requests = Requests::default();
|
||||
|
||||
@ -197,10 +243,15 @@ where
|
||||
Requests::default()
|
||||
};
|
||||
|
||||
let mut balance_increments = post_block_balance_increments(&self.chain_spec, self.block);
|
||||
let mut balance_increments = post_block_balance_increments(
|
||||
self.chain_spec,
|
||||
self.evm.block(),
|
||||
self.input.ommers,
|
||||
self.input.withdrawals,
|
||||
);
|
||||
|
||||
// Irregular state change at Ethereum DAO hardfork
|
||||
if self.chain_spec.fork(EthereumHardfork::Dao).transitions_at_block(self.block.number()) {
|
||||
if self.chain_spec.fork(EthereumHardfork::Dao).transitions_at_block(self.input.number) {
|
||||
// drain balances from hardcoded addresses.
|
||||
let drained_balance: u128 = self
|
||||
.evm
|
||||
|
||||
@ -10,21 +10,20 @@
|
||||
#![allow(clippy::useless_let_if_seq)]
|
||||
|
||||
use alloy_consensus::{BlockHeader, Header, Transaction, Typed2718, EMPTY_OMMER_ROOT_HASH};
|
||||
use alloy_eips::{eip4844::DATA_GAS_PER_BLOB, eip6110, eip7685::Requests, merge::BEACON_NONCE};
|
||||
use alloy_eips::{eip4844::DATA_GAS_PER_BLOB, merge::BEACON_NONCE};
|
||||
use alloy_primitives::U256;
|
||||
use reth_basic_payload_builder::{
|
||||
commit_withdrawals, is_better_payload, BuildArguments, BuildOutcome, PayloadBuilder,
|
||||
PayloadConfig,
|
||||
is_better_payload, BuildArguments, BuildOutcome, PayloadBuilder, PayloadConfig,
|
||||
};
|
||||
use reth_chainspec::{ChainSpec, ChainSpecProvider, EthChainSpec, EthereumHardforks};
|
||||
use reth_errors::RethError;
|
||||
use reth_ethereum_primitives::{Block, BlockBody, Receipt, TransactionSigned};
|
||||
use reth_evm::{
|
||||
system_calls::SystemCaller, ConfigureEvm, Evm, EvmEnv, EvmError, InvalidTxError,
|
||||
NextBlockEnvAttributes,
|
||||
use reth_errors::{BlockExecutionError, BlockValidationError};
|
||||
use reth_ethereum_primitives::{Block, BlockBody, TransactionSigned};
|
||||
use reth_evm::{execute::BlockExecutionStrategy, ConfigureEvm, NextBlockEnvAttributes};
|
||||
use reth_evm_ethereum::{
|
||||
execute::{EthBlockExecutionInput, EthExecutionStrategy},
|
||||
EthEvmConfig,
|
||||
};
|
||||
use reth_evm_ethereum::{eip6110::parse_deposits_from_receipts, EthEvmConfig};
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_execution_types::{BlockExecutionResult, ExecutionOutcome};
|
||||
use reth_payload_builder::{EthBuiltPayload, EthPayloadBuilderAttributes};
|
||||
use reth_payload_builder_primitives::PayloadBuilderError;
|
||||
use reth_payload_primitives::PayloadBuilderAttributes;
|
||||
@ -41,10 +40,7 @@ use reth_transaction_pool::{
|
||||
error::InvalidPoolTransactionError, BestTransactions, BestTransactionsAttributes,
|
||||
PoolTransaction, TransactionPool, ValidPoolTransaction,
|
||||
};
|
||||
use revm::{
|
||||
context_interface::{result::ResultAndState, Block as _},
|
||||
DatabaseCommit,
|
||||
};
|
||||
use revm::context_interface::Block as _;
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
@ -82,27 +78,6 @@ impl<Pool, Client, EvmConfig> EthereumPayloadBuilder<Pool, Client, EvmConfig> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Pool, Client, EvmConfig> EthereumPayloadBuilder<Pool, Client, EvmConfig>
|
||||
where
|
||||
EvmConfig: ConfigureEvm<Header = Header>,
|
||||
{
|
||||
/// Returns the configured [`EvmEnv`] for the targeted payload
|
||||
/// (that has the `parent` as its parent).
|
||||
fn evm_env(
|
||||
&self,
|
||||
config: &PayloadConfig<EthPayloadBuilderAttributes>,
|
||||
parent: &Header,
|
||||
) -> Result<EvmEnv<EvmConfig::Spec>, EvmConfig::Error> {
|
||||
let next_attributes = NextBlockEnvAttributes {
|
||||
timestamp: config.attributes.timestamp(),
|
||||
suggested_fee_recipient: config.attributes.suggested_fee_recipient(),
|
||||
prev_randao: config.attributes.prev_randao(),
|
||||
gas_limit: self.builder_config.gas_limit(parent.gas_limit),
|
||||
};
|
||||
self.evm_config.next_evm_env(parent, next_attributes)
|
||||
}
|
||||
}
|
||||
|
||||
// Default implementation of [PayloadBuilder] for unit type
|
||||
impl<Pool, Client, EvmConfig> PayloadBuilder for EthereumPayloadBuilder<Pool, Client, EvmConfig>
|
||||
where
|
||||
@ -117,17 +92,12 @@ where
|
||||
&self,
|
||||
args: BuildArguments<EthPayloadBuilderAttributes, EthBuiltPayload>,
|
||||
) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError> {
|
||||
let evm_env = self
|
||||
.evm_env(&args.config, &args.config.parent_header)
|
||||
.map_err(PayloadBuilderError::other)?;
|
||||
|
||||
default_ethereum_payload(
|
||||
self.evm_config.clone(),
|
||||
self.client.clone(),
|
||||
self.pool.clone(),
|
||||
self.builder_config.clone(),
|
||||
args,
|
||||
evm_env,
|
||||
|attributes| self.pool.best_transactions_with_attributes(attributes),
|
||||
)
|
||||
}
|
||||
@ -138,17 +108,12 @@ where
|
||||
) -> Result<EthBuiltPayload, PayloadBuilderError> {
|
||||
let args = BuildArguments::new(Default::default(), config, Default::default(), None);
|
||||
|
||||
let evm_env = self
|
||||
.evm_env(&args.config, &args.config.parent_header)
|
||||
.map_err(PayloadBuilderError::other)?;
|
||||
|
||||
default_ethereum_payload(
|
||||
self.evm_config.clone(),
|
||||
self.client.clone(),
|
||||
self.pool.clone(),
|
||||
self.builder_config.clone(),
|
||||
args,
|
||||
evm_env,
|
||||
|attributes| self.pool.best_transactions_with_attributes(attributes),
|
||||
)?
|
||||
.into_payload()
|
||||
@ -168,7 +133,6 @@ pub fn default_ethereum_payload<EvmConfig, Client, Pool, F>(
|
||||
pool: Pool,
|
||||
builder_config: EthereumBuilderConfig,
|
||||
args: BuildArguments<EthPayloadBuilderAttributes, EthBuiltPayload>,
|
||||
evm_env: EvmEnv<EvmConfig::Spec>,
|
||||
best_txs: F,
|
||||
) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError>
|
||||
where
|
||||
@ -178,13 +142,24 @@ where
|
||||
F: FnOnce(BestTransactionsAttributes) -> BestTransactionsIter<Pool>,
|
||||
{
|
||||
let BuildArguments { mut cached_reads, config, cancel, best_payload } = args;
|
||||
let PayloadConfig { parent_header, attributes } = config;
|
||||
|
||||
let chain_spec = client.chain_spec();
|
||||
let state_provider = client.state_by_block_hash(config.parent_header.hash())?;
|
||||
let state_provider = client.state_by_block_hash(parent_header.hash())?;
|
||||
let state = StateProviderDatabase::new(state_provider);
|
||||
let mut db =
|
||||
State::builder().with_database(cached_reads.as_db_mut(state)).with_bundle_update().build();
|
||||
let PayloadConfig { parent_header, attributes } = config;
|
||||
|
||||
let next_attributes = NextBlockEnvAttributes {
|
||||
timestamp: attributes.timestamp(),
|
||||
suggested_fee_recipient: attributes.suggested_fee_recipient(),
|
||||
prev_randao: attributes.prev_randao(),
|
||||
gas_limit: builder_config.gas_limit(parent_header.gas_limit),
|
||||
};
|
||||
let evm_env = evm_config
|
||||
.next_evm_env(&parent_header, next_attributes)
|
||||
.map_err(PayloadBuilderError::other)?;
|
||||
|
||||
let chain_spec = client.chain_spec();
|
||||
|
||||
debug!(target: "payload_builder", id=%attributes.id, parent_header = ?parent_header.hash(), parent_number = parent_header.number, "building new payload");
|
||||
let mut cumulative_gas_used = 0;
|
||||
@ -202,32 +177,27 @@ where
|
||||
let block_number = evm_env.block_env.number;
|
||||
let beneficiary = evm_env.block_env.beneficiary;
|
||||
|
||||
let mut evm = evm_config.evm_with_env(&mut db, evm_env);
|
||||
let mut system_caller = SystemCaller::new(chain_spec.clone());
|
||||
let mut strategy = EthExecutionStrategy::new(
|
||||
evm_config.evm_with_env(&mut db, evm_env),
|
||||
EthBlockExecutionInput {
|
||||
number: parent_header.number + 1,
|
||||
timestamp: attributes.timestamp(),
|
||||
parent_hash: parent_header.hash(),
|
||||
gas_limit: next_attributes.gas_limit,
|
||||
parent_beacon_block_root: attributes.parent_beacon_block_root,
|
||||
beneficiary,
|
||||
ommers: &[],
|
||||
withdrawals: Some(&attributes.withdrawals),
|
||||
},
|
||||
&chain_spec,
|
||||
&evm_config,
|
||||
);
|
||||
|
||||
// apply eip-4788 pre block contract call
|
||||
system_caller
|
||||
.apply_beacon_root_contract_call(attributes.parent_beacon_block_root, &mut evm)
|
||||
.map_err(|err| {
|
||||
warn!(target: "payload_builder",
|
||||
parent_hash=%parent_header.hash(),
|
||||
%err,
|
||||
"failed to apply beacon root contract call for payload"
|
||||
);
|
||||
PayloadBuilderError::Internal(err.into())
|
||||
})?;
|
||||
|
||||
// apply eip-2935 blockhashes update
|
||||
system_caller.apply_blockhashes_contract_call(
|
||||
parent_header.hash(),
|
||||
&mut evm,
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!(target: "payload_builder", parent_hash=%parent_header.hash(), %err, "failed to update parent header blockhashes for payload");
|
||||
strategy.apply_pre_execution_changes().map_err(|err| {
|
||||
warn!(target: "payload_builder", %err, "failed to apply pre-execution changes");
|
||||
PayloadBuilderError::Internal(err.into())
|
||||
})?;
|
||||
|
||||
let mut receipts = Vec::new();
|
||||
let mut block_blob_count = 0;
|
||||
let blob_params = chain_spec.blob_params_at_timestamp(attributes.timestamp);
|
||||
let max_blob_count =
|
||||
@ -278,37 +248,31 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the environment for the tx.
|
||||
let tx_env = evm_config.tx_env(&tx);
|
||||
|
||||
let ResultAndState { result, state } = match evm.transact(tx_env) {
|
||||
Ok(res) => res,
|
||||
Err(err) => {
|
||||
if let Some(err) = err.as_invalid_tx_err() {
|
||||
if err.is_nonce_too_low() {
|
||||
// if the nonce is too low, we can skip this transaction
|
||||
trace!(target: "payload_builder", %err, ?tx, "skipping nonce too low transaction");
|
||||
} else {
|
||||
// if the transaction is invalid, we can skip it and all of its
|
||||
// descendants
|
||||
trace!(target: "payload_builder", %err, ?tx, "skipping invalid transaction and its descendants");
|
||||
best_txs.mark_invalid(
|
||||
&pool_tx,
|
||||
InvalidPoolTransactionError::Consensus(
|
||||
InvalidTransactionError::TxTypeNotSupported,
|
||||
),
|
||||
);
|
||||
}
|
||||
continue
|
||||
let gas_used = match strategy.execute_transaction(tx.as_recovered_ref()) {
|
||||
Ok(gas_used) => gas_used,
|
||||
Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
|
||||
error, ..
|
||||
})) => {
|
||||
if error.is_nonce_too_low() {
|
||||
// if the nonce is too low, we can skip this transaction
|
||||
trace!(target: "payload_builder", %error, ?tx, "skipping nonce too low transaction");
|
||||
} else {
|
||||
// if the transaction is invalid, we can skip it and all of its
|
||||
// descendants
|
||||
trace!(target: "payload_builder", %error, ?tx, "skipping invalid transaction and its descendants");
|
||||
best_txs.mark_invalid(
|
||||
&pool_tx,
|
||||
InvalidPoolTransactionError::Consensus(
|
||||
InvalidTransactionError::TxTypeNotSupported,
|
||||
),
|
||||
);
|
||||
}
|
||||
// this is an error that we should treat as fatal for this attempt
|
||||
return Err(PayloadBuilderError::evm(err))
|
||||
continue
|
||||
}
|
||||
// this is an error that we should treat as fatal for this attempt
|
||||
Err(err) => return Err(PayloadBuilderError::evm(err)),
|
||||
};
|
||||
|
||||
// commit changes
|
||||
evm.db_mut().commit(state);
|
||||
|
||||
// add to the total blob gas used if the transaction successfully executed
|
||||
if let Some(blob_tx) = tx.as_eip4844() {
|
||||
block_blob_count += blob_tx.blob_versioned_hashes.len() as u64;
|
||||
@ -319,23 +283,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let gas_used = result.gas_used();
|
||||
|
||||
// add gas used by the transaction to cumulative gas used, before creating the receipt
|
||||
cumulative_gas_used += gas_used;
|
||||
|
||||
// Push transaction changeset and calculate header bloom filter for receipt.
|
||||
receipts.push(Receipt {
|
||||
tx_type: tx.tx_type(),
|
||||
success: result.is_success(),
|
||||
cumulative_gas_used,
|
||||
logs: result.into_logs().into_iter().collect(),
|
||||
});
|
||||
|
||||
// update add to total fees
|
||||
let miner_fee =
|
||||
tx.effective_tip_per_gas(base_fee).expect("fee is always valid; execution succeeded");
|
||||
total_fees += U256::from(miner_fee) * U256::from(gas_used);
|
||||
cumulative_gas_used += gas_used;
|
||||
|
||||
// append transaction to the block body
|
||||
executed_txs.push(tx.into_tx());
|
||||
@ -344,39 +296,20 @@ where
|
||||
// check if we have a better block
|
||||
if !is_better_payload(best_payload.as_ref(), total_fees) {
|
||||
// Release db
|
||||
drop(evm);
|
||||
|
||||
drop(strategy);
|
||||
// can skip building the block
|
||||
return Ok(BuildOutcome::Aborted { fees: total_fees, cached_reads })
|
||||
}
|
||||
|
||||
// calculate the requests and the requests root
|
||||
let requests = if chain_spec.is_prague_active_at_timestamp(attributes.timestamp) {
|
||||
let deposit_requests = parse_deposits_from_receipts(&chain_spec, receipts.iter())
|
||||
.map_err(|err| PayloadBuilderError::Internal(RethError::Execution(err.into())))?;
|
||||
let BlockExecutionResult { receipts, requests, gas_used } = strategy
|
||||
.apply_post_execution_changes()
|
||||
.map_err(|err| PayloadBuilderError::Internal(err.into()))?;
|
||||
|
||||
let mut requests = Requests::default();
|
||||
|
||||
if !deposit_requests.is_empty() {
|
||||
requests.push_request_with_type(eip6110::DEPOSIT_REQUEST_TYPE, deposit_requests);
|
||||
}
|
||||
|
||||
requests.extend(
|
||||
system_caller
|
||||
.apply_post_execution_changes(&mut evm)
|
||||
.map_err(|err| PayloadBuilderError::Internal(err.into()))?,
|
||||
);
|
||||
|
||||
Some(requests)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Release db
|
||||
drop(evm);
|
||||
|
||||
let withdrawals_root =
|
||||
commit_withdrawals(&mut db, &chain_spec, attributes.timestamp, &attributes.withdrawals)?;
|
||||
let requests =
|
||||
chain_spec.is_prague_active_at_timestamp(attributes.timestamp).then_some(requests);
|
||||
let withdrawals_root = chain_spec
|
||||
.is_shanghai_active_at_timestamp(attributes.timestamp)
|
||||
.then_some(proofs::calculate_withdrawals_root(&attributes.withdrawals));
|
||||
|
||||
// merge all transitions into bundle state, this would apply the withdrawal balance changes
|
||||
// and 4788 contract call
|
||||
@ -449,7 +382,7 @@ where
|
||||
number: parent_header.number + 1,
|
||||
gas_limit: block_gas_limit,
|
||||
difficulty: U256::ZERO,
|
||||
gas_used: cumulative_gas_used,
|
||||
gas_used,
|
||||
extra_data: builder_config.extra_data,
|
||||
parent_beacon_block_root: attributes.parent_beacon_block_root,
|
||||
blob_gas_used,
|
||||
|
||||
Reference in New Issue
Block a user