From ffb4e6fd5d7a51f842059842252df6bf47f8b609 Mon Sep 17 00:00:00 2001 From: Sina M <1591639+s1na@users.noreply.github.com> Date: Mon, 7 Jul 2025 16:17:25 +0200 Subject: [PATCH] consensus/misc/eip4844: implement EIP-7918 (#31965) https://eips.ethereum.org/EIPS/eip-7918 --------- Co-authored-by: Felix Lange --- consensus/misc/eip4844/eip4844.go | 29 +++++++++++++++++-- consensus/misc/eip4844/eip4844_test.go | 40 ++++++++++++++++++++++++++ params/protocol_params.go | 1 + 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/consensus/misc/eip4844/eip4844.go b/consensus/misc/eip4844/eip4844.go index 32b34f4e53..049043e3ce 100644 --- a/consensus/misc/eip4844/eip4844.go +++ b/consensus/misc/eip4844/eip4844.go @@ -71,11 +71,30 @@ func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header, headTim parentExcessBlobGas = *parent.ExcessBlobGas parentBlobGasUsed = *parent.BlobGasUsed } - excessBlobGas := parentExcessBlobGas + parentBlobGasUsed - targetGas := uint64(targetBlobsPerBlock(config, headTimestamp)) * params.BlobTxBlobGasPerBlob + var ( + excessBlobGas = parentExcessBlobGas + parentBlobGasUsed + target = targetBlobsPerBlock(config, headTimestamp) + targetGas = uint64(target) * params.BlobTxBlobGasPerBlob + ) if excessBlobGas < targetGas { return 0 } + if !config.IsOsaka(config.LondonBlock, headTimestamp) { + // Pre-Osaka, we use the formula defined by EIP-4844. + return excessBlobGas - targetGas + } + + // EIP-7918 (post-Osaka) introduces a different formula for computing excess. + var ( + baseCost = big.NewInt(params.BlobBaseCost) + reservePrice = baseCost.Mul(baseCost, parent.BaseFee) + blobPrice = calcBlobPrice(config, parent) + ) + if reservePrice.Cmp(blobPrice) > 0 { + max := MaxBlobsPerBlock(config, headTimestamp) + scaledExcess := parentBlobGasUsed * uint64(max-target) / uint64(max) + return parentExcessBlobGas + scaledExcess + } return excessBlobGas - targetGas } @@ -177,3 +196,9 @@ func fakeExponential(factor, numerator, denominator *big.Int) *big.Int { } return output.Div(output, denominator) } + +// calcBlobPrice calculates the blob price for a block. +func calcBlobPrice(config *params.ChainConfig, header *types.Header) *big.Int { + blobBaseFee := CalcBlobFee(config, header) + return new(big.Int).Mul(blobBaseFee, big.NewInt(params.BlobTxBlobGasPerBlob)) +} diff --git a/consensus/misc/eip4844/eip4844_test.go b/consensus/misc/eip4844/eip4844_test.go index f4e3cb3d9a..555324db65 100644 --- a/consensus/misc/eip4844/eip4844_test.go +++ b/consensus/misc/eip4844/eip4844_test.go @@ -127,3 +127,43 @@ func TestFakeExponential(t *testing.T) { } } } + +func TestCalcExcessBlobGasEIP7918(t *testing.T) { + var ( + cfg = params.MergedTestChainConfig + targetBlobs = targetBlobsPerBlock(cfg, *cfg.CancunTime) + blobGasTarget = uint64(targetBlobs) * params.BlobTxBlobGasPerBlob + ) + makeHeader := func(parentExcess, parentBaseFee uint64, blobsUsed int) *types.Header { + blobGasUsed := uint64(blobsUsed) * params.BlobTxBlobGasPerBlob + return &types.Header{ + BaseFee: big.NewInt(int64(parentBaseFee)), + ExcessBlobGas: &parentExcess, + BlobGasUsed: &blobGasUsed, + } + } + + tests := []struct { + name string + header *types.Header + wantExcessGas uint64 + }{ + { + name: "BelowReservePrice", + header: makeHeader(0, 1_000_000_000, targetBlobs), + wantExcessGas: blobGasTarget * 3 / 9, + }, + { + name: "AboveReservePrice", + header: makeHeader(0, 1, targetBlobs), + wantExcessGas: 0, + }, + } + for _, tc := range tests { + got := CalcExcessBlobGas(cfg, tc.header, *cfg.CancunTime) + if got != tc.wantExcessGas { + t.Fatalf("%s: excess-blob-gas mismatch – have %d, want %d", + tc.name, got, tc.wantExcessGas) + } + } +} diff --git a/params/protocol_params.go b/params/protocol_params.go index 6b06dadaef..d655d8dc0e 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -173,6 +173,7 @@ const ( BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size) BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs BlobTxPointEvaluationPrecompileGas = 50000 // Gas price for the point evaluation precompile. + BlobBaseCost = 1 << 13 // Base execution gas cost for a blob. HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935. )