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 }