Skip to content

Commit

Permalink
refactor!(share): integrate new Namespace type (#2388)
Browse files Browse the repository at this point in the history
## Notable Changes
- `namespace.ID` to  `share.Namespace`
- Changes every comment namespace ID mentioning to just namespace. I
renamed every such mention besides in ADRs. I don't want to touch ADRs
here, as they need a more holistic re-review and up-to-date catchup.
	- Uses all the utility methods on the type, where suitable
- Namespace constructor now only creates Blob Namespaces. For other
reserved namespaces, the predefined globals should be used.
- Uses namespace.ValidateDataNamespace everywhere data is requested.
This is guarantees we verify the namespace are 100% valid and forbids
requesting parity and padding namespaces.
- Restricts PFBs for reserved namespaces 
- Reversed the dependency from `share -> share/ipld` to `share/ipld ->
share`
- NewBlobV0 constructor. Similar to NewNamespaceV0
- `sharetest` pkg for share related testing utilities
- `edstest` pkg for eds related testing utilities

## Follow-ups
- `blobtest` pkg to generate node's blob type


## Refs
* Substitutes zombie PR
#2376. I push to the
branch, but GH does not see commits.
* Based on #2367
* Closes #2301
* Closes #2309 
* Blocked on #2256
  • Loading branch information
Wondertan authored Jun 27, 2023
1 parent 0267e21 commit ccae150
Show file tree
Hide file tree
Showing 72 changed files with 915 additions and 966 deletions.
4 changes: 2 additions & 2 deletions api/docgen/examples.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,13 @@ func init() {
}
addToExampleValues(addrInfo)

namespace, err := share.NewNamespaceV0([]byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10})
namespace, err := share.NewBlobNamespaceV0([]byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10})
if err != nil {
panic(err)
}
addToExampleValues(namespace)

