Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

params,core: add max and target value to chain config #31002

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/devp2p/internal/ethtest/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Tra
GasTipCap: uint256.NewInt(1),
GasFeeCap: uint256.MustFromBig(s.chain.Head().BaseFee()),
Gas: 100000,
BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(*s.chain.Head().ExcessBlobGas())),
BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(s.chain.config, s.chain.Head().Header())),
BlobHashes: makeSidecar(blobdata...).BlobHashes(),
Sidecar: makeSidecar(blobdata...),
}
Expand Down
10 changes: 8 additions & 2 deletions cmd/devp2p/internal/ethtest/testdata/genesis.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
"shanghaiTime": 780,
"cancunTime": 840,
"terminalTotalDifficulty": 9454784,
"ethash": {}
"ethash": {},
"blobSchedule": {
"cancun": {
"target": 3,
"max": 6
}
}
},
"nonce": "0x0",
"timestamp": "0x0",
Expand Down Expand Up @@ -108,4 +114,4 @@
"baseFeePerGas": null,
"excessBlobGas": null,
"blobGasUsed": null
}
}
21 changes: 17 additions & 4 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,28 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
var excessBlobGas uint64
if pre.Env.ExcessBlobGas != nil {
excessBlobGas = *pre.Env.ExcessBlobGas
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
header := &types.Header{
Time: pre.Env.Timestamp,
ExcessBlobGas: pre.Env.ExcessBlobGas,
}
vmContext.BlobBaseFee = eip4844.CalcBlobFee(chainConfig, header)
} else {
// If it is not explicitly defined, but we have the parent values, we try
// to calculate it ourselves.
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
parent := &types.Header{
Time: pre.Env.ParentTimestamp,
ExcessBlobGas: pre.Env.ParentExcessBlobGas,
BlobGasUsed: pre.Env.ParentBlobGasUsed,
}
excessBlobGas = eip4844.CalcExcessBlobGas(chainConfig, parent)
header := &types.Header{
Time: pre.Env.Timestamp,
ExcessBlobGas: &excessBlobGas,
}
vmContext.BlobBaseFee = eip4844.CalcBlobFee(chainConfig, header)
}
}
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
Expand Down Expand Up @@ -234,7 +247,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
txBlobGas := uint64(0)
if tx.Type() == types.BlobTxType {
txBlobGas = uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes()))
if used, max := blobGasUsed+txBlobGas, uint64(params.MaxBlobGasPerBlock); used > max {
if used, max := blobGasUsed+txBlobGas, chainConfig.MaxBlobsPerBlock(pre.Env.Number)*params.BlobTxBlobGasPerBlob; used > max {
err := fmt.Errorf("blob gas (%d) would exceed maximum allowance %d", used, max)
log.Warn("rejected tx", "index", i, "err", err)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
Expand Down
2 changes: 1 addition & 1 deletion consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
if header.ParentBeaconRoot == nil {
return errors.New("header is missing beaconRoot")
}
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
if err := eip4844.VerifyEIP4844Header(chain.Config(), parent, header); err != nil {
return err
}
}
Expand Down
49 changes: 29 additions & 20 deletions consensus/misc/eip4844/eip4844.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,19 @@ import (

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params/forks"
)

var (
minBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
blobGaspriceUpdateFraction = big.NewInt(params.BlobTxBlobGaspriceUpdateFraction)
minBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice)
blobGaspriceUpdateFractionCancun = big.NewInt(params.BlobTxBlobGaspriceUpdateFractionCancun)
blobGaspriceUpdateFractionPrague = big.NewInt(params.BlobTxBlobGaspriceUpdateFractionPrague)
)

