Skip to content

Commit e6f3ce7

Browse files
lightclientMariusVanDerWijdenfjl
authored
params,core: add max and target value to chain config (#31002)
Implements [EIP-7840](ethereum/EIPs#9129) and [EIP-7691](https://github.com/ethereum/EIPs/blob/d96625a4dcbbe2572fa006f062bd02b4582eefd5/EIPS/eip-7691.md). --------- Co-authored-by: Marius van der Wijden <[email protected]> Co-authored-by: Felix Lange <[email protected]>
1 parent eee8682 commit e6f3ce7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+612
-203
lines changed

cmd/devp2p/internal/ethtest/suite.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Tra
743743
GasTipCap: uint256.NewInt(1),
744744
GasFeeCap: uint256.MustFromBig(s.chain.Head().BaseFee()),
745745
Gas: 100000,
746-
BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(*s.chain.Head().ExcessBlobGas())),
746+
BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(s.chain.config, s.chain.Head().Header())),
747747
BlobHashes: makeSidecar(blobdata...).BlobHashes(),
748748
Sidecar: makeSidecar(blobdata...),
749749
}

cmd/devp2p/internal/ethtest/testdata/genesis.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@
1818
"shanghaiTime": 780,
1919
"cancunTime": 840,
2020
"terminalTotalDifficulty": 9454784,
21-
"ethash": {}
21+
"ethash": {},
22+
"blobSchedule": {
23+
"cancun": {
24+
"target": 3,
25+
"max": 6,
26+
"baseFeeUpdateFraction": 3338477
27+
}
28+
}
2229
},
2330
"nonce": "0x0",
2431
"timestamp": "0x0",
@@ -108,4 +115,4 @@
108115
"baseFeePerGas": null,
109116
"excessBlobGas": null,
110117
"blobGasUsed": null
111-
}
118+
}

cmd/evm/internal/t8ntool/execution.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,28 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
178178
var excessBlobGas uint64
179179
if pre.Env.ExcessBlobGas != nil {
180180
excessBlobGas = *pre.Env.ExcessBlobGas
181-
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
181+
header := &types.Header{
182+
Time: pre.Env.Timestamp,
183+
ExcessBlobGas: pre.Env.ExcessBlobGas,
184+
}
185+
vmContext.BlobBaseFee = eip4844.CalcBlobFee(chainConfig, header)
182186
} else {
183187
// If it is not explicitly defined, but we have the parent values, we try
184188
// to calculate it ourselves.
185189
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
186190
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
187191
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
188-
excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
189-
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
192+
parent := &types.Header{
193+
Time: pre.Env.ParentTimestamp,
194+
ExcessBlobGas: pre.Env.ParentExcessBlobGas,
195+
BlobGasUsed: pre.Env.ParentBlobGasUsed,
196+
}
197+
excessBlobGas = eip4844.CalcExcessBlobGas(chainConfig, parent)
198+
header := &types.Header{
199+
Time: pre.Env.Timestamp,
200+
ExcessBlobGas: &excessBlobGas,
201+
}
202+
vmContext.BlobBaseFee = eip4844.CalcBlobFee(chainConfig, header)
190203
}
191204
}
192205
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
@@ -229,7 +242,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
229242
txBlobGas := uint64(0)
230243
if tx.Type() == types.BlobTxType {
231244
txBlobGas = uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes()))
232-
if used, max := blobGasUsed+txBlobGas, uint64(params.MaxBlobGasPerBlock); used > max {
245+
max := eip4844.MaxBlobGasPerBlock(chainConfig, pre.Env.Timestamp)
246+
if used := blobGasUsed + txBlobGas; used > max {
233247
err := fmt.Errorf("blob gas (%d) would exceed maximum allowance %d", used, max)
234248
log.Warn("rejected tx", "index", i, "err", err)
235249
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})

consensus/beacon/consensus.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
282282
if header.ParentBeaconRoot == nil {
283283
return errors.New("header is missing beaconRoot")
284284
}
285-
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
285+
if err := eip4844.VerifyEIP4844Header(chain.Config(), parent, header); err != nil {
286286
return err
287287
}
288288
}

consensus/misc/eip4844/eip4844.go

Lines changed: 89 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ import (
2323

2424
"github.com/ethereum/go-ethereum/core/types"
2525
"github.com/ethereum/go-ethereum/params"
26+
"github.com/ethereum/go-ethereum/params/forks"
2627
)
2728

2829
var (
29-
minBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
30-
blobGaspriceUpdateFraction = big.NewInt(params.BlobTxBlobGaspriceUpdateFraction)
30+
minBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
3131
)
3232

