Skip to content

Commit

Permalink
feat(executor): Update EIP-1559 configurability (#648)
Browse files Browse the repository at this point in the history
* feat(executor): Update EIP-1559 configurability

* fmt
  • Loading branch information
clabby authored Oct 7, 2024
1 parent aa8c8d4 commit 5dd6f3c
Showing 1 changed file with 68 additions and 27 deletions.
95 changes: 68 additions & 27 deletions crates/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ where
payload: OptimismPayloadAttributes,
) -> ExecutorResult<&Header> {
// Prepare the `revm` environment.
let base_fee_params = Self::active_base_fee_params(self.config, &payload)?;
let base_fee_params = Self::active_base_fee_params(
self.config,
self.trie_db.parent_block_header(),
&payload,
)?;
let initialized_block_env = Self::prepare_block_env(
self.revm_spec_id(payload.payload_attributes.timestamp),
self.trie_db.parent_block_header(),
Expand Down Expand Up @@ -306,19 +310,25 @@ where
})
.unwrap_or_default();

// At holocene activation, the base fee parameters from the payload are placed
// into the Header's `nonce` field. Prior to Holocene, the `nonce` field should
// be set to 0.
//
// If the payload's `eip_1559_params` are equal to `0`, then the header's `nonce`
// field is set to the encoded canyon base fee parameters.
let encoded_base_fee_params = self
.config
.is_holocene_active(payload.payload_attributes.timestamp)
.then(|| {
let mut encoded_params = B64::ZERO;
encoded_params[0..4].copy_from_slice(
(base_fee_params.max_change_denominator as u32).to_be_bytes().as_ref(),
);
encoded_params[4..8].copy_from_slice(
(base_fee_params.elasticity_multiplier as u32).to_be_bytes().as_ref(),
);
encoded_params
let payload_params =
payload.eip_1559_params.ok_or(ExecutorError::MissingEIP1559Params)?;

let params = (payload_params == B64::ZERO)
.then(|| encode_canyon_base_fee_params(self.config))
.unwrap_or(payload_params);
Ok::<_, ExecutorError>(params)
})
.transpose()?
.unwrap_or_default();

// Construct the new header.
Expand Down Expand Up @@ -546,33 +556,40 @@ where
///
/// ## Takes
/// - `config`: The rollup config to use for the computation.
/// - `parent_header`: The parent header of the block to be executed.
/// - `payload_attrs`: The payload attributes to use for the computation.
fn active_base_fee_params(
config: &RollupConfig,
parent_header: &Header,
payload_attrs: &OptimismPayloadAttributes,
) -> ExecutorResult<BaseFeeParams> {
// If the payload attribute timestamp is past canyon activation,
// use the canyon base fee params from the rollup config.
let base_fee_params =
if config.is_holocene_active(payload_attrs.payload_attributes.timestamp) {
let params =
payload_attrs.eip_1559_params.ok_or(ExecutorError::MissingEIP1559Params)?;

// If the parameters sent are equal to `0`, use the canyon base fee params.
// Otherwise, use the EIP-1559 parameters sent through the payload.
if params == B64::ZERO {
config.canyon_base_fee_params
} else {
let denominator = u32::from_be_bytes(params[0..4].try_into().unwrap());
let elasticity = u32::from_be_bytes(params[4..8].try_into().unwrap());
BaseFeeParams {
max_change_denominator: denominator as u128,
elasticity_multiplier: elasticity as u128,
}
}
// After Holocene activation, the base fee parameters are stored in the
// `nonce` field of the parent header. If the `nonce` field is not zero,
// then the base fee parameters are extracted from the `nonce` field.
// Otherwise, the canyon base fee parameters are used for the current block.
(parent_header.nonce != B64::ZERO)
.then(|| {
// SAFETY: The `nonce` field is always 8 bytes, and the 4-byte segments are
// guaranteed to be valid `u32` values.
let denominator: u32 =
u32::from_be_bytes(parent_header.nonce[0..4].try_into().unwrap());
let elasticity: u32 =
u32::from_be_bytes(parent_header.nonce[4..8].try_into().unwrap());
BaseFeeParams {
max_change_denominator: denominator as u128,
elasticity_multiplier: elasticity as u128,
}
})
.unwrap_or(config.canyon_base_fee_params)
} else if config.is_canyon_active(payload_attrs.payload_attributes.timestamp) {
// If the payload attribute timestamp is past canyon activation,
// use the canyon base fee params from the rollup config.
config.canyon_base_fee_params
} else {
// If the payload attribute timestamp is prior to canyon activation,
// use the default base fee params from the rollup config.
config.base_fee_params
};

Expand Down Expand Up @@ -696,10 +713,22 @@ where
}
}

/// Encodes the canyon base fee parameters, per Holocene spec.
///
/// <https://specs.optimism.io/protocol/holocene/exec-engine.html#eip1559params-encoding>
fn encode_canyon_base_fee_params(config: &RollupConfig) -> B64 {
let params = config.canyon_base_fee_params;

let mut buf = B64::ZERO;
buf[0..4].copy_from_slice(&(params.max_change_denominator as u32).to_be_bytes());
buf[4..8].copy_from_slice(&(params.elasticity_multiplier as u32).to_be_bytes());
buf
}

#[cfg(test)]
mod test {
use super::*;
use alloy_primitives::{address, b256, hex};
use alloy_primitives::{address, b256, b64, hex};
use alloy_rlp::Decodable;
use alloy_rpc_types_engine::PayloadAttributes;
use anyhow::{anyhow, Result};
Expand Down Expand Up @@ -753,6 +782,18 @@ mod test {
}
}

#[test]
fn test_encode_canyon_1559_params() {
let cfg = RollupConfig {
canyon_base_fee_params: BaseFeeParams {
max_change_denominator: 32,
elasticity_multiplier: 64,
},
..Default::default()
};
assert_eq!(encode_canyon_base_fee_params(&cfg), b64!("0000002000000040"));
}

#[test]
fn test_l2_block_executor_small_block() {
// Static for the execution of block #120794432 on OP mainnet.
Expand Down

0 comments on commit 5dd6f3c

Please sign in to comment.