// VerifyEIP4844Header verifies the presence of the excessBlobGas field and that
// if the current block contains no transactions, the excessBlobGas is updated
// accordingly.
func VerifyEIP4844Header(parent, header *types.Header) error {
func VerifyEIP4844Header(config *params.ChainConfig, parent, header *types.Header) error {
// Verify the header is not malformed
if header.ExcessBlobGas == nil {
return errors.New("header is missing excessBlobGas")
Expand All @@ -42,42 +44,49 @@ func VerifyEIP4844Header(parent, header *types.Header) error {
return errors.New("header is missing blobGasUsed")
}
// Verify that the blob gas used remains within reasonable limits.
if *header.BlobGasUsed > params.MaxBlobGasPerBlock {
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.MaxBlobGasPerBlock)
if max := config.MaxBlobsPerBlock(header.Time) * params.BlobTxBlobGasPerBlob; *header.BlobGasUsed > max {
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, max)
}
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
}
// Verify the excessBlobGas is correct based on the parent header
expectedExcessBlobGas := CalcExcessBlobGas(config, parent)
if *header.ExcessBlobGas != expectedExcessBlobGas {
return fmt.Errorf("invalid excessBlobGas: have %d, want %d", *header.ExcessBlobGas, expectedExcessBlobGas)
}
return nil
}

// CalcExcessBlobGas calculates the excess blob gas after applying the set of
// blobs on top of the excess blob gas.
func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header) uint64 {
var (
target = config.TargetBlobsPerBlock(parent.Time) * params.BlobTxBlobGasPerBlob
parentExcessBlobGas uint64
parentBlobGasUsed uint64
)
if parent.ExcessBlobGas != nil {
parentExcessBlobGas = *parent.ExcessBlobGas
parentBlobGasUsed = *parent.BlobGasUsed
}
expectedExcessBlobGas := CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
if *header.ExcessBlobGas != expectedExcessBlobGas {
return fmt.Errorf("invalid excessBlobGas: have %d, want %d, parent excessBlobGas %d, parent blobDataUsed %d",
*header.ExcessBlobGas, expectedExcessBlobGas, parentExcessBlobGas, parentBlobGasUsed)
}
return nil
}

// CalcExcessBlobGas calculates the excess blob gas after applying the set of
// blobs on top of the excess blob gas.
func CalcExcessBlobGas(parentExcessBlobGas uint64, parentBlobGasUsed uint64) uint64 {
excessBlobGas := parentExcessBlobGas + parentBlobGasUsed
if excessBlobGas < params.BlobTxTargetBlobGasPerBlock {
if excessBlobGas < target {
return 0
}
return excessBlobGas - params.BlobTxTargetBlobGasPerBlock
return excessBlobGas - target
}

// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
func CalcBlobFee(excessBlobGas uint64) *big.Int {
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(excessBlobGas), blobGaspriceUpdateFraction)
func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
switch config.LatestFork(header.Time) {
case forks.Prague:
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), blobGaspriceUpdateFractionPrague)
case forks.Cancun:
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), blobGaspriceUpdateFractionCancun)
default:
panic("calculating blob fee on unsupported fork")
}
}

// fakeExponential approximates factor * e ** (numerator / denominator) using
Expand Down
36 changes: 26 additions & 10 deletions consensus/misc/eip4844/eip4844_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)

