Skip to content

params: Config2 #32224

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

Draft
wants to merge 32 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8cc54f2
params: WIP config2
fjl Jul 15, 2025
cab21e0
params: update
fjl Jul 15, 2025
9268b84
consensus/misc/eip4844: port to config2
fjl Jul 15, 2025
d0a36a3
consensus/misc/eip1559: port to config2
fjl Jul 15, 2025
46adeca
consensus/misc: update DAO fork for config2
fjl Jul 15, 2025
3f128f6
consensus/ethash: port to config2
fjl Jul 15, 2025
f79354d
consensus/beacon: port to config2
fjl Jul 15, 2025
8725dec
params: add BigInt to TerminalTotalDifficulty
fjl Jul 15, 2025
31b6360
consensus: update for config2
fjl Jul 15, 2025
74f62ce
params/forks: add After
fjl Jul 16, 2025
e3725af
params/presets: add TestChainConfig
fjl Jul 16, 2025
fcf3b43
core/types: port to config2
fjl Jul 16, 2025
6b26791
core/rawdb: port to config2
fjl Jul 16, 2025
b25e44a
params: new param system
fjl Jul 18, 2025
73710ff
params: move some code around
fjl Jul 18, 2025
c284949
params/presets: update for new system
fjl Jul 18, 2025
ca4ba1f
params: add SetParam
fjl Jul 18, 2025
2a6cf8b
consensus/misc/eip4844: update
fjl Jul 18, 2025
d031689
consensus/misc/eip1559: update
fjl Jul 18, 2025
3e675b1
consensus/misc: update
fjl Jul 18, 2025
c1954d2
consensus/beacon: update
fjl Jul 18, 2025
8da6d37
params: new fork & parameter registry
fjl Jul 23, 2025
57c395f
core/types: fix parameter access
fjl Jul 23, 2025
13d14f5
params: add validation tests and remove LatestFork
fjl Jul 24, 2025
cf8af42
params: add DependencyOrder function
fjl Jul 24, 2025
336a2da
params: fix param value decoding
fjl Jul 24, 2025
7b5c169
params: add tests for blobschedule validation
fjl Jul 24, 2025
11ac2cc
consensus/misc/eip4844: make it work
fjl Jul 24, 2025
ee78ae4
params: add Defined
fjl Aug 6, 2025
0101ffe
core/vm: port to config2
fjl Aug 6, 2025
1a63295
params: add Rules2 (WIP)
fjl Aug 6, 2025
2157877
consensus/clique: partial port to config2
fjl Aug 6, 2025
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
18 changes: 10 additions & 8 deletions consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params/forks"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
)
Expand Down Expand Up @@ -74,11 +75,12 @@ func New(ethone consensus.Engine) *Beacon {
// isPostMerge reports whether the given block number is assumed to be post-merge.
// Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or
// PoA chain for unit testing purposes.
func isPostMerge(config *params.ChainConfig, blockNum uint64, timestamp uint64) bool {
mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0
func isPostMerge(config *params.Config2, blockNum uint64, timestamp uint64) bool {
ttd := params.TerminalTotalDifficulty.Get(config)
mergedAtGenesis := ttd != nil && ttd.Sign() == 0
return mergedAtGenesis ||
config.MergeNetsplitBlock != nil && blockNum >= config.MergeNetsplitBlock.Uint64() ||
config.ShanghaiTime != nil && timestamp >= *config.ShanghaiTime
config.Active(forks.Paris, blockNum, timestamp) ||
config.Active(forks.Shanghai, blockNum, timestamp)
}

// Author implements consensus.Engine, returning the verified author of the block.
Expand Down Expand Up @@ -256,15 +258,15 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
return err
}
// Verify existence / non-existence of withdrawalsHash.
shanghai := chain.Config().IsShanghai(header.Number, header.Time)
shanghai := chain.Config().Active(forks.Shanghai, header.Number.Uint64(), header.Time)
if shanghai && header.WithdrawalsHash == nil {
return errors.New("missing withdrawalsHash")
}
if !shanghai && header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
}
// Verify the existence / non-existence of cancun-specific header fields
cancun := chain.Config().IsCancun(header.Number, header.Time)
cancun := chain.Config().Active(forks.Cancun, header.Number.Uint64(), header.Time)
if !cancun {
switch {
case header.ExcessBlobGas != nil:
Expand Down Expand Up @@ -357,7 +359,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
if !beacon.IsPoSHeader(header) {
return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts)
}
shanghai := chain.Config().IsShanghai(header.Number, header.Time)
shanghai := chain.Config().Active(forks.Shanghai, header.Number.Uint64(), header.Time)
if shanghai {
// All blocks after Shanghai must include a withdrawals root.
if body.Withdrawals == nil {
Expand All @@ -379,7 +381,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea

// Create the block witness and attach to block.
// This step needs to happen as late as possible to catch all access events.
if chain.Config().IsVerkle(header.Number, header.Time) {
if chain.Config().Active(forks.Verkle, header.Number.Uint64(), header.Time) {
keys := state.AccessEvents().Keys()

// Open the pre-tree to prove the pre-state against
Expand Down
64 changes: 35 additions & 29 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params/forks"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"golang.org/x/crypto/sha3"
Expand All @@ -51,20 +52,25 @@ const (
inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
)

const (
ExtraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
ExtraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal

DiffInTurn = 2 // Block difficulty for in-turn signatures
DiffNoTurn = 1 // Block difficulty for out-of-turn signatures
)

// Clique proof-of-authority protocol constants.
var (
epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes

extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal

nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer
nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer.

uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.

diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures
diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures
diffInTurn = big.NewInt(DiffInTurn)
diffNoTurn = big.NewInt(DiffNoTurn)
)

// Various error messages to mark blocks invalid. These should be private to
Expand Down Expand Up @@ -145,10 +151,10 @@ func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) {
return address, nil
}
// Retrieve the signature from the header extra-data
if len(header.Extra) < extraSeal {
if len(header.Extra) < ExtraSeal {
return common.Address{}, errMissingSignature
}
signature := header.Extra[len(header.Extra)-extraSeal:]
signature := header.Extra[len(header.Extra)-ExtraSeal:]

// Recover the public key and the Ethereum address
pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature)
Expand All @@ -165,8 +171,8 @@ func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) {
// Clique is the proof-of-authority consensus engine proposed to support the
// Ethereum testnet following the Ropsten attacks.
type Clique struct {
config *params.CliqueConfig // Consensus engine configuration parameters
db ethdb.Database // Database to store and retrieve snapshot checkpoints
config *Config // Consensus engine configuration parameters
db ethdb.Database // Database to store and retrieve snapshot checkpoints

recents *lru.Cache[common.Hash, *Snapshot] // Snapshots for recent block to speed up reorgs
signatures *sigLRU // Signatures of recent blocks to speed up mining
Expand All @@ -182,18 +188,17 @@ type Clique struct {

// New creates a Clique proof-of-authority consensus engine with the initial
// signers set to the ones provided by the user.
func New(config *params.CliqueConfig, db ethdb.Database) *Clique {
func New(config Config, db ethdb.Database) *Clique {
// Set any missing consensus parameters to their defaults
conf := *config
if conf.Epoch == 0 {
conf.Epoch = epochLength
if config.Epoch == 0 {
config.Epoch = epochLength
}
// Allocate the snapshot caches and create the engine
recents := lru.NewCache[common.Hash, *Snapshot](inmemorySnapshots)
signatures := lru.NewCache[common.Hash, common.Address](inmemorySignatures)

return &Clique{
config: &conf,
config: &config,
db: db,
recents: recents,
signatures: signatures,
Expand Down Expand Up @@ -260,14 +265,14 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
return errInvalidCheckpointVote
}
// Check that the extra-data contains both the vanity and signature
if len(header.Extra) < extraVanity {
if len(header.Extra) < ExtraVanity {
return errMissingVanity
}
if len(header.Extra) < extraVanity+extraSeal {
if len(header.Extra) < ExtraVanity+ExtraSeal {
return errMissingSignature
}
// Ensure that the extra-data contains a signer list on checkpoint, but none otherwise
signersBytes := len(header.Extra) - extraVanity - extraSeal
signersBytes := len(header.Extra) - ExtraVanity - ExtraSeal
if !checkpoint && signersBytes != 0 {
return errExtraSigners
}
Expand All @@ -292,14 +297,14 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
if header.GasLimit > params.MaxGasLimit {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit)
}
if chain.Config().IsShanghai(header.Number, header.Time) {
if chain.Config().Active(forks.Shanghai, header.Number.Uint64(), header.Time) {
return errors.New("clique does not support shanghai fork")
}
// Verify the non-existence of withdrawalsHash.
if header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
}
if chain.Config().IsCancun(header.Number, header.Time) {
if chain.Config().Active(forks.Cancun, header.Number.Uint64(), header.Time) {
return errors.New("clique does not support cancun fork")
}
// Verify the non-existence of cancun-specific header fields
Expand Down Expand Up @@ -342,7 +347,7 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
if !chain.Config().IsLondon(header.Number) {
if !chain.Config().Active(forks.London, header.Number.Uint64(), header.Time) {
// Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee)
Expand All @@ -365,8 +370,8 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header
for i, signer := range snap.signers() {
copy(signers[i*common.AddressLength:], signer[:])
}
extraSuffix := len(header.Extra) - extraSeal
if !bytes.Equal(header.Extra[extraVanity:extraSuffix], signers) {
extraSuffix := len(header.Extra) - ExtraSeal
if !bytes.Equal(header.Extra[ExtraVanity:extraSuffix], signers) {
return errMismatchingCheckpointSigners
}
}
Expand Down Expand Up @@ -404,9 +409,9 @@ func (c *Clique) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
if checkpoint != nil {
hash := checkpoint.Hash()

signers := make([]common.Address, (len(checkpoint.Extra)-extraVanity-extraSeal)/common.AddressLength)
signers := make([]common.Address, (len(checkpoint.Extra)-ExtraVanity-ExtraSeal)/common.AddressLength)
for i := 0; i < len(signers); i++ {
copy(signers[i][:], checkpoint.Extra[extraVanity+i*common.AddressLength:])
copy(signers[i][:], checkpoint.Extra[ExtraVanity+i*common.AddressLength:])
}
snap = newSnapshot(c.config, c.signatures, number, hash, signers)
if err := snap.store(c.db); err != nil {
Expand Down Expand Up @@ -544,17 +549,17 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
header.Difficulty = calcDifficulty(snap, signer)

// Ensure the extra data has all its components
if len(header.Extra) < extraVanity {
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
if len(header.Extra) < ExtraVanity {
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, ExtraVanity-len(header.Extra))...)
}
header.Extra = header.Extra[:extraVanity]
header.Extra = header.Extra[:ExtraVanity]

if number%c.config.Epoch == 0 {
for _, signer := range snap.signers() {
header.Extra = append(header.Extra, signer[:]...)
}
}
header.Extra = append(header.Extra, make([]byte, extraSeal)...)
header.Extra = append(header.Extra, make([]byte, ExtraSeal)...)

// Mix digest is reserved for now, set to empty
header.MixDigest = common.Hash{}
Expand Down Expand Up @@ -587,7 +592,8 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
c.Finalize(chain, header, state, body)

// Assign the final state root to header.
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
deleteEmptyObjects := chain.Config().Active(forks.SpuriousDragon, header.Number.Uint64(), header.Time)
header.Root = state.IntermediateRoot(deleteEmptyObjects)

// Assemble and return the final block for sealing.
return types.NewBlock(header, &types.Body{Transactions: body.Transactions}, receipts, trie.NewStackTrie(nil)), nil
Expand Down
14 changes: 8 additions & 6 deletions consensus/clique/clique_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
// 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/>.

package clique
package clique_test

import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
Expand All @@ -40,18 +41,19 @@ func TestReimportMirroredState(t *testing.T) {
db = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr = crypto.PubkeyToAddress(key.PublicKey)
engine = New(params.AllCliqueProtocolChanges.Clique, db)
config = clique.ConfigParam.Get(presets.AllCliqueProtocolChanges)
engine = clique.New(config, db)
signer = new(types.HomesteadSigner)
)
genspec := &core.Genesis{
Config: params.AllCliqueProtocolChanges,
ExtraData: make([]byte, extraVanity+common.AddressLength+extraSeal),
ExtraData: make([]byte, clique.ExtraVanity+common.AddressLength+clique.ExtraSeal),
Alloc: map[common.Address]types.Account{
addr: {Balance: big.NewInt(10000000000000000)},
},
BaseFee: big.NewInt(params.InitialBaseFee),
}
copy(genspec.ExtraData[extraVanity:], addr[:])
copy(genspec.ExtraData[clique.ExtraVanity:], addr[:])

// Generate a batch of blocks, each properly signed
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), genspec, engine, nil)
Expand All @@ -60,7 +62,7 @@ func TestReimportMirroredState(t *testing.T) {
_, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) {
// The chain maker doesn't have access to a chain, so the difficulty will be
// lets unset (nil). Set it here to the correct value.
block.SetDifficulty(diffInTurn)
block.SetDifficulty(big.NewInt(clique.DiffInTurn))

// We want to simulate an empty middle block, having the same state as the
// first one. The last is needs a state change again to force a reorg.
Expand All @@ -80,7 +82,7 @@ func TestReimportMirroredState(t *testing.T) {
header.Extra = make([]byte, extraVanity+extraSeal)
header.Difficulty = diffInTurn

sig, _ := crypto.Sign(SealHash(header).Bytes(), key)
sig, _ := crypto.Sign(clique.SealHash(header).Bytes(), key)
copy(header.Extra[len(header.Extra)-extraSeal:], sig)
blocks[i] = block.WithSeal(header)
}
Expand Down
31 changes: 31 additions & 0 deletions consensus/clique/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2025 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library 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,
// 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/>.

package clique

import "github.com/ethereum/go-ethereum/params"

var ConfigParam = params.Define(params.T[Config]{
Name: "clique",
Optional: true, // optional says
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing part of the comment here?

Default: Config{},
})

// Config is the consensus engine configs for proof-of-authority based sealing.
type Config struct {
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint
}
9 changes: 4 additions & 5 deletions consensus/clique/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)

// Vote represents a single vote that an authorized signer made to modify the
Expand All @@ -52,8 +51,8 @@ type sigLRU = lru.Cache[common.Hash, common.Address]

// Snapshot is the state of the authorization voting at a given point in time.
type Snapshot struct {
config *params.CliqueConfig // Consensus engine parameters to fine tune behavior
sigcache *sigLRU // Cache of recent block signatures to speed up ecrecover
config *Config // Consensus engine parameters to fine tune behavior
sigcache *sigLRU // Cache of recent block signatures to speed up ecrecover

Number uint64 `json:"number"` // Block number where the snapshot was created
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
Expand All @@ -66,7 +65,7 @@ type Snapshot struct {
// newSnapshot creates a new snapshot with the specified startup parameters. This
// method does not initialize the set of recent signers, so only ever use if for
// the genesis block.
func newSnapshot(config *params.CliqueConfig, sigcache *sigLRU, number uint64, hash common.Hash, signers []common.Address) *Snapshot {
func newSnapshot(config *Config, sigcache *sigLRU, number uint64, hash common.Hash, signers []common.Address) *Snapshot {
snap := &Snapshot{
config: config,
sigcache: sigcache,
Expand All @@ -83,7 +82,7 @@ func newSnapshot(config *params.CliqueConfig, sigcache *sigLRU, number uint64, h
}

// loadSnapshot loads an existing snapshot from the database.
func loadSnapshot(config *params.CliqueConfig, sigcache *sigLRU, db ethdb.Database, hash common.Hash) (*Snapshot, error) {
func loadSnapshot(config *Config, sigcache *sigLRU, db ethdb.Database, hash common.Hash) (*Snapshot, error) {
blob, err := db.Get(append(rawdb.CliqueSnapshotPrefix, hash[:]...))
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion consensus/clique/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// 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/>.

package clique
package clique_test

import (
"bytes"
Expand Down
2 changes: 1 addition & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
// blockchain during header verification.
type ChainHeaderReader interface {
// Config retrieves the blockchain's chain configuration.
Config() *params.ChainConfig
Config() *params.Config2

// CurrentHeader retrieves the current header from the local chain.
CurrentHeader() *types.Header
Expand Down
Loading
Loading