Skip to content

Commit b38efe1

Browse files
roberto-bayardoInphi
authored andcommitted
- fix issue with not using proper parent block excess data gas by making excess data gas an explicit part of the EVM block context
- add initial enforcement of block level data gas limit
1 parent 28e8789 commit b38efe1

30 files changed

+199
-109
lines changed

accounts/abi/bind/backends/simulated.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,14 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
642642
msg := callMsg{call}
643643

644644
txContext := core.NewEVMTxContext(msg)
645-
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil)
645+
646+
var excessDataGas *big.Int
647+
// Get the last block header
648+
ph := b.blockchain.GetHeaderByHash(block.ParentHash())
649+
if ph != nil {
650+
excessDataGas = ph.ExcessDataGas
651+
}
652+
evmContext := core.NewEVMBlockContext(block.Header(), excessDataGas, b.blockchain, nil)
646653
// Create a new environment which holds all relevant information
647654
// about the transaction and calling mechanisms.
648655
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})

consensus/beacon/consensus.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
346346
if chain.Config().IsSharding(header.Number) {
347347
if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil {
348348
header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs)))
349+
} else {
350+
header.SetExcessDataGas(new(big.Int))
349351
}
350352
}
351353
}

consensus/clique/clique.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,8 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
579579
if chain.Config().IsSharding(header.Number) {
580580
if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil {
581581
header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs)))
582+
} else {
583+
header.SetExcessDataGas(new(big.Int))
582584
}
583585
}
584586
}

consensus/ethash/consensus.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,8 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.
612612
if chain.Config().IsSharding(header.Number) {
613613
if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil {
614614
header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs)))
615+
} else {
616+
header.SetExcessDataGas(new(big.Int))
615617
}
616618
}
617619
}

consensus/misc/eip4844_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ func TestFakeExponential(t *testing.T) {
2828
factor, num, denom int64
2929
want int64
3030
}{
31-
{1, 2, 1, 6}, // approximate 7.389
31+
// When num==0 the return value should always equal the value of factor
32+
{1, 0, 1, 1},
33+
{38493, 0, 1000, 38493},
34+
{0, 1234, 2345, 0}, // should be 0
35+
{1, 2, 1, 6}, // approximate 7.389
3236
{1, 4, 2, 6},
3337
{1, 3, 1, 16}, // approximate 20.09
3438
{1, 6, 2, 18},

core/blockchain.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
16561656
throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps)
16571657

16581658
go func(start time.Time, followup *types.Block, throwaway *state.StateDB, interrupt *uint32) {
1659-
bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt)
1659+
bc.prefetcher.Prefetch(followup, parent.ExcessDataGas, throwaway, bc.vmConfig, &followupInterrupt)
16601660

16611661
blockPrefetchExecuteTimer.Update(time.Since(start))
16621662
if atomic.LoadUint32(interrupt) == 1 {
@@ -1668,7 +1668,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
16681668

16691669
// Process block using the parent state as reference point
16701670
substart := time.Now()
1671-
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
1671+
receipts, logs, usedGas, err := bc.processor.Process(block, parent.ExcessDataGas, statedb, bc.vmConfig)
16721672
if err != nil {
16731673
bc.reportBlock(block, receipts, err)
16741674
atomic.StoreUint32(&followupInterrupt, 1)

core/blockchain_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,12 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
156156
}
157157
return err
158158
}
159-
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil)
159+
parent := blockchain.GetBlockByHash(block.ParentHash())
160+
statedb, err := state.New(parent.Root(), blockchain.stateCache, nil)
160161
if err != nil {
161162
return err
162163
}
163-
receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{})
164+
receipts, _, usedGas, err := blockchain.processor.Process(block, parent.Header().ExcessDataGas, statedb, vm.Config{})
164165
if err != nil {
165166
blockchain.reportBlock(block, receipts, err)
166167
return err
@@ -3913,7 +3914,6 @@ func TestDataBlobTxs(t *testing.T) {
39133914

39143915
blocks, _ := GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *BlockGen) {
39153916
b.SetCoinbase(common.Address{1})
3916-
b.SetExcessDataGas(new(big.Int))
39173917
msg := types.BlobTxMessage{
39183918
Nonce: 0,
39193919
Gas: 500000,

core/chain_makers.go

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func (b *BlockGen) SetCoinbase(addr common.Address) {
5858
panic("coinbase can only be set once")
5959
}
6060
b.header.Coinbase = addr
61-
b.gasPool = new(GasPool).AddGas(b.header.GasLimit)
61+
b.gasPool = new(GasPool).AddGas(b.header.GasLimit).AddDataGas(params.MaxDataGasPerBlock)
6262
}
6363

6464
// SetExtra sets the extra data field of the generated block.
@@ -78,11 +78,6 @@ func (b *BlockGen) SetDifficulty(diff *big.Int) {
7878
b.header.Difficulty = diff
7979
}
8080

81-
// SetExcessDataGas sets the excess_data_gas field of the generated block.
82-
func (b *BlockGen) SetExcessDataGas(excessDataGas *big.Int) {
83-
b.header.SetExcessDataGas(excessDataGas)
84-
}
85-
8681
// AddTx adds a transaction to the generated block. If no coinbase has
8782
// been set, the block's coinbase is set to the zero address.
8883
//
@@ -108,7 +103,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
108103
b.SetCoinbase(common.Address{})
109104
}
110105
b.statedb.Prepare(tx.Hash(), len(b.txs))
111-
receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
106+
receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, b.parent.Header().ExcessDataGas, tx, &b.header.GasUsed, vm.Config{})
112107
if err != nil {
113108
panic(err)
114109
}
@@ -140,15 +135,6 @@ func (b *BlockGen) BaseFee() *big.Int {
140135
return new(big.Int).Set(b.header.BaseFee)
141136
}
142137