func TestCalcExcessBlobGas(t *testing.T) {
var (
config = params.MainnetChainConfig
targetBlobs = config.TargetBlobsPerBlock(*config.CancunTime)
targetBlobGas = targetBlobs * params.BlobTxBlobGasPerBlob
)
var tests = []struct {
excess uint64
blobs uint64
Expand All @@ -34,30 +40,38 @@ func TestCalcExcessBlobGas(t *testing.T) {
// slots are below - or equal - to the target.
{0, 0, 0},
{0, 1, 0},
{0, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, 0},
{0, targetBlobs, 0},

// If the target blob gas is exceeded, the excessBlobGas should increase
// by however much it was overshot
{0, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 1, params.BlobTxBlobGasPerBlob},
{1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 1, params.BlobTxBlobGasPerBlob + 1},
{1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 2, 2*params.BlobTxBlobGasPerBlob + 1},
{0, targetBlobs + 1, params.BlobTxBlobGasPerBlob},
{1, targetBlobs + 1, params.BlobTxBlobGasPerBlob + 1},
{1, targetBlobs + 2, 2*params.BlobTxBlobGasPerBlob + 1},

// The excess blob gas should decrease by however much the target was
// under-shot, capped at zero.
{params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock},
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxTargetBlobGasPerBlock - params.BlobTxBlobGasPerBlob},
{params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxTargetBlobGasPerBlock - (2 * params.BlobTxBlobGasPerBlob)},
{params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0},
{targetBlobGas, targetBlobs, targetBlobGas},
{targetBlobGas, targetBlobs - 1, targetBlobGas - params.BlobTxBlobGasPerBlob},
{targetBlobGas, targetBlobs - 2, targetBlobGas - (2 * params.BlobTxBlobGasPerBlob)},
{params.BlobTxBlobGasPerBlob - 1, targetBlobs - 1, 0},
}
for i, tt := range tests {
result := CalcExcessBlobGas(tt.excess, tt.blobs*params.BlobTxBlobGasPerBlob)
blobGasUsed := tt.blobs * params.BlobTxBlobGasPerBlob
parent := &types.Header{
Time: *config.CancunTime,
ExcessBlobGas: &tt.excess,
BlobGasUsed: &blobGasUsed,
}
result := CalcExcessBlobGas(config, parent)
if result != tt.want {
t.Errorf("test %d: excess blob gas mismatch: have %v, want %v", i, result, tt.want)
}
}
}

func TestCalcBlobFee(t *testing.T) {
zero := uint64(0)

tests := []struct {
excessBlobGas uint64
blobfee int64
Expand All @@ -68,7 +82,9 @@ func TestCalcBlobFee(t *testing.T) {
{10 * 1024 * 1024, 23},
}
for i, tt := range tests {
have := CalcBlobFee(tt.excessBlobGas)
config := &params.ChainConfig{LondonBlock: big.NewInt(0), CancunTime: &zero, BlobScheduleConfig: params.DefaultBlobSchedule}
header := &types.Header{ExcessBlobGas: &tt.excessBlobGas}
have := CalcBlobFee(config, header)
if have.Int64() != tt.blobfee {
t.Errorf("test %d: blobfee mismatch: have %v want %v", i, have, tt.blobfee)
}
Expand Down
5 changes: 2 additions & 3 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2158,9 +2158,8 @@ func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (co
// processing of a block. These logs are later announced as deleted or reborn.
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
var blobGasPrice *big.Int
excessBlobGas := b.ExcessBlobGas()
if excessBlobGas != nil {
blobGasPrice = eip4844.CalcBlobFee(*excessBlobGas)
if b.ExcessBlobGas() != nil {
blobGasPrice = eip4844.CalcBlobFee(bc.chainConfig, b.Header())
}
receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64())
if err := receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), blobGasPrice, b.Transactions()); err != nil {
Expand Down
24 changes: 8 additions & 16 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (b *BlockGen) Difficulty() *big.Int {
// block.
func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
b.header.ParentBeaconRoot = &root
blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
blockContext := NewEVMBlockContext(b.header, b.cm, b.cm.config, &b.header.Coinbase)
ProcessBeaconBlockRoot(root, vm.NewEVM(blockContext, b.statedb, b.cm.config, vm.Config{}))
}

Expand All @@ -114,7 +114,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
b.SetCoinbase(common.Address{})
}
var (
blockContext = NewEVMBlockContext(b.header, bc, &b.header.Coinbase)
blockContext = NewEVMBlockContext(b.header, bc, b.cm.config, &b.header.Coinbase)
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
)
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
Expand Down Expand Up @@ -318,7 +318,7 @@ func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) {
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
}
// create EVM for system calls
blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
blockContext := NewEVMBlockContext(b.header, b.cm, b.cm.config, &b.header.Coinbase)
evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{})
// EIP-7002
ProcessWithdrawalQueue(&requests, evm)
Expand Down Expand Up @@ -381,7 +381,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse

