Change BuildMerkleTreeStore to accept transactions.
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.
This commit is contained in:
parent
82edb203e5
commit
ec641751a8
3 changed files with 10 additions and 10 deletions
16
merkle.go
16
merkle.go
|
@ -40,11 +40,11 @@ func hashMerkleBranches(left *btcwire.ShaHash, right *btcwire.ShaHash) *btcwire.
|
||||||
return newSha
|
return newSha
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildMerkleTreeStore creates a merkle tree from block, stores it using a
|
// BuildMerkleTreeStore creates a merkle tree from a slice of transactions,
|
||||||
// linear array, and returns a slice of the backing array. A linear array was
|
// stores it using a linear array, and returns a slice of the backing array. A
|
||||||
// chosen as opposed to an actual tree structure since it uses about half as
|
// linear array was chosen as opposed to an actual tree structure since it uses
|
||||||
// much memory. The following describes a merkle tree and how it is stored in
|
// about half as much memory. The following describes a merkle tree and how it
|
||||||
// a linear array.
|
// is stored in a linear array.
|
||||||
//
|
//
|
||||||
// A merkle tree is a tree in which every non-leaf node is the hash of its
|
// 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
|
// children nodes. A diagram depicting how this works for bitcoin transactions
|
||||||
|
@ -68,15 +68,15 @@ func hashMerkleBranches(left *btcwire.ShaHash, right *btcwire.ShaHash) *btcwire.
|
||||||
// are calculated by concatenating the left node with itself before hashing.
|
// are calculated by concatenating the left node with itself before hashing.
|
||||||
// Since this function uses nodes that are pointers to the hashes, empty nodes
|
// Since this function uses nodes that are pointers to the hashes, empty nodes
|
||||||
// will be nil.
|
// will be nil.
|
||||||
func BuildMerkleTreeStore(block *btcutil.Block) []*btcwire.ShaHash {
|
func BuildMerkleTreeStore(transactions []*btcutil.Tx) []*btcwire.ShaHash {
|
||||||
// Calculate how many entries are required to hold the binary merkle
|
// Calculate how many entries are required to hold the binary merkle
|
||||||
// tree as a linear array and create an array of that size.
|
// tree as a linear array and create an array of that size.
|
||||||
nextPoT := nextPowerOfTwo(len(block.Transactions()))
|
nextPoT := nextPowerOfTwo(len(transactions))
|
||||||
arraySize := nextPoT*2 - 1
|
arraySize := nextPoT*2 - 1
|
||||||
merkles := make([]*btcwire.ShaHash, arraySize)
|
merkles := make([]*btcwire.ShaHash, arraySize)
|
||||||
|
|
||||||
// Create the base transaction shas and populate the array with them.
|
// Create the base transaction shas and populate the array with them.
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range transactions {
|
||||||
merkles[i] = tx.Sha()
|
merkles[i] = tx.Sha()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
// TestMerkle tests the BuildMerkleTreeStore API.
|
// TestMerkle tests the BuildMerkleTreeStore API.
|
||||||
func TestMerkle(t *testing.T) {
|
func TestMerkle(t *testing.T) {
|
||||||
block := btcutil.NewBlock(&Block100000)
|
block := btcutil.NewBlock(&Block100000)
|
||||||
merkles := btcchain.BuildMerkleTreeStore(block)
|
merkles := btcchain.BuildMerkleTreeStore(block.Transactions())
|
||||||
calculatedMerkleRoot := merkles[len(merkles)-1]
|
calculatedMerkleRoot := merkles[len(merkles)-1]
|
||||||
wantMerkle := &Block100000.Header.MerkleRoot
|
wantMerkle := &Block100000.Header.MerkleRoot
|
||||||
if !wantMerkle.IsEqual(calculatedMerkleRoot) {
|
if !wantMerkle.IsEqual(calculatedMerkleRoot) {
|
||||||
|
|
|
@ -453,7 +453,7 @@ func CheckBlockSanity(block *btcutil.Block, powLimit *big.Int) error {
|
||||||
// checks. Bitcoind builds the tree here and checks the merkle root
|
// checks. Bitcoind builds the tree here and checks the merkle root
|
||||||
// after the following checks, but there is no reason not to check the
|
// after the following checks, but there is no reason not to check the
|
||||||
// merkle root matches here.
|
// merkle root matches here.
|
||||||
merkles := BuildMerkleTreeStore(block)
|
merkles := BuildMerkleTreeStore(block.Transactions())
|
||||||
calculatedMerkleRoot := merkles[len(merkles)-1]
|
calculatedMerkleRoot := merkles[len(merkles)-1]
|
||||||
if !header.MerkleRoot.IsEqual(calculatedMerkleRoot) {
|
if !header.MerkleRoot.IsEqual(calculatedMerkleRoot) {
|
||||||
str := fmt.Sprintf("block merkle root is invalid - block "+
|
str := fmt.Sprintf("block merkle root is invalid - block "+
|
||||||
|
|
Loading…
Reference in a new issue