-
Notifications
You must be signed in to change notification settings - Fork 0
/
merkleproof.go
105 lines (85 loc) · 2.47 KB
/
merkleproof.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
package ergo
/*
#include "ergo.h"
*/
import "C"
import (
"runtime"
"unsafe"
)
type nodeSide uint8
const (
// Left represents left side the node is on in the merkle tree
Left nodeSide = 0
// Right represents right side the node is on in the merkle tree
Right nodeSide = 1
)
type MerkleProof interface {
// AddNode adds a new node and it's hash to the MerkleProof. Hash must be 32 bytes in size
AddNode(hash []byte, side nodeSide) error
// Valid validates the MerkleProof against the provided root hash
Valid(expectedRoot []byte) bool
// ValidBase16 validates the MerkleProof against the provided base16 root hash
ValidBase16(expectedRoot string) bool
}
type merkleProof struct {
p C.MerkleProofPtr
}
func newMerkleProof(m *merkleProof) MerkleProof {
runtime.SetFinalizer(m, finalizeMerkleProof)
return m
}
func NewMerkleProof(leafData []byte) (MerkleProof, error) {
byteData := C.CBytes(leafData)
defer C.free(unsafe.Pointer(byteData))
var p C.MerkleProofPtr
errPtr := C.ergo_merkle_proof_new((*C.uchar)(byteData), C.uintptr_t(len(leafData)), &p)
err := newError(errPtr)
if err.isError() {
return nil, err.error()
}
m := &merkleProof{p: p}
return newMerkleProof(m), nil
}
func NewMerkleProofFromJson(json string) (MerkleProof, error) {
merkleProofJson := C.CString(json)
defer C.free(unsafe.Pointer(merkleProofJson))
var p C.MerkleProofPtr
errPtr := C.ergo_merkle_proof_from_json(merkleProofJson, &p)
err := newError(errPtr)
if err.isError() {
return nil, err.error()
}
m := &merkleProof{p: p}
return newMerkleProof(m), nil
}
func (m *merkleProof) AddNode(hash []byte, side nodeSide) error {
byteData := C.CBytes(hash)
defer C.free(unsafe.Pointer(byteData))
errPtr := C.ergo_merkle_proof_add_node(m.p, (*C.uchar)(byteData), C.uintptr_t(len(hash)), C.uchar(side))
err := newError(errPtr)
if err.isError() {
return err.error()
}
return nil
}
func (m *merkleProof) Valid(expectedRoot []byte) bool {
byteData := C.CBytes(expectedRoot)
defer C.free(unsafe.Pointer(byteData))
res := C.ergo_merkle_proof_valid(m.p, (*C.uchar)(byteData), C.uintptr_t(len(expectedRoot)))
return bool(res)
}
func (m *merkleProof) ValidBase16(expectedRoot string) bool {
rootStr := C.CString(expectedRoot)
defer C.free(unsafe.Pointer(rootStr))
var res C.bool
errPtr := C.ergo_merkle_proof_valid_base16(m.p, rootStr, &res)
err := newError(errPtr)
if err.isError() {
return false
}
return bool(res)
}
func finalizeMerkleProof(m *merkleProof) {
C.ergo_merkle_proof_delete(m.p)
}