if config.IsPrague(b.header.Number, b.header.Time) {
// EIP-2935
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
blockContext := NewEVMBlockContext(b.header, cm, cm.config, &b.header.Coinbase)
blockContext.Random = &common.Hash{} // enable post-merge instruction set
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, evm)
Expand Down Expand Up @@ -440,7 +440,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
var blobGasPrice *big.Int
if block.ExcessBlobGas() != nil {
blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas())
blobGasPrice = eip4844.CalcBlobFee(cm.config, block.Header())
}
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
panic(err)
Expand Down Expand Up @@ -490,7 +490,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
// Pre-execution system calls.
if config.IsPrague(b.header.Number, b.header.Time) {
// EIP-2935
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
blockContext := NewEVMBlockContext(b.header, cm, cm.config, &b.header.Coinbase)
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, evm)
}
Expand Down Expand Up @@ -545,7 +545,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
}
var blobGasPrice *big.Int
if block.ExcessBlobGas() != nil {
blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas())
blobGasPrice = eip4844.CalcBlobFee(cm.config, block.Header())
}
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
panic(err)
Expand Down Expand Up @@ -595,15 +595,7 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi
}
}
if cm.config.IsCancun(header.Number, header.Time) {
var (
parentExcessBlobGas uint64
parentBlobGasUsed uint64
)
if parent.ExcessBlobGas() != nil {
parentExcessBlobGas = *parent.ExcessBlobGas()
parentBlobGasUsed = *parent.BlobGasUsed()
}
excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
excessBlobGas := eip4844.CalcExcessBlobGas(cm.config, parent.Header())
header.ExcessBlobGas = &excessBlobGas
header.BlobGasUsed = new(uint64)
header.ParentBeaconRoot = new(common.Hash)
Expand Down
6 changes: 1 addition & 5 deletions core/chain_makers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func TestGeneratePOSChain(t *testing.T) {
aa = common.Address{0xaa}
bb = common.Address{0xbb}
funds = big.NewInt(0).Mul(big.NewInt(1337), big.NewInt(params.Ether))
config = *params.AllEthashProtocolChanges
config = *params.MergedTestChainConfig
gspec = &Genesis{
Config: &config,
Alloc: types.GenesisAlloc{
Expand All @@ -57,10 +57,6 @@ func TestGeneratePOSChain(t *testing.T) {
db = rawdb.NewMemoryDatabase()
)

config.TerminalTotalDifficulty = common.Big0
config.ShanghaiTime = u64(0)
config.CancunTime = u64(0)

// init 0xaa with some storage elements
storage := make(map[common.Hash]common.Hash)
storage[common.Hash{0x00}] = common.Hash{0x00}
Expand Down
5 changes: 3 additions & 2 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)

Expand All @@ -39,7 +40,7 @@ type ChainContext interface {
}

// NewEVMBlockContext creates a new context for use in the EVM.
func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext {
func NewEVMBlockContext(header *types.Header, chain ChainContext, config *params.ChainConfig, author *common.Address) vm.BlockContext {
var (
beneficiary common.Address
baseFee *big.Int
Expand All @@ -57,7 +58,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
baseFee = new(big.Int).Set(header.BaseFee)
}
if header.ExcessBlobGas != nil {
blobBaseFee = eip4844.CalcBlobFee(*header.ExcessBlobGas)
blobBaseFee = eip4844.CalcBlobFee(config, header)
}
if header.Difficulty.Sign() == 0 {
random = &header.MixDigest
Expand Down
2 changes: 1 addition & 1 deletion core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, time uint64,
// Compute effective blob gas price.
var blobGasPrice *big.Int
if header != nil && header.ExcessBlobGas != nil {
blobGasPrice = eip4844.CalcBlobFee(*header.ExcessBlobGas)
blobGasPrice = eip4844.CalcBlobFee(config, header)
}
if err := receipts.DeriveFields(config, hash, number, time, baseFee, blobGasPrice, body.Transactions); err != nil {
log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
Expand Down
Loading