-
Notifications
You must be signed in to change notification settings - Fork 225
/
accessors_state_sync.go
155 lines (133 loc) · 6.03 KB
/
accessors_state_sync.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// (c) 2022, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package rawdb
import (
"github.com/ava-labs/subnet-evm/ethdb"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
// ReadSyncRoot reads the root corresponding to the main trie of an in-progress
// sync and returns common.Hash{} if no in-progress sync was found.
func ReadSyncRoot(db ethdb.KeyValueReader) (common.Hash, error) {
has, err := db.Has(syncRootKey)
if err != nil || !has {
return common.Hash{}, err
}
root, err := db.Get(syncRootKey)
if err != nil {
return common.Hash{}, err
}
return common.BytesToHash(root), nil
}
// WriteSyncRoot writes root as the root of the main trie of the in-progress sync.
func WriteSyncRoot(db ethdb.KeyValueWriter, root common.Hash) error {
return db.Put(syncRootKey, root[:])
}
// AddCodeToFetch adds a marker that we need to fetch the code for [hash].
func AddCodeToFetch(db ethdb.KeyValueWriter, hash common.Hash) {
if err := db.Put(codeToFetchKey(hash), nil); err != nil {
log.Crit("Failed to put code to fetch", "codeHash", hash, "err", err)
}
}
// DeleteCodeToFetch removes the marker that the code corresponding to [hash] needs to be fetched.
func DeleteCodeToFetch(db ethdb.KeyValueWriter, hash common.Hash) {
if err := db.Delete(codeToFetchKey(hash)); err != nil {
log.Crit("Failed to delete code to fetch", "codeHash", hash, "err", err)
}
}
// NewCodeToFetchIterator returns a KeyLength iterator over all code
// hashes that are pending syncing. It is the caller's responsibility to
// unpack the key and call Release on the returned iterator.
func NewCodeToFetchIterator(db ethdb.Iteratee) ethdb.Iterator {
return NewKeyLengthIterator(
db.NewIterator(CodeToFetchPrefix, nil),
codeToFetchKeyLength,
)
}
func codeToFetchKey(hash common.Hash) []byte {
codeToFetchKey := make([]byte, codeToFetchKeyLength)
copy(codeToFetchKey, CodeToFetchPrefix)
copy(codeToFetchKey[len(CodeToFetchPrefix):], hash[:])
return codeToFetchKey
}
// NewSyncSegmentsIterator returns a KeyLength iterator over all trie segments
// added for root. It is the caller's responsibility to unpack the key and call
// Release on the returned iterator.
func NewSyncSegmentsIterator(db ethdb.Iteratee, root common.Hash) ethdb.Iterator {
segmentsPrefix := make([]byte, len(syncSegmentsPrefix)+common.HashLength)
copy(segmentsPrefix, syncSegmentsPrefix)
copy(segmentsPrefix[len(syncSegmentsPrefix):], root[:])
return NewKeyLengthIterator(
db.NewIterator(segmentsPrefix, nil),
syncSegmentsKeyLength,
)
}
// WriteSyncSegment adds a trie segment for root at the given start position.
func WriteSyncSegment(db ethdb.KeyValueWriter, root common.Hash, start []byte) error {
return db.Put(packSyncSegmentKey(root, start), []byte{0x01})
}
// ClearSegment removes segment markers for root from db
func ClearSyncSegments(db ethdb.KeyValueStore, root common.Hash) error {
segmentsPrefix := make([]byte, len(syncSegmentsPrefix)+common.HashLength)
copy(segmentsPrefix, syncSegmentsPrefix)
copy(segmentsPrefix[len(syncSegmentsPrefix):], root[:])
return ClearPrefix(db, segmentsPrefix)
}
// ClearAllSyncSegments removes all segment markers from db
func ClearAllSyncSegments(db ethdb.KeyValueStore) error {
return ClearPrefix(db, syncSegmentsPrefix)
}
// UnpackSyncSegmentKey returns the root and start position for a trie segment
// key returned from NewSyncSegmentsIterator.
func UnpackSyncSegmentKey(keyBytes []byte) (common.Hash, []byte) {
keyBytes = keyBytes[len(syncSegmentsPrefix):] // skip prefix
root := common.BytesToHash(keyBytes[:common.HashLength])
start := keyBytes[common.HashLength:]
return root, start
}
// packSyncSegmentKey packs root and account into a key for storage in db.
func packSyncSegmentKey(root common.Hash, start []byte) []byte {
bytes := make([]byte, len(syncSegmentsPrefix)+common.HashLength+len(start))
copy(bytes, syncSegmentsPrefix)
copy(bytes[len(syncSegmentsPrefix):], root[:])
copy(bytes[len(syncSegmentsPrefix)+common.HashLength:], start)
return bytes
}
// NewSyncStorageTriesIterator returns a KeyLength iterator over all storage tries
// added for syncing (beginning at seek). It is the caller's responsibility to unpack
// the key and call Release on the returned iterator.
func NewSyncStorageTriesIterator(db ethdb.Iteratee, seek []byte) ethdb.Iterator {
return NewKeyLengthIterator(db.NewIterator(syncStorageTriesPrefix, seek), syncStorageTriesKeyLength)
}
// WriteSyncStorageTrie adds a storage trie for account (with the given root) to be synced.
func WriteSyncStorageTrie(db ethdb.KeyValueWriter, root common.Hash, account common.Hash) error {
return db.Put(packSyncStorageTrieKey(root, account), []byte{0x01})
}
// ClearSyncStorageTrie removes all storage trie accounts (with the given root) from db.
// Intended for use when the trie with root has completed syncing.
func ClearSyncStorageTrie(db ethdb.KeyValueStore, root common.Hash) error {
accountsPrefix := make([]byte, len(syncStorageTriesPrefix)+common.HashLength)
copy(accountsPrefix, syncStorageTriesPrefix)
copy(accountsPrefix[len(syncStorageTriesPrefix):], root[:])
return ClearPrefix(db, accountsPrefix)
}
// ClearAllSyncStorageTries removes all storage tries added for syncing from db
func ClearAllSyncStorageTries(db ethdb.KeyValueStore) error {
return ClearPrefix(db, syncStorageTriesPrefix)
}
// UnpackSyncStorageTrieKey returns the root and account for a storage trie
// key returned from NewSyncStorageTriesIterator.
func UnpackSyncStorageTrieKey(keyBytes []byte) (common.Hash, common.Hash) {
keyBytes = keyBytes[len(syncStorageTriesPrefix):] // skip prefix
root := common.BytesToHash(keyBytes[:common.HashLength])
account := common.BytesToHash(keyBytes[common.HashLength:])
return root, account
}
// packSyncStorageTrieKey packs root and account into a key for storage in db.
func packSyncStorageTrieKey(root common.Hash, account common.Hash) []byte {
bytes := make([]byte, 0, syncStorageTriesKeyLength)
bytes = append(bytes, syncStorageTriesPrefix...)
bytes = append(bytes, root[:]...)
bytes = append(bytes, account[:]...)
return bytes
}