-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.go
71 lines (57 loc) · 1.39 KB
/
util.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
package gomerkle
import (
"hash"
"math"
)
func sum(h hash.Hash, data ...[]byte) []byte {
h.Reset()
for _, d := range data {
// the Hash interface specifies that Write never returns an error
_, _ = h.Write(d)
}
return h.Sum(nil)
}
// number of data elements should be power of 2
// not suitable for parallel calculations cause using same hash.Hash
func buildSubTree(h hash.Hash, full bool, startIndex int, data [][]byte) *Subtree {
nodes := make([]*Node, len(data))
for i := 0; i < len(data); i++ {
nodes[i] = &Node{
hash: sum(h, data[i]),
firstIndex: startIndex + i,
lastIndex: startIndex + i,
}
}
root := sumNodes(h, full, nodes)[0]
return &Subtree{
root: root,
left: nil,
right: nil,
height: int(math.Log2(float64(len(data)))),
hashF: h,
}
}
func sumNodes(h hash.Hash, full bool, nodes []*Node) []*Node {
if len(nodes) == 1 {
return nodes
}
newNodes := make([]*Node, len(nodes)/2)
for i := 0; i < len(nodes); i += 2 {
newNodes[i/2] = joinNodes(h, full, nodes[i], nodes[i+1])
}
return sumNodes(h, full, newNodes)
}
func joinNodes(h hash.Hash, full bool, left *Node, right *Node) *Node {
newNode := &Node{
firstIndex: left.firstIndex,
lastIndex: right.lastIndex,
hash: sum(h, left.hash, right.hash),
}
if full {
newNode.left = left
newNode.right = right
left.parent = newNode
right.parent = newNode
}
return newNode
}