Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add eip1559 params to payload #11473

Closed
wants to merge 16 commits into from
Closed
349 changes: 171 additions & 178 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions crates/ethereum/engine-primitives/src/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,20 @@ impl PayloadBuilderAttributes for EthPayloadBuilderAttributes {
}
}

impl Default for EthPayloadBuilderAttributes {
fn default() -> Self {
Self {
id: PayloadId::new([0; 8]),
parent: B256::default(),
timestamp: 0,
suggested_fee_recipient: Address::ZERO,
prev_randao: B256::default(),
withdrawals: Withdrawals::default(),
parent_beacon_block_root: None,
}
}
}
Comment on lines +251 to +263
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can probably be derived

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires this change in alloy I think, PTAL
alloy-rs/alloy#1442


/// Generates the payload id for the configured payload from the [`PayloadAttributes`].
///
/// Returns an 8-byte identifier by hashing the payload components with sha256 hash.
Expand Down
133 changes: 130 additions & 3 deletions crates/optimism/chainspec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mod op_sepolia;
use std::fmt::Display;

use alloy_genesis::Genesis;
use alloy_primitives::{Parity, Signature, B256, U256};
use alloy_primitives::{b64, Parity, Signature, B256, B64, U256};
pub use base::BASE_MAINNET;
pub use base_sepolia::BASE_SEPOLIA;
pub use dev::OP_DEV;
Expand All @@ -34,21 +34,62 @@ use reth_chainspec::{
};
use reth_ethereum_forks::{ChainHardforks, EthereumHardfork, ForkCondition};
use reth_network_peers::NodeRecord;
use reth_optimism_forks::OptimismHardfork;
use reth_primitives_traits::Header;

/// These are the masks for the base fee denominator and elasticity in the nonce, post Holocene
const DENOMINATOR_MASK: B64 = b64!("FFFFFFFF00000000");
const ELASTICITY_MASK: B64 = b64!("00000000FFFFFFFF");

/// OP stack chain spec type.
#[derive(Debug, Clone, Deref, Into, Constructor, PartialEq, Eq)]
pub struct OpChainSpec {
/// [`ChainSpec`].
pub inner: ChainSpec,
}

/// Fee trait for OP chain specs.
pub trait Fee {
/// Read from parent to determine the base fee for the next block
fn next_block_base_fee(&self, parent: &Header, timestamp: u64) -> U256;
}

/// Returns the signature for the optimism deposit transactions, which don't include a
/// signature.
pub fn optimism_deposit_tx_signature() -> Signature {
Signature::new(U256::ZERO, U256::ZERO, Parity::Parity(false))
}

/// Extracts the Holcene 1599 parameters from the encoded form:
/// <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/holocene/exec-engine.md#eip1559params-encoding>
pub fn decode_holocene_1559_params(nonce: B64) -> (u64, u64) {
let elasticity = nonce & ELASTICITY_MASK;
let denominator = nonce & DENOMINATOR_MASK;
(elasticity.into(), denominator.into())
}

impl Fee for OpChainSpec {
fn next_block_base_fee(&self, parent: &Header, timestamp: u64) -> U256 {
clabby marked this conversation as resolved.
Show resolved Hide resolved
let is_holocene =
self.inner.is_fork_active_at_timestamp(OptimismHardfork::Holocene, timestamp);
// If we are in the Holocene, we need to use the base fee params from the parent block's
// nonce Else, use the base fee params from chainspec
if is_holocene && parent.nonce != B64::ZERO {
// First 4 bytes of the nonce are the base fee denominator, the last 4 bytes are the
// elasticity
let (elasticity, denominator) = decode_holocene_1559_params(parent.nonce);
let base_fee_params = BaseFeeParams::new(denominator as u128, elasticity as u128);
U256::from(parent.next_block_base_fee(base_fee_params).unwrap_or_default())
} else {
U256::from(
parent
.next_block_base_fee(self.base_fee_params_at_timestamp(timestamp))
.unwrap_or_default(),
)
}
}
}

