github.com/dim4egster/coreth@v0.10.2/core/rawdb/accessors_state_sync.go (about) 1 // (c) 2022, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package rawdb 5 6 import ( 7 "github.com/dim4egster/coreth/ethdb" 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/log" 10 ) 11 12 // ReadSyncRoot reads the root corresponding to the main trie of an in-progress 13 // sync and returns common.Hash{} if no in-progress sync was found. 14 func ReadSyncRoot(db ethdb.KeyValueReader) (common.Hash, error) { 15 has, err := db.Has(syncRootKey) 16 if err != nil || !has { 17 return common.Hash{}, err 18 } 19 root, err := db.Get(syncRootKey) 20 if err != nil { 21 return common.Hash{}, err 22 } 23 return common.BytesToHash(root), nil 24 } 25 26 // WriteSyncRoot writes root as the root of the main trie of the in-progress sync. 27 func WriteSyncRoot(db ethdb.KeyValueWriter, root common.Hash) error { 28 return db.Put(syncRootKey, root[:]) 29 } 30 31 // AddCodeToFetch adds a marker that we need to fetch the code for [hash]. 32 func AddCodeToFetch(db ethdb.KeyValueWriter, hash common.Hash) { 33 if err := db.Put(codeToFetchKey(hash), nil); err != nil { 34 log.Crit("Failed to put code to fetch", "codeHash", hash, "err", err) 35 } 36 } 37 38 // DeleteCodeToFetch removes the marker that the code corresponding to [hash] needs to be fetched. 39 func DeleteCodeToFetch(db ethdb.KeyValueWriter, hash common.Hash) { 40 if err := db.Delete(codeToFetchKey(hash)); err != nil { 41 log.Crit("Failed to delete code to fetch", "codeHash", hash, "err", err) 42 } 43 } 44 45 // NewCodeToFetchIterator returns a KeyLength iterator over all code 46 // hashes that are pending syncing. It is the caller's responsibility to 47 // unpack the key and call Release on the returned iterator. 48 func NewCodeToFetchIterator(db ethdb.Iteratee) ethdb.Iterator { 49 return NewKeyLengthIterator( 50 db.NewIterator(CodeToFetchPrefix, nil), 51 codeToFetchKeyLength, 52 ) 53 } 54 55 func codeToFetchKey(hash common.Hash) []byte { 56 codeToFetchKey := make([]byte, codeToFetchKeyLength) 57 copy(codeToFetchKey, CodeToFetchPrefix) 58 copy(codeToFetchKey[len(CodeToFetchPrefix):], hash[:]) 59 return codeToFetchKey 60 } 61 62 // NewSyncSegmentsIterator returns a KeyLength iterator over all trie segments 63 // added for root. It is the caller's responsibility to unpack the key and call 64 // Release on the returned iterator. 65 func NewSyncSegmentsIterator(db ethdb.Iteratee, root common.Hash) ethdb.Iterator { 66 segmentsPrefix := make([]byte, len(syncSegmentsPrefix)+common.HashLength) 67 copy(segmentsPrefix, syncSegmentsPrefix) 68 copy(segmentsPrefix[len(syncSegmentsPrefix):], root[:]) 69 70 return NewKeyLengthIterator( 71 db.NewIterator(segmentsPrefix, nil), 72 syncSegmentsKeyLength, 73 ) 74 } 75 76 // WriteSyncSegment adds a trie segment for root at the given start position. 77 func WriteSyncSegment(db ethdb.KeyValueWriter, root common.Hash, start []byte) error { 78 return db.Put(packSyncSegmentKey(root, start), []byte{0x01}) 79 } 80 81 // ClearSegment removes segment markers for root from db 82 func ClearSyncSegments(db ethdb.KeyValueStore, root common.Hash) error { 83 segmentsPrefix := make([]byte, len(syncSegmentsPrefix)+common.HashLength) 84 copy(segmentsPrefix, syncSegmentsPrefix) 85 copy(segmentsPrefix[len(syncSegmentsPrefix):], root[:]) 86 87 return ClearPrefix(db, segmentsPrefix) 88 } 89 90 // ClearAllSyncSegments removes all segment markers from db 91 func ClearAllSyncSegments(db ethdb.KeyValueStore) error { 92 return ClearPrefix(db, syncSegmentsPrefix) 93 } 94 95 // UnpackSyncSegmentKey returns the root and start position for a trie segment 96 // key returned from NewSyncSegmentsIterator. 97 func UnpackSyncSegmentKey(keyBytes []byte) (common.Hash, []byte) { 98 keyBytes = keyBytes[len(syncSegmentsPrefix):] // skip prefix 99 root := common.BytesToHash(keyBytes[:common.HashLength]) 100 start := keyBytes[common.HashLength:] 101 return root, start 102 } 103 104 // packSyncSegmentKey packs root and account into a key for storage in db. 105 func packSyncSegmentKey(root common.Hash, start []byte) []byte { 106 bytes := make([]byte, len(syncSegmentsPrefix)+common.HashLength+len(start)) 107 copy(bytes, syncSegmentsPrefix) 108 copy(bytes[len(syncSegmentsPrefix):], root[:]) 109 copy(bytes[len(syncSegmentsPrefix)+common.HashLength:], start) 110 return bytes 111 } 112 113 // NewSyncStorageTriesIterator returns a KeyLength iterator over all storage tries 114 // added for syncing (beginning at seek). It is the caller's responsibility to unpack 115 // the key and call Release on the returned iterator. 116 func NewSyncStorageTriesIterator(db ethdb.Iteratee, seek []byte) ethdb.Iterator { 117 return NewKeyLengthIterator(db.NewIterator(syncStorageTriesPrefix, seek), syncStorageTriesKeyLength) 118 } 119 120 // WriteSyncStorageTrie adds a storage trie for account (with the given root) to be synced. 121 func WriteSyncStorageTrie(db ethdb.KeyValueWriter, root common.Hash, account common.Hash) error { 122 return db.Put(packSyncStorageTrieKey(root, account), []byte{0x01}) 123 } 124 125 // ClearSyncStorageTrie removes all storage trie accounts (with the given root) from db. 126 // Intended for use when the trie with root has completed syncing. 127 func ClearSyncStorageTrie(db ethdb.KeyValueStore, root common.Hash) error { 128 accountsPrefix := make([]byte, len(syncStorageTriesPrefix)+common.HashLength) 129 copy(accountsPrefix, syncStorageTriesPrefix) 130 copy(accountsPrefix[len(syncStorageTriesPrefix):], root[:]) 131 return ClearPrefix(db, accountsPrefix) 132 } 133 134 // ClearAllSyncStorageTries removes all storage tries added for syncing from db 135 func ClearAllSyncStorageTries(db ethdb.KeyValueStore) error { 136 return ClearPrefix(db, syncStorageTriesPrefix) 137 } 138 139 // UnpackSyncStorageTrieKey returns the root and account for a storage trie 140 // key returned from NewSyncStorageTriesIterator. 141 func UnpackSyncStorageTrieKey(keyBytes []byte) (common.Hash, common.Hash) { 142 keyBytes = keyBytes[len(syncStorageTriesPrefix):] // skip prefix 143 root := common.BytesToHash(keyBytes[:common.HashLength]) 144 account := common.BytesToHash(keyBytes[common.HashLength:]) 145 return root, account 146 } 147 148 // packSyncStorageTrieKey packs root and account into a key for storage in db. 149 func packSyncStorageTrieKey(root common.Hash, account common.Hash) []byte { 150 bytes := make([]byte, 0, syncStorageTriesKeyLength) 151 bytes = append(bytes, syncStorageTriesPrefix...) 152 bytes = append(bytes, root[:]...) 153 bytes = append(bytes, account[:]...) 154 return bytes 155 }