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

refactor(share/shwap): shwap types improvements #3437

Merged
merged 4 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
17 changes: 0 additions & 17 deletions share/availability.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,12 @@ import (
"context"
"errors"

"github.com/celestiaorg/celestia-app/pkg/da"
"github.com/celestiaorg/rsmt2d"

"github.com/celestiaorg/celestia-node/header"
)

// ErrNotAvailable is returned whenever DA sampling fails.
var ErrNotAvailable = errors.New("share: data not available")

// Root represents root commitment to multiple Shares.
// In practice, it is a commitment to all the Data in a square.
type Root = da.DataAvailabilityHeader

// NewRoot generates Root(DataAvailabilityHeader) using the
// provided extended data square.
func NewRoot(eds *rsmt2d.ExtendedDataSquare) (*Root, error) {
dah, err := da.NewDataAvailabilityHeader(eds)
if err != nil {
return nil, err
}
return &dah, nil
}

// Availability defines interface for validation of Shares' availability.
//
//go:generate mockgen -destination=availability/mocks/availability.go -package=mocks . Availability
Expand Down
31 changes: 31 additions & 0 deletions share/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package share

import (
"github.com/celestiaorg/celestia-app/pkg/da"
"github.com/celestiaorg/rsmt2d"
)

// Root represents root commitment to multiple Shares.
// In practice, it is a commitment to all the Data in a square.
type Root = da.DataAvailabilityHeader

// NewRoot generates Root(DataAvailabilityHeader) using the
// provided extended data square.
func NewRoot(eds *rsmt2d.ExtendedDataSquare) (*Root, error) {
dah, err := da.NewDataAvailabilityHeader(eds)
if err != nil {
return nil, err
}
return &dah, nil
}

// RowsWithNamespace inspects the Root for the Namespace and provides
// a slices of Row indexes containing the namespace.
func RowsWithNamespace(root *Root, namespace Namespace) (idxs []int) {
for i, row := range root.RowRoots {
if !namespace.IsOutsideRange(row, row) {
idxs = append(idxs, i)
}
}
return
}
13 changes: 0 additions & 13 deletions share/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,3 @@ func RootHashForCoordinates(r *Root, axisType rsmt2d.Axis, rowIdx, colIdx uint)
}
return r.ColumnRoots[colIdx]
}

// FilterRootByNamespace returns the row roots from the given share.Root that contain the namespace.
// It also returns the half open range of the roots that contain the namespace.
func FilterRootByNamespace(root *Root, namespace Namespace) (rowRoots [][]byte, from, to int) {
for i, rowRoot := range root.RowRoots {
if !namespace.IsOutsideRange(rowRoot, rowRoot) {
rowRoots = append(rowRoots, rowRoot)
to = i
}
}
to++
return rowRoots, to - len(rowRoots), to
}
92 changes: 0 additions & 92 deletions share/shwap/data_id.go

This file was deleted.

25 changes: 10 additions & 15 deletions share/shwap/eds_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,7 @@ func NewEdsID(height uint64, root *share.Root) (EdsID, error) {
eid := EdsID{
Height: height,
}
return eid, eid.Verify(root)
}

// MarshalBinary encodes an EdsID into its binary form, primarily for storage or network
// transmission.
func (eid EdsID) MarshalBinary() []byte {
data := make([]byte, 0, EdsIDSize)
return eid.appendTo(data)
return eid, eid.Validate(root)
}

// EdsIDFromBinary decodes a byte slice into an EdsID, validating the length of the data.
Expand All @@ -44,9 +37,16 @@ func EdsIDFromBinary(data []byte) (EdsID, error) {
return rid, nil
}

// Verify checks the integrity of an EdsID's fields against the provided Root.
// MarshalBinary encodes an EdsID into its binary form, primarily for storage or network
// transmission.
func (eid EdsID) MarshalBinary() ([]byte, error) {
data := make([]byte, 0, EdsIDSize)
return eid.appendTo(data), nil
}

