Skip to content

Commit

Permalink
rearrange methods and missing comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Wondertan committed May 27, 2024
1 parent 10be1be commit 48fcb3c
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 202 deletions.
14 changes: 7 additions & 7 deletions share/shwap/eds_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@ func NewEdsID(height uint64, root *share.Root) (EdsID, error) {
return eid, eid.Validate(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
}

// EdsIDFromBinary decodes a byte slice into an EdsID, validating the length of the data.
// It returns an error if the data slice does not match the expected size of an EdsID.
func EdsIDFromBinary(data []byte) (EdsID, error) {
Expand All @@ -44,6 +37,13 @@ func EdsIDFromBinary(data []byte) (EdsID, error) {
return rid, nil
}

// 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) Validate(root *share.Root) error {
Expand Down
48 changes: 24 additions & 24 deletions share/shwap/namespace_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,6 @@ import (
// within a namespace.
type NamespacedData []RowNamespaceData

// 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
}

// NamespacedDataFromEDS extracts shares for a specific namespace from an EDS, considering
// each row independently.
func NamespacedDataFromEDS(
Expand Down Expand Up @@ -64,3 +40,27 @@ func NamespacedDataFromEDS(

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
}
90 changes: 45 additions & 45 deletions share/shwap/row.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,51 @@ func NewRow(halfShares []share.Share, side RowSide) Row {
}
}

// RowFromEDS constructs a new Row from an Extended Data Square based on the specified index and
// side.
func RowFromEDS(square *rsmt2d.ExtendedDataSquare, idx int, side RowSide) Row {
sqrLn := int(square.Width())
shares := square.Row(uint(idx))
var halfShares []share.Share
if side == Right {
halfShares = shares[sqrLn/2:] // Take the right half of the shares.
} else {
halfShares = shares[:sqrLn/2] // Take the left half of the shares.
}

return NewRow(halfShares, side)
}

// RowFromProto converts a protobuf Row to a Row structure.
func RowFromProto(r *pb.Row) Row {
return Row{
halfShares: SharesFromProto(r.SharesHalf),
side: sideFromProto(r.GetHalfSide()),
}
}

// Shares reconstructs the complete row shares from the half provided, using RSMT2D for data
// recovery if needed.
func (r Row) Shares() ([]share.Share, error) {
shares := make([]share.Share, len(r.halfShares)*2)
offset := 0
if r.side == Right {
offset = len(r.halfShares) // Position the halfShares in the second half if it's the right side.
}
for i, share := range r.halfShares {
shares[i+offset] = share
}
return share.DefaultRSMT2DCodec().Decode(shares)
}

// ToProto converts the Row to its protobuf representation.
func (r Row) ToProto() *pb.Row {
return &pb.Row{
SharesHalf: SharesToProto(r.halfShares),
HalfSide: r.side.ToProto(),
}
}

// Validate checks if the row's shares match the expected number from the root data and validates
// the side of the row.
func (r Row) Validate(dah *share.Root, idx int) error {
Expand Down Expand Up @@ -80,51 +125,6 @@ func (r Row) verifyInclusion(dah *share.Root, idx int) error {
return nil
}

// Shares reconstructs the complete row shares from the half provided, using RSMT2D for data
// recovery if needed.
func (r Row) Shares() ([]share.Share, error) {
shares := make([]share.Share, len(r.halfShares)*2)
offset := 0
if r.side == Right {
offset = len(r.halfShares) // Position the halfShares in the second half if it's the right side.
}
for i, share := range r.halfShares {
shares[i+offset] = share
}
return share.DefaultRSMT2DCodec().Decode(shares)
}

// ToProto converts the Row to its protobuf representation.
func (r Row) ToProto() *pb.Row {
return &pb.Row{
SharesHalf: SharesToProto(r.halfShares),
HalfSide: r.side.ToProto(),
}
}

// RowFromProto converts a protobuf Row to a Row structure.
func RowFromProto(r *pb.Row) Row {
return Row{
halfShares: SharesFromProto(r.SharesHalf),
side: sideFromProto(r.GetHalfSide()),
}
}

// NewRowFromEDS constructs a new Row from an Extended Data Square based on the specified index and
// side.
func NewRowFromEDS(square *rsmt2d.ExtendedDataSquare, idx int, side RowSide) Row {
sqrLn := int(square.Width())
shares := square.Row(uint(idx))
var halfShares []share.Share
if side == Right {
halfShares = shares[sqrLn/2:] // Take the right half of the shares.
} else {
halfShares = shares[:sqrLn/2] // Take the left half of the shares.
}

return NewRow(halfShares, side)
}

// ToProto converts a RowSide to its protobuf representation.
func (s RowSide) ToProto() pb.Row_HalfSide {
if s == Left {
Expand Down
12 changes: 6 additions & 6 deletions share/shwap/row_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ func NewRowID(height uint64, rowIdx int, root *share.Root) (RowID, error) {
return rid, rid.Validate(root)
}

// MarshalBinary encodes the RowID into a binary form for storage or network transmission.
func (rid RowID) MarshalBinary() ([]byte, error) {
data := make([]byte, 0, RowIDSize)
return rid.appendTo(data), nil
}

// RowIDFromBinary decodes a RowID from its binary representation.
// It returns an error if the input data does not conform to the expected size or content format.
func RowIDFromBinary(data []byte) (RowID, error) {
Expand All @@ -53,6 +47,12 @@ func RowIDFromBinary(data []byte) (RowID, error) {
}, nil
}

// MarshalBinary encodes the RowID into a binary form for storage or network transmission.
func (rid RowID) MarshalBinary() ([]byte, error) {
data := make([]byte, 0, RowIDSize)
return rid.appendTo(data), nil
}

// Validate ensures the RowID's fields are valid given the specified root structure, particularly
// that the row index is within bounds.
func (rid RowID) Validate(root *share.Root) error {
Expand Down
116 changes: 60 additions & 56 deletions share/shwap/row_namespace_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,62 +19,8 @@ type RowNamespaceData struct {
Proof *nmt.Proof `json:"proof"` // Proof of the shares' inclusion in the namespace.
}

func (rnd RowNamespaceData) Validate(dah *share.Root, namespace share.Namespace, rowIdx int) error {
if rnd.Proof == nil || rnd.Proof.IsEmptyProof() {
return fmt.Errorf("nil proof")
}
if len(rnd.Shares) == 0 && !rnd.Proof.IsOfAbsence() {
return fmt.Errorf("empty shares with non-absence proof for row %d", rowIdx)
}

if len(rnd.Shares) > 0 && rnd.Proof.IsOfAbsence() {
return fmt.Errorf("non-empty shares with absence proof for row %d", rowIdx)
}

if err := ValidateShares(rnd.Shares); err != nil {
return fmt.Errorf("invalid shares: %w", err)
}

rowRoot := dah.RowRoots[rowIdx]
if namespace.IsOutsideRange(rowRoot, rowRoot) {
return fmt.Errorf("namespace out of range for row %d", rowIdx)
}

if !rnd.verifyInclusion(rowRoot, namespace) {
return fmt.Errorf("inclusion proof failed for row %d", rowIdx)
}
return nil
}

// verifyInclusion checks the inclusion of the row's shares in the provided root using NMT.
func (rnd RowNamespaceData) verifyInclusion(rowRoot []byte, namespace share.Namespace) bool {
leaves := make([][]byte, 0, len(rnd.Shares))
for _, shr := range rnd.Shares {
namespaceBytes := share.GetNamespace(shr)
leaves = append(leaves, append(namespaceBytes, shr...))
}
return rnd.Proof.VerifyNamespace(
sha256.New(),
namespace.ToNMT(),
leaves,
rowRoot,
)
}

// ToProto converts RowNamespaceData to its protobuf representation for serialization.
func (rnd RowNamespaceData) ToProto() *pb.RowNamespaceData {
return &pb.RowNamespaceData{
Shares: SharesToProto(rnd.Shares),
Proof: &nmt_pb.Proof{
Start: int64(rnd.Proof.Start()),
End: int64(rnd.Proof.End()),
Nodes: rnd.Proof.Nodes(),
LeafHash: rnd.Proof.LeafHash(),
IsMaxNamespaceIgnored: rnd.Proof.IsMaxNamespaceIDIgnored(),
},
}
}

// RowNamespaceDataFromEDS extracts and constructs a RowNamespaceData from the row of given EDS
// identified by the index and the namespace.
func RowNamespaceDataFromEDS(
eds *rsmt2d.ExtendedDataSquare,
namespace share.Namespace,
Expand Down Expand Up @@ -134,6 +80,7 @@ func RowNamespaceDataFromShares(
}, nil
}

// RowNamespaceDataFromProto constructs RowNamespaceData out of its protobuf representation.
func RowNamespaceDataFromProto(row *pb.RowNamespaceData) RowNamespaceData {
var proof nmt.Proof
if row.GetProof().GetLeafHash() != nil {
Expand All @@ -158,3 +105,60 @@ func RowNamespaceDataFromProto(row *pb.RowNamespaceData) RowNamespaceData {
Proof: &proof,
}
}

// ToProto converts RowNamespaceData to its protobuf representation for serialization.
func (rnd RowNamespaceData) ToProto() *pb.RowNamespaceData {
return &pb.RowNamespaceData{
Shares: SharesToProto(rnd.Shares),
Proof: &nmt_pb.Proof{
Start: int64(rnd.Proof.Start()),
End: int64(rnd.Proof.End()),
Nodes: rnd.Proof.Nodes(),
LeafHash: rnd.Proof.LeafHash(),
IsMaxNamespaceIgnored: rnd.Proof.IsMaxNamespaceIDIgnored(),
},
}
}

// Validate checks validity of the RowNamespaceData against the Root, Namespace and Row index.
func (rnd RowNamespaceData) Validate(dah *share.Root, namespace share.Namespace, rowIdx int) error {
if rnd.Proof == nil || rnd.Proof.IsEmptyProof() {
return fmt.Errorf("nil proof")
}
if len(rnd.Shares) == 0 && !rnd.Proof.IsOfAbsence() {
return fmt.Errorf("empty shares with non-absence proof for row %d", rowIdx)
}

if len(rnd.Shares) > 0 && rnd.Proof.IsOfAbsence() {
return fmt.Errorf("non-empty shares with absence proof for row %d", rowIdx)
}

if err := ValidateShares(rnd.Shares); err != nil {
return fmt.Errorf("invalid shares: %w", err)
}

rowRoot := dah.RowRoots[rowIdx]
if namespace.IsOutsideRange(rowRoot, rowRoot) {
return fmt.Errorf("namespace out of range for row %d", rowIdx)
}

if !rnd.verifyInclusion(rowRoot, namespace) {
return fmt.Errorf("inclusion proof failed for row %d", rowIdx)
}
return nil
}

// verifyInclusion checks the inclusion of the row's shares in the provided root using NMT.
func (rnd RowNamespaceData) verifyInclusion(rowRoot []byte, namespace share.Namespace) bool {
leaves := make([][]byte, 0, len(rnd.Shares))
for _, shr := range rnd.Shares {
namespaceBytes := share.GetNamespace(shr)
leaves = append(leaves, append(namespaceBytes, shr...))
}
return rnd.Proof.VerifyNamespace(
sha256.New(),
namespace.ToNMT(),
leaves,
rowRoot,
)
}
18 changes: 9 additions & 9 deletions share/shwap/row_namespace_data_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,6 @@ func NewRowNamespaceDataID(
return did, nil
}

// MarshalBinary encodes RowNamespaceDataID into binary form.
// NOTE: Proto is avoided because
// * Its size is not deterministic which is required for IPLD.
// * No support for uint16
func (s RowNamespaceDataID) MarshalBinary() ([]byte, error) {
data := make([]byte, 0, RowNamespaceDataIDSize)
return s.appendTo(data), nil
}

// RowNamespaceDataIDFromBinary deserializes a RowNamespaceDataID from its binary form. It returns
// an error if the binary data's length does not match the expected size.
func RowNamespaceDataIDFromBinary(data []byte) (RowNamespaceDataID, error) {
Expand All @@ -75,6 +66,15 @@ func RowNamespaceDataIDFromBinary(data []byte) (RowNamespaceDataID, error) {
}, nil
}

// MarshalBinary encodes RowNamespaceDataID into binary form.
// NOTE: Proto is avoided because
// * Its size is not deterministic which is required for IPLD.
// * No support for uint16
func (s RowNamespaceDataID) MarshalBinary() ([]byte, error) {
data := make([]byte, 0, RowNamespaceDataIDSize)
return s.appendTo(data), nil
}

// Validate checks the validity of RowNamespaceDataID's fields, including the RowID and the
// namespace.
func (s RowNamespaceDataID) Validate(root *share.Root) error {
Expand Down
Loading

0 comments on commit 48fcb3c

Please sign in to comment.