Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions crates/consensus/src/block/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,11 @@ impl Header {
///
/// Returns a `None` if no excess blob gas is set, no EIP-4844 support
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?))
Some(blob_params.next_block_excess_blob_gas_osaka(
self.excess_blob_gas?,
self.blob_gas_used?,
self.base_fee_per_gas?,
))
}

/// Calculate a heuristic for the in-memory size of the [Header].
Expand Down Expand Up @@ -652,7 +656,11 @@ pub trait BlockHeader {
///
/// Returns a `None` if no excess blob gas is set, no EIP-4844 support
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()?))
Some(blob_params.next_block_excess_blob_gas_osaka(
self.excess_blob_gas()?,
self.blob_gas_used()?,
self.base_fee_per_gas()?,
))
}

/// Convenience function for [`Self::next_block_excess_blob_gas`] with an optional
Expand Down
6 changes: 5 additions & 1 deletion crates/eips/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ alloy-eip7702.workspace = true
alloy-primitives = { workspace = true, features = ["rlp"] }
alloy-rlp = { workspace = true, features = ["derive"] }
either.workspace = true
thiserror.workspace = true

# serde
alloy-serde = { workspace = true, optional = true }
serde = { workspace = true, optional = true }
serde_with = { workspace = true, optional = true }

# kzg
c-kzg = { workspace = true, optional = true, features = [
Expand Down Expand Up @@ -81,13 +83,15 @@ std = [
"alloy-eip2930/std",
"alloy-eip7702/std",
"derive_more/std",
"serde_json/std",
"sha2?/std",
"either/std",
"serde_with?/std",
"thiserror/std"
]
serde = [
"dep:alloy-serde",
"dep:serde",
"dep:serde_with",
"alloy-primitives/serde",
"c-kzg?/serde",
"alloy-eip2930/serde",
Expand Down
8 changes: 6 additions & 2 deletions crates/eips/src/eip4844/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,12 @@ 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 {
eip7840::BlobParams::cancun()
.next_block_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used)
eip7840::BlobParams::cancun().next_block_excess_blob_gas_osaka(
parent_excess_blob_gas,
parent_blob_gas_used,
// base fee is not used in EIP-4844 excess blob gas calculation
0,
)
}

/// Calculates the blob gas price from the header's excess blob gas field.
Expand Down
83 changes: 65 additions & 18 deletions crates/eips/src/eip7840.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ use crate::{
eip7594, eip7691,
};

/// BLOB_BASE_COST represents the minimum execution gas required to include a blob in a block,
/// as defined by [EIP-7918 (Decoupling Blob Gas from Execution Gas)](https://eips.ethereum.org/EIPS/eip-7918).
/// This ensures that even though blob gas and execution gas are decoupled, there is still a base
/// cost in execution gas to include blobs.
pub const BLOB_BASE_COST: u64 = 2_u64.pow(13);

/// Configuration for the blob-related calculations.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
Expand All @@ -26,8 +32,12 @@ pub struct BlobParams {
pub min_blob_fee: u128,
/// Maximum number of blobs per transaction.
///
/// If not specified, defaults to `max_blob_count` during deserialization.
/// Defaults to `max_blob_count` unless set otherwise.
pub max_blobs_per_tx: u64,
/// Minimum execution gas required to include a blob in a block.
///
/// Defaults to `0` unless set otherwise.
pub blob_base_cost: u64,
}

impl BlobParams {
Expand All @@ -39,6 +49,7 @@ impl BlobParams {
update_fraction: eip4844::BLOB_GASPRICE_UPDATE_FRACTION,
min_blob_fee: eip4844::BLOB_TX_MIN_BLOB_GASPRICE,
max_blobs_per_tx: eip4844::MAX_BLOBS_PER_BLOCK_DENCUN as u64,
blob_base_cost: 0,
}
}

Expand All @@ -50,6 +61,7 @@ impl BlobParams {
update_fraction: eip7691::BLOB_GASPRICE_UPDATE_FRACTION_PECTRA,
min_blob_fee: eip4844::BLOB_TX_MIN_BLOB_GASPRICE,
max_blobs_per_tx: eip7691::MAX_BLOBS_PER_BLOCK_ELECTRA,
blob_base_cost: 0,
}
}

Expand All @@ -61,9 +73,22 @@ impl BlobParams {
update_fraction: eip7691::BLOB_GASPRICE_UPDATE_FRACTION_PECTRA,
min_blob_fee: eip4844::BLOB_TX_MIN_BLOB_GASPRICE,
max_blobs_per_tx: eip7594::MAX_BLOBS_PER_TX_FUSAKA,
blob_base_cost: BLOB_BASE_COST,
}
}

