From f7e13fe1bbc78c8a6b5163518caecff7c2df000e Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Tue, 3 Jun 2025 18:31:48 +0200 Subject: [PATCH] consensus: implement EIP-7918 --- consensus/misc/eip4844/eip4844.go | 26 ++++++++++++- consensus/misc/eip4844/eip4844_test.go | 53 ++++++++++++++++++++++++++ params/protocol_params.go | 1 + 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/consensus/misc/eip4844/eip4844.go b/consensus/misc/eip4844/eip4844.go index 1c0c651964..a800f4786d 100644 --- a/consensus/misc/eip4844/eip4844.go +++ b/consensus/misc/eip4844/eip4844.go @@ -70,11 +70,27 @@ 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) { + return excessBlobGas - targetGas + } + // EIP-7918. + var ( + reservePrice = new(big.Int).Mul(parent.BaseFee, big.NewInt(params.BlobBaseCost)) + 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 } @@ -185,3 +201,9 @@ func fakeExponential(factor, numerator, denominator *big.Int) *big.Int { } return output.Div(output, denominator) } + +// calcBlobPrice calculates the blob price based 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..111eac5b97 100644 --- a/consensus/misc/eip4844/eip4844_test.go +++ b/consensus/misc/eip4844/eip4844_test.go @@ -127,3 +127,56 @@ func TestFakeExponential(t *testing.T) { } } } + +func TestCalcExcessBlobGasEIP7918(t *testing.T) { + // TODO: replace with a test config that has Osaka enabled. + c := *params.MainnetChainConfig + cfg := &c + cfg.OsakaTime = new(uint64) + pragueSchedule := *cfg.BlobScheduleConfig.Prague + cfg.BlobScheduleConfig.Osaka = &pragueSchedule + + var ( + targetBlobs = targetBlobsPerBlock(cfg, *cfg.CancunTime) + blobGasPerBlob = uint64(params.BlobTxBlobGasPerBlob) + blobGasTarget = uint64(targetBlobs) * blobGasPerBlob + ) + + makeHeader := func( + parentExcess uint64, + parentBaseFee uint64, + blobsUsed int, + ) *types.Header { + blobGasUsed := uint64(blobsUsed) * blobGasPerBlob + 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 6fcd0674bc..14a1338c84 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -174,6 +174,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 << 14 // Base execution gas cost for a blob. HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935. )