From 9a1d6ea9ca7d6522b7610b65871eb562ff080e67 Mon Sep 17 00:00:00 2001 From: Darshan Kathiriya <8559992+lakshya-sky@users.noreply.github.com> Date: Mon, 22 Apr 2024 11:46:56 -0400 Subject: [PATCH] feat: base fee param fetching at a specific block (#7783) --- crates/consensus/auto-seal/src/lib.rs | 7 ++- .../ethereum/engine-primitives/src/payload.rs | 5 ++- crates/payload/optimism/src/payload.rs | 2 +- crates/primitives/src/chain/spec.rs | 44 +++++++++++++++---- crates/primitives/src/header.rs | 25 ++++++----- crates/rpc/rpc/src/eth/api/fee_history.rs | 2 +- crates/rpc/rpc/src/eth/api/fees.rs | 2 +- crates/rpc/rpc/src/eth/api/mod.rs | 5 ++- crates/transaction-pool/src/maintain.rs | 10 +++-- 9 files changed, 69 insertions(+), 33 deletions(-) diff --git a/crates/consensus/auto-seal/src/lib.rs b/crates/consensus/auto-seal/src/lib.rs index 59efc0d48..62a293664 100644 --- a/crates/consensus/auto-seal/src/lib.rs +++ b/crates/consensus/auto-seal/src/lib.rs @@ -277,10 +277,9 @@ impl StorageInner { let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs(); // check previous block for base fee - let base_fee_per_gas = self - .headers - .get(&self.best_block) - .and_then(|parent| parent.next_block_base_fee(chain_spec.base_fee_params(timestamp))); + let base_fee_per_gas = self.headers.get(&self.best_block).and_then(|parent| { + parent.next_block_base_fee(chain_spec.base_fee_params_at_timestamp(timestamp)) + }); let mut header = Header { parent_hash: self.best_hash, diff --git a/crates/ethereum/engine-primitives/src/payload.rs b/crates/ethereum/engine-primitives/src/payload.rs index 6e8c820a7..a6c47ebde 100644 --- a/crates/ethereum/engine-primitives/src/payload.rs +++ b/crates/ethereum/engine-primitives/src/payload.rs @@ -245,7 +245,8 @@ impl PayloadBuilderAttributes for EthPayloadBuilderAttributes { }) .map(BlobExcessGasAndPrice::new); - let mut basefee = parent.next_block_base_fee(chain_spec.base_fee_params(self.timestamp())); + 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); @@ -253,7 +254,7 @@ impl PayloadBuilderAttributes for EthPayloadBuilderAttributes { // elasticity multiplier to get the new gas limit. if chain_spec.fork(Hardfork::London).transitions_at_block(parent.number + 1) { let elasticity_multiplier = - chain_spec.base_fee_params(self.timestamp()).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); diff --git a/crates/payload/optimism/src/payload.rs b/crates/payload/optimism/src/payload.rs index 0e4b0c826..d753370fd 100644 --- a/crates/payload/optimism/src/payload.rs +++ b/crates/payload/optimism/src/payload.rs @@ -142,7 +142,7 @@ impl PayloadBuilderAttributes for OptimismPayloadBuilderAttributes { // calculate basefee based on parent block's gas usage basefee: U256::from( parent - .next_block_base_fee(chain_spec.base_fee_params(self.timestamp())) + .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 diff --git a/crates/primitives/src/chain/spec.rs b/crates/primitives/src/chain/spec.rs index 6b2a6a4dc..ee732a9bc 100644 --- a/crates/primitives/src/chain/spec.rs +++ b/crates/primitives/src/chain/spec.rs @@ -661,10 +661,10 @@ impl ChainSpec { } /// Get the [BaseFeeParams] for the chain at the given timestamp. - pub fn base_fee_params(&self, timestamp: u64) -> BaseFeeParams { + pub fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams { match self.base_fee_params { BaseFeeParamsKind::Constant(bf_params) => bf_params, - BaseFeeParamsKind::Variable(ForkBaseFeeParams { 0: ref bf_params }) => { + BaseFeeParamsKind::Variable(ForkBaseFeeParams(ref bf_params)) => { // Walk through the base fee params configuration in reverse order, and return the // first one that corresponds to a hardfork that is active at the // given timestamp. @@ -679,6 +679,25 @@ impl ChainSpec { } } + /// Get the [BaseFeeParams] for the chain at the given block number + pub fn base_fee_params_at_block(&self, block_number: u64) -> BaseFeeParams { + match self.base_fee_params { + BaseFeeParamsKind::Constant(bf_params) => bf_params, + BaseFeeParamsKind::Variable(ForkBaseFeeParams(ref bf_params)) => { + // Walk through the base fee params configuration in reverse order, and return the + // first one that corresponds to a hardfork that is active at the + // given timestamp. + for (fork, params) in bf_params.iter().rev() { + if self.is_fork_active_at_block(*fork, block_number) { + return *params + } + } + + bf_params.first().map(|(_, params)| *params).unwrap_or(BaseFeeParams::ethereum()) + } + } + } + /// Get the hash of the genesis block. pub fn genesis_hash(&self) -> B256 { self.genesis_hash.unwrap_or_else(|| self.genesis_header().hash_slow()) @@ -770,6 +789,12 @@ impl ChainSpec { self.fork(fork).active_at_timestamp(timestamp) } + /// Convenience method to check if a fork is active at a given block number + #[inline] + pub fn is_fork_active_at_block(&self, fork: Hardfork, block_number: u64) -> bool { + self.fork(fork).active_at_block(block_number) + } + /// Convenience method to check if [Hardfork::Shanghai] is active at a given timestamp. #[inline] pub fn is_shanghai_active_at_timestamp(&self, timestamp: u64) -> bool { @@ -3168,8 +3193,9 @@ Post-merge hard forks (timestamp based): genesis.hash_slow(), b256!("f712aa9241cc24369b143cf6dce85f0902a9731e70d66818a3a5845b296c73dd") ); - let base_fee = - genesis.next_block_base_fee(BASE_MAINNET.base_fee_params(genesis.timestamp)).unwrap(); + let base_fee = genesis + .next_block_base_fee(BASE_MAINNET.base_fee_params_at_timestamp(genesis.timestamp)) + .unwrap(); // assert_eq!(base_fee, 980000000); } @@ -3182,8 +3208,9 @@ Post-merge hard forks (timestamp based): genesis.hash_slow(), b256!("0dcc9e089e30b90ddfc55be9a37dd15bc551aeee999d2e2b51414c54eaf934e4") ); - let base_fee = - genesis.next_block_base_fee(BASE_SEPOLIA.base_fee_params(genesis.timestamp)).unwrap(); + let base_fee = genesis + .next_block_base_fee(BASE_SEPOLIA.base_fee_params_at_timestamp(genesis.timestamp)) + .unwrap(); // assert_eq!(base_fee, 980000000); } @@ -3196,8 +3223,9 @@ Post-merge hard forks (timestamp based): genesis.hash_slow(), b256!("102de6ffb001480cc9b8b548fd05c34cd4f46ae4aa91759393db90ea0409887d") ); - let base_fee = - genesis.next_block_base_fee(OP_SEPOLIA.base_fee_params(genesis.timestamp)).unwrap(); + let base_fee = genesis + .next_block_base_fee(OP_SEPOLIA.base_fee_params_at_timestamp(genesis.timestamp)) + .unwrap(); // assert_eq!(base_fee, 980000000); } diff --git a/crates/primitives/src/header.rs b/crates/primitives/src/header.rs index 3846679dc..899fcb368 100644 --- a/crates/primitives/src/header.rs +++ b/crates/primitives/src/header.rs @@ -700,7 +700,8 @@ impl SealedHeader { let parent_gas_limit = if chain_spec.fork(Hardfork::London).transitions_at_block(self.number) { parent.gas_limit * - chain_spec.base_fee_params(self.timestamp).elasticity_multiplier as u64 + chain_spec.base_fee_params_at_timestamp(self.timestamp).elasticity_multiplier + as u64 } else { parent.gas_limit }; @@ -801,16 +802,18 @@ impl SealedHeader { if chain_spec.fork(Hardfork::London).active_at_block(self.number) { let base_fee = self.base_fee_per_gas.ok_or(HeaderValidationError::BaseFeeMissing)?; - let expected_base_fee = - if chain_spec.fork(Hardfork::London).transitions_at_block(self.number) { - constants::EIP1559_INITIAL_BASE_FEE - } else { - // This BaseFeeMissing will not happen as previous blocks are checked to have - // them. - parent - .next_block_base_fee(chain_spec.base_fee_params(self.timestamp)) - .ok_or(HeaderValidationError::BaseFeeMissing)? - }; + let expected_base_fee = if chain_spec + .fork(Hardfork::London) + .transitions_at_block(self.number) + { + constants::EIP1559_INITIAL_BASE_FEE + } else { + // This BaseFeeMissing will not happen as previous blocks are checked to have + // them. + parent + .next_block_base_fee(chain_spec.base_fee_params_at_timestamp(self.timestamp)) + .ok_or(HeaderValidationError::BaseFeeMissing)? + }; if expected_base_fee != base_fee { return Err(HeaderValidationError::BaseFeeDiff(GotExpected { expected: expected_base_fee, diff --git a/crates/rpc/rpc/src/eth/api/fee_history.rs b/crates/rpc/rpc/src/eth/api/fee_history.rs index 4029dc7f9..487dade17 100644 --- a/crates/rpc/rpc/src/eth/api/fee_history.rs +++ b/crates/rpc/rpc/src/eth/api/fee_history.rs @@ -374,7 +374,7 @@ impl FeeHistoryEntry { self.gas_used as u128, self.gas_limit as u128, self.base_fee_per_gas as u128, - chain_spec.base_fee_params(self.timestamp), + chain_spec.base_fee_params_at_timestamp(self.timestamp), ) as u64 } diff --git a/crates/rpc/rpc/src/eth/api/fees.rs b/crates/rpc/rpc/src/eth/api/fees.rs index d93b83d89..da2b846a3 100644 --- a/crates/rpc/rpc/src/eth/api/fees.rs +++ b/crates/rpc/rpc/src/eth/api/fees.rs @@ -188,7 +188,7 @@ where // The unwrap is safe since we checked earlier that we got at least 1 header. let last_header = headers.last().expect("is present"); base_fee_per_gas.push( - self.provider().chain_spec().base_fee_params(last_header.timestamp).next_block_base_fee( + self.provider().chain_spec().base_fee_params_at_timestamp(last_header.timestamp).next_block_base_fee( last_header.gas_used as u128, last_header.gas_limit as u128, last_header.base_fee_per_gas.unwrap_or_default() as u128, diff --git a/crates/rpc/rpc/src/eth/api/mod.rs b/crates/rpc/rpc/src/eth/api/mod.rs index 9044d5cca..c23dfe1ac 100644 --- a/crates/rpc/rpc/src/eth/api/mod.rs +++ b/crates/rpc/rpc/src/eth/api/mod.rs @@ -292,8 +292,9 @@ where // base fee of the child block let chain_spec = self.provider().chain_spec(); - latest_header.base_fee_per_gas = latest_header - .next_block_base_fee(chain_spec.base_fee_params(latest_header.timestamp)); + latest_header.base_fee_per_gas = latest_header.next_block_base_fee( + chain_spec.base_fee_params_at_timestamp(latest_header.timestamp), + ); // update excess blob gas consumed above target latest_header.excess_blob_gas = latest_header.next_block_excess_blob_gas(); diff --git a/crates/transaction-pool/src/maintain.rs b/crates/transaction-pool/src/maintain.rs index e2bdd44c2..52f39cd36 100644 --- a/crates/transaction-pool/src/maintain.rs +++ b/crates/transaction-pool/src/maintain.rs @@ -109,7 +109,7 @@ pub async fn maintain_transaction_pool( last_seen_block_hash: latest.hash(), last_seen_block_number: latest.number, pending_basefee: latest - .next_block_base_fee(chain_spec.base_fee_params(latest.timestamp + 12)) + .next_block_base_fee(chain_spec.base_fee_params_at_timestamp(latest.timestamp + 12)) .unwrap_or_default(), pending_blob_fee: latest.next_block_blob_fee(), }; @@ -265,7 +265,9 @@ pub async fn maintain_transaction_pool( // fees for the next block: `new_tip+1` let pending_block_base_fee = new_tip - .next_block_base_fee(chain_spec.base_fee_params(new_tip.timestamp + 12)) + .next_block_base_fee( + chain_spec.base_fee_params_at_timestamp(new_tip.timestamp + 12), + ) .unwrap_or_default(); let pending_block_blob_fee = new_tip.next_block_blob_fee(); @@ -370,7 +372,9 @@ pub async fn maintain_transaction_pool( // fees for the next block: `tip+1` let pending_block_base_fee = tip - .next_block_base_fee(chain_spec.base_fee_params(tip.timestamp + 12)) + .next_block_base_fee( + chain_spec.base_fee_params_at_timestamp(tip.timestamp + 12), + ) .unwrap_or_default(); let pending_block_blob_fee = tip.next_block_blob_fee();