-
Notifications
You must be signed in to change notification settings - Fork 0
/
trie_queue.go
115 lines (99 loc) · 3.53 KB
/
trie_queue.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// (c) 2021-2022, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package statesync
import (
"github.com/cgcardona/r-subnet-evm/core/rawdb"
"github.com/cgcardona/r-subnet-evm/ethdb"
"github.com/ethereum/go-ethereum/common"
)
// trieQueue persists storage trie roots with their associated
// accounts when [RegisterStorageTrie] is called. These are
// later returned from the [getNextTrie] method.
type trieQueue struct {
db ethdb.Database
nextStorageRoot []byte
}
func NewTrieQueue(db ethdb.Database) *trieQueue {
return &trieQueue{
db: db,
}
}
// clearIfRootDoesNotMatch clears progress and segment markers if
// the persisted root does not match the root we are syncing to.
func (t *trieQueue) clearIfRootDoesNotMatch(root common.Hash) error {
persistedRoot, err := rawdb.ReadSyncRoot(t.db)
if err != nil {
return err
}
if persistedRoot != (common.Hash{}) && persistedRoot != root {
// if not resuming, clear all progress markers
if err := rawdb.ClearAllSyncStorageTries(t.db); err != nil {
return err
}
if err := rawdb.ClearAllSyncSegments(t.db); err != nil {
return err
}
}
return rawdb.WriteSyncRoot(t.db, root)
}
// RegisterStorageTrie is called by the main trie's leaf handling callbacks
// It adds a key built as [syncProgressPrefix+root+account] to the database.
// getNextTrie iterates this prefix to find storage tries and accounts
// associated with them.
func (t *trieQueue) RegisterStorageTrie(root common.Hash, account common.Hash) error {
return rawdb.WriteSyncStorageTrie(t.db, root, account)
}
// StorageTrieDone is called when a storage trie has completed syncing.
// This removes any progress markers for the trie.
func (t *trieQueue) StorageTrieDone(root common.Hash) error {
return rawdb.ClearSyncStorageTrie(t.db, root)
}
// getNextTrie returns the next storage trie to sync, along with a slice
// of accounts that point to the returned storage trie.
// Returns true if there are more storage tries to sync and false otherwise.
// Note: if a non-nil root is returned, getNextTrie guarantees that there will be at least
// one account hash in the returned slice.
func (t *trieQueue) getNextTrie() (common.Hash, []common.Hash, bool, error) {
it := rawdb.NewSyncStorageTriesIterator(t.db, t.nextStorageRoot)
defer it.Release()
var (
root common.Hash
accounts []common.Hash
more bool
)
// Iterate over the keys to find the next storage trie root and all of the account hashes that contain the same storage root.
for it.Next() {
// Unpack the state root and account hash from the current key
nextRoot, nextAccount := rawdb.UnpackSyncStorageTrieKey(it.Key())
// Set the root for the first pass
if root == (common.Hash{}) {
root = nextRoot
}
// If the next root is different than the originally set root, then we've iterated over all of the account hashes that
// have the same storage trie root. Set more to be true, since there is at least one more storage trie.
if root != nextRoot {
t.nextStorageRoot = nextRoot[:]
more = true
break
}
// If we found another account with the same root, add the accountHash.
accounts = append(accounts, nextAccount)
}
return root, accounts, more, it.Error()
}
func (t *trieQueue) countTries() (int, error) {
it := rawdb.NewSyncStorageTriesIterator(t.db, nil)
defer it.Release()
var (
root common.Hash
tries int
)
for it.Next() {
nextRoot, _ := rawdb.UnpackSyncStorageTrieKey(it.Key())
if root == (common.Hash{}) || root != nextRoot {
root = nextRoot
tries++
}
}
return tries, it.Error()
}