github.com/MetalBlockchain/subnet-evm@v0.6.3/trie/preimages.go (about) 1 // (c) 2022, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2022 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package trie 28 29 import ( 30 "sync" 31 32 "github.com/MetalBlockchain/subnet-evm/core/rawdb" 33 "github.com/ethereum/go-ethereum/common" 34 "github.com/ethereum/go-ethereum/ethdb" 35 ) 36 37 const defaultPreimagesLimit = 4 * 1024 * 1024 // 4 MB 38 39 // preimageStore is the store for caching preimages of node key. 40 type preimageStore struct { 41 lock sync.RWMutex 42 disk ethdb.KeyValueStore 43 preimages map[common.Hash][]byte // Preimages of nodes from the secure trie 44 preimagesSize common.StorageSize // Storage size of the preimages cache 45 } 46 47 // newPreimageStore initializes the store for caching preimages. 48 func newPreimageStore(disk ethdb.KeyValueStore) *preimageStore { 49 return &preimageStore{ 50 disk: disk, 51 preimages: make(map[common.Hash][]byte), 52 } 53 } 54 55 // insertPreimage writes a new trie node pre-image to the memory database if it's 56 // yet unknown. The method will NOT make a copy of the slice, only use if the 57 // preimage will NOT be changed later on. 58 func (store *preimageStore) insertPreimage(preimages map[common.Hash][]byte) { 59 store.lock.Lock() 60 defer store.lock.Unlock() 61 62 for hash, preimage := range preimages { 63 if _, ok := store.preimages[hash]; ok { 64 continue 65 } 66 store.preimages[hash] = preimage 67 store.preimagesSize += common.StorageSize(common.HashLength + len(preimage)) 68 } 69 } 70 71 // preimage retrieves a cached trie node pre-image from memory. If it cannot be 72 // found cached, the method queries the persistent database for the content. 73 func (store *preimageStore) preimage(hash common.Hash) []byte { 74 store.lock.RLock() 75 preimage := store.preimages[hash] 76 store.lock.RUnlock() 77 78 if preimage != nil { 79 return preimage 80 } 81 return rawdb.ReadPreimage(store.disk, hash) 82 } 83 84 // commit flushes the cached preimages into the disk. 85 func (store *preimageStore) commit(force bool) error { 86 store.lock.Lock() 87 defer store.lock.Unlock() 88 89 if store.preimagesSize <= defaultPreimagesLimit && !force { 90 return nil 91 } 92 batch := store.disk.NewBatch() 93 rawdb.WritePreimages(batch, store.preimages) 94 if err := batch.Write(); err != nil { 95 return err 96 } 97 store.preimages, store.preimagesSize = make(map[common.Hash][]byte), 0 98 return nil 99 } 100 101 // size returns the current storage size of accumulated preimages. 102 func (store *preimageStore) size() common.StorageSize { 103 store.lock.RLock() 104 defer store.lock.RUnlock() 105 106 return store.preimagesSize 107 }