Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: eip7691 fraction update #1900

Merged
merged 3 commits into from
Dec 8, 2024
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
41 changes: 23 additions & 18 deletions bins/revme/src/cmd/statetest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,24 +282,6 @@ pub fn execute_test_suite(
env.block.difficulty = unit.env.current_difficulty;
// after the Merge prevrandao replaces mix_hash field in block and replaced difficulty opcode in EVM.
env.block.prevrandao = unit.env.current_random;
// EIP-4844
if let Some(current_excess_blob_gas) = unit.env.current_excess_blob_gas {
env.block
.set_blob_excess_gas_and_price(current_excess_blob_gas.to());
} else if let (Some(parent_blob_gas_used), Some(parent_excess_blob_gas)) = (
unit.env.parent_blob_gas_used,
unit.env.parent_excess_blob_gas,
) {
env.block
.set_blob_excess_gas_and_price(calc_excess_blob_gas(
parent_blob_gas_used.to(),
parent_excess_blob_gas.to(),
unit.env
.parent_target_blobs_per_block
.map(|i| i.to())
.unwrap_or(TARGET_BLOB_GAS_PER_BLOCK),
));
}

// tx env
env.tx.caller = if let Some(address) = unit.transaction.sender {
Expand Down Expand Up @@ -332,6 +314,29 @@ pub fn execute_test_suite(
// Enable EOF in Prague tests.
let spec_id = spec_name.to_spec_id();

// EIP-4844
if let Some(current_excess_blob_gas) = unit.env.current_excess_blob_gas {
env.block.set_blob_excess_gas_and_price(
current_excess_blob_gas.to(),
spec_id.is_enabled_in(SpecId::PRAGUE),
);
} else if let (Some(parent_blob_gas_used), Some(parent_excess_blob_gas)) = (
unit.env.parent_blob_gas_used,
unit.env.parent_excess_blob_gas,
) {
env.block.set_blob_excess_gas_and_price(
calc_excess_blob_gas(
parent_blob_gas_used.to(),
parent_excess_blob_gas.to(),
unit.env
.parent_target_blobs_per_block
.map(|i| i.to())
.unwrap_or(TARGET_BLOB_GAS_PER_BLOCK),
),
spec_id.is_enabled_in(SpecId::PRAGUE),
);
}

if spec_id.is_enabled_in(SpecId::MERGE) && env.block.prevrandao.is_none() {
// if spec is merge and prevrandao is not set, set it to default
env.block.prevrandao = Some(B256::default());
Expand Down
6 changes: 5 additions & 1 deletion crates/primitives/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ pub const TARGET_BLOB_GAS_PER_BLOCK: u64 = TARGET_BLOB_NUMBER_PER_BLOCK * GAS_PE
pub const MIN_BLOB_GASPRICE: u64 = 1;

/// Controls the maximum rate of change for blob gas price.
pub const BLOB_GASPRICE_UPDATE_FRACTION: u64 = 3338477;
pub const BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN: u64 = 3338477;

/// Controls the maximum rate of change for blob gas price (Electra).
/// EIP-7691: Blob throughput increase
pub const BLOB_BASE_FEE_UPDATE_FRACTION_ELECTRA: u64 = 5007716;

/// First version of the blob.
pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01;
40 changes: 27 additions & 13 deletions crates/primitives/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pub use handler_cfg::{CfgEnvWithHandlerCfg, EnvWithHandlerCfg, HandlerCfg};

use crate::{
calc_blob_gasprice, calc_excess_blob_gas, AccessListItem, Account, Address, AuthorizationList,
Bytes, InvalidHeader, InvalidTransaction, Spec, SpecId, B256, GAS_PER_BLOB, MAX_CODE_SIZE,
MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG,
Bytes, InvalidHeader, InvalidTransaction, Spec, SpecId, B256, GAS_PER_BLOB,
MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG,
};
use alloy_primitives::TxKind;
use core::cmp::{min, Ordering};
Expand Down Expand Up @@ -174,6 +174,15 @@ impl Env {
return Err(InvalidTransaction::BlobVersionNotSupported);
}
}

// ensure the total blob gas spent is at most equal to the limit
// assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK
if SPEC::SPEC_ID == SpecId::CANCUN {
let num_blobs = self.tx.blob_hashes.len();
if num_blobs > MAX_BLOB_NUMBER_PER_BLOCK as usize {
return Err(InvalidTransaction::TooManyBlobs { have: num_blobs });
}
}
} else {
// if max_fee_per_blob_gas is not set, then blob_hashes must be empty
if !self.tx.blob_hashes.is_empty() {
Expand Down Expand Up @@ -467,8 +476,9 @@ pub struct BlockEnv {
impl BlockEnv {
/// Takes `blob_excess_gas` saves it inside env
/// and calculates `blob_fee` with [`BlobExcessGasAndPrice`].
pub fn set_blob_excess_gas_and_price(&mut self, excess_blob_gas: u64) {
self.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new(excess_blob_gas));
pub fn set_blob_excess_gas_and_price(&mut self, excess_blob_gas: u64, is_prague: bool) {
self.blob_excess_gas_and_price =
Some(BlobExcessGasAndPrice::new(excess_blob_gas, is_prague));
}

/// See [EIP-4844] and [`crate::calc_blob_gasprice`].
Expand Down Expand Up @@ -512,7 +522,7 @@ impl Default for BlockEnv {
basefee: U256::ZERO,
difficulty: U256::ZERO,
prevrandao: Some(B256::ZERO),
blob_excess_gas_and_price: Some(BlobExcessGasAndPrice::new(0)),
blob_excess_gas_and_price: Some(BlobExcessGasAndPrice::new(0, true)),
}
}
}
Expand Down Expand Up @@ -650,8 +660,8 @@ pub struct BlobExcessGasAndPrice {

impl BlobExcessGasAndPrice {
/// Creates a new instance by calculating the blob gas price with [`calc_blob_gasprice`].
pub fn new(excess_blob_gas: u64) -> Self {
let blob_gasprice = calc_blob_gasprice(excess_blob_gas);
pub fn new(excess_blob_gas: u64, is_prague: bool) -> Self {
let blob_gasprice = calc_blob_gasprice(excess_blob_gas, is_prague);
Self {
excess_blob_gas,
blob_gasprice,
Expand All @@ -665,13 +675,17 @@ impl BlobExcessGasAndPrice {
pub fn from_parent_and_target(
parent_excess_blob_gas: u64,
parent_blob_gas_used: u64,
target_blob_gas_per_block: u64,
parent_target_blob_gas_per_block: u64,
is_prague: bool,
) -> Self {
Self::new(calc_excess_blob_gas(
parent_excess_blob_gas,
parent_blob_gas_used,
target_blob_gas_per_block,
))
Self::new(
calc_excess_blob_gas(
parent_excess_blob_gas,
parent_blob_gas_used,
parent_target_blob_gas_per_block,
),
is_prague,
)
}
}

Expand Down
5 changes: 2 additions & 3 deletions crates/primitives/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ pub enum InvalidTransaction {
BlobCreateTransaction,
/// Transaction has more then `max_blob_num_per_block` blobs.
TooManyBlobs {
max: usize,
have: usize,
},
/// Blob transaction contains a versioned hash with an incorrect version
Expand Down Expand Up @@ -394,8 +393,8 @@ impl fmt::Display for InvalidTransaction {
}
Self::EmptyBlobs => write!(f, "empty blobs"),
Self::BlobCreateTransaction => write!(f, "blob create transaction"),
Self::TooManyBlobs { max, have } => {
write!(f, "too many blobs, have {have}, max {max}")
Self::TooManyBlobs { have } => {
write!(f, "too many blobs, have {have}")
}
Self::BlobVersionNotSupported => write!(f, "blob version not supported"),
Self::EofCrateShouldHaveToAddress => write!(f, "EOF crate should have `to` address"),
Expand Down
23 changes: 15 additions & 8 deletions crates/primitives/src/utilities.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{b256, B256, BLOB_GASPRICE_UPDATE_FRACTION, MIN_BLOB_GASPRICE};
use crate::{
b256, B256, BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, BLOB_BASE_FEE_UPDATE_FRACTION_ELECTRA,
MIN_BLOB_GASPRICE,
};
pub use alloy_primitives::keccak256;

/// The Keccak-256 hash of the empty string `""`.
Expand Down Expand Up @@ -26,11 +29,15 @@ pub fn calc_excess_blob_gas(
/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers)
/// (`get_blob_gasprice`).
#[inline]
pub fn calc_blob_gasprice(excess_blob_gas: u64) -> u128 {
pub fn calc_blob_gasprice(excess_blob_gas: u64, is_prague: bool) -> u128 {
fake_exponential(
MIN_BLOB_GASPRICE,
excess_blob_gas,
BLOB_GASPRICE_UPDATE_FRACTION,
if is_prague {
BLOB_BASE_FEE_UPDATE_FRACTION_ELECTRA
} else {
BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
},
)
}

Expand Down Expand Up @@ -132,18 +139,18 @@ mod tests {
(2314057, 1),
(2314058, 2),
(10 * 1024 * 1024, 23),
// calc_blob_gasprice approximates `e ** (excess_blob_gas / BLOB_GASPRICE_UPDATE_FRACTION)` using Taylor expansion
// calc_blob_gasprice approximates `e ** (excess_blob_gas / BLOB_BASE_FEE_UPDATE_FRACTION)` using Taylor expansion
//
// to roughly find where boundaries will be hit:
// 2 ** bits = e ** (excess_blob_gas / BLOB_GASPRICE_UPDATE_FRACTION)
// excess_blob_gas = ln(2 ** bits) * BLOB_GASPRICE_UPDATE_FRACTION
// 2 ** bits = e ** (excess_blob_gas / BLOB_BASE_FEE_UPDATE_FRACTION)
// excess_blob_gas = ln(2 ** bits) * BLOB_BASE_FEE_UPDATE_FRACTION
(148099578, 18446739238971471609), // output is just below the overflow
(148099579, 18446744762204311910), // output is just after the overflow
(161087488, 902580055246494526580),
];

for &(excess, expected) in blob_fee_vectors {
let actual = calc_blob_gasprice(excess);
let actual = calc_blob_gasprice(excess, false);
assert_eq!(actual, expected, "test: {excess}");
}
}
Expand All @@ -167,7 +174,7 @@ mod tests {
(1, 5, 2, 11), // approximate 12.18
(2, 5, 2, 23), // approximate 24.36
(1, 50000000, 2225652, 5709098764),
(1, 380928, BLOB_GASPRICE_UPDATE_FRACTION, 1),
(1, 380928, BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, 1),
] {
let actual = fake_exponential(factor, numerator, denominator);
assert_eq!(actual, expected, "test: {t:?}");
Expand Down
Loading