-
Notifications
You must be signed in to change notification settings - Fork 5
/
merkle.go
56 lines (45 loc) · 1.25 KB
/
merkle.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
package extension
import (
"bytes"
"crypto/sha256"
"fmt"
"hash"
"github.com/dop251/goja"
"golang.org/x/crypto/sha3"
"github.com/smartbch/egvm/egvm-script/utils"
)
func verifyMerkleProof(f goja.FunctionCall, vm *goja.Runtime, h hash.Hash) goja.Value {
root, proof, leaf := utils.GetThreeArrayBuffers(f)
if len(leaf) != 32 {
panic(goja.NewSymbol(fmt.Sprintf("Invalid merkle tree leaf size %d", len(leaf))))
}
if len(proof)%32 != 0 {
panic(goja.NewSymbol(fmt.Sprintf("Invalid merkle proof size %d", len(proof))))
}
computedHash := leaf
for offset := 0; offset < len(proof); offset += 32 {
h.Reset()
node := proof[offset : offset+32]
h.Write(combineTwoHash(node, computedHash))
computedHash = h.Sum(nil)
}
ok := bytes.Equal(root, computedHash)
return vm.ToValue(ok)
}
func combineTwoHash(a, b []byte) []byte {
bf := bytes.NewBuffer(nil)
if bytes.Compare(a, b) < 0 {
bf.Write(a)
bf.Write(b)
return bf.Bytes()
}
bf.Write(b)
bf.Write(a)
return bf.Bytes()
}
func VerifyMerkleProofSha256(f goja.FunctionCall, vm *goja.Runtime) goja.Value {
return verifyMerkleProof(f, vm, sha256.New())
}
func VerifyMerkleProofKeccak256(f goja.FunctionCall, vm *goja.Runtime) goja.Value {
return verifyMerkleProof(f, vm, sha3.NewLegacyKeccak256())
}