rework activation

This commit is contained in:
Guillaume Ballet 2026-01-28 13:28:34 -05:00
parent 09b9c27c83
commit 9cef9dc75e
4 changed files with 69 additions and 16 deletions

View file

@ -179,14 +179,43 @@ func NewDatabaseForTesting() *CachingDB {
} }
var ( var (
conversionProgressAddressKey = common.Hash{1} transitionStartedKey = common.Hash{} // slot 0: non-zero if transition started
conversionProgressSlotKey = common.Hash{2} conversionProgressAddressKey = common.Hash{1} // slot 1: current account pointer
conversionProgressStorageProcessed = common.Hash{3} conversionProgressSlotKey = common.Hash{2} // slot 2: current slot pointer
conversionProgressStorageProcessed = common.Hash{3} // slot 3: storage processed flag
transitionEndedKey = common.Hash{4} // slot 4: non-zero if transition ended
) )
// isTransitionActive checks if the binary tree transition has been activated
func isTransitionActive(reader StateReader) bool {
val, err := reader.Storage(params.BinaryTransitionRegistryAddress, transitionStartedKey)
if err != nil {
return false
}
return val != (common.Hash{})
}
// LoadTransitionState retrieves the Verkle transition state associated with // LoadTransitionState retrieves the Verkle transition state associated with
// the given state root hash from the database. // the given state root hash from the database.
func LoadTransitionState(reader StateReader, root common.Hash) *overlay.TransitionState { func LoadTransitionState(reader StateReader, root common.Hash) *overlay.TransitionState {
startedBytes, err := reader.Storage(params.BinaryTransitionRegistryAddress, transitionStartedKey)
if err != nil {
return nil
}
started := startedBytes != (common.Hash{})
// If not started, return nil to indicate no active transition
if !started {
return nil
}
endedBytes, err := reader.Storage(params.BinaryTransitionRegistryAddress, transitionEndedKey)
if err != nil {
// Registry exists but can't read ended flag - treat as still in transition
endedBytes = common.Hash{}
}
ended := endedBytes != (common.Hash{})
currentAccountBytes, err := reader.Storage(params.BinaryTransitionRegistryAddress, conversionProgressAddressKey) currentAccountBytes, err := reader.Storage(params.BinaryTransitionRegistryAddress, conversionProgressAddressKey)
if err != nil { if err != nil {
panic(fmt.Errorf("error reading conversion account pointer: %w", err)) panic(fmt.Errorf("error reading conversion account pointer: %w", err))
@ -205,6 +234,8 @@ func LoadTransitionState(reader StateReader, root common.Hash) *overlay.Transiti
storageProcessed := storageProcessedBytes[0] == 1 storageProcessed := storageProcessedBytes[0] == 1
return &overlay.TransitionState{ return &overlay.TransitionState{
Started: started,
Ended: ended,
CurrentAccountAddress: &currentAccount, CurrentAccountAddress: &currentAccount,
CurrentSlotHash: currentSlotHash, CurrentSlotHash: currentSlotHash,
StorageProcessed: storageProcessed, StorageProcessed: storageProcessed,
@ -232,8 +263,11 @@ func (db *CachingDB) StateReader(stateRoot common.Hash) (StateReader, error) {
if db.TrieDB().Scheme() == rawdb.PathScheme { if db.TrieDB().Scheme() == rawdb.PathScheme {
reader, err := db.triedb.StateReader(stateRoot) reader, err := db.triedb.StateReader(stateRoot)
if err == nil { if err == nil {
readers = append(readers, newFlatReader(reader)) flatReader := newFlatReader(reader)
ts = LoadTransitionState(readers[len(readers)-1], stateRoot) readers = append(readers, flatReader)
if isTransitionActive(flatReader) || db.triedb.IsVerkle() {
ts = LoadTransitionState(flatReader, stateRoot)
}
} }
} }
// Configure the trie reader, which is expected to be available as the // Configure the trie reader, which is expected to be available as the
@ -274,22 +308,23 @@ func (db *CachingDB) ReadersWithCacheStats(stateRoot common.Hash) (ReaderWithSta
// OpenTrie opens the main account trie at a specific root hash. // OpenTrie opens the main account trie at a specific root hash.
func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) { func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
if db.triedb.IsVerkle() { reader, err := db.StateReader(root)
// if the transition has started, the pointers will be present in the if err != nil {
// overlay tree, and the tree itself will be present, so the tree is tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
// opened and the pointers read, regardless of what comes afterwards. if err != nil {
return nil, err
}
return tr, nil
}
if isTransitionActive(reader) || db.triedb.IsVerkle() {
bt, err := bintrie.NewBinaryTrie(root, db.triedb) bt, err := bintrie.NewBinaryTrie(root, db.triedb)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not open the overlay tree: %w", err) return nil, fmt.Errorf("could not open the overlay tree: %w", err)
} }
reader, err := db.StateReader(root)
if err != nil {
return nil, fmt.Errorf("could not get reader for checking overlay status: %w", err)
}
ts := LoadTransitionState(reader, root) ts := LoadTransitionState(reader, root)
if !ts.InTransition() { if !ts.InTransition() {
// Use BinaryTrie instead of VerkleTrie when IsVerkle is set // Transition complete, use BinaryTrie only
// (IsVerkle actually means Binary Trie mode in this codebase)
return bt, nil return bt, nil
} }
@ -308,7 +343,7 @@ func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
// OpenStorageTrie opens the storage trie of an account. // OpenStorageTrie opens the storage trie of an account.
func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) { func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
if db.triedb.IsVerkle() { if self != nil && self.IsVerkle() {
return self, nil return self, nil
} }
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb) tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb)

View file

@ -93,6 +93,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if config.IsPrague(block.Number(), block.Time()) || config.IsVerkle(block.Number(), block.Time()) { if config.IsPrague(block.Number(), block.Time()) || config.IsVerkle(block.Number(), block.Time()) {
ProcessParentBlockHash(block.ParentHash(), evm) ProcessParentBlockHash(block.ParentHash(), evm)
} }
if config.IsVerkle(header.Number, header.Time) {
statedb.SetCode(params.BinaryTransitionRegistryAddress, []byte{1, 2, 3}, tracing.CodeChangeUnspecified)
statedb.SetNonce(params.BinaryTransitionRegistryAddress, 1, tracing.NonceChangeUnspecified)
statedb.SetState(params.BinaryTransitionRegistryAddress, common.Hash{}, common.Hash{1})
}
// Iterate over and process the individual transactions // Iterate over and process the individual transactions
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {

View file

@ -26,10 +26,12 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
) )
@ -251,6 +253,11 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) { if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) {
core.ProcessParentBlockHash(block.ParentHash(), evm) core.ProcessParentBlockHash(block.ParentHash(), evm)
} }
if eth.blockchain.Config().IsVerkle(block.Number(), block.Time()) {
statedb.SetCode(params.BinaryTransitionRegistryAddress, []byte{1, 2, 3}, tracing.CodeChangeUnspecified)
statedb.SetNonce(params.BinaryTransitionRegistryAddress, 1, tracing.NonceChangeUnspecified)
statedb.SetState(params.BinaryTransitionRegistryAddress, common.Hash{}, common.Hash{1})
}
if txIndex == 0 && len(block.Transactions()) == 0 { if txIndex == 0 && len(block.Transactions()) == 0 {
return nil, context, statedb, release, nil return nil, context, statedb, release, nil
} }

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/stateless" "github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
@ -266,6 +267,11 @@ func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*envir
if miner.chainConfig.IsPrague(header.Number, header.Time) { if miner.chainConfig.IsPrague(header.Number, header.Time) {
core.ProcessParentBlockHash(header.ParentHash, env.evm) core.ProcessParentBlockHash(header.ParentHash, env.evm)
} }
if miner.chainConfig.IsVerkle(header.Number, header.Time) {
env.state.SetCode(params.BinaryTransitionRegistryAddress, []byte{1, 2, 3}, tracing.CodeChangeUnspecified)
env.state.SetNonce(params.BinaryTransitionRegistryAddress, 1, tracing.NonceChangeUnspecified)
env.state.SetState(params.BinaryTransitionRegistryAddress, common.Hash{}, common.Hash{1})
}
return env, nil return env, nil
} }