triedb/pathdb: rename history to state history (#32498)

This is a internal refactoring PR, renaming the history to stateHistory.

It's a pre-requisite PR for merging trienode history, avoid the name
conflict.
This commit is contained in:
rjl493456442 2025-08-26 14:52:39 +08:00 committed by GitHub
parent 16bd164f3b
commit 8c58f4920d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 105 additions and 103 deletions

View file

@ -219,12 +219,14 @@ type Database struct {
isVerkle bool // Flag if database is used for verkle tree isVerkle bool // Flag if database is used for verkle tree
hasher nodeHasher // Trie node hasher hasher nodeHasher // Trie node hasher
config *Config // Configuration for database config *Config // Configuration for database
diskdb ethdb.Database // Persistent storage for matured trie nodes diskdb ethdb.Database // Persistent storage for matured trie nodes
tree *layerTree // The group for all known layers tree *layerTree // The group for all known layers
freezer ethdb.ResettableAncientStore // Freezer for storing trie histories, nil possible in tests
lock sync.RWMutex // Lock to prevent mutations from happening at the same time stateFreezer ethdb.ResettableAncientStore // Freezer for storing state histories, nil possible in tests
indexer *historyIndexer // History indexer stateIndexer *historyIndexer // History indexer historical state data, nil possible
lock sync.RWMutex // Lock to prevent mutations from happening at the same time
} }
// New attempts to load an already existing layer from a persistent key-value // New attempts to load an already existing layer from a persistent key-value
@ -275,8 +277,8 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
log.Crit("Failed to setup the generator", "err", err) log.Crit("Failed to setup the generator", "err", err)
} }
// TODO (rjl493456442) disable the background indexing in read-only mode // TODO (rjl493456442) disable the background indexing in read-only mode
if db.freezer != nil && db.config.EnableStateIndexing { if db.stateFreezer != nil && db.config.EnableStateIndexing {
db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID()) db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID())
log.Info("Enabled state history indexing") log.Info("Enabled state history indexing")
} }
fields := config.fields() fields := config.fields()
@ -304,14 +306,14 @@ func (db *Database) repairHistory() error {
if err != nil { if err != nil {
log.Crit("Failed to open state history freezer", "err", err) log.Crit("Failed to open state history freezer", "err", err)
} }
db.freezer = freezer db.stateFreezer = freezer
// Reset the entire state histories if the trie database is not initialized // Reset the entire state histories if the trie database is not initialized
// yet. This action is necessary because these state histories are not // yet. This action is necessary because these state histories are not
// expected to exist without an initialized trie database. // expected to exist without an initialized trie database.
id := db.tree.bottom().stateID() id := db.tree.bottom().stateID()
if id == 0 { if id == 0 {
frozen, err := db.freezer.Ancients() frozen, err := db.stateFreezer.Ancients()
if err != nil { if err != nil {
log.Crit("Failed to retrieve head of state history", "err", err) log.Crit("Failed to retrieve head of state history", "err", err)
} }
@ -321,7 +323,7 @@ func (db *Database) repairHistory() error {
// Purge all state history indexing data first // Purge all state history indexing data first
rawdb.DeleteStateHistoryIndexMetadata(db.diskdb) rawdb.DeleteStateHistoryIndexMetadata(db.diskdb)
rawdb.DeleteStateHistoryIndex(db.diskdb) rawdb.DeleteStateHistoryIndex(db.diskdb)
err := db.freezer.Reset() err := db.stateFreezer.Reset()
if err != nil { if err != nil {
log.Crit("Failed to reset state histories", "err", err) log.Crit("Failed to reset state histories", "err", err)
} }
@ -331,7 +333,7 @@ func (db *Database) repairHistory() error {
} }
// Truncate the extra state histories above in freezer in case it's not // Truncate the extra state histories above in freezer in case it's not
// aligned with the disk layer. It might happen after a unclean shutdown. // aligned with the disk layer. It might happen after a unclean shutdown.
pruned, err := truncateFromHead(db.diskdb, db.freezer, id) pruned, err := truncateFromHead(db.diskdb, db.stateFreezer, id)
if err != nil { if err != nil {
log.Crit("Failed to truncate extra state histories", "err", err) log.Crit("Failed to truncate extra state histories", "err", err)
} }
@ -507,13 +509,13 @@ func (db *Database) Enable(root common.Hash) error {
// all root->id mappings should be removed as well. Since // all root->id mappings should be removed as well. Since
// mappings can be huge and might take a while to clear // mappings can be huge and might take a while to clear
// them, just leave them in disk and wait for overwriting. // them, just leave them in disk and wait for overwriting.
if db.freezer != nil { if db.stateFreezer != nil {
// TODO(rjl493456442) would be better to group them into a batch. // TODO(rjl493456442) would be better to group them into a batch.
// //
// Purge all state history indexing data first // Purge all state history indexing data first
rawdb.DeleteStateHistoryIndexMetadata(db.diskdb) rawdb.DeleteStateHistoryIndexMetadata(db.diskdb)
rawdb.DeleteStateHistoryIndex(db.diskdb) rawdb.DeleteStateHistoryIndex(db.diskdb)
if err := db.freezer.Reset(); err != nil { if err := db.stateFreezer.Reset(); err != nil {
return err return err
} }
} }
@ -529,9 +531,9 @@ func (db *Database) Enable(root common.Hash) error {
// To ensure the history indexer always matches the current state, we must: // To ensure the history indexer always matches the current state, we must:
// 1. Close any existing indexer // 1. Close any existing indexer
// 2. Re-initialize the indexer so it starts indexing from the new state root. // 2. Re-initialize the indexer so it starts indexing from the new state root.
if db.indexer != nil && db.freezer != nil && db.config.EnableStateIndexing { if db.stateIndexer != nil && db.stateFreezer != nil && db.config.EnableStateIndexing {
db.indexer.close() db.stateIndexer.close()
db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID()) db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID())
log.Info("Re-enabled state history indexing") log.Info("Re-enabled state history indexing")
} }
log.Info("Rebuilt trie database", "root", root) log.Info("Rebuilt trie database", "root", root)
@ -551,7 +553,7 @@ func (db *Database) Recover(root common.Hash) error {
if err := db.modifyAllowed(); err != nil { if err := db.modifyAllowed(); err != nil {
return err return err
} }
if db.freezer == nil { if db.stateFreezer == nil {
return errors.New("state rollback is non-supported") return errors.New("state rollback is non-supported")
} }
// Short circuit if the target state is not recoverable // Short circuit if the target state is not recoverable
@ -564,7 +566,7 @@ func (db *Database) Recover(root common.Hash) error {
dl = db.tree.bottom() dl = db.tree.bottom()
) )
for dl.rootHash() != root { for dl.rootHash() != root {
h, err := readHistory(db.freezer, dl.stateID()) h, err := readStateHistory(db.stateFreezer, dl.stateID())
if err != nil { if err != nil {
return err return err
} }
@ -585,7 +587,7 @@ func (db *Database) Recover(root common.Hash) error {
if err := db.diskdb.SyncKeyValue(); err != nil { if err := db.diskdb.SyncKeyValue(); err != nil {
return err return err
} }
_, err := truncateFromHead(db.diskdb, db.freezer, dl.stateID()) _, err := truncateFromHead(db.diskdb, db.stateFreezer, dl.stateID())
if err != nil { if err != nil {
return err return err
} }
@ -613,12 +615,12 @@ func (db *Database) Recoverable(root common.Hash) bool {
// dev mode. As a consequence, the Pathdb loses the ability for deep reorg // dev mode. As a consequence, the Pathdb loses the ability for deep reorg
// in certain cases. // in certain cases.
// TODO(rjl493456442): Implement the in-memory ancient store. // TODO(rjl493456442): Implement the in-memory ancient store.
if db.freezer == nil { if db.stateFreezer == nil {
return false return false
} }
// Ensure the requested state is a canonical state and all state // Ensure the requested state is a canonical state and all state
// histories in range [id+1, disklayer.ID] are present and complete. // histories in range [id+1, disklayer.ID] are present and complete.
return checkHistories(db.freezer, *id+1, dl.stateID()-*id, func(m *meta) error { return checkStateHistories(db.stateFreezer, *id+1, dl.stateID()-*id, func(m *meta) error {
if m.parent != root { if m.parent != root {
return errors.New("unexpected state history") return errors.New("unexpected state history")
} }
@ -646,14 +648,14 @@ func (db *Database) Close() error {
dl.resetCache() // release the memory held by clean cache dl.resetCache() // release the memory held by clean cache
// Terminate the background state history indexer // Terminate the background state history indexer
if db.indexer != nil { if db.stateIndexer != nil {
db.indexer.close() db.stateIndexer.close()
} }
// Close the attached state history freezer. // Close the attached state history freezer.
if db.freezer == nil { if db.stateFreezer == nil {
return nil return nil
} }
return db.freezer.Close() return db.stateFreezer.Close()
} }
// Size returns the current storage size of the memory cache in front of the // Size returns the current storage size of the memory cache in front of the
@ -704,7 +706,7 @@ func (db *Database) journalPath() string {
// End: State ID of the last history for the query. 0 implies the last available // End: State ID of the last history for the query. 0 implies the last available
// object is selected as the ending point. Note end is included in the query. // object is selected as the ending point. Note end is included in the query.
func (db *Database) AccountHistory(address common.Address, start, end uint64) (*HistoryStats, error) { func (db *Database) AccountHistory(address common.Address, start, end uint64) (*HistoryStats, error) {
return accountHistory(db.freezer, address, start, end) return accountHistory(db.stateFreezer, address, start, end)
} }
// StorageHistory inspects the storage history within the specified range. // StorageHistory inspects the storage history within the specified range.
@ -717,22 +719,22 @@ func (db *Database) AccountHistory(address common.Address, start, end uint64) (*
// //
// Note, slot refers to the hash of the raw slot key. // Note, slot refers to the hash of the raw slot key.
func (db *Database) StorageHistory(address common.Address, slot common.Hash, start uint64, end uint64) (*HistoryStats, error) { func (db *Database) StorageHistory(address common.Address, slot common.Hash, start uint64, end uint64) (*HistoryStats, error) {
return storageHistory(db.freezer, address, slot, start, end) return storageHistory(db.stateFreezer, address, slot, start, end)
} }
// HistoryRange returns the block numbers associated with earliest and latest // HistoryRange returns the block numbers associated with earliest and latest
// state history in the local store. // state history in the local store.
func (db *Database) HistoryRange() (uint64, uint64, error) { func (db *Database) HistoryRange() (uint64, uint64, error) {
return historyRange(db.freezer) return historyRange(db.stateFreezer)
} }
// IndexProgress returns the indexing progress made so far. It provides the // IndexProgress returns the indexing progress made so far. It provides the
// number of states that remain unindexed. // number of states that remain unindexed.
func (db *Database) IndexProgress() (uint64, error) { func (db *Database) IndexProgress() (uint64, error) {
if db.indexer == nil { if db.stateIndexer == nil {
return 0, nil return 0, nil
} }
return db.indexer.progress() return db.stateIndexer.progress()
} }
// AccountIterator creates a new account iterator for the specified root hash and // AccountIterator creates a new account iterator for the specified root hash and

View file

@ -426,7 +426,7 @@ func (t *tester) verifyHistory() error {
for i, root := range t.roots { for i, root := range t.roots {
// The state history related to the state above disk layer should not exist. // The state history related to the state above disk layer should not exist.
if i > bottom { if i > bottom {
_, err := readHistory(t.db.freezer, uint64(i+1)) _, err := readStateHistory(t.db.stateFreezer, uint64(i+1))
if err == nil { if err == nil {
return errors.New("unexpected state history") return errors.New("unexpected state history")
} }
@ -434,7 +434,7 @@ func (t *tester) verifyHistory() error {
} }
// The state history related to the state below or equal to the disk layer // The state history related to the state below or equal to the disk layer
// should exist. // should exist.
obj, err := readHistory(t.db.freezer, uint64(i+1)) obj, err := readStateHistory(t.db.stateFreezer, uint64(i+1))
if err != nil { if err != nil {
return err return err
} }
@ -568,7 +568,7 @@ func TestDisable(t *testing.T) {
t.Fatal("Failed to clean journal") t.Fatal("Failed to clean journal")
} }
// Ensure all trie histories are removed // Ensure all trie histories are removed
n, err := tester.db.freezer.Ancients() n, err := tester.db.stateFreezer.Ancients()
if err != nil { if err != nil {
t.Fatal("Failed to clean state history") t.Fatal("Failed to clean state history")
} }
@ -724,7 +724,7 @@ func TestTailTruncateHistory(t *testing.T) {
tester.db.Close() tester.db.Close()
tester.db = New(tester.db.diskdb, &Config{StateHistory: 10}, false) tester.db = New(tester.db.diskdb, &Config{StateHistory: 10}, false)
head, err := tester.db.freezer.Ancients() head, err := tester.db.stateFreezer.Ancients()
if err != nil { if err != nil {
t.Fatalf("Failed to obtain freezer head") t.Fatalf("Failed to obtain freezer head")
} }

View file

@ -337,16 +337,16 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
overflow bool overflow bool
oldest uint64 oldest uint64
) )
if dl.db.freezer != nil { if dl.db.stateFreezer != nil {
// Bail out with an error if writing the state history fails. // Bail out with an error if writing the state history fails.
// This can happen, for example, if the device is full. // This can happen, for example, if the device is full.
err := writeHistory(dl.db.freezer, bottom) err := writeStateHistory(dl.db.stateFreezer, bottom)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Determine if the persisted history object has exceeded the configured // Determine if the persisted history object has exceeded the configured
// limitation, set the overflow as true if so. // limitation, set the overflow as true if so.
tail, err := dl.db.freezer.Tail() tail, err := dl.db.stateFreezer.Tail()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -356,8 +356,8 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
oldest = bottom.stateID() - limit + 1 // track the id of history **after truncation** oldest = bottom.stateID() - limit + 1 // track the id of history **after truncation**
} }
// Notify the state history indexer for newly created history // Notify the state history indexer for newly created history
if dl.db.indexer != nil { if dl.db.stateIndexer != nil {
if err := dl.db.indexer.extend(bottom.stateID()); err != nil { if err := dl.db.stateIndexer.extend(bottom.stateID()); err != nil {
return nil, err return nil, err
} }
} }
@ -418,7 +418,7 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
// Freeze the live buffer and schedule background flushing // Freeze the live buffer and schedule background flushing
dl.frozen = combined dl.frozen = combined
dl.frozen.flush(bottom.root, dl.db.diskdb, dl.db.freezer, progress, dl.nodes, dl.states, bottom.stateID(), func() { dl.frozen.flush(bottom.root, dl.db.diskdb, dl.db.stateFreezer, progress, dl.nodes, dl.states, bottom.stateID(), func() {
// Resume the background generation if it's not completed yet. // Resume the background generation if it's not completed yet.
// The generator is assumed to be available if the progress is // The generator is assumed to be available if the progress is
// not nil. // not nil.
@ -448,7 +448,7 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
// To remove outdated history objects from the end, we set the 'tail' parameter // To remove outdated history objects from the end, we set the 'tail' parameter
// to 'oldest-1' due to the offset between the freezer index and the history ID. // to 'oldest-1' due to the offset between the freezer index and the history ID.
if overflow { if overflow {
pruned, err := truncateFromTail(ndl.db.diskdb, ndl.db.freezer, oldest-1) pruned, err := truncateFromTail(ndl.db.diskdb, ndl.db.stateFreezer, oldest-1)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -458,7 +458,7 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
} }
// revert applies the given state history and return a reverted disk layer. // revert applies the given state history and return a reverted disk layer.
func (dl *diskLayer) revert(h *history) (*diskLayer, error) { func (dl *diskLayer) revert(h *stateHistory) (*diskLayer, error) {
start := time.Now() start := time.Now()
if h.meta.root != dl.rootHash() { if h.meta.root != dl.rootHash() {
return nil, errUnexpectedHistory return nil, errUnexpectedHistory
@ -484,8 +484,8 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) {
dl.stale = true dl.stale = true
// Unindex the corresponding state history // Unindex the corresponding state history
if dl.db.indexer != nil { if dl.db.stateIndexer != nil {
if err := dl.db.indexer.shorten(dl.id); err != nil { if err := dl.db.stateIndexer.shorten(dl.id); err != nil {
return nil, err return nil, err
} }
} }

View file

@ -180,7 +180,7 @@ func TestBatchIndexerWrite(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
batch = newBatchIndexer(db, false) batch = newBatchIndexer(db, false)
histories = makeHistories(10) histories = makeStateHistories(10)
) )
for i, h := range histories { for i, h := range histories {
if err := batch.process(h, uint64(i+1)); err != nil { if err := batch.process(h, uint64(i+1)); err != nil {
@ -257,7 +257,7 @@ func TestBatchIndexerDelete(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
bw = newBatchIndexer(db, false) bw = newBatchIndexer(db, false)
histories = makeHistories(10) histories = makeStateHistories(10)
) )
// Index histories // Index histories
for i, h := range histories { for i, h := range histories {

View file

@ -93,7 +93,7 @@ func newBatchIndexer(db ethdb.KeyValueStore, delete bool) *batchIndexer {
// process iterates through the accounts and their associated storage slots in the // process iterates through the accounts and their associated storage slots in the
// state history, tracking the mapping between state and history IDs. // state history, tracking the mapping between state and history IDs.
func (b *batchIndexer) process(h *history, historyID uint64) error { func (b *batchIndexer) process(h *stateHistory, historyID uint64) error {
for _, address := range h.accountList { for _, address := range h.accountList {
addrHash := crypto.Keccak256Hash(address.Bytes()) addrHash := crypto.Keccak256Hash(address.Bytes())
b.counter += 1 b.counter += 1
@ -241,7 +241,7 @@ func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancient
} }
return fmt.Errorf("history indexing is out of order, last: %s, requested: %d", last, historyID) return fmt.Errorf("history indexing is out of order, last: %s, requested: %d", last, historyID)
} }
h, err := readHistory(freezer, historyID) h, err := readStateHistory(freezer, historyID)
if err != nil { if err != nil {
return err return err
} }
@ -271,7 +271,7 @@ func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancie
} }
return fmt.Errorf("history unindexing is out of order, last: %s, requested: %d", last, historyID) return fmt.Errorf("history unindexing is out of order, last: %s, requested: %d", last, historyID)
} }
h, err := readHistory(freezer, historyID) h, err := readStateHistory(freezer, historyID)
if err != nil { if err != nil {
return err return err
} }
@ -524,7 +524,7 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
if count > historyReadBatch { if count > historyReadBatch {
count = historyReadBatch count = historyReadBatch
} }
histories, err := readHistories(i.freezer, current, count) histories, err := readStateHistories(i.freezer, current, count)
if err != nil { if err != nil {
// The history read might fall if the history is truncated from // The history read might fall if the history is truncated from
// head due to revert operation. // head due to revert operation.

View file

@ -32,7 +32,7 @@ func TestHistoryIndexerShortenDeadlock(t *testing.T) {
freezer, _ := rawdb.NewStateFreezer(t.TempDir(), false, false) freezer, _ := rawdb.NewStateFreezer(t.TempDir(), false, false)
defer freezer.Close() defer freezer.Close()
histories := makeHistories(100) histories := makeStateHistories(100)
for i, h := range histories { for i, h := range histories {
accountData, storageData, accountIndex, storageIndex := h.encode() accountData, storageData, accountIndex, storageIndex := h.encode()
rawdb.WriteStateHistory(freezer, uint64(i+1), h.meta.encode(), accountIndex, storageIndex, accountData, storageData) rawdb.WriteStateHistory(freezer, uint64(i+1), h.meta.encode(), accountIndex, storageIndex, accountData, storageData)

View file

@ -61,7 +61,7 @@ func sanitizeRange(start, end uint64, freezer ethdb.AncientReader) (uint64, uint
return first, last, nil return first, last, nil
} }
func inspectHistory(freezer ethdb.AncientReader, start, end uint64, onHistory func(*history, *HistoryStats)) (*HistoryStats, error) { func inspectHistory(freezer ethdb.AncientReader, start, end uint64, onHistory func(*stateHistory, *HistoryStats)) (*HistoryStats, error) {
var ( var (
stats = &HistoryStats{} stats = &HistoryStats{}
init = time.Now() init = time.Now()
@ -74,7 +74,7 @@ func inspectHistory(freezer ethdb.AncientReader, start, end uint64, onHistory fu
for id := start; id <= end; id += 1 { for id := start; id <= end; id += 1 {
// The entire history object is decoded, although it's unnecessary for // The entire history object is decoded, although it's unnecessary for
// account inspection. TODO(rjl493456442) optimization is worthwhile. // account inspection. TODO(rjl493456442) optimization is worthwhile.
h, err := readHistory(freezer, id) h, err := readStateHistory(freezer, id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -98,7 +98,7 @@ func inspectHistory(freezer ethdb.AncientReader, start, end uint64, onHistory fu
// accountHistory inspects the account history within the range. // accountHistory inspects the account history within the range.
func accountHistory(freezer ethdb.AncientReader, address common.Address, start, end uint64) (*HistoryStats, error) { func accountHistory(freezer ethdb.AncientReader, address common.Address, start, end uint64) (*HistoryStats, error) {
return inspectHistory(freezer, start, end, func(h *history, stats *HistoryStats) { return inspectHistory(freezer, start, end, func(h *stateHistory, stats *HistoryStats) {
blob, exists := h.accounts[address] blob, exists := h.accounts[address]
if !exists { if !exists {
return return
@ -111,7 +111,7 @@ func accountHistory(freezer ethdb.AncientReader, address common.Address, start,
// storageHistory inspects the storage history within the range. // storageHistory inspects the storage history within the range.
func storageHistory(freezer ethdb.AncientReader, address common.Address, slot common.Hash, start uint64, end uint64) (*HistoryStats, error) { func storageHistory(freezer ethdb.AncientReader, address common.Address, slot common.Hash, start uint64, end uint64) (*HistoryStats, error) {
slotHash := crypto.Keccak256Hash(slot.Bytes()) slotHash := crypto.Keccak256Hash(slot.Bytes())
return inspectHistory(freezer, start, end, func(h *history, stats *HistoryStats) { return inspectHistory(freezer, start, end, func(h *stateHistory, stats *HistoryStats) {
slots, exists := h.storages[address] slots, exists := h.storages[address]
if !exists { if !exists {
return return
@ -145,11 +145,11 @@ func historyRange(freezer ethdb.AncientReader) (uint64, uint64, error) {
} }
last := head - 1 last := head - 1
fh, err := readHistory(freezer, first) fh, err := readStateHistory(freezer, first)
if err != nil { if err != nil {
return 0, 0, err return 0, 0, err
} }
lh, err := readHistory(freezer, last) lh, err := readStateHistory(freezer, last)
if err != nil { if err != nil {
return 0, 0, err return 0, 0, err
} }

View file

@ -133,7 +133,7 @@ func testHistoryReader(t *testing.T, historyLimit uint64) {
var ( var (
roots = env.roots roots = env.roots
dRoot = env.db.tree.bottom().rootHash() dRoot = env.db.tree.bottom().rootHash()
hr = newHistoryReader(env.db.diskdb, env.db.freezer) hr = newHistoryReader(env.db.diskdb, env.db.stateFreezer)
) )
for _, root := range roots { for _, root := range roots {
if root == dRoot { if root == dRoot {

View file

@ -234,12 +234,13 @@ func (m *meta) decode(blob []byte) error {
} }
} }
// history represents a set of state changes belong to a block along with // stateHistory represents a set of state changes belong to a block along with
// the metadata including the state roots involved in the state transition. // the metadata including the state roots involved in the state transition.
//
// State history objects in disk are linked with each other by a unique id // State history objects in disk are linked with each other by a unique id
// (8-bytes integer), the oldest state history object can be pruned on demand // (8-bytes integer), the oldest state history object can be pruned on demand
// in order to control the storage size. // in order to control the storage size.
type history struct { type stateHistory struct {
meta *meta // Meta data of history meta *meta // Meta data of history
accounts map[common.Address][]byte // Account data keyed by its address hash accounts map[common.Address][]byte // Account data keyed by its address hash
accountList []common.Address // Sorted account hash list accountList []common.Address // Sorted account hash list
@ -247,8 +248,8 @@ type history struct {
storageList map[common.Address][]common.Hash // Sorted slot hash list storageList map[common.Address][]common.Hash // Sorted slot hash list
} }
// newHistory constructs the state history object with provided state change set. // newStateHistory constructs the state history object with provided states.
func newHistory(root common.Hash, parent common.Hash, block uint64, accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte, rawStorageKey bool) *history { func newStateHistory(root common.Hash, parent common.Hash, block uint64, accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte, rawStorageKey bool) *stateHistory {
var ( var (
accountList = slices.SortedFunc(maps.Keys(accounts), common.Address.Cmp) accountList = slices.SortedFunc(maps.Keys(accounts), common.Address.Cmp)
storageList = make(map[common.Address][]common.Hash) storageList = make(map[common.Address][]common.Hash)
@ -260,7 +261,7 @@ func newHistory(root common.Hash, parent common.Hash, block uint64, accounts map
if !rawStorageKey { if !rawStorageKey {
version = stateHistoryV0 version = stateHistoryV0
} }
return &history{ return &stateHistory{
meta: &meta{ meta: &meta{
version: version, version: version,
parent: parent, parent: parent,
@ -276,7 +277,7 @@ func newHistory(root common.Hash, parent common.Hash, block uint64, accounts map
// stateSet returns the state set, keyed by the hash of the account address // stateSet returns the state set, keyed by the hash of the account address
// and the hash of the storage slot key. // and the hash of the storage slot key.
func (h *history) stateSet() (map[common.Hash][]byte, map[common.Hash]map[common.Hash][]byte) { func (h *stateHistory) stateSet() (map[common.Hash][]byte, map[common.Hash]map[common.Hash][]byte) {
var ( var (
accounts = make(map[common.Hash][]byte) accounts = make(map[common.Hash][]byte)
storages = make(map[common.Hash]map[common.Hash][]byte) storages = make(map[common.Hash]map[common.Hash][]byte)
@ -304,7 +305,7 @@ func (h *history) stateSet() (map[common.Hash][]byte, map[common.Hash]map[common
// encode serializes the state history and returns four byte streams represent // encode serializes the state history and returns four byte streams represent
// concatenated account/storage data, account/storage indexes respectively. // concatenated account/storage data, account/storage indexes respectively.
func (h *history) encode() ([]byte, []byte, []byte, []byte) { func (h *stateHistory) encode() ([]byte, []byte, []byte, []byte) {
var ( var (
slotNumber uint32 // the number of processed slots slotNumber uint32 // the number of processed slots
accountData []byte // the buffer for concatenated account data accountData []byte // the buffer for concatenated account data
@ -459,7 +460,7 @@ func (r *decoder) readStorage(accIndex accountIndex) ([]common.Hash, map[common.
} }
// decode deserializes the account and storage data from the provided byte stream. // decode deserializes the account and storage data from the provided byte stream.
func (h *history) decode(accountData, storageData, accountIndexes, storageIndexes []byte) error { func (h *stateHistory) decode(accountData, storageData, accountIndexes, storageIndexes []byte) error {
var ( var (
count = len(accountIndexes) / accountIndexSize count = len(accountIndexes) / accountIndexSize
accounts = make(map[common.Address][]byte, count) accounts = make(map[common.Address][]byte, count)
@ -503,8 +504,8 @@ func (h *history) decode(accountData, storageData, accountIndexes, storageIndexe
return nil return nil
} }
// readHistory reads and decodes the state history object by the given id. // readStateHistory reads a single state history records with the specified id.
func readHistory(reader ethdb.AncientReader, id uint64) (*history, error) { func readStateHistory(reader ethdb.AncientReader, id uint64) (*stateHistory, error) {
mData, accountIndexes, storageIndexes, accountData, storageData, err := rawdb.ReadStateHistory(reader, id) mData, accountIndexes, storageIndexes, accountData, storageData, err := rawdb.ReadStateHistory(reader, id)
if err != nil { if err != nil {
return nil, err return nil, err
@ -513,17 +514,16 @@ func readHistory(reader ethdb.AncientReader, id uint64) (*history, error) {
if err := m.decode(mData); err != nil { if err := m.decode(mData); err != nil {
return nil, err return nil, err
} }
h := history{meta: &m} h := stateHistory{meta: &m}
if err := h.decode(accountData, storageData, accountIndexes, storageIndexes); err != nil { if err := h.decode(accountData, storageData, accountIndexes, storageIndexes); err != nil {
return nil, err return nil, err
} }
return &h, nil return &h, nil
} }
// readHistories reads and decodes a list of state histories with the specific // readStateHistories reads a list of state history records within the specified range.
// history range. func readStateHistories(freezer ethdb.AncientReader, start uint64, count uint64) ([]*stateHistory, error) {
func readHistories(freezer ethdb.AncientReader, start uint64, count uint64) ([]*history, error) { var histories []*stateHistory
var histories []*history
metaList, aIndexList, sIndexList, aDataList, sDataList, err := rawdb.ReadStateHistoryList(freezer, start, count) metaList, aIndexList, sIndexList, aDataList, sDataList, err := rawdb.ReadStateHistoryList(freezer, start, count)
if err != nil { if err != nil {
return nil, err return nil, err
@ -533,7 +533,7 @@ func readHistories(freezer ethdb.AncientReader, start uint64, count uint64) ([]*
if err := m.decode(metaList[i]); err != nil { if err := m.decode(metaList[i]); err != nil {
return nil, err return nil, err
} }
h := history{meta: &m} h := stateHistory{meta: &m}
if err := h.decode(aDataList[i], sDataList[i], aIndexList[i], sIndexList[i]); err != nil { if err := h.decode(aDataList[i], sDataList[i], aIndexList[i], sIndexList[i]); err != nil {
return nil, err return nil, err
} }
@ -542,15 +542,15 @@ func readHistories(freezer ethdb.AncientReader, start uint64, count uint64) ([]*
return histories, nil return histories, nil
} }
// writeHistory persists the state history with the provided state set. // writeStateHistory persists the state history associated with the given diff layer.
func writeHistory(writer ethdb.AncientWriter, dl *diffLayer) error { func writeStateHistory(writer ethdb.AncientWriter, dl *diffLayer) error {
// Short circuit if state set is not available. // Short circuit if state set is not available.
if dl.states == nil { if dl.states == nil {
return errors.New("state change set is not available") return errors.New("state change set is not available")
} }
var ( var (
start = time.Now() start = time.Now()
history = newHistory(dl.rootHash(), dl.parentLayer().rootHash(), dl.block, dl.states.accountOrigin, dl.states.storageOrigin, dl.states.rawStorageKey) history = newStateHistory(dl.rootHash(), dl.parentLayer().rootHash(), dl.block, dl.states.accountOrigin, dl.states.storageOrigin, dl.states.rawStorageKey)
) )
accountData, storageData, accountIndex, storageIndex := history.encode() accountData, storageData, accountIndex, storageIndex := history.encode()
dataSize := common.StorageSize(len(accountData) + len(storageData)) dataSize := common.StorageSize(len(accountData) + len(storageData))
@ -568,9 +568,9 @@ func writeHistory(writer ethdb.AncientWriter, dl *diffLayer) error {
return nil return nil
} }
// checkHistories retrieves a batch of meta objects with the specified range // checkStateHistories retrieves a batch of meta objects with the specified range
// and performs the callback on each item. // and performs the callback on each item.
func checkHistories(reader ethdb.AncientReader, start, count uint64, check func(*meta) error) error { func checkStateHistories(reader ethdb.AncientReader, start, count uint64, check func(*meta) error) error {
for count > 0 { for count > 0 {
number := count number := count
if number > 10000 { if number > 10000 {

View file

@ -49,36 +49,36 @@ func randomStateSet(n int) (map[common.Address][]byte, map[common.Address]map[co
return accounts, storages return accounts, storages
} }
func makeHistory(rawStorageKey bool) *history { func makeStateHistory(rawStorageKey bool) *stateHistory {
accounts, storages := randomStateSet(3) accounts, storages := randomStateSet(3)
return newHistory(testrand.Hash(), types.EmptyRootHash, 0, accounts, storages, rawStorageKey) return newStateHistory(testrand.Hash(), types.EmptyRootHash, 0, accounts, storages, rawStorageKey)
} }
func makeHistories(n int) []*history { func makeStateHistories(n int) []*stateHistory {
var ( var (
parent = types.EmptyRootHash parent = types.EmptyRootHash
result []*history result []*stateHistory
) )
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
root := testrand.Hash() root := testrand.Hash()
accounts, storages := randomStateSet(3) accounts, storages := randomStateSet(3)
h := newHistory(root, parent, uint64(i), accounts, storages, false) h := newStateHistory(root, parent, uint64(i), accounts, storages, false)
parent = root parent = root
result = append(result, h) result = append(result, h)
} }
return result return result
} }
func TestEncodeDecodeHistory(t *testing.T) { func TestEncodeDecodeStateHistory(t *testing.T) {
testEncodeDecodeHistory(t, false) testEncodeDecodeStateHistory(t, false)
testEncodeDecodeHistory(t, true) testEncodeDecodeStateHistory(t, true)
} }
func testEncodeDecodeHistory(t *testing.T, rawStorageKey bool) { func testEncodeDecodeStateHistory(t *testing.T, rawStorageKey bool) {
var ( var (
m meta m meta
dec history dec stateHistory
obj = makeHistory(rawStorageKey) obj = makeStateHistory(rawStorageKey)
) )
// check if meta data can be correctly encode/decode // check if meta data can be correctly encode/decode
blob := obj.meta.encode() blob := obj.meta.encode()
@ -108,7 +108,7 @@ func testEncodeDecodeHistory(t *testing.T, rawStorageKey bool) {
} }
} }
func checkHistory(t *testing.T, db ethdb.KeyValueReader, freezer ethdb.AncientReader, id uint64, root common.Hash, exist bool) { func checkStateHistory(t *testing.T, db ethdb.KeyValueReader, freezer ethdb.AncientReader, id uint64, root common.Hash, exist bool) {
blob := rawdb.ReadStateHistoryMeta(freezer, id) blob := rawdb.ReadStateHistoryMeta(freezer, id)
if exist && len(blob) == 0 { if exist && len(blob) == 0 {
t.Fatalf("Failed to load trie history, %d", id) t.Fatalf("Failed to load trie history, %d", id)
@ -126,14 +126,14 @@ func checkHistory(t *testing.T, db ethdb.KeyValueReader, freezer ethdb.AncientRe
func checkHistoriesInRange(t *testing.T, db ethdb.KeyValueReader, freezer ethdb.AncientReader, from, to uint64, roots []common.Hash, exist bool) { func checkHistoriesInRange(t *testing.T, db ethdb.KeyValueReader, freezer ethdb.AncientReader, from, to uint64, roots []common.Hash, exist bool) {
for i, j := from, 0; i <= to; i, j = i+1, j+1 { for i, j := from, 0; i <= to; i, j = i+1, j+1 {
checkHistory(t, db, freezer, i, roots[j], exist) checkStateHistory(t, db, freezer, i, roots[j], exist)
} }
} }
func TestTruncateHeadHistory(t *testing.T) { func TestTruncateHeadStateHistory(t *testing.T) {
var ( var (
roots []common.Hash roots []common.Hash
hs = makeHistories(10) hs = makeStateHistories(10)
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false) freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false)
) )
@ -158,10 +158,10 @@ func TestTruncateHeadHistory(t *testing.T) {
} }
} }
func TestTruncateTailHistory(t *testing.T) { func TestTruncateTailStateHistory(t *testing.T) {
var ( var (
roots []common.Hash roots []common.Hash
hs = makeHistories(10) hs = makeStateHistories(10)
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false) freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false)
) )
@ -183,7 +183,7 @@ func TestTruncateTailHistory(t *testing.T) {
} }
} }
func TestTruncateTailHistories(t *testing.T) { func TestTruncateTailStateHistories(t *testing.T) {
var cases = []struct { var cases = []struct {
limit uint64 limit uint64
expPruned int expPruned int
@ -204,7 +204,7 @@ func TestTruncateTailHistories(t *testing.T) {
for i, c := range cases { for i, c := range cases {
var ( var (
roots []common.Hash roots []common.Hash
hs = makeHistories(10) hs = makeStateHistories(10)
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
freezer, _ = rawdb.NewStateFreezer(t.TempDir()+fmt.Sprintf("%d", i), false, false) freezer, _ = rawdb.NewStateFreezer(t.TempDir()+fmt.Sprintf("%d", i), false, false)
) )
@ -232,7 +232,7 @@ func TestTruncateTailHistories(t *testing.T) {
func TestTruncateOutOfRange(t *testing.T) { func TestTruncateOutOfRange(t *testing.T) {
var ( var (
hs = makeHistories(10) hs = makeStateHistories(10)
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false) freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false)
) )

View file

@ -207,10 +207,10 @@ type HistoricalStateReader struct {
// HistoricReader constructs a reader for accessing the requested historic state. // HistoricReader constructs a reader for accessing the requested historic state.
func (db *Database) HistoricReader(root common.Hash) (*HistoricalStateReader, error) { func (db *Database) HistoricReader(root common.Hash) (*HistoricalStateReader, error) {
// Bail out if the state history hasn't been fully indexed // Bail out if the state history hasn't been fully indexed
if db.indexer == nil || db.freezer == nil { if db.stateIndexer == nil || db.stateFreezer == nil {
return nil, fmt.Errorf("historical state %x is not available", root) return nil, fmt.Errorf("historical state %x is not available", root)
} }
if !db.indexer.inited() { if !db.stateIndexer.inited() {
return nil, errors.New("state histories haven't been fully indexed yet") return nil, errors.New("state histories haven't been fully indexed yet")
} }
// States at the current disk layer or above are directly accessible via // States at the current disk layer or above are directly accessible via
@ -230,7 +230,7 @@ func (db *Database) HistoricReader(root common.Hash) (*HistoricalStateReader, er
return &HistoricalStateReader{ return &HistoricalStateReader{
id: *id, id: *id,
db: db, db: db,
reader: newHistoryReader(db.diskdb, db.freezer), reader: newHistoryReader(db.diskdb, db.stateFreezer),
}, nil }, nil
} }