Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(blob): add marshaling for blob and proof #2286

Merged
merged 4 commits into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions api/docgen/examples.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import (
"golang.org/x/text/language"

"github.com/celestiaorg/go-fraud"
"github.com/celestiaorg/nmt"
"github.com/celestiaorg/rsmt2d"

"github.com/celestiaorg/celestia-node/blob"
"github.com/celestiaorg/celestia-node/das"
"github.com/celestiaorg/celestia-node/header"
"github.com/celestiaorg/celestia-node/nodebuilder/node"
Expand Down Expand Up @@ -128,6 +130,10 @@ func init() {
Addrs: []multiaddr.Multiaddr{ma},
}
addToExampleValues(addrInfo)

proof := nmt.NewInclusionProof(0, 4, [][]byte{[]byte("test")}, true)
blobProof := &blob.Proof{&proof}
addToExampleValues(blobProof)
}

func addToExampleValues(v interface{}) {
Expand Down
75 changes: 73 additions & 2 deletions blob/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package blob

import (
"bytes"
"encoding/json"
"fmt"

appns "github.com/celestiaorg/celestia-app/pkg/namespace"
"github.com/celestiaorg/celestia-app/x/blob/types"
"github.com/celestiaorg/nmt"
"github.com/celestiaorg/nmt/namespace"

"github.com/celestiaorg/celestia-node/share/ipld"
)

// Commitment is a Merkle Root of the subtree built from shares of the Blob.
Expand Down Expand Up @@ -57,11 +60,47 @@ func (p Proof) equal(input Proof) error {
return nil
}

type jsonProof struct {
Start int `json:"start"`
End int `json:"end"`
Nodes [][]byte `json:"nodes"`
}
Wondertan marked this conversation as resolved.
Show resolved Hide resolved

func (p *Proof) MarshalJSON() ([]byte, error) {
proofs := make([]jsonProof, 0, p.Len())
for _, pp := range *p {
proofs = append(proofs, jsonProof{
Start: pp.Start(),
End: pp.End(),
Nodes: pp.Nodes(),
})
}

return json.Marshal(proofs)
}

func (p *Proof) UnmarshalJSON(data []byte) error {
var proofs []jsonProof
err := json.Unmarshal(data, &proofs)
if err != nil {
return err
}

nmtProofs := make([]*nmt.Proof, len(proofs))
for i, jProof := range proofs {
nmtProof := nmt.NewInclusionProof(jProof.Start, jProof.End, jProof.Nodes, ipld.NMTIgnoreMaxNamespace)
nmtProofs[i] = &nmtProof
}

*p = nmtProofs
return nil
}

// Blob represents any application-specific binary data that anyone can submit to Celestia.
type Blob struct {
types.Blob
types.Blob `json:"blob"`

Commitment Commitment
Commitment Commitment `json:"commitment"`
}

// NewBlob constructs a new blob from the provided namespace.ID and data.
Expand Down Expand Up @@ -91,3 +130,35 @@ func NewBlob(shareVersion uint8, namespace namespace.ID, data []byte) (*Blob, er
func (b *Blob) Namespace() namespace.ID {
return append([]byte{uint8(b.NamespaceVersion)}, b.NamespaceId...)
}

type jsonBlob struct {
Namespace namespace.ID `json:"namespace"`
Data []byte `json:"data"`
ShareVersion uint32 `json:"share_version"`
Commitment Commitment `json:"commitment"`
}

func (b *Blob) MarshalJSON() ([]byte, error) {
blob := &jsonBlob{
Namespace: b.Namespace(),
Data: b.Data,
ShareVersion: b.ShareVersion,
Commitment: b.Commitment,
}
return json.Marshal(blob)
}

func (b *Blob) UnmarshalJSON(data []byte) error {
var blob jsonBlob
err := json.Unmarshal(data, &blob)
if err != nil {
return err
}

b.Blob.NamespaceVersion = uint32(blob.Namespace[0])
b.Blob.NamespaceId = blob.Namespace[1:]
b.Blob.Data = blob.Data
b.Blob.ShareVersion = blob.ShareVersion
b.Commitment = blob.Commitment
return nil
}
12 changes: 12 additions & 0 deletions blob/blob_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package blob

import (
"reflect"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -62,6 +63,17 @@ func TestBlob(t *testing.T) {
assert.Equal(t, blob[0].Commitment, b[0].Commitment)
},
},
{
name: "blob marshaling",
expectedRes: func(t *testing.T) {
data, err := blob[0].MarshalJSON()
require.NoError(t, err)

newBlob := &Blob{}
require.NoError(t, newBlob.UnmarshalJSON(data))
require.True(t, reflect.DeepEqual(blob[0], newBlob))
},
},
}

for _, tt := range test {
Expand Down
19 changes: 19 additions & 0 deletions blob/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,25 @@ func TestBlobService_Get(t *testing.T) {

},
},
{
name: "marshal proof",
doFn: func() (interface{}, error) {
proof, err := service.GetProof(ctx, 1, blobs0[1].Namespace(), blobs0[1].Commitment)
require.NoError(t, err)
return proof.MarshalJSON()
},
expectedResult: func(i interface{}, err error) {
require.NoError(t, err)
jsonData, ok := i.([]byte)
require.True(t, ok)
var proof Proof
require.NoError(t, proof.UnmarshalJSON(jsonData))

newProof, err := service.GetProof(ctx, 1, blobs0[1].Namespace(), blobs0[1].Commitment)
require.NoError(t, err)
require.NoError(t, proof.equal(*newProof))
},
},
}

for _, tt := range test {
Expand Down