-
Notifications
You must be signed in to change notification settings - Fork 10
/
merkleroot.go
179 lines (158 loc) · 5.93 KB
/
merkleroot.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package bc
import (
"encoding/hex"
"fmt"
"math"
"github.com/libsv/go-bk/crypto"
"github.com/libsv/go-bt/v2"
"github.com/libsv/go-p2p/chaincfg/chainhash"
)
// TxsToTxIDs takes an array of transactions
// and returns instead an array of their
// corresponding transaction IDs.
func TxsToTxIDs(txs []string) ([]string, error) {
txids := make([]string, 0, len(txs))
for i, tx := range txs {
t, err := bt.NewTxFromString(tx)
if err != nil {
return nil, fmt.Errorf("invalid transaction at index: %q", i)
}
txids = append(txids, t.TxID())
}
return txids, nil
}
// BuildMerkleRootFromCoinbase builds the merkle root of the block from the coinbase transaction hash (txid)
// and the merkle branches needed to work up the merkle tree and returns the merkle root byte array.
func BuildMerkleRootFromCoinbase(coinbaseHash []byte, merkleBranches []string) []byte {
acc := coinbaseHash
for i := 0; i < len(merkleBranches); i++ {
branch, _ := hex.DecodeString(merkleBranches[i])
concat := append(acc, branch...)
hash := crypto.Sha256d(concat)
acc = hash[:]
}
return acc
}
// BuildMerkleRoot builds the Merkle Root
// from a list of transactions.
func BuildMerkleRoot(txids []string) (string, error) {
merkles, err := BuildMerkleTreeStore(txids)
if err != nil {
return "", err
}
return merkles[len(merkles)-1], nil
}
// BuildMerkleTreeStore creates a merkle tree from a slice of transaction IDs,
// 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.
//
// The additional bool parameter indicates if we are generating the merkle tree
// using witness transaction id's rather than regular transaction id's. This
// also presents an additional case wherein the wtxid of the coinbase transaction
// is the zeroHash.
//
// based off of bsvd:
// https://github.com/bitcoinsv/bsvd/blob/4c29707f717300d3eb92352081c3b0fec556881b/blockchain/merkle.go#L74
func BuildMerkleTreeStore(txids []string) ([]string, error) {
// // Calculate how many entries are re?n array of that size.
nextPoT := nextPowerOfTwo(len(txids))
arraySize := nextPoT*2 - 1
merkles := make([]string, arraySize)
// Create the base transaction hashes and populate the array with them.
copy(merkles, txids)
// 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] == "":
merkles[offset] = ""
// When there is no right child, the parent is generated by
// hashing the concatenation of the left child with itself.
case merkles[i+1] == "":
newHash, err := MerkleTreeParentStr(merkles[i], merkles[i])
if err != nil {
return nil, err
}
merkles[offset] = newHash
// The normal case sets the parent node to the double sha256
// of the concatenation of the left and right children.
default:
// newHash := HashMerkleBranches(merkles[i], merkles[i+1])
newHash, err := MerkleTreeParentStr(merkles[i], merkles[i+1])
if err != nil {
return nil, err
}
merkles[offset] = newHash
}
offset++
}
return merkles, nil
}
// BuildMerkleTreeStoreChainHash has the same functionality as BuildMerkleTreeStore but uses chainhash as a type to avoid string conversions.
func BuildMerkleTreeStoreChainHash(txids []*chainhash.Hash) []*chainhash.Hash {
// // Calculate how many entries are re?n array of that size.
nextPoT := nextPowerOfTwo(len(txids))
arraySize := nextPoT*2 - 1
merkles := make([]*chainhash.Hash, arraySize)
// Create the base transaction hashes and populate the array with them.
copy(merkles, txids)
// 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].IsEqual(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].IsEqual(nil):
merkles[offset] = MerkleTreeParentBytes(merkles[i], merkles[i])
// The normal case sets the parent node to the double sha256
// of the concatenation of the left and right children.
default:
merkles[offset] = MerkleTreeParentBytes(merkles[i], merkles[i+1])
}
offset++
}
return merkles
}
// 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
}