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  }