github.com/btcsuite/btcd@v0.24.0/blockchain/rolling_merkle.go (about)

     1  package blockchain
     2  
     3  import (
     4  	"math/bits"
     5  
     6  	"github.com/btcsuite/btcd/btcutil"
     7  	"github.com/btcsuite/btcd/chaincfg/chainhash"
     8  )
     9  
    10  // rollingMerkleTreeStore calculates the merkle root by only allocating O(logN)
    11  // memory where N is the total amount of leaves being included in the tree.
    12  type rollingMerkleTreeStore struct {
    13  	// roots are where the temporary merkle roots get stored while the
    14  	// merkle root is being calculated.
    15  	roots []chainhash.Hash
    16  
    17  	// numLeaves is the total leaves the store has processed.  numLeaves
    18  	// is required for the root calculation algorithm to work.
    19  	numLeaves uint64
    20  }
    21  
    22  // newRollingMerkleTreeStore returns a rollingMerkleTreeStore with the roots
    23  // allocated based on the passed in size.
    24  //
    25  // NOTE: If more elements are added in than the passed in size, there will be
    26  // additional allocations which in turn hurts performance.
    27  func newRollingMerkleTreeStore(size uint64) rollingMerkleTreeStore {
    28  	var alloc int
    29  	if size != 0 {
    30  		alloc = bits.Len64(size - 1)
    31  	}
    32  	return rollingMerkleTreeStore{roots: make([]chainhash.Hash, 0, alloc)}
    33  }
    34  
    35  // add adds a single hash to the merkle tree store.  Refer to algorithm 1 "AddOne" in
    36  // the utreexo paper (https://eprint.iacr.org/2019/611.pdf) for the exact algorithm.
    37  func (s *rollingMerkleTreeStore) add(add chainhash.Hash) {
    38  	// We can tell where the roots are by looking at the binary representation
    39  	// of the numLeaves.  Wherever there's a 1, there's a root.
    40  	//
    41  	// numLeaves of 8 will be '1000' in binary, so there will be one root at
    42  	// row 3. numLeaves of 3 will be '11' in binary, so there's two roots.  One at
    43  	// row 0 and one at row 1.  Row 0 is the leaf row.
    44  	//
    45  	// In this loop below, we're looking for these roots by checking if there's
    46  	// a '1', starting from the LSB.  If there is a '1', we'll hash the root being
    47  	// added with that root until we hit a '0'.
    48  	newRoot := add
    49  	for h := uint8(0); (s.numLeaves>>h)&1 == 1; h++ {
    50  		// Pop off the last root.
    51  		var root chainhash.Hash
    52  		root, s.roots = s.roots[len(s.roots)-1], s.roots[:len(s.roots)-1]
    53  
    54  		// Calculate the hash of the new root and append it.
    55  		newRoot = HashMerkleBranches(&root, &newRoot)
    56  	}
    57  	s.roots = append(s.roots, newRoot)
    58  	s.numLeaves++
    59  }
    60  
    61  // calcMerkleRoot returns the merkle root for the passed in transactions.
    62  func (s *rollingMerkleTreeStore) calcMerkleRoot(adds []*btcutil.Tx, witness bool) chainhash.Hash {
    63  	for i := range adds {
    64  		// If we're computing a witness merkle root, instead of the
    65  		// regular txid, we use the modified wtxid which includes a
    66  		// transaction's witness data within the digest.  Additionally,
    67  		// the coinbase's wtxid is all zeroes.
    68  		switch {
    69  		case witness && i == 0:
    70  			var zeroHash chainhash.Hash
    71  			s.add(zeroHash)
    72  		case witness:
    73  			s.add(*adds[i].WitnessHash())
    74  		default:
    75  			s.add(*adds[i].Hash())
    76  		}
    77  	}
    78  
    79  	// If we only have one leaf, then the hash of that tx is the merkle root.
    80  	if s.numLeaves == 1 {
    81  		return s.roots[0]
    82  	}
    83  
    84  	// Add on the last tx again if there's an odd number of txs.
    85  	if len(adds) > 0 && len(adds)%2 != 0 {
    86  		switch {
    87  		case witness:
    88  			s.add(*adds[len(adds)-1].WitnessHash())
    89  		default:
    90  			s.add(*adds[len(adds)-1].Hash())
    91  		}
    92  	}
    93  
    94  	// If we still have more than 1 root after adding on the last tx again,
    95  	// we need to do the same for the upper rows.
    96  	//
    97  	// For example, the below tree has 6 leaves.  For row 1, you'll need to
    98  	// hash 'F' with itself to create 'C' so you have something to hash with
    99  	// 'B'.  For bigger trees we may need to do the same in rows 2 or 3 as
   100  	// well.
   101  	//
   102  	// row :3         A
   103  	//              /   \
   104  	// row :2     B       C
   105  	//           / \     / \
   106  	// row :1   D   E   F   F
   107  	//         / \ / \ / \
   108  	// row :0  1 2 3 4 5 6
   109  	for len(s.roots) > 1 {
   110  		// If we have to keep adding the last node in the set, bitshift
   111  		// the num leaves right by 1.  This effectively moves the row up
   112  		// for calculation.  We do this until we reach a row where there's
   113  		// an odd number of leaves.
   114  		//
   115  		// row :3         A
   116  		//              /   \
   117  		// row :2     B       C        D
   118  		//           / \     / \     /   \
   119  		// row :1   E   F   G   H   I     J
   120  		//         / \ / \ / \ / \ / \   / \
   121  		// row :0  1 2 3 4 5 6 7 8 9 10 11 12
   122  		//
   123  		// In the above tree, 12 leaves were added and there's an odd amount
   124  		// of leaves at row 2.  Because of this, we'll bitshift right twice.
   125  		currentLeaves := s.numLeaves
   126  		for h := uint8(0); (currentLeaves>>h)&1 == 0; h++ {
   127  			s.numLeaves >>= 1
   128  		}
   129  
   130  		// Add the last root again so that it'll get hashed with itself.
   131  		h := s.roots[len(s.roots)-1]
   132  		s.add(h)
   133  	}
   134  
   135  	return s.roots[0]
   136  }