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:
garwah
2024-09-17 21:43:31 +10:00
committed by GitHub
parent abd4642d65
commit 2a04b1c100
12 changed files with 203 additions and 317 deletions

View File

@ -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

View File

@ -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",

View File

@ -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();
}
}

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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");

View File

@ -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.

View File

@ -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.

View File

@ -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.