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

refactoring(share/ipld)!: rework getLeavesByNamespace #1870

Merged
merged 10 commits into from
Mar 24, 2023
16 changes: 9 additions & 7 deletions share/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ipfs/go-cid"
format "github.com/ipfs/go-ipld-format"

"github.com/celestiaorg/nmt"
"github.com/celestiaorg/nmt/namespace"

"github.com/celestiaorg/celestia-node/share/ipld"
Expand Down Expand Up @@ -50,24 +51,25 @@ func GetSharesByNamespace(
root cid.Cid,
nID namespace.ID,
maxShares int,
proofContainer *ipld.Proof,
) ([]Share, error) {
) ([]Share, *nmt.Proof, error) {
ctx, span := tracer.Start(ctx, "get-shares-by-namespace")
defer span.End()

leaves, err := ipld.GetLeavesByNamespace(ctx, bGetter, root, nID, maxShares, proofContainer)
if err != nil && leaves == nil {
return nil, err
data := ipld.NewNamespaceData(maxShares, nID, ipld.WithLeaves(), ipld.WithProofs())
err := data.CollectLeavesByNamespace(ctx, bGetter, root)
if err != nil {
return nil, nil, err
}

leaves := data.Leaves()

shares := make([]Share, len(leaves))
for i, leaf := range leaves {
if leaf != nil {
shares[i] = leafToShare(leaf)
}
}

return shares, err
return shares, data.Proof(), err
}

// leafToShare converts an NMT leaf into a Share.
Expand Down
52 changes: 26 additions & 26 deletions share/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/stretchr/testify/require"

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

Expand Down Expand Up @@ -168,7 +167,7 @@ func TestGetSharesByNamespace(t *testing.T) {
var shares []Share
for _, row := range eds.RowRoots() {
rcid := ipld.MustCidFromNamespacedSha256(row)
rowShares, err := GetSharesByNamespace(ctx, bServ, rcid, nID, len(eds.RowRoots()), nil)
rowShares, _, err := GetSharesByNamespace(ctx, bServ, rcid, nID, len(eds.RowRoots()))
require.NoError(t, err)

shares = append(shares, rowShares...)
Expand All @@ -182,7 +181,7 @@ func TestGetSharesByNamespace(t *testing.T) {
}
}

func TestGetLeavesByNamespace_IncompleteData(t *testing.T) {
func TestCollectLeavesByNamespace_IncompleteData(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
bServ := mdutils.Bserv()
Expand Down Expand Up @@ -222,13 +221,15 @@ func TestGetLeavesByNamespace_IncompleteData(t *testing.T) {
err = bServ.DeleteBlock(ctx, r.Cid())
require.NoError(t, err)

leaves, err := ipld.GetLeavesByNamespace(ctx, bServ, rcid, nid, len(shares), nil)
namespaceData := ipld.NewNamespaceData(len(shares), nid, ipld.WithLeaves())
err = namespaceData.CollectLeavesByNamespace(ctx, bServ, rcid)
leaves := namespaceData.Leaves()
assert.Nil(t, leaves[1])
assert.Equal(t, 4, len(leaves))
require.Error(t, err)
}

func TestGetLeavesByNamespace_AbsentNamespaceId(t *testing.T) {
func TestCollectLeavesByNamespace_AbsentNamespaceId(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
bServ := mdutils.Bserv()
Expand Down Expand Up @@ -279,7 +280,7 @@ func TestGetLeavesByNamespace_AbsentNamespaceId(t *testing.T) {
}
}

func TestGetLeavesByNamespace_MultipleRowsContainingSameNamespaceId(t *testing.T) {
func TestCollectLeavesByNamespace_MultipleRowsContainingSameNamespaceId(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
bServ := mdutils.Bserv()
Expand All @@ -303,11 +304,12 @@ func TestGetLeavesByNamespace_MultipleRowsContainingSameNamespaceId(t *testing.T

for _, row := range eds.RowRoots() {
rcid := ipld.MustCidFromNamespacedSha256(row)
leaves, err := ipld.GetLeavesByNamespace(ctx, bServ, rcid, nid, len(shares), nil)
data := ipld.NewNamespaceData(len(shares), nid, ipld.WithLeaves())
err := data.CollectLeavesByNamespace(ctx, bServ, rcid)
assert.Nil(t, err)

leaves := data.Leaves()
for _, node := range leaves {
// test that the data returned by getLeavesByNamespace for nid
// test that the data returned by collectLeavesByNamespace for nid
// matches the commonNamespaceData that was copied across almost all data
assert.Equal(t, commonNamespaceData, node.RawData()[NamespaceSize:])
}
Expand Down Expand Up @@ -353,10 +355,10 @@ func TestGetSharesWithProofsByNamespace(t *testing.T) {
var shares []Share
for _, row := range eds.RowRoots() {
rcid := ipld.MustCidFromNamespacedSha256(row)
proof := new(ipld.Proof)
rowShares, err := GetSharesByNamespace(ctx, bServ, rcid, nID, len(eds.RowRoots()), proof)
rowShares, proof, err := GetSharesByNamespace(ctx, bServ, rcid, nID, len(eds.RowRoots()))
require.NoError(t, err)
if rowShares != nil {
if len(rowShares) > 0 {
require.NotNil(t, proof)
// append shares to check integrity later
shares = append(shares, rowShares...)

Expand All @@ -366,23 +368,19 @@ func TestGetSharesWithProofsByNamespace(t *testing.T) {
leaves = append(leaves, append(sh[:NamespaceSize], sh...))
}

proofNodes := make([][]byte, 0, len(proof.Nodes))
for _, n := range proof.Nodes {
proofNodes = append(proofNodes, ipld.NamespacedSha256FromCID(n))
}

// construct new proof
inclusionProof := nmt.NewInclusionProof(
proof.Start,
proof.End,
proofNodes,
ipld.NMTIgnoreMaxNamespace)
// verify namespace
verified := proof.VerifyNamespace(
sha256.New(),
nID,
leaves,
ipld.NamespacedSha256FromCID(rcid))
require.True(t, verified)

// verify inclusion
verified := inclusionProof.VerifyNamespace(
verified = proof.VerifyInclusion(
sha256.New(),
nID,
leaves,
rowShares,
ipld.NamespacedSha256FromCID(rcid))
require.True(t, verified)
}
Expand Down Expand Up @@ -448,7 +446,9 @@ func assertNoRowContainsNID(

// for each row root cid check if the minNID exists
for _, rowCID := range rowRootCIDs {
leaves, err := ipld.GetLeavesByNamespace(context.Background(), bServ, rowCID, nID, rowRootCount, nil)
data := ipld.NewNamespaceData(rowRootCount, nID, ipld.WithProofs())
err := data.CollectLeavesByNamespace(context.Background(), bServ, rowCID)
leaves := data.Leaves()
assert.Nil(t, leaves)
assert.Nil(t, err)
}
Expand Down
20 changes: 3 additions & 17 deletions share/getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"github.com/celestiaorg/nmt"
"github.com/celestiaorg/nmt/namespace"
"github.com/celestiaorg/rsmt2d"

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

// Getter interface provides a set of accessors for shares by the Root.
Expand Down Expand Up @@ -44,7 +42,7 @@ func (ns NamespacedShares) Flatten() []Share {
// NamespacedRow represents all shares with proofs within a specific namespace of a single EDS row.
type NamespacedRow struct {
Shares []Share
Proof *ipld.Proof
Proof *nmt.Proof
}

// Verify validates NamespacedShares by checking every row with nmt inclusion proof.
Expand Down Expand Up @@ -78,20 +76,8 @@ func (row *NamespacedRow) verify(rowRoot []byte, nID namespace.ID) bool {
leaves = append(leaves, append(sh[:NamespaceSize], sh...))
}

proofNodes := make([][]byte, 0, len(row.Proof.Nodes))
for _, n := range row.Proof.Nodes {
proofNodes = append(proofNodes, ipld.NamespacedSha256FromCID(n))
}

// construct new proof
inclusionProof := nmt.NewInclusionProof(
row.Proof.Start,
row.Proof.End,
proofNodes,
ipld.NMTIgnoreMaxNamespace)

// verify inclusion
return inclusionProof.VerifyNamespace(
// verify namespace
return row.Proof.VerifyNamespace(
sha256.New(),
nID,
leaves,
Expand Down
3 changes: 1 addition & 2 deletions share/getters/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ func collectSharesByNamespace(
// shadow loop variables, to ensure correct values are captured
i, rootCID := i, rootCID
errGroup.Go(func() error {
proof := new(ipld.Proof)
row, err := share.GetSharesByNamespace(ctx, bg, rootCID, nID, len(root.RowsRoots), proof)
row, proof, err := share.GetSharesByNamespace(ctx, bg, rootCID, nID, len(root.RowsRoots))
shares[i] = share.NamespacedRow{
Shares: row,
Proof: proof,
Expand Down
Loading