3333
// VerifyEIP4844Header verifies the presence of the excessBlobGas field and that
3434
// if the current block contains no transactions, the excessBlobGas is updated
3535
// accordingly.
36-
func VerifyEIP4844Header(parent, header *types.Header) error {
36+
func VerifyEIP4844Header(config *params.ChainConfig, parent, header *types.Header) error {
3737
// Verify the header is not malformed
3838
if header.ExcessBlobGas == nil {
3939
return errors.New("header is missing excessBlobGas")
@@ -42,42 +42,112 @@ func VerifyEIP4844Header(parent, header *types.Header) error {
4242
return errors.New("header is missing blobGasUsed")
4343
}
4444
// Verify that the blob gas used remains within reasonable limits.
45-
if *header.BlobGasUsed > params.MaxBlobGasPerBlock {
46-
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.MaxBlobGasPerBlock)
45+
maxBlobGas := MaxBlobGasPerBlock(config, header.Time)
46+
if *header.BlobGasUsed > maxBlobGas {
47+
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, maxBlobGas)
4748
}
4849
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
4950
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
5051
}
5152
// Verify the excessBlobGas is correct based on the parent header
53+
expectedExcessBlobGas := CalcExcessBlobGas(config, parent)
54+
if *header.ExcessBlobGas != expectedExcessBlobGas {
55+
return fmt.Errorf("invalid excessBlobGas: have %d, want %d", *header.ExcessBlobGas, expectedExcessBlobGas)
56+
}
57+
return nil
58+
}
59+
60+
// CalcExcessBlobGas calculates the excess blob gas after applying the set of
61+
// blobs on top of the excess blob gas.
62+
func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header) uint64 {
5263
var (
64+
targetGas = uint64(targetBlobsPerBlock(config, parent.Time)) * params.BlobTxBlobGasPerBlob
5365
parentExcessBlobGas uint64
5466
parentBlobGasUsed uint64
5567
)
5668
if parent.ExcessBlobGas != nil {
5769
parentExcessBlobGas = *parent.ExcessBlobGas
5870
parentBlobGasUsed = *parent.BlobGasUsed
5971
}
60-
expectedExcessBlobGas := CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
61-
if *header.ExcessBlobGas != expectedExcessBlobGas {
62-
return fmt.Errorf("invalid excessBlobGas: have %d, want %d, parent excessBlobGas %d, parent blobDataUsed %d",
63-
*header.ExcessBlobGas, expectedExcessBlobGas, parentExcessBlobGas, parentBlobGasUsed)
72+
excessBlobGas := parentExcessBlobGas + parentBlobGasUsed
73+
if excessBlobGas < targetGas {
74+
return 0
6475
}
65-
return nil
76+
return excessBlobGas - targetGas
6677
}
6778

68-
// CalcExcessBlobGas calculates the excess blob gas after applying the set of
69-
// blobs on top of the excess blob gas.
70-
func CalcExcessBlobGas(parentExcessBlobGas uint64, parentBlobGasUsed uint64) uint64 {
71-
excessBlobGas := parentExcessBlobGas + parentBlobGasUsed
72-
if excessBlobGas < params.BlobTxTargetBlobGasPerBlock {
79+
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
80+
func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
81+
var frac uint64
82+
switch config.LatestFork(header.Time) {
83+
case forks.Prague:
84+
frac = config.BlobScheduleConfig.Prague.UpdateFraction
85+
case forks.Cancun:
86+
frac = config.BlobScheduleConfig.Cancun.UpdateFraction
87+
default:
88+
panic("calculating blob fee on unsupported fork")
89+
}
90+
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(frac))
91+
}
92+
93+
// MaxBlobsPerBlock returns the max blobs per block for a block at the given timestamp.
94+
func MaxBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
95+
if cfg.BlobScheduleConfig == nil {
96+
return 0
97+
}
98+
var (
99+
london = cfg.LondonBlock
100+
s = cfg.BlobScheduleConfig
101+
)
102+
switch {
103+
case cfg.IsPrague(london, time) && s.Prague != nil:
104+
return s.Prague.Max
105+
case cfg.IsCancun(london, time) && s.Cancun != nil:
106+
return s.Cancun.Max
107+
default:
73108
return 0
74109
}
75-
return excessBlobGas - params.BlobTxTargetBlobGasPerBlock
76110
}
77111