143-
// ExcessDataGas returns the EIP-4844 excess_data_gas of the block being generated.
144-
func (b *BlockGen) ExcessDataGas() *big.Int {
145-
v := new(big.Int)
146-
if b.header.ExcessDataGas != nil {
147-
v.Set(b.header.ExcessDataGas)
148-
}
149-
return v
150-
}
151-
152138
// AddUncheckedReceipt forcefully adds a receipts to the block without a
153139
// backing transaction.
154140
//

core/evm.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,15 @@ type ChainContext interface {
3636
}
3737

3838
// NewEVMBlockContext creates a new context for use in the EVM.
39-
func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext {
39+
//
40+
// excessDataGas must be set to the excessDataGas value from the *parent* block header, and can be
41+
// nil if the parent block is not of EIP-4844 type. It is read only.
42+
func NewEVMBlockContext(header *types.Header, excessDataGas *big.Int, chain ChainContext, author *common.Address) vm.BlockContext {
4043
var (
41-
beneficiary common.Address
42-
baseFee *big.Int
43-
random *common.Hash
44-
excessDataGas *big.Int
44+
beneficiary common.Address
45+
baseFee *big.Int
46+
random *common.Hash
47+
edg *big.Int
4548
)
4649

4750
// If we don't have an explicit author (i.e. not mining), extract from the header
@@ -56,8 +59,8 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
5659
if header.Difficulty.Cmp(common.Big0) == 0 {
5760
random = &header.MixDigest
5861
}
59-
if header.ExcessDataGas != nil {
60-
excessDataGas = new(big.Int).Set(header.ExcessDataGas)
62+
if excessDataGas != nil {
63+
edg = new(big.Int).Set(excessDataGas)
6164
}
6265
return vm.BlockContext{
6366
CanTransfer: CanTransfer,
@@ -68,7 +71,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
6871
Time: new(big.Int).SetUint64(header.Time),
6972
Difficulty: new(big.Int).Set(header.Difficulty),
7073
BaseFee: baseFee,
71-
ExcessDataGas: excessDataGas,
74+
ExcessDataGas: edg,
7275
GasLimit: header.GasLimit,
7376
Random: random,
7477
}

core/gaspool.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,58 @@ import (
2323

2424
// GasPool tracks the amount of gas available during execution of the transactions
2525
// in a block. The zero value is a pool with zero gas available.
26-
type GasPool uint64
26+
type GasPool struct {
27+
gas, dataGas uint64
28+
}
2729

2830
// AddGas makes gas available for execution.
2931
func (gp *GasPool) AddGas(amount uint64) *GasPool {
30-
if uint64(*gp) > math.MaxUint64-amount {
32+
if gp.gas > math.MaxUint64-amount {
3133
panic("gas pool pushed above uint64")
3234
}
33-
*(*uint64)(gp) += amount
35+
gp.gas += amount
3436
return gp
3537
}
3638

3739
// SubGas deducts the given amount from the pool if enough gas is
3840
// available and returns an error otherwise.
3941
func (gp *GasPool) SubGas(amount uint64) error {
40-
if uint64(*gp) < amount {
42+
if gp.gas < amount {
4143
return ErrGasLimitReached
4244
}
43-
*(*uint64)(gp) -= amount
45+
gp.gas -= amount
4446
return nil
4547
}
4648

4749
// Gas returns the amount of gas remaining in the pool.
4850
func (gp *GasPool) Gas() uint64 {
49-
return uint64(*gp)
51+
return gp.gas
52+
}
53+
54+
// AddDataGas makes data gas available for execution.
55+
func (gp *GasPool) AddDataGas(amount uint64) *GasPool {
56+
if gp.dataGas > math.MaxUint64-amount {
57+
panic("data gas pool pushed above uint64")
58+
}
59+
gp.dataGas += amount
60+
return gp
61+
}
62+
63+
// SubDataGas deducts the given amount from the pool if enough data gas is available and returns an
64+
// error otherwise.
65+
func (gp *GasPool) SubDataGas(amount uint64) error {
66+
if gp.dataGas < amount {
67+
return ErrGasLimitReached
68+
}
69+
gp.dataGas -= amount
70+
return nil
71+
}
72+
73+
// DataGas returns the amount of data gas remaining in the pool.
74+
func (gp *GasPool) DataGas() uint64 {
75+
return gp.dataGas
5076
}
5177

5278
func (gp *GasPool) String() string {
53-
return fmt.Sprintf("%d", *gp)
79+
return fmt.Sprintf("gas: %d, data_gas: %d", gp.gas, gp.dataGas)
5480
}

0 commit comments

Comments
 (0)