Skip to content

Commit

Permalink
feat(proof.go): adding JSON marshal/unmarshal (#214)
Browse files Browse the repository at this point in the history
Adds json marshaling/unmarshaling to `nmt.Proof`.

As found elsewhere in the go stdlib, `UnmarshalJSON` must be defined on
the pointer receiver although `MarshalJSON` is a value receiver.

This is needed because the fields are private. Does this need to be the
case? If we make them public, JSON marshaling will work by default.
  • Loading branch information
distractedm1nd authored Jun 27, 2023
1 parent bbecc53 commit 564300a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
34 changes: 34 additions & 0 deletions proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nmt

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"hash"
Expand Down Expand Up @@ -47,6 +48,39 @@ type Proof struct {
isMaxNamespaceIDIgnored bool
}

type jsonProof struct {
Start int `json:"start"`
End int `json:"end"`
Nodes [][]byte `json:"nodes"`
LeafHash []byte `json:"leaf_hash"`
IsMaxNamespaceIDIgnored bool `json:"is_max_namespace_id_ignored"`
}

func (proof Proof) MarshalJSON() ([]byte, error) {
jsonProofObj := jsonProof{
Start: proof.start,
End: proof.end,
Nodes: proof.nodes,
LeafHash: proof.leafHash,
IsMaxNamespaceIDIgnored: proof.isMaxNamespaceIDIgnored,
}
return json.Marshal(jsonProofObj)
}

func (proof *Proof) UnmarshalJSON(data []byte) error {
var jsonProofObj jsonProof
err := json.Unmarshal(data, &jsonProofObj)
if err != nil {
return err
}
proof.start = jsonProofObj.Start
proof.end = jsonProofObj.End
proof.nodes = jsonProofObj.Nodes
proof.leafHash = jsonProofObj.LeafHash
proof.isMaxNamespaceIDIgnored = jsonProofObj.IsMaxNamespaceIDIgnored
return nil
}

// Start index of this proof.
func (proof Proof) Start() int {
return proof.start
Expand Down
23 changes: 23 additions & 0 deletions proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,29 @@ import (
"github.com/celestiaorg/nmt/namespace"
)

func TestJsonMarshal_Proof(t *testing.T) {
// create a tree with 4 leaves
nIDSize := 1
tree := exampleNMT(nIDSize, true, 1, 2, 3, 4)

// build a proof for an NID that is within the namespace range of the tree
nID := []byte{1}
proof, err := tree.ProveNamespace(nID)
require.NoError(t, err)

// marshal the proof to JSON
jsonProof, err := proof.MarshalJSON()
require.NoError(t, err)

// unmarshal the proof from JSON
var unmarshalledProof Proof
err = unmarshalledProof.UnmarshalJSON(jsonProof)
require.NoError(t, err)

// verify that the unmarshalled proof is equal to the original proof
assert.Equal(t, proof, unmarshalledProof)
}

// TestVerifyNamespace_EmptyProof tests the correct behaviour of VerifyNamespace for valid and invalid empty proofs.
func TestVerifyNamespace_EmptyProof(t *testing.T) {
// create a tree with 4 leaves
Expand Down

0 comments on commit 564300a

Please sign in to comment.