github.com/lbryio/lbcd@v0.22.119/claimtrie/merkletrie/merkletrie.go (about)

     1  package merkletrie
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"runtime"
     7  	"sort"
     8  	"sync"
     9  
    10  	"github.com/pkg/errors"
    11  
    12  	"github.com/lbryio/lbcd/chaincfg/chainhash"
    13  	"github.com/lbryio/lbcd/claimtrie/node"
    14  )
    15  
    16  var (
    17  	// EmptyTrieHash represents the Merkle Hash of an empty PersistentTrie.
    18  	// "0000000000000000000000000000000000000000000000000000000000000001"
    19  	EmptyTrieHash  = &chainhash.Hash{1}
    20  	NoChildrenHash = &chainhash.Hash{2}
    21  	NoClaimsHash   = &chainhash.Hash{3}
    22  )
    23  
    24  // PersistentTrie implements a 256-way prefix tree.
    25  type PersistentTrie struct {
    26  	repo Repo
    27  
    28  	root *vertex
    29  	bufs *sync.Pool
    30  }
    31  
    32  // NewPersistentTrie returns a PersistentTrie.
    33  func NewPersistentTrie(repo Repo) *PersistentTrie {
    34  
    35  	tr := &PersistentTrie{
    36  		repo: repo,
    37  		bufs: &sync.Pool{
    38  			New: func() interface{} {
    39  				return new(bytes.Buffer)
    40  			},
    41  		},
    42  		root: newVertex(EmptyTrieHash),
    43  	}
    44  
    45  	return tr
    46  }
    47  
    48  // SetRoot drops all resolved nodes in the PersistentTrie, and set the Root with specified hash.
    49  func (t *PersistentTrie) SetRoot(h *chainhash.Hash) error {
    50  	t.root = newVertex(h)
    51  	runtime.GC()
    52  	return nil
    53  }
    54  
    55  // Update updates the nodes along the path to the key.
    56  // Each node is resolved or created with their Hash cleared.
    57  func (t *PersistentTrie) Update(name []byte, hash *chainhash.Hash, restoreChildren bool) {
    58  
    59  	n := t.root
    60  	for i, ch := range name {
    61  		if restoreChildren && len(n.childLinks) == 0 {
    62  			t.resolveChildLinks(n, name[:i])
    63  		}
    64  		if n.childLinks[ch] == nil {
    65  			n.childLinks[ch] = newVertex(nil)
    66  		}
    67  		n.merkleHash = nil
    68  		n = n.childLinks[ch]
    69  	}
    70  
    71  	if restoreChildren && len(n.childLinks) == 0 {
    72  		t.resolveChildLinks(n, name)
    73  	}
    74  	n.merkleHash = nil
    75  	n.claimsHash = hash
    76  }
    77  
    78  // resolveChildLinks updates the links on n
    79  func (t *PersistentTrie) resolveChildLinks(n *vertex, key []byte) {
    80  
    81  	if n.merkleHash == nil {
    82  		return
    83  	}
    84  
    85  	b := t.bufs.Get().(*bytes.Buffer)
    86  	defer t.bufs.Put(b)
    87  	b.Reset()
    88  	b.Write(key)
    89  	b.Write(n.merkleHash[:])
    90  
    91  	result, closer, err := t.repo.Get(b.Bytes())
    92  	if result == nil {
    93  		return
    94  	} else if err != nil {
    95  		panic(err)
    96  	}
    97  	defer closer.Close()
    98  
    99  	nb := nbuf(result)
   100  	_, n.claimsHash = nb.hasValue()
   101  	for i := 0; i < nb.entries(); i++ {
   102  		p, h := nb.entry(i)
   103  		n.childLinks[p] = newVertex(h)
   104  	}
   105  }
   106  
   107  // MerkleHash returns the Merkle Hash of the PersistentTrie.
   108  // All nodes must have been resolved before calling this function.
   109  func (t *PersistentTrie) MerkleHash() *chainhash.Hash {
   110  	buf := make([]byte, 0, 256)
   111  	if h := t.merkle(buf, t.root); h == nil {
   112  		return EmptyTrieHash
   113  	}
   114  	return t.root.merkleHash
   115  }
   116  
   117  // merkle recursively resolves the hashes of the node.
   118  // All nodes must have been resolved before calling this function.
   119  func (t *PersistentTrie) merkle(prefix []byte, v *vertex) *chainhash.Hash {
   120  	if v.merkleHash != nil {
   121  		return v.merkleHash
   122  	}
   123  
   124  	b := t.bufs.Get().(*bytes.Buffer)
   125  	defer t.bufs.Put(b)
   126  	b.Reset()
   127  
   128  	keys := keysInOrder(v)
   129  
   130  	for _, ch := range keys {
   131  		child := v.childLinks[ch]
   132  		if child == nil {
   133  			continue
   134  		}
   135  		p := append(prefix, ch)
   136  		h := t.merkle(p, child)
   137  		if h != nil {
   138  			b.WriteByte(ch) // nolint : errchk
   139  			b.Write(h[:])   // nolint : errchk
   140  		}
   141  		if h == nil || len(prefix) > 4 { // TODO: determine the right number here
   142  			delete(v.childLinks, ch) // keep the RAM down (they get recreated on Update)
   143  		}
   144  	}
   145  
   146  	if v.claimsHash != nil {
   147  		b.Write(v.claimsHash[:])
   148  	}
   149  
   150  	if b.Len() > 0 {
   151  		h := chainhash.DoubleHashH(b.Bytes())
   152  		v.merkleHash = &h
   153  		t.repo.Set(append(prefix, h[:]...), b.Bytes())
   154  	}
   155  
   156  	return v.merkleHash
   157  }
   158  
   159  func keysInOrder(v *vertex) []byte {
   160  	keys := make([]byte, 0, len(v.childLinks))
   161  	for key := range v.childLinks {
   162  		keys = append(keys, key)
   163  	}
   164  	sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
   165  	return keys
   166  }
   167  
   168  func (t *PersistentTrie) MerkleHashAllClaims() *chainhash.Hash {
   169  	buf := make([]byte, 0, 256)
   170  	if h := t.merkleAllClaims(buf, t.root); h == nil {
   171  		return EmptyTrieHash
   172  	}
   173  	return t.root.merkleHash
   174  }
   175  
   176  func (t *PersistentTrie) merkleAllClaims(prefix []byte, v *vertex) *chainhash.Hash {
   177  	if v.merkleHash != nil {
   178  		return v.merkleHash
   179  	}
   180  	b := t.bufs.Get().(*bytes.Buffer)
   181  	defer t.bufs.Put(b)
   182  	b.Reset()
   183  
   184  	keys := keysInOrder(v)
   185  	childHashes := make([]*chainhash.Hash, 0, len(keys))
   186  	for _, ch := range keys {
   187  		n := v.childLinks[ch]
   188  		if n == nil {
   189  			continue
   190  		}
   191  		p := append(prefix, ch)
   192  		h := t.merkleAllClaims(p, n)
   193  		if h != nil {
   194  			childHashes = append(childHashes, h)
   195  			b.WriteByte(ch) // nolint : errchk
   196  			b.Write(h[:])   // nolint : errchk
   197  		}
   198  		if h == nil || len(prefix) > 4 { // TODO: determine the right number here
   199  			delete(v.childLinks, ch) // keep the RAM down (they get recreated on Update)
   200  		}
   201  	}
   202  
   203  	if len(childHashes) > 1 || v.claimsHash != nil { // yeah, about that 1 there -- old code used the condensed trie
   204  		left := NoChildrenHash
   205  		if len(childHashes) > 0 {
   206  			left = node.ComputeMerkleRoot(childHashes)
   207  		}
   208  		right := NoClaimsHash
   209  		if v.claimsHash != nil {
   210  			b.Write(v.claimsHash[:]) // for Has Value, nolint : errchk
   211  			right = v.claimsHash
   212  		}
   213  
   214  		h := node.HashMerkleBranches(left, right)
   215  		v.merkleHash = h
   216  		t.repo.Set(append(prefix, h[:]...), b.Bytes())
   217  	} else if len(childHashes) == 1 {
   218  		v.merkleHash = childHashes[0] // pass it up the tree
   219  		t.repo.Set(append(prefix, v.merkleHash[:]...), b.Bytes())
   220  	}
   221  
   222  	return v.merkleHash
   223  }
   224  
   225  func (t *PersistentTrie) Close() error {
   226  	return errors.WithStack(t.repo.Close())
   227  }
   228  
   229  func (t *PersistentTrie) Dump(s string) {
   230  	// TODO: this function is in the wrong spot; either it goes with its caller or it needs to be a generic iterator
   231  	// we don't want fmt used in here either way
   232  
   233  	v := t.root
   234  
   235  	for i := 0; i < len(s); i++ {
   236  		t.resolveChildLinks(v, []byte(s[:i]))
   237  		ch := s[i]
   238  		v = v.childLinks[ch]
   239  		if v == nil {
   240  			fmt.Printf("Missing child at %s\n", s[:i+1])
   241  			return
   242  		}
   243  	}
   244  	t.resolveChildLinks(v, []byte(s))
   245  
   246  	fmt.Printf("Node hash: %s, has value: %t\n", v.merkleHash.String(), v.claimsHash != nil)
   247  
   248  	for key, value := range v.childLinks {
   249  		fmt.Printf("  Child %s hash: %s\n", string(key), value.merkleHash.String())
   250  	}
   251  }
   252  
   253  func (t *PersistentTrie) Flush() error {
   254  	return t.repo.Flush()
   255  }