// Validate checks the integrity of an EdsID's fields against the provided Root.
// It ensures that the EdsID is not constructed with a zero Height and that the root is not nil.
func (eid EdsID) Verify(root *share.Root) error {
func (eid EdsID) Validate(root *share.Root) error {
if root == nil {
return fmt.Errorf("provided Root is nil")
}
Expand All @@ -56,11 +56,6 @@ func (eid EdsID) Verify(root *share.Root) error {
return nil
}

// GetHeight returns the Height of the EdsID.
func (eid EdsID) GetHeight() uint64 {
return eid.Height
}

// appendTo helps in the binary encoding of EdsID by appending the binary form of Height to the
// given byte slice.
func (eid EdsID) appendTo(data []byte) []byte {
Expand Down
6 changes: 4 additions & 2 deletions share/shwap/eds_id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ func TestEdsID(t *testing.T) {
id, err := NewEdsID(2, root)
require.NoError(t, err)

data := id.MarshalBinary()
data, err := id.MarshalBinary()
require.NoError(t, err)

idOut, err := EdsIDFromBinary(data)
require.NoError(t, err)
assert.EqualValues(t, id, idOut)

err = idOut.Verify(root)
err = idOut.Validate(root)
require.NoError(t, err)
}
66 changes: 66 additions & 0 deletions share/shwap/namespace_data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package shwap

import (
"fmt"

"github.com/celestiaorg/rsmt2d"

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

// NamespacedData stores collections of RowNamespaceData, each representing shares and their proofs
// within a namespace.
type NamespacedData []RowNamespaceData

// NamespacedDataFromEDS extracts shares for a specific namespace from an EDS, considering
// each row independently.
func NamespacedDataFromEDS(
square *rsmt2d.ExtendedDataSquare,
namespace share.Namespace,
) (NamespacedData, error) {
root, err := share.NewRoot(square)
if err != nil {
return nil, fmt.Errorf("error computing root: %w", err)
}

rows := make(NamespacedData, 0, len(root.RowRoots))
for rowIdx, rowRoot := range root.RowRoots {
if namespace.IsOutsideRange(rowRoot, rowRoot) {
continue
}

shares := square.Row(uint(rowIdx))
rowData, err := RowNamespaceDataFromShares(shares, namespace, rowIdx)
if err != nil {
return nil, fmt.Errorf("failed to process row %d: %w", rowIdx, err)
}

rows = append(rows, rowData)
}

return rows, nil
}

// Flatten combines all shares from all rows within the namespace into a single slice.
func (ns NamespacedData) Flatten() []share.Share {
var shares []share.Share
for _, row := range ns {
shares = append(shares, row.Shares...)
}
return shares
}

// Validate checks the integrity of the NamespacedData against a provided root and namespace.
func (ns NamespacedData) Validate(root *share.Root, namespace share.Namespace) error {
rowIdxs := share.RowsWithNamespace(root, namespace)
if len(rowIdxs) != len(ns) {
return fmt.Errorf("expected %d rows, found %d rows", len(rowIdxs), len(ns))
}

for i, row := range ns {
if err := row.Validate(root, namespace, rowIdxs[i]); err != nil {
return fmt.Errorf("validating row: %w", err)
}
}
return nil
}
25 changes: 12 additions & 13 deletions share/shwap/namespaced_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestNamespacedRowFromShares(t *testing.T) {
require.NoError(t, err)
extended := slices.Concat(shares, parity)

nr, err := NamespacedRowFromShares(extended, minNamespace, 0)
nr, err := RowNamespaceDataFromShares(extended, minNamespace, 0)
require.NoError(t, err)
require.Equal(t, namespacedAmount, len(nr.Shares))
}
Expand All @@ -46,7 +46,7 @@ func TestNamespacedRowFromSharesNonIncluded(t *testing.T) {
require.NoError(t, err)
extended := slices.Concat(shares, parity)

nr, err := NamespacedRowFromShares(extended, absentNs, 0)
nr, err := RowNamespaceDataFromShares(extended, absentNs, 0)
require.NoError(t, err)
require.Len(t, nr.Shares, 0)
require.True(t, nr.Proof.IsOfAbsence())
Expand All @@ -58,12 +58,12 @@ func TestNamespacedSharesFromEDS(t *testing.T) {
namespace := sharetest.RandV0Namespace()
for amount := 1; amount < sharesAmount; amount++ {
eds, root := edstest.RandEDSWithNamespace(t, namespace, amount, odsSize)
nd, err := NewNamespacedSharesFromEDS(eds, namespace)
nd, err := NamespacedDataFromEDS(eds, namespace)
require.NoError(t, err)
require.True(t, len(nd) > 0)
require.Len(t, nd.Flatten(), amount)

err = nd.Verify(root, namespace)
err = nd.Validate(root, namespace)
require.NoError(t, err)
}
}
Expand All @@ -74,17 +74,16 @@ func TestValidateNamespacedRow(t *testing.T) {
namespace := sharetest.RandV0Namespace()
for amount := 1; amount < sharesAmount; amount++ {
eds, root := edstest.RandEDSWithNamespace(t, namespace, amount, odsSize)
nd, err := NewNamespacedSharesFromEDS(eds, namespace)
nd, err := NamespacedDataFromEDS(eds, namespace)
require.NoError(t, err)
require.True(t, len(nd) > 0)

_, from, to := share.FilterRootByNamespace(root, namespace)
require.Len(t, nd, to-from)
idx := from
for _, row := range nd {
err = row.Validate(root, namespace, idx)
rowIdx := share.RowsWithNamespace(root, namespace)
require.Len(t, nd, len(rowIdx))

for i, rowIdx := range rowIdx {
err = nd[i].Validate(root, namespace, rowIdx)
require.NoError(t, err)
idx++
}
}
}
Expand All @@ -93,12 +92,12 @@ func TestNamespacedRowProtoEncoding(t *testing.T) {
const odsSize = 8
namespace := sharetest.RandV0Namespace()
eds, _ := edstest.RandEDSWithNamespace(t, namespace, odsSize, odsSize)
nd, err := NewNamespacedSharesFromEDS(eds, namespace)
nd, err := NamespacedDataFromEDS(eds, namespace)
require.NoError(t, err)
require.True(t, len(nd) > 0)

expected := nd[0]
pb := expected.ToProto()
ndOut := NamespacedRowFromProto(pb)
ndOut := RowNamespaceDataFromProto(pb)
require.Equal(t, expected, ndOut)
}
Loading
Loading