78-
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
79-
func CalcBlobFee(excessBlobGas uint64) *big.Int {
80-
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(excessBlobGas), blobGaspriceUpdateFraction)
112+
// MaxBlobsPerBlock returns the maximum blob gas that can be spent in a block at the given timestamp.
113+
func MaxBlobGasPerBlock(cfg *params.ChainConfig, time uint64) uint64 {
114+
return uint64(MaxBlobsPerBlock(cfg, time)) * params.BlobTxBlobGasPerBlob
115+
}
116+
117+
// LatestMaxBlobsPerBlock returns the latest max blobs per block defined by the
118+
// configuration, regardless of the currently active fork.
119+
func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int {
120+
s := cfg.BlobScheduleConfig
121+
if s == nil {
122+
return 0
123+
}
124+
switch {
125+
case s.Prague != nil:
126+
return s.Prague.Max
127+
case s.Cancun != nil:
128+
return s.Cancun.Max
129+
default:
130+
return 0
131+
}
132+
}
133+
134+
// targetBlobsPerBlock returns the target number of blobs in a block at the given timestamp.
135+
func targetBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
136+
if cfg.BlobScheduleConfig == nil {
137+
return 0
138+
}
139+
var (
140+
london = cfg.LondonBlock
141+
s = cfg.BlobScheduleConfig
142+
)
143+
switch {
144+
case cfg.IsPrague(london, time) && s.Prague != nil:
145+
return s.Prague.Target
146+
case cfg.IsCancun(london, time) && s.Cancun != nil:
147+
return s.Cancun.Target
148+
default:
149+
return 0
150+
}
81151
}
82152

83153
// fakeExponential approximates factor * e ** (numerator / denominator) using

consensus/misc/eip4844/eip4844_test.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,43 +21,57 @@ import (
2121
"math/big"
2222
"testing"
2323

24+
"github.com/ethereum/go-ethereum/core/types"
2425
"github.com/ethereum/go-ethereum/params"
2526
)
2627

2728
func TestCalcExcessBlobGas(t *testing.T) {
29+
var (
30+
config = params.MainnetChainConfig
31+
targetBlobs = targetBlobsPerBlock(config, *config.CancunTime)
32+
targetBlobGas = uint64(targetBlobs) * params.BlobTxBlobGasPerBlob
33+
)
2834
var tests = []struct {
2935
excess uint64
30-
blobs uint64
36+
blobs int
3137
want uint64
3238
}{
3339
// The excess blob gas should not increase from zero if the used blob
3440
// slots are below - or equal - to the target.
3541
{0, 0, 0},
3642
{0, 1, 0},
37-
{0, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, 0},
43+
{0, targetBlobs, 0},
3844

3945
// If the target blob gas is exceeded, the excessBlobGas should increase
4046
// by however much it was overshot
41-
{0, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 1, params.BlobTxBlobGasPerBlob},
42-
{1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 1, params.BlobTxBlobGasPerBlob + 1},
43-
{1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 2, 2*params.BlobTxBlobGasPerBlob + 1},
47+
{0, targetBlobs + 1, params.BlobTxBlobGasPerBlob},
48+
{1, targetBlobs + 1, params.BlobTxBlobGasPerBlob + 1},
49+
{1, targetBlobs + 2, 2*params.BlobTxBlobGasPerBlob + 1},
4450

4551
// The excess blob gas should decrease by however much the target was
4652
// under-shot, capped at zero.
47-
{params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock},
48-
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxTargetBlobGasPerBlock - params.BlobTxBlobGasPerBlob},
49-
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxTargetBlobGasPerBlock - (2 * params.BlobTxBlobGasPerBlob)},
50-
{params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0},
53+
{targetBlobGas, targetBlobs, targetBlobGas},
54+
{targetBlobGas, targetBlobs - 1, targetBlobGas - params.BlobTxBlobGasPerBlob},
55+
{targetBlobGas, targetBlobs - 2, targetBlobGas - (2 * params.BlobTxBlobGasPerBlob)},
56+
{params.BlobTxBlobGasPerBlob - 1, targetBlobs - 1, 0},
5157
}
5258
for i, tt := range tests {
53-
result := CalcExcessBlobGas(tt.excess, tt.blobs*params.BlobTxBlobGasPerBlob)
59+
blobGasUsed := uint64(tt.blobs) * params.BlobTxBlobGasPerBlob
60+
parent := &types.Header{
61+
Time: *config.CancunTime,
62+
ExcessBlobGas: &tt.excess,
63+
BlobGasUsed: &blobGasUsed,
64+
}
65+
result := CalcExcessBlobGas(config, parent)
5466
if result != tt.want {
5567
t.Errorf("test %d: excess blob gas mismatch: have %v, want %v", i, result, tt.want)
5668
}
5769
}
5870
}
5971

