mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Move cfg_env and block_env configuration from PayloadBuilderAttributes into PayloadBuilder (#10510)
Co-authored-by: garwah <garwah@garwah> Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
@ -13,13 +13,11 @@ workspace = true
|
||||
[dependencies]
|
||||
# reth
|
||||
reth-chainspec.workspace = true
|
||||
reth-evm-ethereum.workspace = true
|
||||
reth-primitives.workspace = true
|
||||
reth-engine-primitives.workspace = true
|
||||
reth-payload-primitives.workspace = true
|
||||
reth-rpc-types.workspace = true
|
||||
reth-rpc-types-compat.workspace = true
|
||||
revm-primitives.workspace = true
|
||||
alloy-rlp.workspace = true
|
||||
reth-chain-state.workspace = true
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
//! Ethereum specific
|
||||
//! Ethereum specific engine API types and impls.
|
||||
|
||||
#![doc(
|
||||
html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
|
||||
|
||||
@ -2,13 +2,8 @@
|
||||
|
||||
use alloy_rlp::Encodable;
|
||||
use reth_chain_state::ExecutedBlock;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_evm_ethereum::revm_spec_by_timestamp_after_merge;
|
||||
use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes};
|
||||
use reth_primitives::{
|
||||
constants::EIP1559_INITIAL_BASE_FEE, Address, BlobTransactionSidecar, EthereumHardfork, Header,
|
||||
SealedBlock, Withdrawals, B256, U256,
|
||||
};
|
||||
use reth_primitives::{Address, BlobTransactionSidecar, SealedBlock, Withdrawals, B256, U256};
|
||||
use reth_rpc_types::engine::{
|
||||
ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4,
|
||||
ExecutionPayloadV1, PayloadAttributes, PayloadId,
|
||||
@ -17,7 +12,6 @@ use reth_rpc_types_compat::engine::payload::{
|
||||
block_to_payload_v1, block_to_payload_v3, block_to_payload_v4,
|
||||
convert_block_to_payload_field_v2,
|
||||
};
|
||||
use revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId};
|
||||
use std::convert::Infallible;
|
||||
|
||||
/// Contains the built payload.
|
||||
@ -250,65 +244,6 @@ impl PayloadBuilderAttributes for EthPayloadBuilderAttributes {
|
||||
fn withdrawals(&self) -> &Withdrawals {
|
||||
&self.withdrawals
|
||||
}
|
||||
|
||||
fn cfg_and_block_env(
|
||||
&self,
|
||||
chain_spec: &ChainSpec,
|
||||
parent: &Header,
|
||||
) -> (CfgEnvWithHandlerCfg, BlockEnv) {
|
||||
// configure evm env based on parent block
|
||||
let cfg = CfgEnv::default().with_chain_id(chain_spec.chain().id());
|
||||
|
||||
// ensure we're not missing any timestamp based hardforks
|
||||
let spec_id = revm_spec_by_timestamp_after_merge(chain_spec, self.timestamp());
|
||||
|
||||
// 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
|
||||
let blob_excess_gas_and_price = parent
|
||||
.next_block_excess_blob_gas()
|
||||
.or_else(|| {
|
||||
if spec_id == SpecId::CANCUN {
|
||||
// default excess blob gas is zero
|
||||
Some(0)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(BlobExcessGasAndPrice::new);
|
||||
|
||||
let mut basefee =
|
||||
parent.next_block_base_fee(chain_spec.base_fee_params_at_timestamp(self.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 chain_spec.fork(EthereumHardfork::London).transitions_at_block(parent.number + 1) {
|
||||
let elasticity_multiplier =
|
||||
chain_spec.base_fee_params_at_timestamp(self.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: U256::from(parent.number + 1),
|
||||
coinbase: self.suggested_fee_recipient(),
|
||||
timestamp: U256::from(self.timestamp()),
|
||||
difficulty: U256::ZERO,
|
||||
prevrandao: Some(self.prev_randao()),
|
||||
gas_limit,
|
||||
// calculate basefee based on parent block's gas usage
|
||||
basefee: basefee.map(U256::from).unwrap_or_default(),
|
||||
// calculate excess gas based on parent block's blob gas usage
|
||||
blob_excess_gas_and_price,
|
||||
};
|
||||
|
||||
(CfgEnvWithHandlerCfg::new_with_spec_id(cfg, spec_id), block_env)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates the payload id for the configured payload from the [`PayloadAttributes`].
|
||||
@ -338,94 +273,10 @@ pub(crate) fn payload_id(parent: &B256, attributes: &PayloadAttributes) -> Paylo
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use reth_primitives::Genesis;
|
||||
|
||||
#[test]
|
||||
fn ensure_first_london_block_base_fee_is_set() {
|
||||
let hive_london = r#"
|
||||
{
|
||||
"config": {
|
||||
"ethash": {},
|
||||
"chainId": 7,
|
||||
"homesteadBlock": 0,
|
||||
"eip150Block": 0,
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"constantinopleBlock": 0,
|
||||
"petersburgBlock": 0,
|
||||
"istanbulBlock": 0,
|
||||
"muirGlacierBlock": 0,
|
||||
"berlinBlock": 0,
|
||||
"londonBlock": 1,
|
||||
"mergeNetsplitBlock": 1,
|
||||
"terminalTotalDifficulty": 196608,
|
||||
"shanghaiTime": 4662,
|
||||
"cancunTime": 4662
|
||||
},
|
||||
"nonce": "0x0",
|
||||
"timestamp": "0x1234",
|
||||
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x2fefd8",
|
||||
"difficulty": "0x30000",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||
"alloc": {
|
||||
"0000000000000000000000000000000000000314": {
|
||||
"code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029",
|
||||
"storage": {
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000001234",
|
||||
"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
"balance": "0x0"
|
||||
},
|
||||
"0000000000000000000000000000000000000315": {
|
||||
"code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029",
|
||||
"balance": "0x9999999999999999999999999999999"
|
||||
},
|
||||
"0000000000000000000000000000000000000316": {
|
||||
"code": "0x444355",
|
||||
"balance": "0x0"
|
||||
},
|
||||
"0000000000000000000000000000000000000317": {
|
||||
"code": "0x600160003555",
|
||||
"balance": "0x0"
|
||||
},
|
||||
"000f3df6d732807ef1319fb7b8bb8522d0beac02": {
|
||||
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500",
|
||||
"balance": "0x0",
|
||||
"nonce": "0x1"
|
||||
}
|
||||
},
|
||||
"number": "0x0",
|
||||
"gasUsed": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"baseFeePerGas": null,
|
||||
"excessBlobGas": null,
|
||||
"blobGasUsed": null
|
||||
}
|
||||
"#;
|
||||
|
||||
fn attributes_serde() {
|
||||
let attributes = r#"{"timestamp":"0x1235","prevRandao":"0xf343b00e02dc34ec0124241f74f32191be28fb370bb48060f5fa4df99bda774c","suggestedFeeRecipient":"0x0000000000000000000000000000000000000000","withdrawals":null,"parentBeaconBlockRoot":null}"#;
|
||||
let attributes: PayloadAttributes = serde_json::from_str(attributes).unwrap();
|
||||
|
||||
// check that it deserializes properly
|
||||
let genesis: Genesis = serde_json::from_str(hive_london).unwrap();
|
||||
let chainspec = ChainSpec::from(genesis);
|
||||
let payload_builder_attributes =
|
||||
EthPayloadBuilderAttributes::new(chainspec.genesis_hash(), attributes);
|
||||
|
||||
// use cfg_and_block_env
|
||||
let cfg_and_block_env =
|
||||
payload_builder_attributes.cfg_and_block_env(&chainspec, chainspec.genesis_header());
|
||||
|
||||
// ensure the base fee is non zero
|
||||
assert_eq!(cfg_and_block_env.1.basefee, U256::from(EIP1559_INITIAL_BASE_FEE));
|
||||
|
||||
// ensure the gas limit is double the previous block's gas limit
|
||||
assert_eq!(
|
||||
cfg_and_block_env.1.gas_limit,
|
||||
U256::from(chainspec.genesis_header().gas_limit * 2)
|
||||
);
|
||||
let _attributes: PayloadAttributes = serde_json::from_str(attributes).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,11 +18,13 @@ reth-revm.workspace = true
|
||||
reth-transaction-pool.workspace = true
|
||||
reth-provider.workspace = true
|
||||
reth-payload-builder.workspace = true
|
||||
reth-payload-primitives.workspace = true
|
||||
reth-execution-types.workspace = true
|
||||
reth-basic-payload-builder.workspace = true
|
||||
reth-evm.workspace = true
|
||||
reth-evm-ethereum.workspace = true
|
||||
reth-errors.workspace = true
|
||||
reth-chainspec.workspace = true
|
||||
reth-trie.workspace = true
|
||||
reth-chain-state.workspace = true
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ use reth_basic_payload_builder::{
|
||||
PayloadConfig, WithdrawalsOutcome,
|
||||
};
|
||||
use reth_chain_state::ExecutedBlock;
|
||||
use reth_chainspec::EthereumHardfork;
|
||||
use reth_errors::RethError;
|
||||
use reth_evm::{
|
||||
system_calls::{
|
||||
@ -23,15 +24,19 @@ use reth_evm::{
|
||||
},
|
||||
ConfigureEvm,
|
||||
};
|
||||
use reth_evm_ethereum::{eip6110::parse_deposits_from_receipts, EthEvmConfig};
|
||||
use reth_evm_ethereum::{
|
||||
eip6110::parse_deposits_from_receipts, revm_spec_by_timestamp_after_merge, EthEvmConfig,
|
||||
};
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_payload_builder::{
|
||||
error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes,
|
||||
};
|
||||
use reth_payload_primitives::PayloadBuilderAttributes;
|
||||
use reth_primitives::{
|
||||
constants::{eip4844::MAX_DATA_GAS_PER_BLOCK, BEACON_NONCE},
|
||||
constants::{eip4844::MAX_DATA_GAS_PER_BLOCK, BEACON_NONCE, EIP1559_INITIAL_BASE_FEE},
|
||||
eip4844::calculate_excess_blob_gas,
|
||||
proofs::{self, calculate_requests_root},
|
||||
revm_primitives::{BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId},
|
||||
Block, EthereumHardforks, Header, IntoRecoveredTransaction, Receipt, EMPTY_OMMER_ROOT_HASH,
|
||||
U256,
|
||||
};
|
||||
@ -43,7 +48,9 @@ use reth_transaction_pool::{
|
||||
use reth_trie::HashedPostState;
|
||||
use revm::{
|
||||
db::states::bundle_state::BundleRetention,
|
||||
primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState},
|
||||
primitives::{
|
||||
BlobExcessGasAndPrice, EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState,
|
||||
},
|
||||
DatabaseCommit, State,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
@ -63,6 +70,84 @@ impl<EvmConfig> EthereumPayloadBuilder<EvmConfig> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<EvmConfig> EthereumPayloadBuilder<EvmConfig>
|
||||
where
|
||||
EvmConfig: ConfigureEvm,
|
||||
{
|
||||
/// Returns the configured [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for the targeted payload
|
||||
/// (that has the `parent` as its parent).
|
||||
///
|
||||
/// The `chain_spec` is used to determine the correct chain id and hardfork for the payload
|
||||
/// based on its timestamp.
|
||||
///
|
||||
/// Block related settings are derived from the `parent` block and the configured attributes.
|
||||
///
|
||||
/// NOTE: This is only intended for beacon consensus (after merge).
|
||||
fn cfg_and_block_env(
|
||||
&self,
|
||||
config: &PayloadConfig<EthPayloadBuilderAttributes>,
|
||||
parent: &Header,
|
||||
) -> (CfgEnvWithHandlerCfg, BlockEnv) {
|
||||
// configure evm env based on parent block
|
||||
let cfg = CfgEnv::default().with_chain_id(config.chain_spec.chain().id());
|
||||
|
||||
// ensure we're not missing any timestamp based hardforks
|
||||
let spec_id =
|
||||
revm_spec_by_timestamp_after_merge(&config.chain_spec, config.attributes.timestamp());
|
||||
|
||||
// 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
|
||||
let blob_excess_gas_and_price = parent
|
||||
.next_block_excess_blob_gas()
|
||||
.or_else(|| {
|
||||
if spec_id == SpecId::CANCUN {
|
||||
// default excess blob gas is zero
|
||||
Some(0)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(BlobExcessGasAndPrice::new);
|
||||
|
||||
let mut basefee = parent.next_block_base_fee(
|
||||
config.chain_spec.base_fee_params_at_timestamp(config.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 config.chain_spec.fork(EthereumHardfork::London).transitions_at_block(parent.number + 1)
|
||||
{
|
||||
let elasticity_multiplier = config
|
||||
.chain_spec
|
||||
.base_fee_params_at_timestamp(config.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: U256::from(parent.number + 1),
|
||||
coinbase: config.attributes.suggested_fee_recipient(),
|
||||
timestamp: U256::from(config.attributes.timestamp()),
|
||||
difficulty: U256::ZERO,
|
||||
prevrandao: Some(config.attributes.prev_randao()),
|
||||
gas_limit,
|
||||
// calculate basefee based on parent block's gas usage
|
||||
basefee: basefee.map(U256::from).unwrap_or_default(),
|
||||
// calculate excess gas based on parent block's blob gas usage
|
||||
blob_excess_gas_and_price,
|
||||
};
|
||||
|
||||
(CfgEnvWithHandlerCfg::new_with_spec_id(cfg, spec_id), block_env)
|
||||
}
|
||||
}
|
||||
|
||||
// Default implementation of [PayloadBuilder] for unit type
|
||||
impl<EvmConfig, Pool, Client> PayloadBuilder<Pool, Client> for EthereumPayloadBuilder<EvmConfig>
|
||||
where
|
||||
@ -77,7 +162,8 @@ where
|
||||
&self,
|
||||
args: BuildArguments<Pool, Client, EthPayloadBuilderAttributes, EthBuiltPayload>,
|
||||
) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError> {
|
||||
default_ethereum_payload(self.evm_config.clone(), args)
|
||||
let (cfg_env, block_env) = self.cfg_and_block_env(&args.config, &args.config.parent_block);
|
||||
default_ethereum_payload(self.evm_config.clone(), args, cfg_env, block_env)
|
||||
}
|
||||
|
||||
fn build_empty_payload(
|
||||
@ -94,7 +180,8 @@ where
|
||||
cancel: Default::default(),
|
||||
best_payload: None,
|
||||
};
|
||||
default_ethereum_payload(self.evm_config.clone(), args)?
|
||||
let (cfg_env, block_env) = self.cfg_and_block_env(&args.config, &args.config.parent_block);
|
||||
default_ethereum_payload(self.evm_config.clone(), args, cfg_env, block_env)?
|
||||
.into_payload()
|
||||
.ok_or_else(|| PayloadBuilderError::MissingPayload)
|
||||
}
|
||||
@ -109,6 +196,8 @@ where
|
||||
pub fn default_ethereum_payload<EvmConfig, Pool, Client>(
|
||||
evm_config: EvmConfig,
|
||||
args: BuildArguments<Pool, Client, EthPayloadBuilderAttributes, EthBuiltPayload>,
|
||||
initialized_cfg: CfgEnvWithHandlerCfg,
|
||||
initialized_block_env: BlockEnv,
|
||||
) -> Result<BuildOutcome<EthBuiltPayload>, PayloadBuilderError>
|
||||
where
|
||||
EvmConfig: ConfigureEvm,
|
||||
@ -121,15 +210,7 @@ where
|
||||
let state = StateProviderDatabase::new(state_provider);
|
||||
let mut db =
|
||||
State::builder().with_database_ref(cached_reads.as_db(state)).with_bundle_update().build();
|
||||
let extra_data = config.extra_data();
|
||||
let PayloadConfig {
|
||||
initialized_block_env,
|
||||
initialized_cfg,
|
||||
parent_block,
|
||||
attributes,
|
||||
chain_spec,
|
||||
..
|
||||
} = config;
|
||||
let PayloadConfig { parent_block, extra_data, attributes, chain_spec } = config;
|
||||
|
||||
debug!(target: "payload_builder", id=%attributes.id, parent_hash = ?parent_block.hash(), parent_number = parent_block.number, "building new payload");
|
||||
let mut cumulative_gas_used = 0;
|
||||
|
||||
@ -127,7 +127,10 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
|
||||
data: Bytes,
|
||||
);
|
||||
|
||||
/// Fill [`CfgEnvWithHandlerCfg`] fields according to the chain spec and given header
|
||||
/// Fill [`CfgEnvWithHandlerCfg`] fields according to the chain spec and given header.
|
||||
///
|
||||
/// This must set the corresponding spec id in the handler cfg, based on timestamp or total
|
||||
/// difficulty
|
||||
fn fill_cfg_env(
|
||||
&self,
|
||||
cfg_env: &mut CfgEnvWithHandlerCfg,
|
||||
@ -158,6 +161,8 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
|
||||
|
||||
/// Convenience function to call both [`fill_cfg_env`](ConfigureEvmEnv::fill_cfg_env) and
|
||||
/// [`ConfigureEvmEnv::fill_block_env`].
|
||||
///
|
||||
/// Note: Implementers should ensure that all fields are required fields are filled.
|
||||
fn fill_cfg_and_block_env(
|
||||
&self,
|
||||
cfg: &mut CfgEnvWithHandlerCfg,
|
||||
|
||||
@ -9,11 +9,16 @@ use reth_basic_payload_builder::*;
|
||||
use reth_chain_state::ExecutedBlock;
|
||||
use reth_chainspec::{EthereumHardforks, OptimismHardfork};
|
||||
use reth_evm::{system_calls::pre_block_beacon_root_contract_call, ConfigureEvm};
|
||||
use reth_evm_optimism::revm_spec_by_timestamp_after_bedrock;
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_payload_builder::error::PayloadBuilderError;
|
||||
use reth_payload_primitives::PayloadBuilderAttributes;
|
||||
use reth_primitives::{
|
||||
constants::BEACON_NONCE, eip4844::calculate_excess_blob_gas, proofs, Block, Header,
|
||||
IntoRecoveredTransaction, Receipt, TxType, EMPTY_OMMER_ROOT_HASH,
|
||||
constants::BEACON_NONCE,
|
||||
eip4844::calculate_excess_blob_gas,
|
||||
proofs,
|
||||
revm_primitives::{BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId},
|
||||
Block, Header, IntoRecoveredTransaction, Receipt, TxType, EMPTY_OMMER_ROOT_HASH,
|
||||
};
|
||||
use reth_provider::StateProviderFactory;
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
@ -23,7 +28,10 @@ use reth_transaction_pool::{
|
||||
use reth_trie::HashedPostState;
|
||||
use revm::{
|
||||
db::states::bundle_state::BundleRetention,
|
||||
primitives::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState},
|
||||
primitives::{
|
||||
BlobExcessGasAndPrice, EVMError, EnvWithHandlerCfg, HandlerCfg, InvalidTransaction,
|
||||
ResultAndState,
|
||||
},
|
||||
DatabaseCommit, State,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
@ -60,6 +68,64 @@ impl<EvmConfig> OptimismPayloadBuilder<EvmConfig> {
|
||||
pub const fn is_compute_pending_block(&self) -> bool {
|
||||
self.compute_pending_block
|
||||
}
|
||||
|
||||
fn cfg_and_block_env(
|
||||
&self,
|
||||
config: &PayloadConfig<OptimismPayloadBuilderAttributes>,
|
||||
parent: &Header,
|
||||
) -> (CfgEnvWithHandlerCfg, BlockEnv) {
|
||||
// configure evm env based on parent block
|
||||
let cfg = CfgEnv::default().with_chain_id(config.chain_spec.chain().id());
|
||||
|
||||
// ensure we're not missing any timestamp based hardforks
|
||||
let spec_id =
|
||||
revm_spec_by_timestamp_after_bedrock(&config.chain_spec, config.attributes.timestamp());
|
||||
|
||||
// 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
|
||||
let blob_excess_gas_and_price = parent
|
||||
.next_block_excess_blob_gas()
|
||||
.or_else(|| {
|
||||
if spec_id.is_enabled_in(SpecId::CANCUN) {
|
||||
// default excess blob gas is zero
|
||||
Some(0)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(BlobExcessGasAndPrice::new);
|
||||
|
||||
let block_env = BlockEnv {
|
||||
number: U256::from(parent.number + 1),
|
||||
coinbase: config.attributes.suggested_fee_recipient(),
|
||||
timestamp: U256::from(config.attributes.timestamp()),
|
||||
difficulty: U256::ZERO,
|
||||
prevrandao: Some(config.attributes.prev_randao()),
|
||||
gas_limit: U256::from(parent.gas_limit),
|
||||
// calculate basefee based on parent block's gas usage
|
||||
basefee: U256::from(
|
||||
parent
|
||||
.next_block_base_fee(
|
||||
config
|
||||
.chain_spec
|
||||
.base_fee_params_at_timestamp(config.attributes.timestamp()),
|
||||
)
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
// calculate excess gas based on parent block's blob gas usage
|
||||
blob_excess_gas_and_price,
|
||||
};
|
||||
|
||||
let cfg_with_handler_cfg;
|
||||
{
|
||||
cfg_with_handler_cfg = CfgEnvWithHandlerCfg {
|
||||
cfg_env: cfg,
|
||||
handler_cfg: HandlerCfg { spec_id, is_optimism: true },
|
||||
};
|
||||
}
|
||||
|
||||
(cfg_with_handler_cfg, block_env)
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of the [`PayloadBuilder`] trait for [`OptimismPayloadBuilder`].
|
||||
@ -76,7 +142,14 @@ where
|
||||
&self,
|
||||
args: BuildArguments<Pool, Client, OptimismPayloadBuilderAttributes, OptimismBuiltPayload>,
|
||||
) -> Result<BuildOutcome<OptimismBuiltPayload>, PayloadBuilderError> {
|
||||
optimism_payload(self.evm_config.clone(), args, self.compute_pending_block)
|
||||
let (cfg_env, block_env) = self.cfg_and_block_env(&args.config, &args.config.parent_block);
|
||||
optimism_payload(
|
||||
self.evm_config.clone(),
|
||||
args,
|
||||
cfg_env,
|
||||
block_env,
|
||||
self.compute_pending_block,
|
||||
)
|
||||
}
|
||||
|
||||
fn on_missing_payload(
|
||||
@ -104,7 +177,8 @@ where
|
||||
cancel: Default::default(),
|
||||
best_payload: None,
|
||||
};
|
||||
optimism_payload(self.evm_config.clone(), args, false)?
|
||||
let (cfg_env, block_env) = self.cfg_and_block_env(&args.config, &args.config.parent_block);
|
||||
optimism_payload(self.evm_config.clone(), args, cfg_env, block_env, false)?
|
||||
.into_payload()
|
||||
.ok_or_else(|| PayloadBuilderError::MissingPayload)
|
||||
}
|
||||
@ -122,6 +196,8 @@ where
|
||||
pub(crate) fn optimism_payload<EvmConfig, Pool, Client>(
|
||||
evm_config: EvmConfig,
|
||||
args: BuildArguments<Pool, Client, OptimismPayloadBuilderAttributes, OptimismBuiltPayload>,
|
||||
initialized_cfg: CfgEnvWithHandlerCfg,
|
||||
initialized_block_env: BlockEnv,
|
||||
_compute_pending_block: bool,
|
||||
) -> Result<BuildOutcome<OptimismBuiltPayload>, PayloadBuilderError>
|
||||
where
|
||||
@ -135,15 +211,7 @@ where
|
||||
let state = StateProviderDatabase::new(state_provider);
|
||||
let mut db =
|
||||
State::builder().with_database_ref(cached_reads.as_db(state)).with_bundle_update().build();
|
||||
let extra_data = config.extra_data();
|
||||
let PayloadConfig {
|
||||
initialized_block_env,
|
||||
initialized_cfg,
|
||||
parent_block,
|
||||
attributes,
|
||||
chain_spec,
|
||||
..
|
||||
} = config;
|
||||
let PayloadConfig { parent_block, attributes, chain_spec, extra_data } = config;
|
||||
|
||||
debug!(target: "payload_builder", id=%attributes.payload_attributes.payload_id(), parent_hash = ?parent_block.hash(), parent_number = parent_block.number, "building new payload");
|
||||
|
||||
|
||||
@ -6,13 +6,10 @@ use alloy_primitives::{Address, B256, U256};
|
||||
use alloy_rlp::Encodable;
|
||||
use reth_chain_state::ExecutedBlock;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_evm_optimism::revm_spec_by_timestamp_after_bedrock;
|
||||
use reth_payload_builder::EthPayloadBuilderAttributes;
|
||||
use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes};
|
||||
use reth_primitives::{
|
||||
revm_primitives::{BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, SpecId},
|
||||
transaction::WithEncoded,
|
||||
BlobTransactionSidecar, Header, SealedBlock, TransactionSigned, Withdrawals,
|
||||
transaction::WithEncoded, BlobTransactionSidecar, SealedBlock, TransactionSigned, Withdrawals,
|
||||
};
|
||||
/// Re-export for use in downstream arguments.
|
||||
pub use reth_rpc_types::optimism::OptimismPayloadAttributes;
|
||||
@ -24,7 +21,6 @@ use reth_rpc_types_compat::engine::payload::{
|
||||
block_to_payload_v1, block_to_payload_v3, block_to_payload_v4,
|
||||
convert_block_to_payload_field_v2,
|
||||
};
|
||||
use revm::primitives::HandlerCfg;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Optimism Payload Builder Attributes
|
||||
@ -106,59 +102,6 @@ impl PayloadBuilderAttributes for OptimismPayloadBuilderAttributes {
|
||||
fn withdrawals(&self) -> &Withdrawals {
|
||||
&self.payload_attributes.withdrawals
|
||||
}
|
||||
|
||||
fn cfg_and_block_env(
|
||||
&self,
|
||||
chain_spec: &ChainSpec,
|
||||
parent: &Header,
|
||||
) -> (CfgEnvWithHandlerCfg, BlockEnv) {
|
||||
// configure evm env based on parent block
|
||||
let cfg = CfgEnv::default().with_chain_id(chain_spec.chain().id());
|
||||
|
||||
// ensure we're not missing any timestamp based hardforks
|
||||
let spec_id = revm_spec_by_timestamp_after_bedrock(chain_spec, self.timestamp());
|
||||
|
||||
// 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
|
||||
let blob_excess_gas_and_price = parent
|
||||
.next_block_excess_blob_gas()
|
||||
.or_else(|| {
|
||||
if spec_id.is_enabled_in(SpecId::CANCUN) {
|
||||
// default excess blob gas is zero
|
||||
Some(0)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(BlobExcessGasAndPrice::new);
|
||||
|
||||
let block_env = BlockEnv {
|
||||
number: U256::from(parent.number + 1),
|
||||
coinbase: self.suggested_fee_recipient(),
|
||||
timestamp: U256::from(self.timestamp()),
|
||||
difficulty: U256::ZERO,
|
||||
prevrandao: Some(self.prev_randao()),
|
||||
gas_limit: U256::from(parent.gas_limit),
|
||||
// calculate basefee based on parent block's gas usage
|
||||
basefee: U256::from(
|
||||
parent
|
||||
.next_block_base_fee(chain_spec.base_fee_params_at_timestamp(self.timestamp()))
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
// calculate excess gas based on parent block's blob gas usage
|
||||
blob_excess_gas_and_price,
|
||||
};
|
||||
|
||||
let cfg_with_handler_cfg;
|
||||
{
|
||||
cfg_with_handler_cfg = CfgEnvWithHandlerCfg {
|
||||
cfg_env: cfg,
|
||||
handler_cfg: HandlerCfg { spec_id, is_optimism: true },
|
||||
};
|
||||
}
|
||||
|
||||
(cfg_with_handler_cfg, block_env)
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains the built payload.
|
||||
|
||||
@ -27,10 +27,7 @@ use reth_provider::{
|
||||
use reth_revm::state_change::post_block_withdrawals_balance_increments;
|
||||
use reth_tasks::TaskSpawner;
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use revm::{
|
||||
primitives::{BlockEnv, CfgEnvWithHandlerCfg},
|
||||
Database, State,
|
||||
};
|
||||
use revm::{Database, State};
|
||||
use std::{
|
||||
fmt,
|
||||
future::Future,
|
||||
@ -673,10 +670,6 @@ impl Drop for Cancelled {
|
||||
/// Static config for how to build a payload.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PayloadConfig<Attributes> {
|
||||
/// Pre-configured block environment.
|
||||
pub initialized_block_env: BlockEnv,
|
||||
/// Configuration for the environment.
|
||||
pub initialized_cfg: CfgEnvWithHandlerCfg,
|
||||
/// The parent block.
|
||||
pub parent_block: Arc<SealedBlock>,
|
||||
/// Block extra data.
|
||||
@ -699,24 +692,13 @@ where
|
||||
Attributes: PayloadBuilderAttributes,
|
||||
{
|
||||
/// Create new payload config.
|
||||
pub fn new(
|
||||
pub const fn new(
|
||||
parent_block: Arc<SealedBlock>,
|
||||
extra_data: Bytes,
|
||||
attributes: Attributes,
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
) -> Self {
|
||||
// configure evm env based on parent block
|
||||
let (initialized_cfg, initialized_block_env) =
|
||||
attributes.cfg_and_block_env(&chain_spec, &parent_block);
|
||||
|
||||
Self {
|
||||
initialized_block_env,
|
||||
initialized_cfg,
|
||||
parent_block,
|
||||
extra_data,
|
||||
attributes,
|
||||
chain_spec,
|
||||
}
|
||||
Self { parent_block, extra_data, attributes, chain_spec }
|
||||
}
|
||||
|
||||
/// Returns the payload id.
|
||||
|
||||
@ -1,19 +1,15 @@
|
||||
use crate::{
|
||||
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
|
||||
};
|
||||
use reth_chain_state::ExecutedBlock;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_primitives::{
|
||||
revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg},
|
||||
Address, Header, SealedBlock, Withdrawals, B256, U256,
|
||||
};
|
||||
use reth_primitives::{Address, SealedBlock, Withdrawals, B256, U256};
|
||||
use reth_rpc_types::{
|
||||
engine::{PayloadAttributes as EthPayloadAttributes, PayloadId},
|
||||
optimism::OptimismPayloadAttributes,
|
||||
Withdrawal,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
|
||||
};
|
||||
|
||||
/// Represents a built payload type that contains a built [`SealedBlock`] and can be converted into
|
||||
/// engine API execution payloads.
|
||||
pub trait BuiltPayload: Send + Sync + std::fmt::Debug {
|
||||
@ -70,21 +66,6 @@ pub trait PayloadBuilderAttributes: Send + Sync + std::fmt::Debug {
|
||||
|
||||
/// Returns the withdrawals for the running payload job.
|
||||
fn withdrawals(&self) -> &Withdrawals;
|
||||
|
||||
/// Returns the configured [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for the targeted payload
|
||||
/// (that has the `parent` as its parent).
|
||||
///
|
||||
/// The `chain_spec` is used to determine the correct chain id and hardfork for the payload
|
||||
/// based on its timestamp.
|
||||
///
|
||||
/// Block related settings are derived from the `parent` block and the configured attributes.
|
||||
///
|
||||
/// NOTE: This is only intended for beacon consensus (after merge).
|
||||
fn cfg_and_block_env(
|
||||
&self,
|
||||
chain_spec: &ChainSpec,
|
||||
parent: &Header,
|
||||
) -> (CfgEnvWithHandlerCfg, BlockEnv);
|
||||
}
|
||||
|
||||
/// The execution payload attribute type the CL node emits via the engine API.
|
||||
|
||||
Reference in New Issue
Block a user