diff --git a/blob/service.go b/blob/service.go index 0b43493e27..0876a45a0c 100644 --- a/blob/service.go +++ b/blob/service.go @@ -193,8 +193,7 @@ func (s *Service) getByCommitment( namespacedShares, err := s.shareGetter.GetSharesByNamespace(ctx, header.DAH, nID) if err != nil { - if errors.Is(err, share.ErrNamespaceNotFound) || - errors.Is(err, share.ErrNotFound) { + if errors.Is(err, share.ErrNotFound) { err = ErrBlobNotFound } return nil, nil, err diff --git a/share/availability/light/availability_test.go b/share/availability/light/availability_test.go index 4980af031e..ca72596816 100644 --- a/share/availability/light/availability_test.go +++ b/share/availability/light/availability_test.go @@ -141,8 +141,9 @@ func TestService_GetSharesByNamespaceNotFound(t *testing.T) { getter, root := GetterWithRandSquare(t, 1) root.RowRoots = nil - _, err := getter.GetSharesByNamespace(context.Background(), root, namespace.RandomNamespace().Bytes()) - assert.ErrorIs(t, err, share.ErrNamespaceNotFound) + emptyShares, err := getter.GetSharesByNamespace(context.Background(), root, namespace.RandomNamespace().Bytes()) + require.NoError(t, err) + require.Empty(t, emptyShares.Flatten()) } func BenchmarkService_GetSharesByNamespace(b *testing.B) { diff --git a/share/get_test.go b/share/get_test.go index 25711e5a65..1b9df69be3 100644 --- a/share/get_test.go +++ b/share/get_test.go @@ -237,7 +237,7 @@ func TestCollectLeavesByNamespace_AbsentNamespaceId(t *testing.T) { t.Cleanup(cancel) bServ := mdutils.Bserv() - shares := RandShares(t, 16) + shares := RandShares(t, 1024) // set all shares to the same namespace id nids, err := randomNids(5) diff --git a/share/getter.go b/share/getter.go index 6ba729c71a..15f384a2c4 100644 --- a/share/getter.go +++ b/share/getter.go @@ -17,9 +17,6 @@ import ( var ( // ErrNotFound is used to indicate that requested data could not be found. ErrNotFound = errors.New("share: data not found") - // ErrNamespaceNotFound is returned by GetSharesByNamespace when data for requested root does - // not include any shares from the given namespace - ErrNamespaceNotFound = errors.New("share: namespace not found in data") ) // Getter interface provides a set of accessors for shares by the Root. @@ -35,6 +32,9 @@ type Getter interface { // GetSharesByNamespace gets all shares from an EDS within the given namespace. // Shares are returned in a row-by-row order if the namespace spans multiple rows. + // Inclusion of returned data could be verified using Verify method on NamespacedShares. + // If no shares are found for target namespace non-inclusion could be also verified by calling + // Verify method. GetSharesByNamespace(context.Context, *Root, namespace.ID) (NamespacedShares, error) } diff --git a/share/getters/cascade.go b/share/getters/cascade.go index 1a0d8fb274..01540de926 100644 --- a/share/getters/cascade.go +++ b/share/getters/cascade.go @@ -122,8 +122,8 @@ func cascadeGetters[V any]( getCtx, cancel := ctxWithSplitTimeout(ctx, len(getters)-i, 0) val, getErr := get(getCtx, getter) cancel() - if getErr == nil || errors.Is(getErr, share.ErrNamespaceNotFound) { - return val, getErr + if getErr == nil { + return val, nil } if errors.Is(getErr, errOperationNotSupported) { diff --git a/share/getters/getter_test.go b/share/getters/getter_test.go index c9bf82031a..20b7e25191 100644 --- a/share/getters/getter_test.go +++ b/share/getters/getter_test.go @@ -138,8 +138,9 @@ func TestStoreGetter(t *testing.T) { // nid not found nID = make([]byte, namespace.NamespaceSize) - _, err = sg.GetSharesByNamespace(ctx, &dah, nID) - require.ErrorIs(t, err, share.ErrNamespaceNotFound) + emptyShares, err := sg.GetSharesByNamespace(ctx, &dah, nID) + require.NoError(t, err) + require.Empty(t, emptyShares.Flatten()) // root not found root := share.Root{} @@ -216,13 +217,14 @@ func TestIPLDGetter(t *testing.T) { // nid not found nID = make([]byte, namespace.NamespaceSize) emptyShares, err := sg.GetSharesByNamespace(ctx, &dah, nID) - require.ErrorIs(t, err, share.ErrNamespaceNotFound) + require.NoError(t, err) require.Nil(t, emptyShares) // nid doesnt exist in root root := share.Root{} - _, err = sg.GetSharesByNamespace(ctx, &root, nID) - require.ErrorIs(t, err, share.ErrNamespaceNotFound) + emptyShares, err = sg.GetSharesByNamespace(ctx, &root, nID) + require.NoError(t, err) + require.Empty(t, emptyShares.Flatten()) }) } diff --git a/share/getters/shrex.go b/share/getters/shrex.go index 58a85abc0c..99da2f8758 100644 --- a/share/getters/shrex.go +++ b/share/getters/shrex.go @@ -191,7 +191,7 @@ func (sg *ShrexGetter) GetSharesByNamespace( // verify that the namespace could exist inside the roots before starting network requests roots := filterRootsByNamespace(root, id) if len(roots) == 0 { - return nil, share.ErrNamespaceNotFound + return nil, nil } for { @@ -218,18 +218,15 @@ func (sg *ShrexGetter) GetSharesByNamespace( cancel() switch { case getErr == nil: - if getErr = nd.Verify(root, id); getErr != nil { + // both inclusion and non-inclusion cases needs verification + if verErr := nd.Verify(root, id); verErr != nil { + getErr = verErr setStatus(peers.ResultBlacklistPeer) break } setStatus(peers.ResultNoop) sg.metrics.recordNDAttempt(ctx, attempt, true) - return nd, getErr - case errors.Is(getErr, share.ErrNamespaceNotFound): - // TODO: will be merged with first case once non-inclusion proofs are ready - setStatus(peers.ResultNoop) - sg.metrics.recordNDAttempt(ctx, attempt, true) - return nd, getErr + return nd, nil case errors.Is(getErr, context.DeadlineExceeded), errors.Is(getErr, context.Canceled): setStatus(peers.ResultCooldownPeer) diff --git a/share/getters/shrex_test.go b/share/getters/shrex_test.go index db60e0138a..72ac78e69b 100644 --- a/share/getters/shrex_test.go +++ b/share/getters/shrex_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/require" "github.com/celestiaorg/celestia-app/pkg/da" - "github.com/celestiaorg/celestia-app/pkg/namespace" libhead "github.com/celestiaorg/go-header" + "github.com/celestiaorg/nmt" nmtnamespace "github.com/celestiaorg/nmt/namespace" "github.com/celestiaorg/rsmt2d" @@ -24,6 +24,7 @@ import ( "github.com/celestiaorg/celestia-node/header/headertest" "github.com/celestiaorg/celestia-node/share" "github.com/celestiaorg/celestia-node/share/eds" + "github.com/celestiaorg/celestia-node/share/ipld" "github.com/celestiaorg/celestia-node/share/p2p/discovery" "github.com/celestiaorg/celestia-node/share/p2p/peers" "github.com/celestiaorg/celestia-node/share/p2p/shrexeds" @@ -88,12 +89,12 @@ func TestShrexGetter(t *testing.T) { require.ErrorIs(t, err, share.ErrNotFound) }) - t.Run("ND_namespace_not_found", func(t *testing.T) { + t.Run("ND_namespace_not_included", func(t *testing.T) { ctx, cancel := context.WithTimeout(ctx, time.Second) t.Cleanup(cancel) // generate test data - eds, dah, nID := generateTestEDS(t) + eds, dah, maxNID := generateTestEDS(t) require.NoError(t, edsStore.Put(ctx, dah.Hash(), eds)) peerManager.Validate(ctx, srvHost.ID(), shrexsub.Notification{ DataHash: dah.Hash(), @@ -101,10 +102,43 @@ func TestShrexGetter(t *testing.T) { }) // corrupt NID - nID[4]++ + nID := make([]byte, ipld.NamespaceSize) + copy(nID, maxNID) + nID[ipld.NamespaceSize-1]-- // pray for last byte to not be 0x00 + // check for namespace to be between max and min namespace in root + require.Len(t, filterRootsByNamespace(&dah, maxNID), 1) - _, err := getter.GetSharesByNamespace(ctx, &dah, nID) - require.ErrorIs(t, err, share.ErrNamespaceNotFound) + emptyShares, err := getter.GetSharesByNamespace(ctx, &dah, nID) + require.NoError(t, err) + // no shares should be returned + require.Empty(t, emptyShares.Flatten()) + require.Nil(t, emptyShares.Verify(&dah, nID)) + }) + + t.Run("ND_namespace_not_in_dah", func(t *testing.T) { + ctx, cancel := context.WithTimeout(ctx, time.Second) + t.Cleanup(cancel) + + // generate test data + eds, dah, maxNID := generateTestEDS(t) + require.NoError(t, edsStore.Put(ctx, dah.Hash(), eds)) + peerManager.Validate(ctx, srvHost.ID(), shrexsub.Notification{ + DataHash: dah.Hash(), + Height: 1, + }) + + // corrupt NID + nID := make([]byte, ipld.NamespaceSize) + copy(nID, maxNID) + nID[ipld.NamespaceSize-1]++ // pray for last byte to not be 0xFF + // check for namespace to be not in root + require.Len(t, filterRootsByNamespace(&dah, nID), 0) + + emptyShares, err := getter.GetSharesByNamespace(ctx, &dah, nID) + require.NoError(t, err) + // no shares should be returned + require.Empty(t, emptyShares.Flatten()) + require.Nil(t, emptyShares.Verify(&dah, nID)) }) t.Run("EDS_Available", func(t *testing.T) { @@ -166,8 +200,8 @@ func newStore(t *testing.T) (*eds.Store, error) { func generateTestEDS(t *testing.T) (*rsmt2d.ExtendedDataSquare, da.DataAvailabilityHeader, nmtnamespace.ID) { eds := share.RandEDS(t, 4) dah := da.NewDataAvailabilityHeader(eds) - randNID := dah.RowRoots[(len(dah.RowRoots)-1)/2][:namespace.NamespaceSize] - return eds, dah, randNID + max := nmt.MaxNamespace(dah.RowRoots[(len(dah.RowRoots))/2-1], ipld.NamespaceSize) + return eds, dah, max } func testManager( diff --git a/share/getters/store.go b/share/getters/store.go index 91200b78f3..f39f41fc80 100644 --- a/share/getters/store.go +++ b/share/getters/store.go @@ -122,10 +122,6 @@ func (sg *StoreGetter) GetSharesByNamespace( // wrap the read-only CAR blockstore in a getter blockGetter := eds.NewBlockGetter(bs) shares, err = collectSharesByNamespace(ctx, blockGetter, root, nID) - if errors.Is(err, ipld.ErrNodeNotFound) { - // convert error to satisfy getter interface contract - err = share.ErrNotFound - } if err != nil { return nil, fmt.Errorf("getter/store: failed to retrieve shares by namespace: %w", err) } diff --git a/share/getters/utils.go b/share/getters/utils.go index c0b882f330..79438204bd 100644 --- a/share/getters/utils.go +++ b/share/getters/utils.go @@ -59,7 +59,7 @@ func collectSharesByNamespace( rootCIDs := filterRootsByNamespace(root, nID) if len(rootCIDs) == 0 { - return nil, share.ErrNamespaceNotFound + return nil, nil } errGroup, ctx := errgroup.WithContext(ctx) @@ -83,12 +83,6 @@ func collectSharesByNamespace( if err := errGroup.Wait(); err != nil { return nil, err } - - // return ErrNamespaceNotFound if no shares are found for the namespace.ID - if len(rootCIDs) == 1 && len(shares[0].Shares) == 0 { - return nil, share.ErrNamespaceNotFound - } - return shares, nil } diff --git a/share/ipld/namespace_data.go b/share/ipld/namespace_data.go index b38e5884b5..f86a9803ac 100644 --- a/share/ipld/namespace_data.go +++ b/share/ipld/namespace_data.go @@ -137,7 +137,7 @@ func (n *NamespaceData) addProof(d direction, cid cid.Cid, depth int) { // Leaves returns retrieved leaves within the bounds in case `WithLeaves` option was passed, // otherwise nil will be returned. func (n *NamespaceData) Leaves() []ipld.Node { - if n.leaves == nil || n.noLeaves() { + if n.leaves == nil || n.noLeaves() || n.isAbsentNamespace.Load() { return nil } return n.leaves[n.bounds.lowest : n.bounds.highest+1] diff --git a/share/p2p/shrexnd/client.go b/share/p2p/shrexnd/client.go index ab407126de..b59bb347a7 100644 --- a/share/p2p/shrexnd/client.go +++ b/share/p2p/shrexnd/client.go @@ -56,7 +56,7 @@ func (c *Client) RequestND( ) (share.NamespacedShares, error) { shares, err := c.doRequest(ctx, root, nID, peer) if err == nil { - return shares, err + return shares, nil } if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { c.metrics.ObserveRequests(ctx, 1, p2p.StatusTimeout) @@ -71,7 +71,7 @@ func (c *Client) RequestND( return nil, context.DeadlineExceeded } } - if err != p2p.ErrNotFound && err != share.ErrNamespaceNotFound { + if err != p2p.ErrNotFound { log.Warnw("client-nd: peer returned err", "err", err) } return nil, err @@ -119,19 +119,11 @@ func (c *Client) doRequest( return nil, fmt.Errorf("client-nd: reading response: %w", err) } - if err = c.statusToErr(ctx, resp.Status); err != nil { - return nil, fmt.Errorf("client-nd: response code is not OK: %w", err) - } - - shares, err := convertToNamespacedShares(resp.Rows) - if err != nil { - return nil, fmt.Errorf("client-nd: converting response to shares: %w", err) - } - return shares, nil + return c.convertResponse(ctx, resp) } // convertToNamespacedShares converts proto Rows to share.NamespacedShares -func convertToNamespacedShares(rows []*pb.Row) (share.NamespacedShares, error) { +func convertToNamespacedShares(rows []*pb.Row) share.NamespacedShares { shares := make([]share.NamespacedRow, 0, len(rows)) for _, row := range rows { var proof *nmt.Proof @@ -150,7 +142,24 @@ func convertToNamespacedShares(rows []*pb.Row) (share.NamespacedShares, error) { Proof: proof, }) } - return shares, nil + return shares +} + +func convertToNonInclusionProofs(rows []*pb.Row) share.NamespacedShares { + shares := make([]share.NamespacedRow, 0, len(rows)) + for _, row := range rows { + proof := nmt.NewAbsenceProof( + int(row.Proof.Start), + int(row.Proof.End), + row.Proof.Nodes, + row.Proof.Hashleaf, + ipld.NMTIgnoreMaxNamespace, + ) + shares = append(shares, share.NamespacedRow{ + Proof: &proof, + }) + } + return shares } func (c *Client) setStreamDeadlines(ctx context.Context, stream network.Stream) { @@ -181,22 +190,23 @@ func (c *Client) setStreamDeadlines(ctx context.Context, stream network.Stream) } } -func (c *Client) statusToErr(ctx context.Context, code pb.StatusCode) error { - switch code { +func (c *Client) convertResponse( + ctx context.Context, resp pb.GetSharesByNamespaceResponse) (share.NamespacedShares, error) { + switch resp.Status { case pb.StatusCode_OK: c.metrics.ObserveRequests(ctx, 1, p2p.StatusSuccess) - return nil + return convertToNamespacedShares(resp.Rows), nil + case pb.StatusCode_NAMESPACE_NOT_FOUND: + return convertToNonInclusionProofs(resp.Rows), nil case pb.StatusCode_NOT_FOUND: c.metrics.ObserveRequests(ctx, 1, p2p.StatusNotFound) - return p2p.ErrNotFound - case pb.StatusCode_NAMESPACE_NOT_FOUND: - return share.ErrNamespaceNotFound + return nil, p2p.ErrNotFound case pb.StatusCode_INVALID: log.Debug("client-nd: invalid request") fallthrough case pb.StatusCode_INTERNAL: fallthrough default: - return p2p.ErrInvalidResponse + return nil, p2p.ErrInvalidResponse } } diff --git a/share/p2p/shrexnd/exchange_test.go b/share/p2p/shrexnd/exchange_test.go index 8c5a132fdc..25528595d7 100644 --- a/share/p2p/shrexnd/exchange_test.go +++ b/share/p2p/shrexnd/exchange_test.go @@ -49,8 +49,9 @@ func TestExchange_RequestND_NotFound(t *testing.T) { require.NoError(t, edsStore.Put(ctx, dah.Hash(), eds)) randNID := dah.RowRoots[(len(dah.RowRoots)-1)/2][:namespace.NamespaceSize] - _, err := client.RequestND(ctx, &dah, randNID, server.host.ID()) - require.ErrorIs(t, err, share.ErrNamespaceNotFound) + emptyShares, err := client.RequestND(ctx, &dah, randNID, server.host.ID()) + require.NoError(t, err) + require.Empty(t, emptyShares.Flatten()) }) } @@ -119,7 +120,7 @@ func (m notFoundGetter) GetEDS( func (m notFoundGetter) GetSharesByNamespace( _ context.Context, _ *share.Root, _ nmtnamespace.ID, ) (share.NamespacedShares, error) { - return nil, share.ErrNamespaceNotFound + return nil, nil } func newStore(t *testing.T) *eds.Store { diff --git a/share/p2p/shrexnd/pb/share.pb.go b/share/p2p/shrexnd/pb/share.pb.go index d902570410..7e19bebc09 100644 --- a/share/p2p/shrexnd/pb/share.pb.go +++ b/share/p2p/shrexnd/pb/share.pb.go @@ -213,9 +213,10 @@ func (m *Row) GetProof() *Proof { } type Proof struct { - Start int64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` - End int64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` - Nodes [][]byte `protobuf:"bytes,3,rep,name=Nodes,proto3" json:"Nodes,omitempty"` + Start int64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` + End int64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` + Nodes [][]byte `protobuf:"bytes,3,rep,name=nodes,proto3" json:"nodes,omitempty"` + Hashleaf []byte `protobuf:"bytes,4,opt,name=hashleaf,proto3" json:"hashleaf,omitempty"` } func (m *Proof) Reset() { *m = Proof{} } @@ -272,6 +273,13 @@ func (m *Proof) GetNodes() [][]byte { return nil } +func (m *Proof) GetHashleaf() []byte { + if m != nil { + return m.Hashleaf + } + return nil +} + func init() { proto.RegisterEnum("share.p2p.shrex.nd.StatusCode", StatusCode_name, StatusCode_value) proto.RegisterType((*GetSharesByNamespaceRequest)(nil), "share.p2p.shrex.nd.GetSharesByNamespaceRequest") @@ -283,32 +291,33 @@ func init() { func init() { proto.RegisterFile("share/p2p/shrexnd/pb/share.proto", fileDescriptor_ed9f13149b0de397) } var fileDescriptor_ed9f13149b0de397 = []byte{ - // 386 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xc1, 0xae, 0x93, 0x40, - 0x14, 0x86, 0x81, 0xb9, 0xc5, 0x7b, 0x0f, 0x68, 0xc8, 0x68, 0xbc, 0x98, 0x6b, 0x48, 0x65, 0xd5, - 0x68, 0x02, 0x09, 0x26, 0xee, 0x69, 0x8b, 0x4a, 0xac, 0xd3, 0x66, 0x5a, 0x75, 0x65, 0x08, 0x95, - 0x31, 0xb8, 0x90, 0x19, 0x99, 0x69, 0xaa, 0x6b, 0x5f, 0xc0, 0xc7, 0x72, 0xd9, 0xa5, 0x4b, 0xd3, - 0xbe, 0x88, 0x61, 0xa8, 0x76, 0x61, 0x77, 0xfc, 0xff, 0xf9, 0xce, 0x7f, 0xce, 0x21, 0x03, 0x43, - 0x59, 0x97, 0x2d, 0x8b, 0x45, 0x22, 0x62, 0x59, 0xb7, 0xec, 0x6b, 0x53, 0xc5, 0x62, 0x1d, 0x6b, - 0x33, 0x12, 0x2d, 0x57, 0x1c, 0xe3, 0xa3, 0x48, 0x44, 0xa4, 0x89, 0xa8, 0xa9, 0xc2, 0xf7, 0x70, - 0xf3, 0x82, 0xa9, 0x65, 0x57, 0x90, 0xe3, 0x6f, 0xa4, 0xfc, 0xcc, 0xa4, 0x28, 0x3f, 0x30, 0xca, - 0xbe, 0x6c, 0x98, 0x54, 0xf8, 0x06, 0xae, 0x5a, 0xce, 0x55, 0x51, 0x97, 0xb2, 0xf6, 0xcd, 0xa1, - 0x39, 0x72, 0xe9, 0x65, 0x67, 0xbc, 0x2c, 0x65, 0x8d, 0x1f, 0x81, 0xdb, 0xfc, 0x6d, 0x28, 0x3e, - 0x55, 0xbe, 0xa5, 0xeb, 0xce, 0x3f, 0x2f, 0xaf, 0xc2, 0xef, 0x26, 0x3c, 0x3c, 0x9f, 0x2f, 0x05, - 0x6f, 0x24, 0xc3, 0xcf, 0xc0, 0x96, 0xaa, 0x54, 0x1b, 0xa9, 0xd3, 0xef, 0x24, 0x41, 0xf4, 0xff, - 0x92, 0xd1, 0x52, 0x13, 0x13, 0x5e, 0x31, 0x7a, 0xa4, 0xf1, 0x13, 0xb8, 0x68, 0xf9, 0x56, 0xfa, - 0xd6, 0x10, 0x8d, 0x9c, 0xe4, 0xfa, 0x5c, 0x17, 0xe5, 0x5b, 0xaa, 0xa1, 0x90, 0x00, 0xa2, 0x7c, - 0x8b, 0xef, 0x83, 0xad, 0xb1, 0x6e, 0x16, 0x1a, 0xb9, 0xf4, 0xa8, 0x70, 0x0c, 0x03, 0xd1, 0x72, - 0xfe, 0x51, 0x1f, 0xe0, 0x24, 0x0f, 0xce, 0x85, 0x2d, 0x3a, 0x80, 0xf6, 0x5c, 0x98, 0xc1, 0x40, - 0x6b, 0x7c, 0x0f, 0x06, 0x52, 0x95, 0xad, 0xd2, 0xcb, 0x23, 0xda, 0x0b, 0xec, 0x01, 0x62, 0x4d, - 0xff, 0x3b, 0x10, 0xed, 0x3e, 0x3b, 0x8e, 0xf0, 0x8a, 0x49, 0x1f, 0xe9, 0xc1, 0xbd, 0x78, 0xfc, - 0x0e, 0xe0, 0x74, 0x19, 0x76, 0xe0, 0x56, 0x4e, 0xde, 0xa6, 0xb3, 0x7c, 0xea, 0x19, 0xd8, 0x06, - 0x6b, 0xfe, 0xca, 0x33, 0xf1, 0x6d, 0xb8, 0x22, 0xf3, 0x55, 0xf1, 0x7c, 0xfe, 0x86, 0x4c, 0x3d, - 0x0b, 0xbb, 0x70, 0x99, 0x93, 0x55, 0x46, 0x49, 0x3a, 0xf3, 0x10, 0xbe, 0x86, 0xbb, 0x24, 0x7d, - 0x9d, 0x2d, 0x17, 0xe9, 0x24, 0x2b, 0x4e, 0xd8, 0xc5, 0xd8, 0xff, 0xb9, 0x0f, 0xcc, 0xdd, 0x3e, - 0x30, 0x7f, 0xef, 0x03, 0xf3, 0xc7, 0x21, 0x30, 0x76, 0x87, 0xc0, 0xf8, 0x75, 0x08, 0x8c, 0xb5, - 0xad, 0x5f, 0xc2, 0xd3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xba, 0xc1, 0x4e, 0xec, 0x2d, 0x02, - 0x00, 0x00, + // 401 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xcf, 0x6e, 0xd3, 0x40, + 0x10, 0xc6, 0xe3, 0x6c, 0x62, 0xd2, 0xb1, 0x41, 0xd6, 0x80, 0xa8, 0xa1, 0xc8, 0x0a, 0x3e, 0x45, + 0x20, 0xd9, 0x92, 0x91, 0xb8, 0xbb, 0x6d, 0x00, 0x8b, 0xb2, 0xa9, 0x36, 0x05, 0x4e, 0xc8, 0xda, + 0xe2, 0xad, 0x8c, 0x04, 0xde, 0xc5, 0xbb, 0x55, 0xe0, 0xcc, 0x0b, 0xf0, 0x58, 0x1c, 0x7b, 0xe4, + 0x88, 0x92, 0x17, 0x41, 0x5e, 0xa7, 0xf4, 0x40, 0x6e, 0xfb, 0xcd, 0xfc, 0xe6, 0xdf, 0xa7, 0x85, + 0xa9, 0xae, 0x79, 0x2b, 0x52, 0x95, 0xa9, 0x54, 0xd7, 0xad, 0xf8, 0xd6, 0x54, 0xa9, 0x3a, 0x4f, + 0x6d, 0x30, 0x51, 0xad, 0x34, 0x12, 0x71, 0x2b, 0x32, 0x95, 0x58, 0x22, 0x69, 0xaa, 0xf8, 0x03, + 0x1c, 0xbc, 0x14, 0x66, 0xd9, 0x25, 0xf4, 0xe1, 0x77, 0xca, 0xbf, 0x08, 0xad, 0xf8, 0x47, 0xc1, + 0xc4, 0xd7, 0x4b, 0xa1, 0x0d, 0x1e, 0xc0, 0x5e, 0x2b, 0xa5, 0x29, 0x6b, 0xae, 0xeb, 0xd0, 0x99, + 0x3a, 0x33, 0x9f, 0x4d, 0xba, 0xc0, 0x2b, 0xae, 0x6b, 0x7c, 0x0c, 0x7e, 0x73, 0x5d, 0x50, 0x7e, + 0xaa, 0xc2, 0xa1, 0xcd, 0x7b, 0xff, 0x62, 0x45, 0x15, 0xff, 0x70, 0xe0, 0xd1, 0xee, 0xfe, 0x5a, + 0xc9, 0x46, 0x0b, 0x7c, 0x0e, 0xae, 0x36, 0xdc, 0x5c, 0x6a, 0xdb, 0xfd, 0x4e, 0x16, 0x25, 0xff, + 0x2f, 0x99, 0x2c, 0x2d, 0x71, 0x24, 0x2b, 0xc1, 0xb6, 0x34, 0x3e, 0x85, 0x51, 0x2b, 0x57, 0x3a, + 0x1c, 0x4e, 0xc9, 0xcc, 0xcb, 0xf6, 0x77, 0x55, 0x31, 0xb9, 0x62, 0x16, 0x8a, 0x29, 0x10, 0x26, + 0x57, 0x78, 0x1f, 0x5c, 0x8b, 0x75, 0xb3, 0xc8, 0xcc, 0x67, 0x5b, 0x85, 0x29, 0x8c, 0x55, 0x2b, + 0xe5, 0x85, 0x3d, 0xc0, 0xcb, 0x1e, 0xec, 0x6a, 0x76, 0xda, 0x01, 0xac, 0xe7, 0x62, 0x0e, 0x63, + 0xab, 0xf1, 0x1e, 0x8c, 0xb5, 0xe1, 0xad, 0xb1, 0xcb, 0x13, 0xd6, 0x0b, 0x0c, 0x80, 0x88, 0xa6, + 0xb7, 0x83, 0xb0, 0xee, 0xd9, 0x71, 0x8d, 0xac, 0x84, 0x0e, 0x89, 0x1d, 0xdc, 0x0b, 0x7c, 0x08, + 0x93, 0xce, 0xd7, 0xcf, 0x82, 0x5f, 0x84, 0xa3, 0xde, 0xdb, 0x6b, 0xfd, 0xe4, 0x3d, 0xc0, 0xcd, + 0xd5, 0xe8, 0xc1, 0xad, 0x82, 0xbe, 0xcb, 0x4f, 0x8a, 0xe3, 0x60, 0x80, 0x2e, 0x0c, 0x17, 0xaf, + 0x03, 0x07, 0x6f, 0xc3, 0x1e, 0x5d, 0x9c, 0x95, 0x2f, 0x16, 0x6f, 0xe9, 0x71, 0x30, 0x44, 0x1f, + 0x26, 0x05, 0x3d, 0x9b, 0x33, 0x9a, 0x9f, 0x04, 0x04, 0xf7, 0xe1, 0x2e, 0xcd, 0xdf, 0xcc, 0x97, + 0xa7, 0xf9, 0xd1, 0xbc, 0xbc, 0xc1, 0x46, 0x87, 0xe1, 0xaf, 0x75, 0xe4, 0x5c, 0xad, 0x23, 0xe7, + 0xcf, 0x3a, 0x72, 0x7e, 0x6e, 0xa2, 0xc1, 0xd5, 0x26, 0x1a, 0xfc, 0xde, 0x44, 0x83, 0x73, 0xd7, + 0xfe, 0x92, 0x67, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd2, 0x3e, 0x78, 0x01, 0x49, 0x02, 0x00, + 0x00, } func (m *GetSharesByNamespaceRequest) Marshal() (dAtA []byte, err error) { @@ -454,6 +463,13 @@ func (m *Proof) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Hashleaf) > 0 { + i -= len(m.Hashleaf) + copy(dAtA[i:], m.Hashleaf) + i = encodeVarintShare(dAtA, i, uint64(len(m.Hashleaf))) + i-- + dAtA[i] = 0x22 + } if len(m.Nodes) > 0 { for iNdEx := len(m.Nodes) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Nodes[iNdEx]) @@ -559,6 +575,10 @@ func (m *Proof) Size() (n int) { n += 1 + l + sovShare(uint64(l)) } } + l = len(m.Hashleaf) + if l > 0 { + n += 1 + l + sovShare(uint64(l)) + } return n } @@ -1006,6 +1026,40 @@ func (m *Proof) Unmarshal(dAtA []byte) error { m.Nodes = append(m.Nodes, make([]byte, postIndex-iNdEx)) copy(m.Nodes[len(m.Nodes)-1], dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hashleaf", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowShare + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthShare + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthShare + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hashleaf = append(m.Hashleaf[:0], dAtA[iNdEx:postIndex]...) + if m.Hashleaf == nil { + m.Hashleaf = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipShare(dAtA[iNdEx:]) diff --git a/share/p2p/shrexnd/pb/share.proto b/share/p2p/shrexnd/pb/share.proto index 3d6a896641..09d77d29f3 100644 --- a/share/p2p/shrexnd/pb/share.proto +++ b/share/p2p/shrexnd/pb/share.proto @@ -28,5 +28,6 @@ message Row { message Proof { int64 start = 1; int64 end = 2; - repeated bytes Nodes = 3; + repeated bytes nodes = 3; + bytes hashleaf = 4; } diff --git a/share/p2p/shrexnd/server.go b/share/p2p/shrexnd/server.go index 67f64b8393..72c5231eff 100644 --- a/share/p2p/shrexnd/server.go +++ b/share/p2p/shrexnd/server.go @@ -136,9 +136,6 @@ func (srv *Server) handleNamespacedData(ctx context.Context, stream network.Stre logger.Warn("server: nd not found") srv.respondNotFoundError(ctx, logger, stream) return - case errors.Is(err, share.ErrNamespaceNotFound): - srv.respondNamespaceNotFoundError(ctx, logger, stream) - return case err != nil: logger.Errorw("server: retrieving shares", "err", err) srv.respondInternalError(ctx, logger, stream) @@ -170,15 +167,6 @@ func (srv *Server) respondNotFoundError(ctx context.Context, srv.respond(ctx, logger, stream, resp) } -// respondNamespaceNotFoundError sends a namespace not found response to client -func (srv *Server) respondNamespaceNotFoundError(ctx context.Context, - logger *zap.SugaredLogger, stream network.Stream) { - resp := &pb.GetSharesByNamespaceResponse{ - Status: pb.StatusCode_NAMESPACE_NOT_FOUND, - } - srv.respond(ctx, logger, stream, resp) -} - // respondInternalError sends internal error response to client func (srv *Server) respondInternalError(ctx context.Context, logger *zap.SugaredLogger, stream network.Stream) { @@ -192,22 +180,26 @@ func (srv *Server) respondInternalError(ctx context.Context, func namespacedSharesToResponse(shares share.NamespacedShares) *pb.GetSharesByNamespaceResponse { rows := make([]*pb.Row, 0, len(shares)) for _, row := range shares { - proof := &pb.Proof{ - Start: int64(row.Proof.Start()), - End: int64(row.Proof.End()), - Nodes: row.Proof.Nodes(), - } - row := &pb.Row{ Shares: row.Shares, - Proof: proof, + Proof: &pb.Proof{ + Start: int64(row.Proof.Start()), + End: int64(row.Proof.End()), + Nodes: row.Proof.Nodes(), + Hashleaf: row.Proof.LeafHash(), + }, } rows = append(rows, row) } + status := pb.StatusCode_OK + if len(shares) == 0 || (len(shares) == 1 && len(shares[0].Shares) == 0) { + status = pb.StatusCode_NAMESPACE_NOT_FOUND + } + return &pb.GetSharesByNamespaceResponse{ - Status: pb.StatusCode_OK, + Status: status, Rows: rows, } }