-
Notifications
You must be signed in to change notification settings - Fork 10
/
merklebranches.go
94 lines (69 loc) · 1.85 KB
/
merklebranches.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
package bc
import (
"encoding/hex"
"fmt"
"github.com/libsv/go-bk/crypto"
"github.com/libsv/go-bt/v2"
)
func getHashes(txHashes []string) []string {
hashes := make([]string, 0, len(txHashes))
for i, tx := range txHashes {
hashes[i] = ReverseHexString(tx)
}
return hashes
}
// GetMerkleBranches comment.
func GetMerkleBranches(template []string) []string {
hashes := getHashes(template)
var branches []string
var walkBranch func(hashes []string) []string
walkBranch = func(hashes []string) []string {
var results []string
tot := len(hashes)
if len(hashes) < 2 {
return make([]string, 0)
}
branches = append(branches, hashes[1])
for i := 0; i < tot; i += 2 {
var a, _ = hex.DecodeString(hashes[i])
var b []byte
if (i + 1) < tot {
b, _ = hex.DecodeString(hashes[i+1])
} else {
b = a
}
concat := append(a, b...)
hash := crypto.Sha256d(concat)
results = append(results, hex.EncodeToString(hash[:]))
}
return walkBranch(results)
}
walkBranch(hashes)
return branches
}
// MerkleRootFromBranches returns a Merkle root given a transaction hash (txid), the index in
// which it is positioned in the Merkle tree, and the branches needed along the way (Merkle path).
func MerkleRootFromBranches(txHash string, txIndex int, branches []string) (string, error) {
hash, err := hex.DecodeString(txHash)
if err != nil {
return "", err
}
hash = bt.ReverseBytes(hash)
for _, b := range branches {
h, err := hex.DecodeString(b)
if err != nil {
return "", err
}
h = bt.ReverseBytes(h)
if txIndex&1 > 0 {
hash = crypto.Sha256d(append(h, hash...))
} else {
hash = crypto.Sha256d(append(hash, h...))
}
txIndex >>= 1
}
if txIndex > 0 {
return "", fmt.Errorf("index %d out of range for proof of length %d", txIndex, len(branches))
}
return hex.EncodeToString(bt.ReverseBytes(hash)), nil
}