ec641751a8
This commit modifies the BuildMerkleTreeStore function to accept a slice of btcutil.Tx transactions as opposed to a full block. This allows more flexibility when calculating merkle roots since a full block may not be created yet (particularly when generating blocks that need to be solved in mining). Previously, the BuildMerkleTreeStore function accepted a btcutil.Block because originally the block itself cached the transaction hashes and it was necessary to have access to the block to make use of the cached transactions. However, the code has since been improved such that it caches transaction hashes directly in each btcutil.Tx. This means the code can remain as efficient as before while allowing the individual transacitons to be passed.
108 lines
3.9 KiB
Go
108 lines
3.9 KiB
Go
// Copyright (c) 2013-2014 Conformal Systems LLC.
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package btcchain
|
|
|
|
import (
|
|
"github.com/conformal/btcutil"
|
|
"github.com/conformal/btcwire"
|
|
"math"
|
|
)
|
|
|
|
// nextPowerOfTwo returns the next highest power of two from a given number if
|
|
// it is not already a power of two. This is a helper function used during the
|
|
// calculation of a merkle tree.
|
|
func nextPowerOfTwo(n int) int {
|
|
// Return the number if it's already a power of 2.
|
|
if n&(n-1) == 0 {
|
|
return n
|
|
}
|
|
|
|
// Figure out and return the next power of two.
|
|
exponent := uint(math.Log2(float64(n))) + 1
|
|
return 1 << exponent // 2^exponent
|
|
}
|
|
|
|
// hashMerkleBranches takes two hashes, treated as the left and right tree
|
|
// nodes, and returns the hash of their concatenation. This is a helper
|
|
// function used to during generatation of a merkle tree.
|
|
func hashMerkleBranches(left *btcwire.ShaHash, right *btcwire.ShaHash) *btcwire.ShaHash {
|
|
// Concatenate the left and right nodes.
|
|
var sha [btcwire.HashSize * 2]byte
|
|
copy(sha[:btcwire.HashSize], left.Bytes())
|
|
copy(sha[btcwire.HashSize:], right.Bytes())
|
|
|
|
// Create a new sha hash from the double sha 256. Ignore the error
|
|
// here since SetBytes can't fail here due to the fact DoubleSha256
|
|
// always returns a []byte of the right size regardless of input.
|
|
newSha, _ := btcwire.NewShaHash(btcwire.DoubleSha256(sha[:]))
|
|
return newSha
|
|
}
|
|
|
|
// BuildMerkleTreeStore creates a merkle tree from a slice of transactions,
|
|
// stores it using a linear array, and returns a slice of the backing array. A
|
|
// linear array was chosen as opposed to an actual tree structure since it uses
|
|
// about half as much memory. The following describes a merkle tree and how it
|
|
// is stored in a linear array.
|
|
//
|
|
// A merkle tree is a tree in which every non-leaf node is the hash of its
|
|
// children nodes. A diagram depicting how this works for bitcoin transactions
|
|
// where h(x) is a double sha256 follows:
|
|
//
|
|
// root = h1234 = h(h12 + h34)
|
|
// / \
|
|
// h12 = h(h1 + h2) h34 = h(h3 + h4)
|
|
// / \ / \
|
|
// h1 = h(tx1) h2 = h(tx2) h3 = h(tx3) h4 = h(tx4)
|
|
//
|
|
// The above stored as a linear array is as follows:
|
|
//
|
|
// [h1 h2 h3 h4 h12 h34 root]
|
|
//
|
|
// As the above shows, the merkle root is always the last element in the array.
|
|
//
|
|
// The number of inputs is not always a power of two which results in a
|
|
// balanced tree structure as above. In that case, parent nodes with no
|
|
// children are also zero and parent nodes with only a single left node
|
|
// are calculated by concatenating the left node with itself before hashing.
|
|
// Since this function uses nodes that are pointers to the hashes, empty nodes
|
|
// will be nil.
|
|
func BuildMerkleTreeStore(transactions []*btcutil.Tx) []*btcwire.ShaHash {
|
|
// Calculate how many entries are required to hold the binary merkle
|
|
// tree as a linear array and create an array of that size.
|
|
nextPoT := nextPowerOfTwo(len(transactions))
|
|
arraySize := nextPoT*2 - 1
|
|
merkles := make([]*btcwire.ShaHash, arraySize)
|
|
|
|
// Create the base transaction shas and populate the array with them.
|
|
for i, tx := range transactions {
|
|
merkles[i] = tx.Sha()
|
|
}
|
|
|
|
// Start the array offset after the last transaction and adjusted to the
|
|
// next power of two.
|
|
offset := nextPoT
|
|
for i := 0; i < arraySize-1; i += 2 {
|
|
switch {
|
|
// When there is no left child node, the parent is nil too.
|
|
case merkles[i] == nil:
|
|
merkles[offset] = nil
|
|
|
|
// When there is no right child, the parent is generated by
|
|
// hashing the concatenation of the left child with itself.
|
|
case merkles[i+1] == nil:
|
|
newSha := hashMerkleBranches(merkles[i], merkles[i])
|
|
merkles[offset] = newSha
|
|
|
|
// The normal case sets the parent node to the double sha256
|
|
// of the concatentation of the left and right children.
|
|
default:
|
|
newSha := hashMerkleBranches(merkles[i], merkles[i+1])
|
|
merkles[offset] = newSha
|
|
}
|
|
offset++
|
|
}
|
|
|
|
return merkles
|
|
}
|