generatedBlob, err := blob.NewBlob(0, namespace, []byte("This is an example of some blob data"))
generatedBlob, err := blob.NewBlobV0(namespace, []byte("This is an example of some blob data"))
if err != nil {
panic(err)
}
Expand Down
8 changes: 4 additions & 4 deletions api/gateway/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ func (h *Handler) RegisterEndpoints(rpc *Server, deprecatedEndpointsEnabled bool
rpc.RegisterHandlerFunc(submitTxEndpoint, h.handleSubmitTx, http.MethodPost)

// share endpoints
rpc.RegisterHandlerFunc(fmt.Sprintf("%s/{%s}/height/{%s}", namespacedSharesEndpoint, nIDKey, heightKey),
rpc.RegisterHandlerFunc(fmt.Sprintf("%s/{%s}/height/{%s}", namespacedSharesEndpoint, namespaceKey, heightKey),
h.handleSharesByNamespaceRequest, http.MethodGet)
rpc.RegisterHandlerFunc(fmt.Sprintf("%s/{%s}", namespacedSharesEndpoint, nIDKey),
rpc.RegisterHandlerFunc(fmt.Sprintf("%s/{%s}", namespacedSharesEndpoint, namespaceKey),
h.handleSharesByNamespaceRequest, http.MethodGet)
rpc.RegisterHandlerFunc(fmt.Sprintf("%s/{%s}/height/{%s}", namespacedDataEndpoint, nIDKey, heightKey),
rpc.RegisterHandlerFunc(fmt.Sprintf("%s/{%s}/height/{%s}", namespacedDataEndpoint, namespaceKey, heightKey),
h.handleDataByNamespaceRequest, http.MethodGet)
rpc.RegisterHandlerFunc(fmt.Sprintf("%s/{%s}", namespacedDataEndpoint, nIDKey),
rpc.RegisterHandlerFunc(fmt.Sprintf("%s/{%s}", namespacedDataEndpoint, namespaceKey),
h.handleDataByNamespaceRequest, http.MethodGet)

// DAS endpoints
Expand Down
24 changes: 11 additions & 13 deletions api/gateway/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/gorilla/mux"

"github.com/celestiaorg/celestia-app/pkg/shares"
"github.com/celestiaorg/nmt/namespace"

"github.com/celestiaorg/celestia-node/share"
)
Expand All @@ -20,7 +19,7 @@ const (
namespacedDataEndpoint = "/namespaced_data"
)

var nIDKey = "nid"
var namespaceKey = "nid"

// NamespacedSharesResponse represents the response to a
// SharesByNamespace request.
Expand All @@ -37,12 +36,12 @@ type NamespacedDataResponse struct {
}

func (h *Handler) handleSharesByNamespaceRequest(w http.ResponseWriter, r *http.Request) {
height, nID, err := parseGetByNamespaceArgs(r)
height, namespace, err := parseGetByNamespaceArgs(r)
if err != nil {
writeError(w, http.StatusBadRequest, namespacedSharesEndpoint, err)
return
}
shares, err := h.getShares(r.Context(), height, nID)
shares, err := h.getShares(r.Context(), height, namespace)
if err != nil {
writeError(w, http.StatusInternalServerError, namespacedSharesEndpoint, err)
return
Expand All @@ -62,12 +61,12 @@ func (h *Handler) handleSharesByNamespaceRequest(w http.ResponseWriter, r *http.
}

func (h *Handler) handleDataByNamespaceRequest(w http.ResponseWriter, r *http.Request) {
height, nID, err := parseGetByNamespaceArgs(r)
height, namespace, err := parseGetByNamespaceArgs(r)
if err != nil {
writeError(w, http.StatusBadRequest, namespacedDataEndpoint, err)
return
}
shares, err := h.getShares(r.Context(), height, nID)
shares, err := h.getShares(r.Context(), height, namespace)
if err != nil {
writeError(w, http.StatusInternalServerError, namespacedDataEndpoint, err)
return
Expand All @@ -91,13 +90,13 @@ func (h *Handler) handleDataByNamespaceRequest(w http.ResponseWriter, r *http.Re
}
}

func (h *Handler) getShares(ctx context.Context, height uint64, nID namespace.ID) ([]share.Share, error) {
func (h *Handler) getShares(ctx context.Context, height uint64, namespace share.Namespace) ([]share.Share, error) {
header, err := h.header.GetByHeight(ctx, height)
if err != nil {
return nil, err
}

shares, err := h.share.GetSharesByNamespace(ctx, header.DAH, nID)
shares, err := h.share.GetSharesByNamespace(ctx, header.DAH, namespace)
if err != nil {
return nil, err
}
Expand All @@ -124,7 +123,7 @@ func dataFromShares(input []share.Share) (data [][]byte, err error) {
return data, nil
}

func parseGetByNamespaceArgs(r *http.Request) (height uint64, nID namespace.ID, err error) {
func parseGetByNamespaceArgs(r *http.Request) (height uint64, namespace share.Namespace, err error) {
vars := mux.Vars(r)
// if a height was given, parse it, otherwise get namespaced shares/data from the latest header
if strHeight, ok := vars[heightKey]; ok {
Expand All @@ -133,11 +132,10 @@ func parseGetByNamespaceArgs(r *http.Request) (height uint64, nID namespace.ID,
return 0, nil, err
}
}
hexNID := vars[nIDKey]
nID, err = hex.DecodeString(hexNID)
hexNamespace := vars[namespaceKey]
namespace, err = hex.DecodeString(hexNamespace)
if err != nil {
return 0, nil, err
}

return height, nID, nil
return height, namespace, namespace.ValidateForData()
}
9 changes: 5 additions & 4 deletions api/gateway/share_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import (
coretypes "github.com/tendermint/tendermint/types"

"github.com/celestiaorg/celestia-app/pkg/appconsts"
"github.com/celestiaorg/celestia-app/pkg/namespace"
"github.com/celestiaorg/celestia-app/pkg/shares"

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

func Test_dataFromShares(t *testing.T) {
Expand All @@ -19,13 +20,13 @@ func Test_dataFromShares(t *testing.T) {
[]byte("BEEEEAHP"),
}

ns := namespace.RandomBlobNamespace()
ns := sharetest.RandV0Namespace()
sss := shares.NewSparseShareSplitter()
for _, data := range testData {
b := coretypes.Blob{
Data: data,
NamespaceID: ns.ID,
NamespaceVersion: ns.Version,
NamespaceID: ns.ID(),
NamespaceVersion: ns.Version(),
ShareVersion: appconsts.ShareVersionZero,
}
err := sss.Write(b)
Expand Down
6 changes: 2 additions & 4 deletions api/gateway/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"github.com/cosmos/cosmos-sdk/types"
"github.com/gorilla/mux"

"github.com/celestiaorg/celestia-app/pkg/appconsts"

"github.com/celestiaorg/celestia-node/blob"
"github.com/celestiaorg/celestia-node/state"
)
Expand Down Expand Up @@ -131,7 +129,7 @@ func (h *Handler) handleSubmitPFB(w http.ResponseWriter, r *http.Request) {
writeError(w, http.StatusBadRequest, submitPFBEndpoint, err)
return
}
nID, err := hex.DecodeString(req.NamespaceID)
namespace, err := hex.DecodeString(req.NamespaceID)
if err != nil {
writeError(w, http.StatusBadRequest, submitPFBEndpoint, err)
return
Expand All @@ -143,7 +141,7 @@ func (h *Handler) handleSubmitPFB(w http.ResponseWriter, r *http.Request) {
}
fee := types.NewInt(req.Fee)

constructedBlob, err := blob.NewBlob(appconsts.DefaultShareVersion, nID, data)
constructedBlob, err := blob.NewBlobV0(namespace, data)
if err != nil {
writeError(w, http.StatusBadRequest, submitPFBEndpoint, err)
return
Expand Down
2 changes: 1 addition & 1 deletion api/gateway/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestHandleSubmitPFB(t *testing.T) {
mock.EXPECT().SubmitPayForBlob(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
Return(&txResponse, timedErr)

ns, err := share.NewNamespaceV0([]byte("abc"))
ns, err := share.NewBlobNamespaceV0([]byte("abc"))
require.NoError(t, err)
hexNs := hex.EncodeToString(ns[:])

Expand Down
57 changes: 35 additions & 22 deletions blob/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import (
"encoding/json"
"fmt"

appns "github.com/celestiaorg/celestia-app/pkg/namespace"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

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

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

Expand Down Expand Up @@ -101,41 +103,51 @@ type Blob struct {
types.Blob `json:"blob"`

Commitment Commitment `json:"commitment"`

// the celestia-node's namespace type
// this is to avoid converting to and from app's type
namespace share.Namespace
}

// NewBlob constructs a new blob from the provided namespace.ID and data.
func NewBlob(shareVersion uint8, namespace namespace.ID, data []byte) (*Blob, error) {
if len(namespace) != appns.NamespaceSize {
return nil, fmt.Errorf("invalid size of the namespace id. got:%d, want:%d", len(namespace), appns.NamespaceSize)
}
// NewBlobV0 constructs a new blob from the provided Namespace and data.
// The blob will be formatted as v0 shares.
func NewBlobV0(namespace share.Namespace, data []byte) (*Blob, error) {
return NewBlob(appconsts.ShareVersionZero, namespace, data)
}

ns, err := appns.New(namespace[appns.NamespaceVersionSize-1], namespace[appns.NamespaceVersionSize:])
if err != nil {
// NewBlob constructs a new blob from the provided Namespace, data and share version.
func NewBlob(shareVersion uint8, namespace share.Namespace, data []byte) (*Blob, error) {
if len(data) == 0 || len(data) > appconsts.DefaultMaxBytes {
return nil, fmt.Errorf("blob data must be > 0 && <= %d, but it was %d bytes", appconsts.DefaultMaxBytes, len(data))
}
if err := namespace.ValidateForBlob(); err != nil {
return nil, err
}

blob, err := types.NewBlob(ns, data, shareVersion)
if err != nil {
return nil, err
blob := tmproto.Blob{
NamespaceId: namespace.ID(),
Data: data,
ShareVersion: uint32(shareVersion),
NamespaceVersion: uint32(namespace.Version()),
}

com, err := types.CreateCommitment(blob)
com, err := types.CreateCommitment(&blob)
if err != nil {
return nil, err
}
return &Blob{Blob: *blob, Commitment: com}, nil
return &Blob{Blob: blob, Commitment: com, namespace: namespace}, nil
}

// Namespace returns blob's namespace.
func (b *Blob) Namespace() namespace.ID {
return append([]byte{uint8(b.NamespaceVersion)}, b.NamespaceId...)
func (b *Blob) Namespace() share.Namespace {
return b.namespace
}

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

func (b *Blob) MarshalJSON() ([]byte, error) {
Expand All @@ -155,10 +167,11 @@ func (b *Blob) UnmarshalJSON(data []byte) error {
return err
}

b.Blob.NamespaceVersion = uint32(blob.Namespace[0])
b.Blob.NamespaceId = blob.Namespace[1:]
b.Blob.NamespaceVersion = uint32(blob.Namespace.Version())
b.Blob.NamespaceId = blob.Namespace.ID()
b.Blob.Data = blob.Data
b.Blob.ShareVersion = blob.ShareVersion
b.Commitment = blob.Commitment
b.namespace = blob.Namespace
return nil
}
10 changes: 3 additions & 7 deletions blob/blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ import (
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/types"

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

"github.com/celestiaorg/celestia-node/blob/blobtest"
)

func TestBlob(t *testing.T) {
appBlobs, err := blobtest.GenerateBlobs([]int{1}, false)
appBlobs, err := blobtest.GenerateV0Blobs([]int{1}, false)
require.NoError(t, err)
blob, err := convertBlobs(appBlobs...)
require.NoError(t, err)
Expand All @@ -42,12 +41,9 @@ func TestBlob(t *testing.T) {
},
},
{
name: "verify nID",
name: "verify namespace",
expectedRes: func(t *testing.T) {
ns, err := appns.New(
blob[0].Namespace()[appns.NamespaceVersionSize-1],
blob[0].Namespace()[appns.NamespaceVersionSize:],
)
ns := blob[0].Namespace().ToAppNamespace()
require.NoError(t, err)
require.NoError(t, apptypes.ValidateBlobNamespace(ns))
},
Expand Down
8 changes: 5 additions & 3 deletions blob/blobtest/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import (
"github.com/celestiaorg/celestia-node/share"
)

func GenerateBlobs(sizes []int, sameNID bool) ([]types.Blob, error) {
// GenerateV0Blobs is a test utility producing v0 share formatted blobs with the
// requested size and random namespaces.
func GenerateV0Blobs(sizes []int, sameNamespace bool) ([]types.Blob, error) {
blobs := make([]types.Blob, 0, len(sizes))

for _, size := range sizes {
size := rawBlobSize(appconsts.FirstSparseShareContentSize * size)
appBlob := testfactory.GenerateRandomBlob(size)
if !sameNID {
nid, err := share.NewNamespaceV0(tmrand.Bytes(7))
if !sameNamespace {
nid, err := share.NewBlobNamespaceV0(tmrand.Bytes(7))
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions blob/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ func SharesToBlobs(rawShares []share.Share) ([]*Blob, error) {
}

appShares := make([]shares.Share, 0, len(rawShares))
for _, sh := range rawShares {
bShare, err := shares.NewShare(sh)
for _, shr := range rawShares {
bShare, err := shares.NewShare(shr)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit ccae150

Please sign in to comment.