Skip to content

Commit

Permalink
fix: handling ErrNamespaceNotFound for node v0.10.0 (cosmos#953)
Browse files Browse the repository at this point in the history
We have made a breaking change in node v0.10.0 regarding data requests.
celestiaorg/celestia-node@62a0b97

Previously, a "data not found" meant both "the node failed to retrieve
that data, please retry" as well as "the node retrieved the data
successfully, but your namespace is not included in the data". We have
split these errors, so now we have an `ErrNamespaceNotFound` which
indicates a successful request for empty data.

I have no idea how to test rollkit so would love some help on getting
that set up

---------

Co-authored-by: Ganesha Upadhyaya <gupadhyaya@Ganeshas-MacBook-Pro-2.local>
  • Loading branch information
distractedm1nd and Ganesha Upadhyaya authored Jun 8, 2023
1 parent 5766a91 commit 784a455
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 15 deletions.
42 changes: 30 additions & 12 deletions da/celestia/celestia.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ type Config struct {
}

// Init initializes DataAvailabilityLayerClient instance.
func (c *DataAvailabilityLayerClient) Init(namespaceID types.NamespaceID, config []byte, kvStore ds.Datastore, logger log.Logger) error {
func (c *DataAvailabilityLayerClient) Init(
namespaceID types.NamespaceID, config []byte, kvStore ds.Datastore, logger log.Logger,
) error {
c.namespaceID = namespaceID
c.logger = logger

Expand Down Expand Up @@ -106,9 +108,12 @@ func (c *DataAvailabilityLayerClient) SubmitBlock(ctx context.Context, block *ty
}

// CheckBlockAvailability queries DA layer to check data availability of block at given height.
func (c *DataAvailabilityLayerClient) CheckBlockAvailability(ctx context.Context, dataLayerHeight uint64) da.ResultCheckBlock {
func (c *DataAvailabilityLayerClient) CheckBlockAvailability(
ctx context.Context, dataLayerHeight uint64,
) da.ResultCheckBlock {
shares, err := c.client.NamespacedShares(ctx, c.namespaceID, dataLayerHeight)
if err != nil {
code := dataRequestErrorToStatus(err)
if code != da.StatusSuccess {
return da.ResultCheckBlock{
BaseResult: da.BaseResult{
Code: da.StatusError,
Expand All @@ -127,18 +132,15 @@ func (c *DataAvailabilityLayerClient) CheckBlockAvailability(ctx context.Context
}

// RetrieveBlocks gets a batch of blocks from DA layer.
func (c *DataAvailabilityLayerClient) RetrieveBlocks(ctx context.Context, dataLayerHeight uint64) da.ResultRetrieveBlocks {
func (c *DataAvailabilityLayerClient) RetrieveBlocks(
ctx context.Context, dataLayerHeight uint64,
) da.ResultRetrieveBlocks {
data, err := c.client.NamespacedData(ctx, c.namespaceID, dataLayerHeight)
if err != nil {
var code da.StatusCode
if strings.Contains(err.Error(), da.ErrDataNotFound.Error()) || strings.Contains(err.Error(), da.ErrEDSNotFound.Error()) {
code = da.StatusNotFound
} else {
code = da.StatusError
}
status := dataRequestErrorToStatus(err)
if status != da.StatusSuccess {
return da.ResultRetrieveBlocks{
BaseResult: da.BaseResult{
Code: code,
Code: status,
Message: err.Error(),
},
}
Expand Down Expand Up @@ -172,3 +174,19 @@ func (c *DataAvailabilityLayerClient) RetrieveBlocks(ctx context.Context, dataLa
Blocks: blocks,
}
}

func dataRequestErrorToStatus(err error) da.StatusCode {
switch {
case err == nil,
// ErrNamespaceNotFound is a success because it means no retries are necessary, the
// namespace doesn't exist in the block.
// TODO: Once node implements non-inclusion proofs, ErrNamespaceNotFound needs to be verified
strings.Contains(err.Error(), da.ErrNamespaceNotFound.Error()):
return da.StatusSuccess
case strings.Contains(err.Error(), da.ErrDataNotFound.Error()),
strings.Contains(err.Error(), da.ErrEDSNotFound.Error()):
return da.StatusNotFound
default:
return da.StatusError
}
}
18 changes: 18 additions & 0 deletions da/celestia/celestia_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package celestia

import (
"errors"
"testing"

"github.com/stretchr/testify/assert"

"github.com/rollkit/rollkit/da"
)

func TestDataRequestErrorToStatus(t *testing.T) {
assert := assert.New(t)
assert.Equal(da.StatusSuccess, dataRequestErrorToStatus(da.ErrNamespaceNotFound))
assert.Equal(da.StatusNotFound, dataRequestErrorToStatus(da.ErrDataNotFound))
assert.Equal(da.StatusNotFound, dataRequestErrorToStatus(da.ErrEDSNotFound))
assert.Equal(da.StatusError, dataRequestErrorToStatus(errors.New("some random error")))
}
10 changes: 7 additions & 3 deletions da/da.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import (
"github.com/rollkit/rollkit/types"
)

// ErrNotFound is used to indicated that requested data could not be found.
var ErrDataNotFound = errors.New("data not found")
var ErrEDSNotFound = errors.New("eds not found")
var (
// ErrDataNotFound is used to indicated that requested data failed to be retrieved.
ErrDataNotFound = errors.New("data not found")
// ErrNamespaceNotFound is used to indicate that the block contains data, but not for the requested namespace.
ErrNamespaceNotFound = errors.New("namespace not found in data")
ErrEDSNotFound = errors.New("eds not found")
)

// StatusCode is a type for DA layer return status.
// TODO: define an enum of different non-happy-path cases
Expand Down

0 comments on commit 784a455

Please sign in to comment.