Skip to content

Commit

Permalink
implement MerkleProof
Browse files Browse the repository at this point in the history
  • Loading branch information
Alesfatalis committed Apr 8, 2024
1 parent 56742f2 commit e17f295
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 0 deletions.
105 changes: 105 additions & 0 deletions merkleproof.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,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.ulong(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.ulong(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.ulong(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)
}
32 changes: 32 additions & 0 deletions merkleproof_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package ergo

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestBlockProof(t *testing.T) {
json := `{
"leafData": "563b34b96e65788d767a10b0c2ce4a9ef5dcb9f7f7919781624870d56506dc5b",
"levels": [
["274d105b42c2da3e03519865470ccef5072d389b153535ca7192fef4abf3b3ed", 0],
["c1887cee0c42318ac04dfa93b8ef6b40c2b53a83b0e111f91a16b0842166e76e", 0],
["58be076cd9ef596a739ec551cbb6b467b95044c05a80a66a7f256d4ebafd787f", 0]]
}`

testMerkleProof, testMerkleProofErr := NewMerkleProofFromJson(json)
assert.NoError(t, testMerkleProofErr)

root := "250063ac1cec3bf56f727f644f49b70515616afa6009857a29b1fe298441e69a"
assert.True(t, testMerkleProof.ValidBase16(root))
}

func TestMinerProof(t *testing.T) {
json := `{"leafData":"642c15c62553edd8fd9af9a6f754f3c7a6c03faacd0c9b9d5b7d11052c6c6fe8","levels":[["39b79af823a92aa72ced2c6d9e7f7f4687de5b5af7fab0ad205d3e54bda3f3ae",1]]}`

testMerkleProof, testMerkleProofErr := NewMerkleProofFromJson(json)
assert.NoError(t, testMerkleProofErr)

root := "74c851610658a40f5ae74aa3a4babd5751bd827a6ccc1fe069468ef487cb90a8"
assert.True(t, testMerkleProof.ValidBase16(root))
}

0 comments on commit e17f295

Please sign in to comment.