self-review

This commit is contained in:
Guillaume Ballet 2026-04-30 14:31:38 +02:00
parent d8ed290a40
commit 9a5140a590
No known key found for this signature in database
8 changed files with 54 additions and 52 deletions

View file

@ -2149,18 +2149,18 @@ type ExecuteConfig struct {
// transition, a transition UBTDatabase is built; otherwise (transition
// ended, or chainConfig.UBTTransitionEndTime crossed) a plain UBTDatabase
// is returned with the transition wrap disabled.
func (bc *BlockChain) stateDatabase(parentRoot common.Hash, header *types.Header) state.Database {
func (bc *BlockChain) stateDatabase(parentRoot common.Hash, header *types.Header) (state.Database, error) {
if !bc.chainConfig.IsUBT(header.Number, header.Time) {
return state.NewMPTDatabase(bc.triedb, bc.codedb).WithSnapshot(bc.snaps)
return state.NewMPTDatabase(bc.triedb, bc.codedb).WithSnapshot(bc.snaps), nil
}
// Past the configured transition end: pure binary, no wrap, no MPT base.
if !bc.chainConfig.UBTTransitionActive(header.Number, header.Time) {
return state.NewUBTDatabase(bc.bintriedbOrMain(), bc.codedb).WithTransitionTreeWrap(false)
return state.NewUBTDatabase(bc.bintriedbOrMain(), bc.codedb).WithTransitionTreeWrap(false), nil
}
// First UBT block: parent is pre-UBT; seed the transition with parent root.
parent := bc.GetHeaderByHash(header.ParentHash)
if parent != nil && !bc.chainConfig.IsUBT(parent.Number, parent.Time) {
return state.NewTransitionUBTDatabase(bc.bintriedbOrMain(), bc.triedb, bc.codedb, parentRoot)
return state.NewTransitionUBTDatabase(bc.bintriedbOrMain(), bc.triedb, bc.codedb, parentRoot), nil
}
// Subsequent UBT block while the transition is active: probe the registry
// to see whether a base root is still recorded.
@ -2180,18 +2180,21 @@ func (bc *BlockChain) bintriedbOrMain() *triedb.Database {
// probeTransitionDatabase reads the transition registry from the binary trie
// at the given root and chooses between a transition-mode UBTDatabase (if
// the registry still records a base root) and a plain UBTDatabase otherwise.
func (bc *BlockChain) probeTransitionDatabase(root common.Hash) state.Database {
func (bc *BlockChain) probeTransitionDatabase(root common.Hash) (state.Database, error) {
bindb := bc.bintriedbOrMain()
plain := state.NewUBTDatabase(bindb, bc.codedb)
reader, err := plain.StateReader(root)
if err != nil {
return plain
return nil, err
}
ts, err := overlay.LoadTransitionState(storageReaderFunc(reader.Storage))
if err != nil {
return nil, err
}
ts := overlay.LoadTransitionState(storageReaderFunc(reader.Storage), root)
if ts == nil || ts.Transitioned() || ts.BaseRoot == (common.Hash{}) {
return plain
return plain, nil
}
return state.NewTransitionUBTDatabase(bindb, bc.triedb, bc.codedb, ts.BaseRoot)
return state.NewTransitionUBTDatabase(bindb, bc.triedb, bc.codedb, ts.BaseRoot), nil
}
// storageReaderFunc adapts a state-reader Storage method to overlay.StorageReader.
@ -2212,7 +2215,10 @@ func (bc *BlockChain) ProcessBlock(ctx context.Context, parentRoot common.Hash,
)
defer interrupt.Store(true) // terminate the prefetch at the end
sdb := bc.stateDatabase(parentRoot, block.Header())
sdb, err := bc.stateDatabase(parentRoot, block.Header())
if err != nil {
return nil, err
}
// If prefetching is enabled, run that against the current state to pre-cache
// transactions and probabilistically some of the account/storage trie nodes.
//

View file

@ -421,13 +421,21 @@ func (bc *BlockChain) State() (*state.StateDB, error) {
// StateAt returns a new mutable state based on a particular point in time.
func (bc *BlockChain) StateAt(header *types.Header) (*state.StateDB, error) {
return state.New(header.Root, bc.stateDatabase(header.Root, header))
db, err := bc.stateDatabase(header.Root, header)
if err != nil {
return nil, err
}
return state.New(header.Root, db)
}
// StateAtForkBoundary returns a new mutable state based on the parent state
// and the given header, handling the transition across the UBT fork.
func (bc *BlockChain) StateAtForkBoundary(parent *types.Header, header *types.Header) (*state.StateDB, error) {
return state.New(parent.Root, bc.stateDatabase(parent.Root, header))
db, err := bc.stateDatabase(parent.Root, header)
if err != nil {
return nil, err
}
return state.New(parent.Root, db)
}
// HistoricState returns a historic state specified by the given header.

View file

@ -39,9 +39,8 @@ type StorageReader interface {
Storage(addr common.Address, slot common.Hash) (common.Hash, error)
}
// TransitionState holds the progress markers of the MPT-to-binary
// translation process. It is reconstructed on demand from the storage of the
// binary transition registry system contract.
// TransitionState is a structure that holds the progress markers of the
// translation process.
type TransitionState struct {
CurrentAccountAddress *common.Address // address of the last translated account
CurrentSlotHash common.Hash // hash of the last translated storage slot
@ -98,10 +97,13 @@ func IsTransitionActive(reader StorageReader) bool {
//
// The root parameter is unused; it is retained on the signature so callers
// can express the state version they intend to read.
func LoadTransitionState(reader StorageReader, root common.Hash) *TransitionState {
func LoadTransitionState(reader StorageReader) (*TransitionState, error) {
started, err := reader.Storage(params.BinaryTransitionRegistryAddress, transitionStartedKey)
if err != nil || started == (common.Hash{}) {
return nil
if err != nil {
return nil, err
}
if started == (common.Hash{}) {
return nil, nil
}
ended, _ := reader.Storage(params.BinaryTransitionRegistryAddress, transitionEndedKey)
@ -114,8 +116,14 @@ func LoadTransitionState(reader StorageReader, root common.Hash) *TransitionStat
currentAddr = &addr
}
slotHash, _ := reader.Storage(params.BinaryTransitionRegistryAddress, conversionProgressSlotKey)
storageProcessed, _ := reader.Storage(params.BinaryTransitionRegistryAddress, conversionProgressStorageProcessed)
slotHash, err := reader.Storage(params.BinaryTransitionRegistryAddress, conversionProgressSlotKey)
if err != nil {
return nil, err
}
storageProcessed, err := reader.Storage(params.BinaryTransitionRegistryAddress, conversionProgressStorageProcessed)
if err != nil {
return nil, err
}
return &TransitionState{
Started: true,
@ -124,5 +132,5 @@ func LoadTransitionState(reader StorageReader, root common.Hash) *TransitionStat
CurrentAccountAddress: currentAddr,
CurrentSlotHash: slotHash,
StorageProcessed: storageProcessed != (common.Hash{}),
}
}, nil
}

View file

@ -457,4 +457,3 @@ func trienodeHistoryIndexBlockKey(addressHash common.Hash, path []byte, blockID
return out
}

View file

@ -138,9 +138,7 @@ func (db *UBTDatabase) ReadersWithCacheStats(stateRoot common.Hash) (Reader, Rea
return ra, rb, nil
}
// OpenTrie opens the main account trie at a specific root hash. During an
// active transition, the binary trie is wrapped in a TransitionTrie so writes
// land on the binary trie while reads fall through to the frozen MPT base.
// OpenTrie opens the main account trie at a specific root hash.
func (db *UBTDatabase) OpenTrie(root common.Hash) (Trie, error) {
bt, err := bintrie.NewBinaryTrie(root, db.triedb)
if err != nil {
@ -157,9 +155,7 @@ func (db *UBTDatabase) OpenTrie(root common.Hash) (Trie, error) {
}
// OpenStorageTrie opens the storage trie of an account. In binary trie mode
// the unified trie carries all state, so the main trie is reused. During the
// transition, an MPT storage trie is opened for accounts that have not yet
// been migrated.
// the unified trie carries all state, so the main trie is reused.
func (db *UBTDatabase) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
if self != nil && self.IsUBT() {
return self, nil

View file

@ -288,7 +288,11 @@ func newUBTTrieReader(root common.Hash, bindb *triedb.Database, mptdb *triedb.Da
}
var base *trie.StateTrie
if wrapInTransitionTrie && mptdb != nil {
if ts := overlay.LoadTransitionState(&binTrieStorageReader{tr: binTrie}, root); ts != nil && ts.BaseRoot != (common.Hash{}) {
ts, err := overlay.LoadTransitionState(&binTrieStorageReader{tr: binTrie})
if err != nil {
return nil, err
}
if ts != nil && ts.BaseRoot != (common.Hash{}) {
base, err = trie.NewStateTrie(trie.StateTrieID(ts.BaseRoot), mptdb)
if err != nil {
return nil, err

View file

@ -469,12 +469,8 @@ type ChainConfig struct {
UBTTime *uint64 `json:"ubtTime,omitempty"` // UBT switch time (nil = no fork, 0 = already on UBT)
// UBTTransitionEndTime is the timestamp at which the MPT-to-binary
// transition tree is no longer applied. While UBT is active and the
// timestamp is below this value (or nil), state access is wrapped in a
// TransitionTrie that overlays the binary trie on the frozen MPT base.
// Once headers reach this time, the transition wrapper is dropped and
// state is read directly from the binary trie. nil = wrapper stays on
// indefinitely. Mirrors the threshold semantics of TerminalTotalDifficulty.
// transition tree is no longer applied. Mirrors the threshold semantics
// of TerminalTotalDifficulty.
UBTTransitionEndTime *uint64 `json:"ubtTransitionEndTime,omitempty"`
// TerminalTotalDifficulty is the amount of total difficulty reached by
@ -897,16 +893,7 @@ func (c *ChainConfig) UBTTransitionActive(num *big.Int, time uint64) bool {
return c.UBTTransitionEndTime == nil || time < *c.UBTTransitionEndTime
}
// IsUBTGenesis checks whether the verkle fork is activated at the genesis block.
//
// Verkle mode is considered enabled if the verkle fork time is configured,
// regardless of whether the local time has surpassed the fork activation time.
// This is a temporary workaround for verkle devnet testing, where verkle is
// activated at genesis, and the configured activation date has already passed.
//
// In production networks (mainnet and public testnets), verkle activation
// always occurs after the genesis block, making this function irrelevant in
// those cases.
// IsUBTGenesis checks whether the UBT fork is activated at the genesis block.
func (c *ChainConfig) IsUBTGenesis() bool {
return c.EnableUBTAtGenesis
}

View file

@ -224,13 +224,7 @@ var (
ConsolidationQueueCode = common.FromHex("3373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd")
// BinaryTransitionRegistryAddress is the system contract that exposes the
// MPT-to-binary transition state via storage slots:
// slot 0 = transition started flag
// slot 1 = address of the last translated account
// slot 2 = hash of the last translated storage slot
// slot 3 = "storage processed" flag
// slot 4 = transition ended flag
// slot 5 = frozen MPT base root
// MPT-to-binary transition state via storage slots.
BinaryTransitionRegistryAddress = common.HexToAddress("0x1622162216221622162216221622162216221622")
)