/// Set max blobs per transaction on [`BlobParams`].
pub const fn with_max_blobs_per_tx(mut self, max_blobs_per_tx: u64) -> Self {
self.max_blobs_per_tx = max_blobs_per_tx;
self
}

/// Set blob base cost on [`BlobParams`].
pub const fn with_blob_base_cost(mut self, blob_base_cost: u64) -> Self {
self.blob_base_cost = blob_base_cost;
self
}

/// Returns the maximum available blob gas in a block.
///
/// This is `max blob count * DATA_GAS_PER_BLOB`
Expand All @@ -81,13 +106,39 @@ impl BlobParams {
/// Calculates the `excess_blob_gas` value for the next block based on the current block
/// `excess_blob_gas` and `blob_gas_used`.
#[inline]
// #[deprecated(note = "Use `next_block_excess_blob_gas_osaka` instead")]
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)
self.next_block_excess_blob_gas_osaka(excess_blob_gas, blob_gas_used, 0)
}

/// Calculates the `excess_blob_gas` value for the next block based on the current block
/// `excess_blob_gas`, `blob_gas_used` and `base_fee_per_gas`.
#[inline]
pub const fn next_block_excess_blob_gas_osaka(
&self,
excess_blob_gas: u64,
blob_gas_used: u64,
base_fee_per_gas: u64,
) -> u64 {
let next_excess_blob_gas = excess_blob_gas + blob_gas_used;
let target_blob_gas = self.target_blob_gas_per_block();
if next_excess_blob_gas < target_blob_gas {
return 0;
}

if self.blob_base_cost as u128 * base_fee_per_gas as u128
> DATA_GAS_PER_BLOB as u128 * self.calc_blob_fee(excess_blob_gas)
{
let scaled_excess = blob_gas_used * (self.max_blob_count - self.target_blob_count)
/ self.max_blob_count;
excess_blob_gas + scaled_excess
} else {
next_excess_blob_gas - target_blob_gas
}
}

/// Calculates the blob fee for block based on its `excess_blob_gas`.
Expand All @@ -104,14 +155,14 @@ mod serde_impl {
#[derive(serde::Serialize, serde::Deserialize, Clone, Copy)]
#[serde(rename_all = "camelCase")]
pub(crate) struct SerdeHelper {
#[serde(rename = "target")]
target_blob_count: u64,
#[serde(rename = "max")]
max_blob_count: u64,
#[serde(rename = "baseFeeUpdateFraction")]
update_fraction: u128,
#[serde(rename = "max")]
max_blob_count: u64,
#[serde(rename = "target")]
target_blob_count: u64,
#[serde(skip_serializing)]
min_blob_fee: Option<u128>,
max_blobs_per_tx: Option<u64>,
}

impl From<BlobParams> for SerdeHelper {
Expand All @@ -121,7 +172,8 @@ mod serde_impl {
max_blob_count,
update_fraction,
min_blob_fee,
max_blobs_per_tx,
max_blobs_per_tx: _,
blob_base_cost: _,
} = params;

Self {
Expand All @@ -130,27 +182,22 @@ mod serde_impl {
update_fraction,
min_blob_fee: (min_blob_fee != eip4844::BLOB_TX_MIN_BLOB_GASPRICE)
.then_some(min_blob_fee),
max_blobs_per_tx: Some(max_blobs_per_tx),
}
}
}

impl From<SerdeHelper> for BlobParams {
fn from(helper: SerdeHelper) -> Self {
let SerdeHelper {
target_blob_count,
max_blob_count,
update_fraction,
min_blob_fee,
max_blobs_per_tx,
} = helper;
let SerdeHelper { target_blob_count, max_blob_count, update_fraction, min_blob_fee } =
helper;

Self {
target_blob_count,
max_blob_count,
update_fraction,
min_blob_fee: min_blob_fee.unwrap_or(eip4844::BLOB_TX_MIN_BLOB_GASPRICE),
max_blobs_per_tx: max_blobs_per_tx.unwrap_or(max_blob_count),
max_blobs_per_tx: max_blob_count,
blob_base_cost: 0,
}
}
}
Expand Down
Loading
Loading