-
Notifications
You must be signed in to change notification settings - Fork 0
/
proof.go
97 lines (83 loc) · 2.08 KB
/
proof.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
package fastmerkle
import "bytes"
type Proof struct {
pre []subRoot
leaf []byte
post []subRoot
}
type subRoot struct {
i int
subr []byte
}
func (tree *MerkleTree) limit(stream [][]byte, n int) [][]byte {
r := make([][]byte, 0)
for _, s := range stream {
if n == 0 {
break
}
r = append(r, []byte(s))
n--
}
return r
}
func (tree *MerkleTree) subroot(stream [][]byte, k int) []byte {
return tree.Root(tree.limit(stream, 1<<k))
}
func (tree *MerkleTree) readLeaf(stream [][]byte) []byte {
if len(stream) == 0 {
return nil
}
return tree.leafHash(stream[0])
}
func (tree *MerkleTree) stringToByteSlice(s string) []byte {
return []byte(s)
}
func (tree *MerkleTree) bitTest(i int, n int) bool {
return (i & (1 << n)) != 0
}
func (tree *MerkleTree) ones(i int) []int {
r := []int{}
for n := 0; n < 32; n++ {
if tree.bitTest(i, n) {
r = append(r, n)
}
}
return r
}
func (tree *MerkleTree) zeros(i int) []int {
r := []int{}
for n := 0; n < 32; n++ {
if !tree.bitTest(i, n) {
r = append(r, n)
}
}
return r
}
func (tree *MerkleTree) proveLeaf(stream [][]byte, index int) *Proof {
pre := make([]subRoot, 0, len(tree.ones(index)))
for _, k := range tree.ones(index) {
pre = append(pre, subRoot{i: k, subr: tree.subroot(stream, k)})
}
post := make([]subRoot, 0, len(tree.zeros(index)))
for _, k := range tree.zeros(index) {
post = append(post, subRoot{i: k, subr: tree.subroot(stream, k)})
}
return &Proof{pre: pre, leaf: tree.readLeaf(stream), post: post}
}
func (tree *MerkleTree) loadStack(stk map[int][]byte, blks []subRoot) map[int][]byte {
for _, blk := range blks {
stk = tree.insert(stk, blk.subr, blk.i)
}
return stk
}
func (tree *MerkleTree) rootFromProofAndLeaf(leaf []byte, proof *Proof) []byte {
stk := make(map[int][]byte)
stk = tree.loadStack(stk, proof.pre)
stk = tree.insert(stk, leaf, 0)
stk = tree.loadStack(stk, proof.post)
stk = tree.insert(stk, leaf, 0)
return tree.Digest()
}
func (tree *MerkleTree) verifyLeaf(knownroot []byte, leaf []byte, proof *Proof) bool {
return bytes.Equal(knownroot, tree.rootFromProofAndLeaf(leaf, proof))
}