impl EthChainSpec for OpChainSpec {
fn chain(&self) -> alloy_chains::Chain {
self.inner.chain()
Expand Down Expand Up @@ -272,11 +313,14 @@ impl OptimismGenesisInfo {

#[cfg(test)]
mod tests {
use crate::OpChainSpec;
use alloc::sync::Arc;
use alloy_genesis::{ChainConfig, Genesis};
use alloy_primitives::b256;
use reth_chainspec::{test_fork_ids, BaseFeeParams, BaseFeeParamsKind};
use alloy_primitives::{b256, U256};
use reth_chainspec::{test_fork_ids, BaseFeeParams, BaseFeeParamsKind, ChainSpec};
use reth_ethereum_forks::{EthereumHardfork, ForkCondition, ForkHash, ForkId, Head};
use reth_optimism_forks::{OptimismHardfork, OptimismHardforks};
use std::str::FromStr;

use crate::*;

Expand Down Expand Up @@ -770,4 +814,87 @@ mod tests {
.all(|(expected, actual)| &**expected == *actual));
assert_eq!(expected_hardforks.len(), hardforks.len());
}

#[test]
fn test_get_base_fee_pre_holocene() {
let op_chain_spec = &BASE_SEPOLIA;
let parent = Header {
base_fee_per_gas: Some(1),
gas_used: 15763614,
gas_limit: 144000000,
..Default::default()
};
let base_fee = op_chain_spec.next_block_base_fee(&parent, 0);
assert_eq!(
base_fee,
U256::from(
parent
.next_block_base_fee(op_chain_spec.base_fee_params_at_timestamp(0))
.unwrap_or_default()
)
);
}

fn holocene_chainspec() -> Arc<OpChainSpec> {
let mut hardforks = OptimismHardfork::base_sepolia();
hardforks.insert(OptimismHardfork::Holocene.boxed(), ForkCondition::Timestamp(1800000000));
Arc::new(OpChainSpec {
inner: ChainSpec {
chain: BASE_SEPOLIA.inner.chain,
genesis: BASE_SEPOLIA.inner.genesis.clone(),
genesis_hash: BASE_SEPOLIA.inner.genesis_hash.clone(),
paris_block_and_final_difficulty: Some((0, U256::from(0))),
hardforks,
base_fee_params: BASE_SEPOLIA.inner.base_fee_params.clone(),
max_gas_limit: crate::constants::BASE_SEPOLIA_MAX_GAS_LIMIT,
prune_delete_limit: 10000,
..Default::default()
},
})
}

#[test]
fn test_get_base_fee_holocene_nonce_not_set() {
let op_chain_spec = holocene_chainspec();
let parent = Header {
base_fee_per_gas: Some(1),
gas_used: 15763614,
gas_limit: 144000000,
timestamp: 1800000003,
..Default::default()
};

let base_fee = op_chain_spec.next_block_base_fee(&parent, 1800000005);
assert_eq!(
base_fee,
U256::from(
parent
.next_block_base_fee(op_chain_spec.base_fee_params_at_timestamp(0))
.unwrap_or_default()
)
);
}

#[test]
fn test_get_base_fee_holocene_nonce_set() {
let op_chain_spec = holocene_chainspec();
let parent = Header {
base_fee_per_gas: Some(1),
gas_used: 15763614,
gas_limit: 144000000,
nonce: B64::from_str("0x0000000800000008").unwrap(),
timestamp: 1800000003,
..Default::default()
};

let base_fee = op_chain_spec.next_block_base_fee(&parent, 1800000005);
assert_eq!(
base_fee,
U256::from(
parent
.next_block_base_fee(BaseFeeParams::new(0x00000008, 0x00000008))
.unwrap_or_default()
)
);
}
}
3 changes: 1 addition & 2 deletions crates/optimism/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ reth-prune-types.workspace = true

# ethereum
alloy-primitives.workspace = true
alloy-eips.workspace = true
op-alloy-consensus.workspace = true

# Optimism
Expand All @@ -39,8 +40,6 @@ thiserror.workspace = true
tracing.workspace = true

[dev-dependencies]
alloy-eips.workspace = true

reth-revm = { workspace = true, features = ["test-utils"] }
reth-optimism-chainspec.workspace = true
alloy-genesis.workspace = true
Expand Down
8 changes: 6 additions & 2 deletions crates/optimism/evm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ pub fn revm_spec_by_timestamp_after_bedrock(
chain_spec: &ChainSpec,
timestamp: u64,
) -> revm_primitives::SpecId {
if chain_spec.fork(OptimismHardfork::Granite).active_at_timestamp(timestamp) {
if chain_spec.fork(OptimismHardfork::Holocene).active_at_timestamp(timestamp) {
revm_primitives::HOLOCENE
} else if chain_spec.fork(OptimismHardfork::Granite).active_at_timestamp(timestamp) {
revm_primitives::GRANITE
} else if chain_spec.fork(OptimismHardfork::Fjord).active_at_timestamp(timestamp) {
revm_primitives::FJORD
Expand All @@ -29,7 +31,9 @@ pub fn revm_spec_by_timestamp_after_bedrock(

/// Map the latest active hardfork at the given block to a revm [`SpecId`](revm_primitives::SpecId).
pub fn revm_spec(chain_spec: &ChainSpec, block: &Head) -> revm_primitives::SpecId {
if chain_spec.fork(OptimismHardfork::Granite).active_at_head(block) {
if chain_spec.fork(OptimismHardfork::Holocene).active_at_head(block) {
revm_primitives::HOLOCENE
} else if chain_spec.fork(OptimismHardfork::Granite).active_at_head(block) {
revm_primitives::GRANITE
} else if chain_spec.fork(OptimismHardfork::Fjord).active_at_head(block) {
revm_primitives::FJORD
Expand Down
10 changes: 2 additions & 8 deletions crates/optimism/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

use alloy_primitives::{Address, U256};
use reth_evm::{ConfigureEvm, ConfigureEvmEnv, NextBlockEnvAttributes};
use reth_optimism_chainspec::OpChainSpec;
use reth_optimism_chainspec::{Fee, OpChainSpec};
use reth_primitives::{
revm_primitives::{AnalysisKind, CfgEnvWithHandlerCfg, TxEnv},
transaction::FillTxEnv,
Expand Down Expand Up @@ -160,13 +160,7 @@ impl ConfigureEvmEnv for OptimismEvmConfig {
prevrandao: Some(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(
self.chain_spec.base_fee_params_at_timestamp(attributes.timestamp),
)
.unwrap_or_default(),
),
basefee: self.chain_spec.next_block_base_fee(parent, attributes.timestamp),
// calculate excess gas based on parent block's blob gas usage
blob_excess_gas_and_price,
};
Expand Down
4 changes: 4 additions & 0 deletions crates/optimism/hardforks/src/hardfork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ hardfork!(
Fjord,
/// Granite: <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#granite>
Granite,
/// Holocene: <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#holocene>
Holocene,
}
);

Expand Down Expand Up @@ -156,6 +158,7 @@ impl OptimismHardfork {
Self::Ecotone => Some(1708534800),
Self::Fjord => Some(1716998400),
Self::Granite => Some(1723478400),
Self::Holocene => None, // TODO: update when Holocene is defined
},
)
}
Expand Down Expand Up @@ -190,6 +193,7 @@ impl OptimismHardfork {
Self::Ecotone => Some(1710374401),
Self::Fjord => Some(1720627201),
Self::Granite => Some(1726070401),
Self::Holocene => None, // TODO: update when Holocene is defined
},
)
}
Expand Down
Loading
Loading