github.com/theQRL/go-zond@v0.1.1/trie/triedb/pathdb/layertree.go (about) 1 // Copyright 2022 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/> 16 17 package pathdb 18 19 import ( 20 "errors" 21 "fmt" 22 "sync" 23 24 "github.com/theQRL/go-zond/common" 25 "github.com/theQRL/go-zond/core/types" 26 "github.com/theQRL/go-zond/trie/trienode" 27 "github.com/theQRL/go-zond/trie/triestate" 28 ) 29 30 // layerTree is a group of state layers identified by the state root. 31 // This structure defines a few basic operations for manipulating 32 // state layers linked with each other in a tree structure. It's 33 // thread-safe to use. However, callers need to ensure the thread-safety 34 // of the referenced layer by themselves. 35 type layerTree struct { 36 lock sync.RWMutex 37 layers map[common.Hash]layer 38 } 39 40 // newLayerTree constructs the layerTree with the given head layer. 41 func newLayerTree(head layer) *layerTree { 42 tree := new(layerTree) 43 tree.reset(head) 44 return tree 45 } 46 47 // reset initializes the layerTree by the given head layer. 48 // All the ancestors will be iterated out and linked in the tree. 49 func (tree *layerTree) reset(head layer) { 50 tree.lock.Lock() 51 defer tree.lock.Unlock() 52 53 var layers = make(map[common.Hash]layer) 54 for head != nil { 55 layers[head.rootHash()] = head 56 head = head.parentLayer() 57 } 58 tree.layers = layers 59 } 60 61 // get retrieves a layer belonging to the given state root. 62 func (tree *layerTree) get(root common.Hash) layer { 63 tree.lock.RLock() 64 defer tree.lock.RUnlock() 65 66 return tree.layers[types.TrieRootHash(root)] 67 } 68 69 // forEach iterates the stored layers inside and applies the 70 // given callback on them. 71 func (tree *layerTree) forEach(onLayer func(layer)) { 72 tree.lock.RLock() 73 defer tree.lock.RUnlock() 74 75 for _, layer := range tree.layers { 76 onLayer(layer) 77 } 78 } 79 80 // len returns the number of layers cached. 81 func (tree *layerTree) len() int { 82 tree.lock.RLock() 83 defer tree.lock.RUnlock() 84 85 return len(tree.layers) 86 } 87 88 // add inserts a new layer into the tree if it can be linked to an existing old parent. 89 func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error { 90 // Reject noop updates to avoid self-loops. This is a special case that can 91 // happen for clique networks and proof-of-stake networks where empty blocks 92 // don't modify the state (0 block subsidy). 93 // 94 // Although we could silently ignore this internally, it should be the caller's 95 // responsibility to avoid even attempting to insert such a layer. 96 root, parentRoot = types.TrieRootHash(root), types.TrieRootHash(parentRoot) 97 if root == parentRoot { 98 return errors.New("layer cycle") 99 } 100 parent := tree.get(parentRoot) 101 if parent == nil { 102 return fmt.Errorf("triedb parent [%#x] layer missing", parentRoot) 103 } 104 l := parent.update(root, parent.stateID()+1, block, nodes.Flatten(), states) 105 106 tree.lock.Lock() 107 tree.layers[l.rootHash()] = l 108 tree.lock.Unlock() 109 return nil 110 } 111 112 // cap traverses downwards the diff tree until the number of allowed diff layers 113 // are crossed. All diffs beyond the permitted number are flattened downwards. 114 func (tree *layerTree) cap(root common.Hash, layers int) error { 115 // Retrieve the head layer to cap from 116 root = types.TrieRootHash(root) 117 l := tree.get(root) 118 if l == nil { 119 return fmt.Errorf("triedb layer [%#x] missing", root) 120 } 121 diff, ok := l.(*diffLayer) 122 if !ok { 123 return fmt.Errorf("triedb layer [%#x] is disk layer", root) 124 } 125 tree.lock.Lock() 126 defer tree.lock.Unlock() 127 128 // If full commit was requested, flatten the diffs and merge onto disk 129 if layers == 0 { 130 base, err := diff.persist(true) 131 if err != nil { 132 return err 133 } 134 // Replace the entire layer tree with the flat base 135 tree.layers = map[common.Hash]layer{base.rootHash(): base} 136 return nil 137 } 138 // Dive until we run out of layers or reach the persistent database 139 for i := 0; i < layers-1; i++ { 140 // If we still have diff layers below, continue down 141 if parent, ok := diff.parentLayer().(*diffLayer); ok { 142 diff = parent 143 } else { 144 // Diff stack too shallow, return without modifications 145 return nil 146 } 147 } 148 // We're out of layers, flatten anything below, stopping if it's the disk or if 149 // the memory limit is not yet exceeded. 150 switch parent := diff.parentLayer().(type) { 151 case *diskLayer: 152 return nil 153 154 case *diffLayer: 155 // Hold the lock to prevent any read operations until the new 156 // parent is linked correctly. 157 diff.lock.Lock() 158 159 base, err := parent.persist(false) 160 if err != nil { 161 diff.lock.Unlock() 162 return err 163 } 164 tree.layers[base.rootHash()] = base 165 diff.parent = base 166 167 diff.lock.Unlock() 168 169 default: 170 panic(fmt.Sprintf("unknown data layer in triedb: %T", parent)) 171 } 172 // Remove any layer that is stale or links into a stale layer 173 children := make(map[common.Hash][]common.Hash) 174 for root, layer := range tree.layers { 175 if dl, ok := layer.(*diffLayer); ok { 176 parent := dl.parentLayer().rootHash() 177 children[parent] = append(children[parent], root) 178 } 179 } 180 var remove func(root common.Hash) 181 remove = func(root common.Hash) { 182 delete(tree.layers, root) 183 for _, child := range children[root] { 184 remove(child) 185 } 186 delete(children, root) 187 } 188 for root, layer := range tree.layers { 189 if dl, ok := layer.(*diskLayer); ok && dl.isStale() { 190 remove(root) 191 } 192 } 193 return nil 194 } 195 196 // bottom returns the bottom-most disk layer in this tree. 197 func (tree *layerTree) bottom() *diskLayer { 198 tree.lock.RLock() 199 defer tree.lock.RUnlock() 200 201 if len(tree.layers) == 0 { 202 return nil // Shouldn't happen, empty tree 203 } 204 // pick a random one as the entry point 205 var current layer 206 for _, layer := range tree.layers { 207 current = layer 208 break 209 } 210 for current.parentLayer() != nil { 211 current = current.parentLayer() 212 } 213 return current.(*diskLayer) 214 }