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  }