github.com/koko1123/flow-go-1@v0.29.6/storage/merkle/node.go (about)

     1  // (c) 2019 Dapper Labs - ALL RIGHTS RESERVED
     2  
     3  package merkle
     4  
     5  import (
     6  	"golang.org/x/crypto/blake2b"
     7  )
     8  
     9  // The node represents a generic vertex in the sparse Merkle trie.
    10  // CONVENTION:
    11  //   - This implementation guarantees that within the trie there are
    12  //     _never_ nil-references to descendants. We completely avoid this by
    13  //     utilizing `short nodes` that represent any path-segment without branching.
    14  type node interface {
    15  	// Hash computes recursively the hash of this respective sub trie.
    16  	// To simplify enforcing cryptographic security, we introduce the convention
    17  	// that hashing a nil node is an illegal operation, which panics.
    18  	// If cacheEnabled is set the node stores the computed hash value for future
    19  	// calls to the Hash function. Note that the cached value is only returned
    20  	// when cacheEnabled is also set for the future calls.
    21  	Hash(cacheEnabled bool) []byte
    22  
    23  	// MaxDepthOfDescendants returns the length of the longest path from this node to any of the decedent leaf nodes,
    24  	// i.e. it returns the maximum depth of the subtree under this node.
    25  	MaxDepthOfDescendants() uint
    26  }
    27  
    28  // NodeTags encodes the type of node when hashing it. Required for cryptographic
    29  // safety to prevent collision attacks (replacing a full node with a short node
    30  // that has identical hash would otherwise be possible).
    31  // Values are intended to be global constants and must be unique.
    32  var (
    33  	leafNodeTag  = []byte{0}
    34  	fullNodeTag  = []byte{1}
    35  	shortNodeTag = []byte{2}
    36  )
    37  
    38  // Short Node
    39  // Per convention a Short node has always _one child_, which is either
    40  // a full node or a leaf.
    41  
    42  type short struct {
    43  	count           int    // holds the count of bits in the path
    44  	path            []byte // holds the common path to the next node
    45  	child           node   // holds the child after the common path; never nil
    46  	cachedHashValue []byte // cached hash value
    47  }
    48  
    49  var _ node = &short{}
    50  
    51  func computeShortHash(count int, path []byte, childHash []byte) []byte {
    52  	c := serializedPathSegmentLength(count)
    53  	h, _ := blake2b.New256(shortNodeTag) // blake2b.New256(..) never errors for given MAC (verified in tests)
    54  	_, _ = h.Write(c[:])                 // blake2b.Write(..) never errors for _any_ input
    55  	_, _ = h.Write(path)                 // blake2b.Write(..) never errors for _any_ input
    56  	_, _ = h.Write(childHash)            // blake2b.Write(..) never errors for _any_ input
    57  	return h.Sum(nil)
    58  }
    59  
    60  func (n *short) Hash(cacheEnabled bool) []byte {
    61  	if !cacheEnabled {
    62  		return computeShortHash(n.count, n.path, n.child.Hash(cacheEnabled))
    63  	}
    64  	if len(n.cachedHashValue) == 0 {
    65  		n.cachedHashValue = computeShortHash(n.count, n.path, n.child.Hash(cacheEnabled))
    66  	}
    67  	return n.cachedHashValue
    68  }
    69  
    70  func (n *short) MaxDepthOfDescendants() uint {
    71  	return n.child.MaxDepthOfDescendants() + 1
    72  }
    73  
    74  // serializedPathSegmentLength serializes the bitCount into two bytes.
    75  // We are able to represent key length of up to 65528 bits
    76  func serializedPathSegmentLength(bitCount int) [2]byte {
    77  	var byteCount [2]byte
    78  	byteCount[0] = byte(bitCount >> 8)
    79  	byteCount[1] = byte(bitCount)
    80  	return byteCount
    81  }
    82  
    83  //Full Node
    84  // Per convention a Full Node has always _two children_. Nil values not allowed.
    85  
    86  type full struct {
    87  	left            node   // holds the left path node (bit 0); never nil
    88  	right           node   // holds the right path node (bit 1); never nil
    89  	cachedHashValue []byte // cached hash value
    90  }
    91  
    92  var _ node = &full{}
    93  
    94  func computeFullHash(leftChildHash, rightChildHash []byte) []byte {
    95  	h, _ := blake2b.New256(fullNodeTag) // blake2b.New256(..) never errors for given MAC (verified in tests)
    96  	_, _ = h.Write(leftChildHash)       // blake2b.Write(..) never errors for _any_ input
    97  	_, _ = h.Write(rightChildHash)      // blake2b.Write(..) never errors for _any_ input
    98  	return h.Sum(nil)
    99  }
   100  
   101  func (n *full) Hash(cacheEnabled bool) []byte {
   102  	if !cacheEnabled {
   103  		return computeFullHash(n.left.Hash(cacheEnabled), n.right.Hash(cacheEnabled))
   104  	}
   105  	if len(n.cachedHashValue) == 0 {
   106  		n.cachedHashValue = computeFullHash(n.left.Hash(cacheEnabled), n.right.Hash(cacheEnabled))
   107  	}
   108  	return n.cachedHashValue
   109  }
   110  
   111  func (n *full) MaxDepthOfDescendants() uint {
   112  	left := n.left.MaxDepthOfDescendants()
   113  	right := n.right.MaxDepthOfDescendants()
   114  	if left < right {
   115  		return right + 1
   116  	}
   117  	return left + 1
   118  }
   119  
   120  // Leaf Node
   121  // Leaf represents a key-value pair. We only store the value, because the
   122  // key is implicitly stored as the merkle path through the tree.
   123  
   124  type leaf struct {
   125  	val             []byte
   126  	cachedHashValue []byte // cached hash value
   127  }
   128  
   129  var _ node = &leaf{}
   130  
   131  func computeLeafHash(value []byte) []byte {
   132  	h, _ := blake2b.New256(leafNodeTag) // blake2b.New256(..) never errors for given MAC (verified in tests)
   133  	_, _ = h.Write(value)               // blake2b.Write(..) never errors for _any_ input
   134  	return h.Sum(nil)
   135  }
   136  
   137  func (n *leaf) Hash(cacheEnabled bool) []byte {
   138  	if !cacheEnabled {
   139  		return computeLeafHash(n.val)
   140  	}
   141  	if len(n.cachedHashValue) == 0 {
   142  		n.cachedHashValue = computeLeafHash(n.val)
   143  	}
   144  	return n.cachedHashValue
   145  }
   146  
   147  func (n *leaf) MaxDepthOfDescendants() uint {
   148  	return 0
   149  }
   150  
   151  // Dummy Node
   152  // Dummy node type as substitute for `nil`. Not used in the trie, but as zero
   153  // value for auxiliary variables during trie update operations. This reduces
   154  // complexity of the business logic, as we can then also apply the convention of
   155  // "nodes are never nil" to the auxiliary variables.
   156  
   157  type dummy struct{}
   158  
   159  var _ node = &dummy{}
   160  
   161  func (n *dummy) Hash(_ bool) []byte {
   162  	// Per convention, Hash should never be called by the business logic but
   163  	// is required to implement the node interface
   164  	panic("dummy node has no hash")
   165  }
   166  
   167  func (n *dummy) MaxDepthOfDescendants() uint {
   168  	return 0
   169  }