Skip to content

Commit

Permalink
feat: EIP-7840 (#1828)
Browse files Browse the repository at this point in the history
* wip

* wip

* fix

* fmt

* fix

* add eip link

* fmt
  • Loading branch information
klkvr authored Dec 23, 2024
1 parent e8ed23b commit 4cd7313
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 30 deletions.
33 changes: 13 additions & 20 deletions crates/consensus/src/block/header.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::constants::{EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH};
use alloc::vec::Vec;
use alloy_eips::{
calc_blob_gasprice,
eip1559::{calc_next_block_base_fee, BaseFeeParams},
eip1898::BlockWithParent,
eip4844::{self},
eip7840::BlobParams,
merge::ALLOWED_FUTURE_BLOCK_TIME_SECONDS,
BlockNumHash,
};
Expand Down Expand Up @@ -191,17 +190,17 @@ impl Header {
/// Returns the blob fee for _this_ block according to the EIP-4844 spec.
///
/// Returns `None` if `excess_blob_gas` is None
pub fn blob_fee(&self) -> Option<u128> {
self.excess_blob_gas.map(calc_blob_gasprice)
pub fn blob_fee(&self, blob_params: BlobParams) -> Option<u128> {
Some(blob_params.calc_blob_fee(self.excess_blob_gas?))
}

/// Returns the blob fee for the next block according to the EIP-4844 spec.
///
/// Returns `None` if `excess_blob_gas` is None.
///
/// See also [Self::next_block_excess_blob_gas]
pub fn next_block_blob_fee(&self) -> Option<u128> {
Some(eip4844::calc_blob_gasprice(self.next_block_excess_blob_gas()?))
pub fn next_block_blob_fee(&self, blob_params: BlobParams) -> Option<u128> {
Some(blob_params.calc_blob_fee(self.next_block_excess_blob_gas(blob_params)?))
}

/// Calculate base fee for next block according to the EIP-1559 spec.
Expand All @@ -220,11 +219,8 @@ impl Header {
/// spec.
///
/// Returns a `None` if no excess blob gas is set, no EIP-4844 support
pub fn next_block_excess_blob_gas(&self) -> Option<u64> {
let excess_blob_gas = self.excess_blob_gas?;
let blob_gas_used = self.blob_gas_used?;

Some(eip4844::calc_excess_blob_gas(excess_blob_gas, blob_gas_used))
pub fn next_block_excess_blob_gas(&self, blob_params: BlobParams) -> Option<u64> {
Some(blob_params.next_block_excess_blob_gas(self.excess_blob_gas?, self.blob_gas_used?))
}

/// Calculate a heuristic for the in-memory size of the [Header].
Expand Down Expand Up @@ -602,28 +598,25 @@ pub trait BlockHeader {
/// Returns the blob fee for _this_ block according to the EIP-4844 spec.
///
/// Returns `None` if `excess_blob_gas` is None
fn blob_fee(&self) -> Option<u128> {
self.excess_blob_gas().map(calc_blob_gasprice)
fn blob_fee(&self, blob_params: BlobParams) -> Option<u128> {
Some(blob_params.calc_blob_fee(self.excess_blob_gas()?))
}

/// Calculate excess blob gas for the next block according to the EIP-4844
/// spec.
///
/// Returns a `None` if no excess blob gas is set, no EIP-4844 support
fn next_block_excess_blob_gas(&self) -> Option<u64> {
let excess_blob_gas = self.excess_blob_gas()?;
let blob_gas_used = self.blob_gas_used()?;

Some(eip4844::calc_excess_blob_gas(excess_blob_gas, blob_gas_used))
fn next_block_excess_blob_gas(&self, blob_params: BlobParams) -> Option<u64> {
Some(blob_params.next_block_excess_blob_gas(self.excess_blob_gas()?, self.blob_gas_used()?))
}

/// Returns the blob fee for the next block according to the EIP-4844 spec.
///
/// Returns `None` if `excess_blob_gas` is None.
///
/// See also [BlockHeader::next_block_excess_blob_gas]
fn next_block_blob_fee(&self) -> Option<u128> {
Some(eip4844::calc_blob_gasprice(self.next_block_excess_blob_gas()?))
fn next_block_blob_fee(&self, blob_params: BlobParams) -> Option<u128> {
Some(blob_params.calc_blob_fee(self.next_block_excess_blob_gas(blob_params)?))
}

/// Calculate base fee for next block according to the EIP-1559 spec.
Expand Down
11 changes: 5 additions & 6 deletions crates/eips/src/eip4844/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub use sidecar::*;

use alloy_primitives::{b256, FixedBytes, B256, U256};

use crate::eip7840;

/// The modulus of the BLS group used in the KZG commitment scheme. All field
/// elements contained in a blob MUST be STRICTLY LESS than this value.
pub const BLS_MODULUS_BYTES: B256 =
Expand Down Expand Up @@ -125,7 +127,8 @@ pub fn kzg_to_versioned_hash(commitment: &[u8]) -> B256 {
/// (`calc_excess_blob_gas`).
#[inline]
pub const fn calc_excess_blob_gas(parent_excess_blob_gas: u64, parent_blob_gas_used: u64) -> u64 {
(parent_excess_blob_gas + parent_blob_gas_used).saturating_sub(TARGET_DATA_GAS_PER_BLOCK)
eip7840::BlobParams::cancun()
.next_block_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used)
}

/// Calculates the blob gas price from the header's excess blob gas field.
Expand All @@ -134,11 +137,7 @@ pub const fn calc_excess_blob_gas(parent_excess_blob_gas: u64, parent_blob_gas_u
/// (`get_blob_gasprice`).
#[inline]
pub const fn calc_blob_gasprice(excess_blob_gas: u64) -> u128 {
fake_exponential(
BLOB_TX_MIN_BLOB_GASPRICE,
excess_blob_gas as u128,
BLOB_GASPRICE_UPDATE_FRACTION,
)
eip7840::BlobParams::cancun().calc_blob_fee(excess_blob_gas)
}

/// Approximates `factor * e ** (numerator / denominator)` using Taylor expansion.
Expand Down
68 changes: 68 additions & 0 deletions crates/eips/src/eip7840.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! Contains constants and utility functions for [EIP-7840](https://github.com/ethereum/EIPs/tree/master/EIPS/eip-7840.md)
use crate::{eip4844, eip7691};

/// A single item of `blobSchedule` defined in EIP-7840.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BlobScheduleItem {
/// Target blob count for the block.
#[cfg_attr(feature = "serde", serde(rename = "target"))]
pub target_blob_count: u64,
/// Max blob count for the block.
#[cfg_attr(feature = "serde", serde(rename = "max"))]
pub max_blob_count: u64,
}

/// Configuration for the blob-related calculations.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BlobParams {
/// Target blob count for the block.
pub target_blob_count: u64,
/// Max blob count for the block.
pub max_blob_count: u64,
/// Update fraction for excess blob gas calculation.
pub update_fraction: u128,
/// Minimum gas price for a data blob.
pub min_blob_fee: u128,
}

impl BlobParams {
/// Returns [`BlobParams`] configuration activated with Cancun hardfork.
pub const fn cancun() -> Self {
Self {
target_blob_count: eip4844::TARGET_BLOBS_PER_BLOCK,
max_blob_count: eip4844::MAX_BLOBS_PER_BLOCK as u64,
update_fraction: eip4844::BLOB_GASPRICE_UPDATE_FRACTION,
min_blob_fee: eip4844::BLOB_TX_MIN_BLOB_GASPRICE,
}
}

/// Returns [`BlobParams`] configuration activated with Prague hardfork.
pub const fn prague() -> Self {
Self {
target_blob_count: eip7691::TARGET_BLOBS_PER_BLOCK_ELECTRA,
max_blob_count: eip7691::MAX_BLOBS_PER_BLOCK_ELECTRA,
update_fraction: eip7691::BLOB_GASPRICE_UPDATE_FRACTION_PECTRA,
min_blob_fee: eip4844::BLOB_TX_MIN_BLOB_GASPRICE,
}
}

/// Calculates the `excess_blob_gas` value for the next block based on the current block
/// `excess_blob_gas` and `blob_gas_used`.
#[inline]
pub const fn next_block_excess_blob_gas(
&self,
excess_blob_gas: u64,
blob_gas_used: u64,
) -> u64 {
(excess_blob_gas + blob_gas_used)
.saturating_sub(eip4844::DATA_GAS_PER_BLOB * self.target_blob_count)
}

/// Calculates the blob fee for block based on its `excess_blob_gas`.
#[inline]
pub const fn calc_blob_fee(&self, excess_blob_gas: u64) -> u128 {
eip4844::fake_exponential(self.min_blob_fee, excess_blob_gas as u128, self.update_fraction)
}
}
2 changes: 2 additions & 0 deletions crates/eips/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ pub mod eip7685;
pub mod eip7691;

pub mod eip7702;

pub mod eip7840;
1 change: 1 addition & 0 deletions crates/genesis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ rustdoc-args = ["--cfg", "docsrs"]
workspace = true

[dependencies]
alloy-eips = { workspace = true, features = ["serde"] }
alloy-primitives.workspace = true
alloy-serde.workspace = true
alloy-trie = { workspace = true, features = ["ethereum"] }
Expand Down
8 changes: 8 additions & 0 deletions crates/genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
extern crate alloc;

use alloc::{collections::BTreeMap, string::String};
use alloy_eips::eip7840::BlobScheduleItem;
use alloy_primitives::{keccak256, Address, Bytes, B256, U256};
use alloy_serde::{storage::deserialize_storage_map, ttd::deserialize_json_ttd_opt, OtherFields};
use alloy_trie::{TrieAccount, EMPTY_ROOT_HASH, KECCAK_EMPTY};
Expand Down Expand Up @@ -479,6 +480,12 @@ pub struct ChainConfig {
/// The deposit contract address
#[serde(default, skip_serializing_if = "Option::is_none")]
pub deposit_contract_address: Option<Address>,

/// The blob schedule for the chain, indexed by hardfork name.
///
/// See [EIP-7840](https://github.com/ethereum/EIPs/tree/master/EIPS/eip-7840.md).
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub blob_schedule: BTreeMap<String, BlobScheduleItem>,
}

impl ChainConfig {
Expand Down Expand Up @@ -604,6 +611,7 @@ impl Default for ChainConfig {
parlia: None,
extra_fields: Default::default(),
deposit_contract_address: None,
blob_schedule: Default::default(),
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions crates/rpc-types-eth/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use alloy_primitives::{Address, BlockHash, Bloom, Bytes, Sealable, B256, B64, U2
use alloy_rlp::Encodable;
use core::ops::{Deref, DerefMut};

use alloy_eips::eip7840::BlobParams;
pub use alloy_eips::{
calc_blob_gasprice, calc_excess_blob_gas, BlockHashOrNumber, BlockId, BlockNumHash,
BlockNumberOrTag, ForkBlock, RpcBlockHash,
Expand Down Expand Up @@ -194,16 +195,16 @@ impl<H: BlockHeader> Header<H> {
/// Returns `None` if `excess_blob_gas` is None.
///
/// See also [Self::next_block_excess_blob_gas]
pub fn next_block_blob_fee(&self) -> Option<u128> {
self.inner.next_block_blob_fee()
pub fn next_block_blob_fee(&self, blob_params: BlobParams) -> Option<u128> {
self.inner.next_block_blob_fee(blob_params)
}

/// Calculate excess blob gas for the next block according to the EIP-4844
/// spec.
///
/// Returns a `None` if no excess blob gas is set, no EIP-4844 support
pub fn next_block_excess_blob_gas(&self) -> Option<u64> {
self.inner.next_block_excess_blob_gas()
pub fn next_block_excess_blob_gas(&self, blob_params: BlobParams) -> Option<u64> {
self.inner.next_block_excess_blob_gas(blob_params)
}
}

Expand Down

0 comments on commit 4cd7313

Please sign in to comment.