6072
func TestCalcBlobFee(t *testing.T) {
73+
zero := uint64(0)
74+
6175
tests := []struct {
6276
excessBlobGas uint64
6377
blobfee int64
@@ -68,7 +82,9 @@ func TestCalcBlobFee(t *testing.T) {
6882
{10 * 1024 * 1024, 23},
6983
}
7084
for i, tt := range tests {
71-
have := CalcBlobFee(tt.excessBlobGas)
85+
config := &params.ChainConfig{LondonBlock: big.NewInt(0), CancunTime: &zero, BlobScheduleConfig: params.DefaultBlobSchedule}
86+
header := &types.Header{ExcessBlobGas: &tt.excessBlobGas}
87+
have := CalcBlobFee(config, header)
7288
if have.Int64() != tt.blobfee {
7389
t.Errorf("test %d: blobfee mismatch: have %v want %v", i, have, tt.blobfee)
7490
}

core/blockchain.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,9 +2139,8 @@ func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (co
21392139
// processing of a block. These logs are later announced as deleted or reborn.
21402140
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
21412141
var blobGasPrice *big.Int
2142-
excessBlobGas := b.ExcessBlobGas()
2143-
if excessBlobGas != nil {
2144-
blobGasPrice = eip4844.CalcBlobFee(*excessBlobGas)
2142+
if b.ExcessBlobGas() != nil {
2143+
blobGasPrice = eip4844.CalcBlobFee(bc.chainConfig, b.Header())
21452144
}
21462145
receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64())
21472146
if err := receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), blobGasPrice, b.Transactions()); err != nil {

core/chain_makers.go

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
143143
// instruction will panic during execution if it attempts to access a block number outside
144144
// of the range created by GenerateChain.
145145
func (b *BlockGen) AddTx(tx *types.Transaction) {
146-
b.addTx(nil, vm.Config{}, tx)
146+
// Wrap the chain config in an empty BlockChain object to satisfy ChainContext.
147+
bc := &BlockChain{chainConfig: b.cm.config}
148+
b.addTx(bc, vm.Config{}, tx)
147149
}
148150

149151
// AddTxWithChain adds a transaction to the generated block. If no coinbase has
@@ -445,7 +447,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
445447
}
446448
var blobGasPrice *big.Int
447449
if block.ExcessBlobGas() != nil {
448-
blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas())
450+
blobGasPrice = eip4844.CalcBlobFee(cm.config, block.Header())
449451
}
450452
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
451453
panic(err)
@@ -548,7 +550,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
548550
}
549551
var blobGasPrice *big.Int
550552
if block.ExcessBlobGas() != nil {
551-
blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas())
553+
blobGasPrice = eip4844.CalcBlobFee(cm.config, block.Header())
552554
}
553555
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
554556
panic(err)
@@ -598,15 +600,7 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi
598600
}
599601
}
600602
if cm.config.IsCancun(header.Number, header.Time) {
601-
var (
602-
parentExcessBlobGas uint64
603-
parentBlobGasUsed uint64
604-
)
605-
if parent.ExcessBlobGas() != nil {
606-
parentExcessBlobGas = *parent.ExcessBlobGas()
607-
parentBlobGasUsed = *parent.BlobGasUsed()
608-
}
609-
excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
603+
excessBlobGas := eip4844.CalcExcessBlobGas(cm.config, parent.Header())
610604
header.ExcessBlobGas = &excessBlobGas
611605
header.BlobGasUsed = new(uint64)
612606
header.ParentBeaconRoot = new(common.Hash)

core/chain_makers_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestGeneratePOSChain(t *testing.T) {
4242
aa = common.Address{0xaa}
4343
bb = common.Address{0xbb}
4444
funds = big.NewInt(0).Mul(big.NewInt(1337), big.NewInt(params.Ether))
45-
config = *params.AllEthashProtocolChanges
45+
config = *params.MergedTestChainConfig
4646
gspec = &Genesis{
4747
Config: &config,
4848
Alloc: types.GenesisAlloc{
@@ -57,10 +57,6 @@ func TestGeneratePOSChain(t *testing.T) {
5757
db = rawdb.NewMemoryDatabase()
5858
)
5959

60-
config.TerminalTotalDifficulty = common.Big0
61-
config.ShanghaiTime = u64(0)
62-
config.CancunTime = u64(0)
63-
6460
// init 0xaa with some storage elements
6561
storage := make(map[common.Hash]common.Hash)
6662
storage[common.Hash{0x00}] = common.Hash{0x00}

0 commit comments

Comments
 (0)