Skip to content

Commit

Permalink
Implement EIP-7691 blob gas price changes for pdn-5 (#13426)
Browse files Browse the repository at this point in the history
See ethereum/EIPs#9060

Tasks board - #12401
  • Loading branch information
somnathb1 committed Jan 27, 2025
1 parent 07c6e9c commit c0532dd
Show file tree
Hide file tree
Showing 42 changed files with 260 additions and 180 deletions.
4 changes: 2 additions & 2 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func (b *SimulatedBackend) emptyPendingBlock() {
b.pendingBlock = blockChain.Blocks[0]
b.pendingReceipts = blockChain.Receipts[0]
b.pendingHeader = blockChain.Headers[0]
b.gasPool = new(core.GasPool).AddGas(b.pendingHeader.GasLimit).AddBlobGas(b.m.ChainConfig.GetMaxBlobGasPerBlock())
b.gasPool = new(core.GasPool).AddGas(b.pendingHeader.GasLimit).AddBlobGas(b.m.ChainConfig.GetMaxBlobGasPerBlock(b.pendingHeader.Time))
if b.pendingReaderTx != nil {
b.pendingReaderTx.Rollback()
}
Expand Down Expand Up @@ -721,7 +721,7 @@ func (b *SimulatedBackend) callContract(_ context.Context, call ethereum.CallMsg

txContext := core.NewEVMTxContext(msg)
header := block.Header()
evmContext := core.NewEVMBlockContext(header, core.GetHashFn(header, b.getHeader), b.m.Engine, nil)
evmContext := core.NewEVMBlockContext(header, core.GetHashFn(header, b.getHeader), b.m.Engine, nil, b.m.ChainConfig)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmEnv := vm.NewEVM(evmContext, txContext, statedb, b.m.ChainConfig, vm.Config{})
Expand Down
2 changes: 1 addition & 1 deletion cmd/devnet/services/polygon/proofgenerator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func (rg *requestGenerator) GetTransactionReceipt(ctx context.Context, hash libc
var usedGas uint64
var usedBlobGas uint64

gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock())
gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock(block.Header().Time))

noopWriter := state.NewNoopWriter()

Expand Down
2 changes: 1 addition & 1 deletion cmd/state/commands/opcode_tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ func runBlock(engine consensus.Engine, ibs *state.IntraBlockState, txnWriter sta
chainConfig *chain2.Config, getHeader func(hash libcommon.Hash, number uint64) *types.Header, block *types.Block, vmConfig vm.Config, trace bool, logger log.Logger) (types.Receipts, error) {
header := block.Header()
vmConfig.TraceJumpDest = true
gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock())
gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock(header.Time))
usedGas := new(uint64)
usedBlobGas := new(uint64)
var receipts types.Receipts
Expand Down
2 changes: 1 addition & 1 deletion cmd/state/exec3/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func (rw *Worker) RunTxTaskNoLock(txTask *exec22.TxTask) {
blockContext := txTask.EvmBlockContext
if !rw.background {
getHashFn := core.GetHashFn(header, rw.getHeader)
blockContext = core.NewEVMBlockContext(header, getHashFn, rw.engine, nil /* author */)
blockContext = core.NewEVMBlockContext(header, getHashFn, rw.engine, nil /* author */, rw.chainConfig)
}
rw.evm.ResetBetweenBlocks(blockContext, core.NewEVMTxContext(msg), ibs, vmConfig, rules)

Expand Down
2 changes: 1 addition & 1 deletion consensus/merge/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ func (s *Merge) verifyHeader(chain consensus.ChainHeaderReader, header, parent *
if err := misc.VerifyPresenceOfCancunHeaderFields(header); err != nil {
return err
}
expectedExcessBlobGas := misc.CalcExcessBlobGas(chain.Config(), parent)
expectedExcessBlobGas := misc.CalcExcessBlobGas(chain.Config(), parent, header.Time)
if *header.ExcessBlobGas != expectedExcessBlobGas {
return fmt.Errorf("invalid excessBlobGas: have %d, want %d", *header.ExcessBlobGas, expectedExcessBlobGas)
}
Expand Down
11 changes: 9 additions & 2 deletions consensus/misc/eip1559.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,17 @@ func (f eip1559Calculator) CurrentFees(chainConfig *chain.Config, db kv.Getter)
}

if currentHeader.ExcessBlobGas != nil {
excessBlobGas := CalcExcessBlobGas(chainConfig, currentHeader)
b, err := GetBlobGasPrice(chainConfig, excessBlobGas)
var nextHeaderTime = currentHeader.Time + 1 // Speculative - Next header must be at least 1 second ahead
parentHeader := rawdb.ReadHeaderByNumber(db, currentHeader.Number.Uint64()-1)
if parentHeader != nil {
nextHeaderTime = currentHeader.Time + (currentHeader.Time - parentHeader.Time) // This difference should be close enough to seconds per slot
}
excessBlobGas := CalcExcessBlobGas(chainConfig, currentHeader, nextHeaderTime)
b, err := GetBlobGasPrice(chainConfig, excessBlobGas, nextHeaderTime)
if err == nil {
blobFee = b.Uint64()
} else {
return 0, 0, 0, 0, err
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions consensus/misc/eip4844.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import (
)

// CalcExcessBlobGas implements calc_excess_blob_gas from EIP-4844
func CalcExcessBlobGas(config *chain.Config, parent *types.Header) uint64 {
// Updated for EIP-7691: currentHeaderTime is used to determine the fork, and hence params
func CalcExcessBlobGas(config *chain.Config, parent *types.Header, currentHeaderTime uint64) uint64 {
var excessBlobGas, blobGasUsed uint64
if parent.ExcessBlobGas != nil {
excessBlobGas = *parent.ExcessBlobGas
Expand All @@ -37,10 +38,10 @@ func CalcExcessBlobGas(config *chain.Config, parent *types.Header) uint64 {
blobGasUsed = *parent.BlobGasUsed
}

if excessBlobGas+blobGasUsed < config.GetTargetBlobGasPerBlock() {
if excessBlobGas+blobGasUsed < config.GetTargetBlobGasPerBlock(currentHeaderTime) {
return 0
}
return excessBlobGas + blobGasUsed - config.GetTargetBlobGasPerBlock()
return excessBlobGas + blobGasUsed - config.GetTargetBlobGasPerBlock(currentHeaderTime)
}

// FakeExponential approximates factor * e ** (num / denom) using a taylor expansion
Expand Down Expand Up @@ -99,8 +100,8 @@ func VerifyAbsenceOfCancunHeaderFields(header *types.Header) error {
return nil
}

func GetBlobGasPrice(config *chain.Config, excessBlobGas uint64) (*uint256.Int, error) {
return FakeExponential(uint256.NewInt(config.GetMinBlobGasPrice()), uint256.NewInt(config.GetBlobGasPriceUpdateFraction()), excessBlobGas)
func GetBlobGasPrice(config *chain.Config, excessBlobGas uint64, headerTime uint64) (*uint256.Int, error) {
return FakeExponential(uint256.NewInt(config.GetMinBlobGasPrice()), uint256.NewInt(config.GetBlobGasPriceUpdateFraction(headerTime)), excessBlobGas)
}

func GetBlobGasUsed(numBlobs int) uint64 {
Expand Down
6 changes: 3 additions & 3 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func ExecuteBlockEphemerally(
usedGas := new(uint64)
usedBlobGas := new(uint64)
gp := new(GasPool)
gp.AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock())
gp.AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock(block.Time()))

if err := InitializeBlockExecution(engine, chainReader, block.Header(), chainConfig, ibs, logger); err != nil {
return nil, err
Expand Down Expand Up @@ -265,7 +265,7 @@ func SysCallContract(contract libcommon.Address, data []byte, chainConfig *chain
author = &state.SystemAddress
txContext = NewEVMTxContext(msg)
}
blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), engine, author)
blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), engine, author, chainConfig)
evm := vm.NewEVM(blockContext, txContext, ibs, chainConfig, vmConfig)

ret, _, err := evm.Call(
Expand Down Expand Up @@ -299,7 +299,7 @@ func SysCreate(contract libcommon.Address, data []byte, chainConfig chain.Config
// Create a new context to be used in the EVM environment
author := &contract
txContext := NewEVMTxContext(msg)
blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), nil, author)
blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), nil, author, &chainConfig)
evm := vm.NewEVM(blockContext, txContext, ibs, &chainConfig, vmConfig)

ret, _, err := evm.SysCreate(
Expand Down
2 changes: 1 addition & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ func MakeEmptyHeader(parent *types.Header, chainConfig *chain.Config, timestamp
}

if chainConfig.IsCancun(header.Time) {
excessBlobGas := misc.CalcExcessBlobGas(chainConfig, parent)
excessBlobGas := misc.CalcExcessBlobGas(chainConfig, parent, header.Time)
header.ExcessBlobGas = &excessBlobGas
header.BlobGasUsed = new(uint64)
}
Expand Down
27 changes: 18 additions & 9 deletions core/evm.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
// (original work)
// Copyright 2024 The Erigon Authors
// (modifications)
// This file is part of Erigon.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// Erigon is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// Erigon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// along with Erigon. If not, see <http://www.gnu.org/licenses/>.

package core

Expand All @@ -22,16 +25,19 @@ import (

"github.com/holiman/uint256"

"github.com/erigontech/erigon-lib/chain"
libcommon "github.com/erigontech/erigon-lib/common"

"github.com/erigontech/erigon/consensus"
"github.com/erigontech/erigon/consensus/merge"
"github.com/erigontech/erigon/consensus/misc"
"github.com/erigontech/erigon/core/types"
"github.com/erigontech/erigon/core/vm/evmtypes"
)

// NewEVMBlockContext creates a new context for use in the EVM.
func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) libcommon.Hash, engine consensus.EngineReader, author *libcommon.Address) evmtypes.BlockContext {
func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) libcommon.Hash,
engine consensus.EngineReader, author *libcommon.Address, config *chain.Config) evmtypes.BlockContext {
// If we don't have an explicit author (i.e. not mining), extract from the header
var beneficiary libcommon.Address
if author == nil {
Expand All @@ -54,10 +60,13 @@ func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) libco
*prevRandDao = header.MixDigest
}

var excessBlobGas *uint64
var blobBaseFee *uint256.Int
if header.ExcessBlobGas != nil {
excessBlobGas = new(uint64)
*excessBlobGas = *header.ExcessBlobGas
var err error
blobBaseFee, err = misc.GetBlobGasPrice(config, *header.ExcessBlobGas, header.Time)
if err != nil {
panic(err)
}
}

var transferFunc evmtypes.TransferFunc
Expand All @@ -81,7 +90,7 @@ func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) libco
BaseFee: &baseFee,
GasLimit: header.GasLimit,
PrevRanDao: prevRandDao,
ExcessBlobGas: excessBlobGas,
BlobBaseFee: blobBaseFee,
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func ApplyTransaction(config *chain.Config, blockHashFunc func(n uint64) libcomm
// about the transaction and calling mechanisms.
cfg.SkipAnalysis = SkipAnalysis(config, header.Number.Uint64())

blockContext := NewEVMBlockContext(header, blockHashFunc, engine, author)
blockContext := NewEVMBlockContext(header, blockHashFunc, engine, author, config)
vmenv := vm.NewEVM(blockContext, evmtypes.TxContext{}, ibs, config, cfg)

return applyTransaction(config, engine, gp, ibs, stateWriter, header, tx, usedGas, usedBlobGas, vmenv, cfg)
Expand Down
23 changes: 8 additions & 15 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (

cmath "github.com/erigontech/erigon/common/math"
"github.com/erigontech/erigon/common/u256"
"github.com/erigontech/erigon/consensus/misc"
"github.com/erigontech/erigon/core/types"
"github.com/erigontech/erigon/core/vm"
"github.com/erigontech/erigon/core/vm/evmtypes"
Expand Down Expand Up @@ -172,13 +171,10 @@ func (st *StateTransition) buyGas(gasBailout bool) error {
// compute blob fee for eip-4844 data blobs if any
blobGasVal := new(uint256.Int)
if st.evm.ChainRules().IsCancun {
if st.evm.Context.ExcessBlobGas == nil {
blobGasPrice := st.evm.Context.BlobBaseFee
if blobGasPrice == nil {
return fmt.Errorf("%w: Cancun is active but ExcessBlobGas is nil", ErrInternalFailure)
}
blobGasPrice, err := misc.GetBlobGasPrice(st.evm.ChainConfig(), *st.evm.Context.ExcessBlobGas)
if err != nil {
return err
}
blobGasVal, overflow = blobGasVal.MulOverflow(blobGasPrice, new(uint256.Int).SetUint64(st.msg.BlobGas()))
if overflow {
return fmt.Errorf("%w: overflow converting blob gas: %v", ErrInsufficientFunds, blobGasVal)
Expand Down Expand Up @@ -211,7 +207,8 @@ func (st *StateTransition) buyGas(gasBailout bool) error {
}
}
}
if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 {
balance := st.state.GetBalance(st.msg.From())
if have, want := balance, balanceCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want)
}
st.state.SubBalance(st.msg.From(), gasVal)
Expand Down Expand Up @@ -280,18 +277,14 @@ func (st *StateTransition) preCheck(gasBailout bool) error {
}
}
if st.msg.BlobGas() > 0 && st.evm.ChainRules().IsCancun {
if st.evm.Context.ExcessBlobGas == nil {
blobGasPrice := st.evm.Context.BlobBaseFee
if blobGasPrice == nil {
return fmt.Errorf("%w: Cancun is active but ExcessBlobGas is nil", ErrInternalFailure)
}
blobGasPrice, err := misc.GetBlobGasPrice(st.evm.ChainConfig(), *st.evm.Context.ExcessBlobGas)
if err != nil {
return err
}
maxFeePerBlobGas := st.msg.MaxFeePerBlobGas()
if !st.evm.Config().NoBaseFee && blobGasPrice.Cmp(maxFeePerBlobGas) > 0 {
return fmt.Errorf("%w: address %v, maxFeePerBlobGas: %v blobGasPrice: %v, excessBlobGas: %v",
ErrMaxFeePerBlobGas,
st.msg.From().Hex(), st.msg.MaxFeePerBlobGas(), blobGasPrice, st.evm.Context.ExcessBlobGas)
return fmt.Errorf("%w: address %v, maxFeePerBlobGas: %v < blobGasPrice: %v",
ErrMaxFeePerBlobGas, st.msg.From().Hex(), st.msg.MaxFeePerBlobGas(), blobGasPrice)
}
}

Expand Down
7 changes: 1 addition & 6 deletions core/vm/eips.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (

libcommon "github.com/erigontech/erigon-lib/common"

"github.com/erigontech/erigon/consensus/misc"
"github.com/erigontech/erigon/params"
)

Expand Down Expand Up @@ -303,11 +302,7 @@ func enable6780(jt *JumpTable) {

// opBlobBaseFee implements the BLOBBASEFEE opcode
func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
excessBlobGas := interpreter.evm.Context.ExcessBlobGas
blobBaseFee, err := misc.GetBlobGasPrice(interpreter.evm.ChainConfig(), *excessBlobGas)
if err != nil {
return nil, err
}
blobBaseFee := interpreter.evm.Context.BlobBaseFee
callContext.Stack.Push(blobBaseFee)
return nil, nil
}
Expand Down
34 changes: 25 additions & 9 deletions core/vm/evmtypes/evmtypes.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
// Copyright 2024 The Erigon Authors
// This file is part of Erigon.
//
// Erigon is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Erigon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Erigon. If not, see <http://www.gnu.org/licenses/>.

package evmtypes

import (
Expand Down Expand Up @@ -25,15 +41,15 @@ type BlockContext struct {
PostApplyMessage PostApplyMessageFunc

// Block information
Coinbase common.Address // Provides information for COINBASE
GasLimit uint64 // Provides information for GASLIMIT
MaxGasLimit bool // Use GasLimit override for 2^256-1 (to be compatible with OpenEthereum's trace_call)
BlockNumber uint64 // Provides information for NUMBER
Time uint64 // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY
BaseFee *uint256.Int // Provides information for BASEFEE
PrevRanDao *common.Hash // Provides information for PREVRANDAO
ExcessBlobGas *uint64 // Provides information for handling data blobs
Coinbase common.Address // Provides information for COINBASE
GasLimit uint64 // Provides information for GASLIMIT
MaxGasLimit bool // Use GasLimit override for 2^256-1 (to be compatible with OpenEthereum's trace_call)
BlockNumber uint64 // Provides information for NUMBER
Time uint64 // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY
BaseFee *uint256.Int // Provides information for BASEFEE
PrevRanDao *common.Hash // Provides information for PREVRANDAO
BlobBaseFee *uint256.Int // Provides information for BLOBBASEFEE
}

// TxContext provides the EVM with information about a transaction.
Expand Down
Loading

0 comments on commit c0532dd

Please sign in to comment.