chore: move next base fee to header impl (#2400)

This commit is contained in:
Matthias Seitz
2023-04-26 12:31:35 +02:00
committed by GitHub
parent 04947d2c49
commit 9fb66ffeff
8 changed files with 77 additions and 82 deletions

1
Cargo.lock generated
View File

@ -5086,7 +5086,6 @@ dependencies = [
"futures-core",
"futures-util",
"metrics",
"reth-consensus-common",
"reth-interfaces",
"reth-metrics-derive",
"reth-primitives",

View File

@ -234,32 +234,6 @@ pub fn validate_block_standalone(
Ok(())
}
/// Calculate base fee for next block. EIP-1559 spec
pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u64) -> u64 {
let gas_target = gas_limit / constants::EIP1559_ELASTICITY_MULTIPLIER;
if gas_used == gas_target {
return base_fee
}
if gas_used > gas_target {
let gas_used_delta = gas_used - gas_target;
let base_fee_delta = std::cmp::max(
1,
base_fee as u128 * gas_used_delta as u128 /
gas_target as u128 /
constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128,
);
base_fee + (base_fee_delta as u64)
} else {
let gas_used_delta = gas_target - gas_used;
let base_fee_per_gas_delta = base_fee as u128 * gas_used_delta as u128 /
gas_target as u128 /
constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128;
base_fee.saturating_sub(base_fee_per_gas_delta as u64)
}
}
/// Validate block in regards to parent
pub fn validate_header_regarding_parent(
parent: &SealedHeader,
@ -320,11 +294,7 @@ pub fn validate_header_regarding_parent(
constants::EIP1559_INITIAL_BASE_FEE
} else {
// This BaseFeeMissing will not happen as previous blocks are checked to have them.
calculate_next_block_base_fee(
parent.gas_used,
parent.gas_limit,
parent.base_fee_per_gas.ok_or(ConsensusError::BaseFeeMissing)?,
)
parent.next_block_base_fee().ok_or(ConsensusError::BaseFeeMissing)?
};
if expected_base_fee != base_fee {
return Err(ConsensusError::BaseFeeDiff { expected: expected_base_fee, got: base_fee })
@ -428,33 +398,6 @@ mod tests {
};
use std::ops::RangeBounds;
#[test]
fn calculate_base_fee_success() {
let base_fee = [
1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0,
1, 2,
];
let gas_used = [
10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000,
10000000,
];
let gas_limit = [
10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000,
18000000, 18000000,
];
let next_base_fee = [
1125000000, 1083333333, 1053571428, 1179939062, 1116028649, 918084097, 1063811730, 1,
2, 3,
];
for i in 0..base_fee.len() {
assert_eq!(
next_base_fee[i],
calculate_next_block_base_fee(gas_used[i], gas_limit[i], base_fee[i])
);
}
}
mock! {
WithdrawalsProvider {}

View File

@ -13,7 +13,6 @@ reth-primitives = { path = "../../primitives" }
reth-rpc-types = { path = "../../rpc/rpc-types" }
reth-rlp = { path = "../../rlp" }
reth-interfaces = { path = "../../interfaces" }
reth-consensus-common = { path = "../../consensus/common" }
reth-revm-primitives = { path = "../../revm/revm-primitives" }
## ethereum

View File

@ -1,6 +1,5 @@
//! Contains types required for building a payload.
use reth_consensus_common::validation::calculate_next_block_base_fee;
use reth_primitives::{Address, ChainSpec, Header, SealedBlock, Withdrawal, H256, U256};
use reth_revm_primitives::config::revm_spec_by_timestamp_after_merge;
use reth_rlp::Encodable;
@ -135,11 +134,7 @@ impl PayloadBuilderAttributes {
prevrandao: Some(self.prev_randao),
gas_limit: U256::from(parent.gas_limit),
// calculate basefee based on parent block's gas usage
basefee: U256::from(calculate_next_block_base_fee(
parent.gas_used,
parent.gas_limit,
parent.base_fee_per_gas.unwrap_or_default(),
)),
basefee: U256::from(parent.next_block_base_fee().unwrap_or_default()),
};
(cfg, block_env)

View File

@ -0,0 +1,61 @@
//! Helpers for working with EIP-1559 base fee
use crate::constants;
/// Calculate base fee for next block. [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) spec
pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u64) -> u64 {
let gas_target = gas_limit / constants::EIP1559_ELASTICITY_MULTIPLIER;
if gas_used == gas_target {
return base_fee
}
if gas_used > gas_target {
let gas_used_delta = gas_used - gas_target;
let base_fee_delta = std::cmp::max(
1,
base_fee as u128 * gas_used_delta as u128 /
gas_target as u128 /
constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128,
);
base_fee + (base_fee_delta as u64)
} else {
let gas_used_delta = gas_target - gas_used;
let base_fee_per_gas_delta = base_fee as u128 * gas_used_delta as u128 /
gas_target as u128 /
constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128;
base_fee.saturating_sub(base_fee_per_gas_delta as u64)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn calculate_base_fee_success() {
let base_fee = [
1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0,
1, 2,
];
let gas_used = [
10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000,
10000000,
];
let gas_limit = [
10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000,
18000000, 18000000,
];
let next_base_fee = [
1125000000, 1083333333, 1053571428, 1179939062, 1116028649, 918084097, 1063811730, 1,
2, 3,
];
for i in 0..base_fee.len() {
assert_eq!(
next_base_fee[i],
calculate_next_block_base_fee(gas_used[i], gas_limit[i], base_fee[i])
);
}
}
}

View File

@ -1,4 +1,5 @@
use crate::{
basefee::calculate_next_block_base_fee,
keccak256,
proofs::{EMPTY_LIST_HASH, EMPTY_ROOT},
BlockHash, BlockNumber, Bloom, Bytes, H160, H256, U256,
@ -145,6 +146,13 @@ impl Header {
self.transactions_root == EMPTY_ROOT
}
/// Calculate base fee for next block according to the EIP-1559 spec.
///
/// Returns a `None` if no base fee is set, no EIP-1559 support
pub fn next_block_base_fee(&self) -> Option<u64> {
Some(calculate_next_block_base_fee(self.gas_used, self.gas_limit, self.base_fee_per_gas?))
}
/// Seal the header with a known hash.
///
/// WARNING: This method does not perform validation whether the hash is correct.

View File

@ -10,6 +10,7 @@
//! This crate contains Ethereum primitive types and helper functions.
mod account;
pub mod basefee;
mod bits;
mod block;
pub mod bloom;

View File

@ -5,7 +5,6 @@ use crate::{
Pool, TransactionOrdering, TransactionPool, TransactionValidator,
};
use futures_util::{Stream, StreamExt};
use reth_consensus_common::validation::calculate_next_block_base_fee;
use reth_primitives::{Address, BlockHash, FromRecoveredTransaction};
use reth_provider::{BlockProvider, CanonStateNotification, PostState, StateProviderFactory};
use std::{
@ -46,11 +45,8 @@ pub async fn maintain_transaction_pool<Client, V, T, St>(
let new_tip = new_blocks.tip();
// base fee for the next block: `new_tip+1`
let pending_block_base_fee = calculate_next_block_base_fee(
new_tip.gas_used,
new_tip.gas_limit,
new_tip.base_fee_per_gas.unwrap_or_default(),
) as u128;
let pending_block_base_fee =
new_tip.next_block_base_fee().unwrap_or_default() as u128;
// we know all changed account in the new chain
let new_changed_accounts: HashSet<_> =
@ -133,11 +129,8 @@ pub async fn maintain_transaction_pool<Client, V, T, St>(
}
// base fee for the next block: `first_block+1`
let pending_block_base_fee = calculate_next_block_base_fee(
first_block.gas_used,
first_block.gas_limit,
first_block.base_fee_per_gas.unwrap_or_default(),
) as u128;
let pending_block_base_fee =
first_block.next_block_base_fee().unwrap_or_default() as u128;
let changed_accounts = changed_accounts_iter(state).collect();
let update = CanonicalStateUpdate {
hash: first_block.hash,
@ -169,11 +162,7 @@ pub async fn maintain_transaction_pool<Client, V, T, St>(
let (blocks, state) = new.inner();
let tip = blocks.tip();
// base fee for the next block: `tip+1`
let pending_block_base_fee = calculate_next_block_base_fee(
tip.gas_used,
tip.gas_limit,
tip.base_fee_per_gas.unwrap_or_default(),
) as u128;
let pending_block_base_fee = tip.next_block_base_fee().unwrap_or_default() as u128;
let first_block = blocks.first();
// check if the range of the commit is canonical