From e61e9fb2086d1b89edf7ab1d930b42ce7de21702 Mon Sep 17 00:00:00 2001 From: Vlad <13818348+walldiss@users.noreply.github.com> Date: Wed, 8 May 2024 17:11:48 +0500 Subject: [PATCH 1/7] add shwap types --- share/share.go | 8 + share/shwap/data_id.go | 92 +++ share/shwap/data_id_test.go | 27 + share/shwap/eds_id.go | 68 ++ share/shwap/eds_id_test.go | 28 + share/shwap/namespaced_data.go | 193 ++++++ share/shwap/proto/types.pb.go | 1114 ++++++++++++++++++++++++++++++++ share/shwap/proto/types.proto | 35 + share/shwap/row.go | 139 ++++ share/shwap/row_id.go | 80 +++ share/shwap/row_id_test.go | 28 + share/shwap/sample.go | 119 ++++ share/shwap/sample_id.go | 92 +++ share/shwap/sample_id_test.go | 28 + share/shwap/share.go | 37 ++ 15 files changed, 2088 insertions(+) create mode 100644 share/shwap/data_id.go create mode 100644 share/shwap/data_id_test.go create mode 100644 share/shwap/eds_id.go create mode 100644 share/shwap/eds_id_test.go create mode 100644 share/shwap/namespaced_data.go create mode 100644 share/shwap/proto/types.pb.go create mode 100644 share/shwap/proto/types.proto create mode 100644 share/shwap/row.go create mode 100644 share/shwap/row_id.go create mode 100644 share/shwap/row_id_test.go create mode 100644 share/shwap/sample.go create mode 100644 share/shwap/sample_id.go create mode 100644 share/shwap/sample_id_test.go create mode 100644 share/shwap/share.go diff --git a/share/share.go b/share/share.go index f140685eaf..f79e168022 100644 --- a/share/share.go +++ b/share/share.go @@ -101,3 +101,11 @@ func MustDataHashFromString(datahash string) DataHash { func NewSHA256Hasher() hash.Hash { return sha256.New() } + +// RootHashForCoordinates returns the root hash for the given coordinates. +func RootHashForCoordinates(r *Root, axisType rsmt2d.Axis, colIdx, rowIdx uint) []byte { + if axisType == rsmt2d.Row { + return r.RowRoots[rowIdx] + } + return r.ColumnRoots[colIdx] +} diff --git a/share/shwap/data_id.go b/share/shwap/data_id.go new file mode 100644 index 0000000000..729bb4e5e0 --- /dev/null +++ b/share/shwap/data_id.go @@ -0,0 +1,92 @@ +package shwap + +import ( + "fmt" + + "github.com/celestiaorg/celestia-node/share" +) + +// DataIDSize defines the total size of a DataID in bytes, combining the size of a RowID and the +// size of a Namespace. +const DataIDSize = RowIDSize + share.NamespaceSize + +// DataID uniquely identifies a piece of namespaced data within a row of an Extended Data Square +// (EDS). +type DataID struct { + RowID // Embedded RowID representing the specific row in the EDS. + DataNamespace string // DataNamespace is a string representation of the namespace to facilitate comparisons. + // TODO(@walldiss): Remove the need for string comparisons after updating the bitswap global roots + // cache to use reference counting. +} + +// NewDataID creates a new DataID with the specified parameters. It validates the DataID against +// the provided Root before returning. +func NewDataID(height uint64, rowIdx uint16, namespace share.Namespace, root *share.Root) (DataID, error) { + did := DataID{ + RowID: RowID{ + EdsID: EdsID{ + Height: height, + }, + RowIndex: rowIdx, + }, + DataNamespace: string(namespace), + } + + if err := did.Verify(root); err != nil { + return DataID{}, err + } + return did, nil +} + +// Namespace retrieves the namespace part of the DataID as a share.Namespace type. +func (s DataID) Namespace() share.Namespace { + return share.Namespace(s.DataNamespace) +} + +// MarshalBinary encodes DataID into binary form. +// NOTE: Proto is avoided because +// * Its size is not deterministic which is required for IPLD. +// * No support for uint16 +func (s DataID) MarshalBinary() []byte { + data := make([]byte, 0, DataIDSize) + return s.appendTo(data) +} + +// DataIDFromBinary deserializes a DataID from its binary form. It returns an error if the binary +// data's length does not match the expected size. +func DataIDFromBinary(data []byte) (DataID, error) { + if len(data) != DataIDSize { + return DataID{}, fmt.Errorf("invalid DataID data length: expected %d, got %d", DataIDSize, len(data)) + } + + rid, err := RowIDFromBinary(data[:RowIDSize]) + if err != nil { + return DataID{}, fmt.Errorf("error unmarshaling RowID: %w", err) + } + + nsData := data[RowIDSize:] + ns := share.Namespace(nsData) + if err := ns.ValidateForData(); err != nil { + return DataID{}, fmt.Errorf("error validating DataNamespace: %w", err) + } + + return DataID{RowID: rid, DataNamespace: string(ns)}, nil +} + +// Verify checks the validity of DataID's fields, including the RowID and the namespace. +func (s DataID) Verify(root *share.Root) error { + if err := s.RowID.Verify(root); err != nil { + return fmt.Errorf("error validating RowID: %w", err) + } + if err := s.Namespace().ValidateForData(); err != nil { + return fmt.Errorf("error validating DataNamespace: %w", err) + } + + return nil +} + +// appendTo helps in appending the binary form of DataNamespace to the serialized RowID data. +func (s DataID) appendTo(data []byte) []byte { + data = s.RowID.appendTo(data) + return append(data, s.DataNamespace...) +} diff --git a/share/shwap/data_id_test.go b/share/shwap/data_id_test.go new file mode 100644 index 0000000000..38dad94f8f --- /dev/null +++ b/share/shwap/data_id_test.go @@ -0,0 +1,27 @@ +package shwap + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/celestiaorg/celestia-node/share/eds/edstest" + "github.com/celestiaorg/celestia-node/share/sharetest" +) + +func TestDataID(t *testing.T) { + ns := sharetest.RandV0Namespace() + _, root := edstest.RandEDSWithNamespace(t, ns, 8, 4) + + id, err := NewDataID(1, 1, ns, root) + require.NoError(t, err) + + data := id.MarshalBinary() + sidOut, err := DataIDFromBinary(data) + require.NoError(t, err) + assert.EqualValues(t, id, sidOut) + + err = sidOut.Verify(root) + require.NoError(t, err) +} diff --git a/share/shwap/eds_id.go b/share/shwap/eds_id.go new file mode 100644 index 0000000000..83d7cc737b --- /dev/null +++ b/share/shwap/eds_id.go @@ -0,0 +1,68 @@ +package shwap + +import ( + "encoding/binary" + "fmt" + + "github.com/celestiaorg/celestia-node/share" +) + +// EdsIDSize defines the byte size of the EdsID. +const EdsIDSize = 8 + +// EdsID represents a unique identifier for a row, using the height of the block +// to identify the data square in the chain. +type EdsID struct { + Height uint64 // Height specifies the block height. +} + +// NewEdsID creates a new EdsID using the given height and verifies it against the provided Root. +// It returns an error if the verification fails. +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) +} + +// 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) { + if len(data) != EdsIDSize { + return EdsID{}, fmt.Errorf("invalid EdsID data length: %d != %d", len(data), EdsIDSize) + } + rid := EdsID{ + Height: binary.BigEndian.Uint64(data), + } + return rid, nil +} + +// Verify 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 { + if root == nil { + return fmt.Errorf("provided Root is nil") + } + if eid.Height == 0 { + return fmt.Errorf("height cannot be zero") + } + 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 { + return binary.BigEndian.AppendUint64(data, eid.Height) +} diff --git a/share/shwap/eds_id_test.go b/share/shwap/eds_id_test.go new file mode 100644 index 0000000000..c9296eef4d --- /dev/null +++ b/share/shwap/eds_id_test.go @@ -0,0 +1,28 @@ +package shwap + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/edstest" +) + +func TestEdsID(t *testing.T) { + square := edstest.RandEDS(t, 2) + root, err := share.NewRoot(square) + require.NoError(t, err) + + id, err := NewEdsID(2, root) + require.NoError(t, err) + + data := id.MarshalBinary() + idOut, err := EdsIDFromBinary(data) + require.NoError(t, err) + assert.EqualValues(t, id, idOut) + + err = idOut.Verify(root) + require.NoError(t, err) +} diff --git a/share/shwap/namespaced_data.go b/share/shwap/namespaced_data.go new file mode 100644 index 0000000000..65afa67687 --- /dev/null +++ b/share/shwap/namespaced_data.go @@ -0,0 +1,193 @@ +package shwap + +import ( + "crypto/sha256" + "fmt" + + "github.com/celestiaorg/celestia-app/pkg/wrapper" + "github.com/celestiaorg/nmt" + nmt_pb "github.com/celestiaorg/nmt/pb" + "github.com/celestiaorg/rsmt2d" + + "github.com/celestiaorg/celestia-node/share" + types_pb "github.com/celestiaorg/celestia-node/share/shwap/proto" +) + +// NamespacedData stores collections of RowNamespaceData, each representing shares and their proofs +// 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 +} + +// RowNamespaceData holds shares and their corresponding proof for a single row within a namespace. +type RowNamespaceData struct { + Shares []share.Share `json:"shares"` // Shares within the namespace. + Proof *nmt.Proof `json:"proof"` // Proof of the shares' inclusion in the namespace. +} + +// Verify checks the integrity of the NamespacedData against a provided root and namespace. +func (ns NamespacedData) Verify(root *share.Root, namespace share.Namespace) error { + var originalRoots [][]byte + for _, rowRoot := range root.RowRoots { + if !namespace.IsOutsideRange(rowRoot, rowRoot) { + originalRoots = append(originalRoots, rowRoot) + } + } + + if len(originalRoots) != len(ns) { + return fmt.Errorf("expected %d rows, found %d rows", len(originalRoots), len(ns)) + } + + for i, row := range ns { + if row.Proof == nil || len(row.Shares) == 0 { + return fmt.Errorf("row %d is missing proofs or shares", i) + } + if !row.VerifyInclusion(originalRoots[i], namespace) { + return fmt.Errorf("failed to verify row %d", i) + } + } + return nil +} + +func (rnd RowNamespaceData) Validate(dah *share.Root, rowIdx int, namespace share.Namespace) error { + if len(rnd.Shares) == 0 && rnd.Proof.IsEmptyProof() { + return fmt.Errorf("row contains no data or proof") + } + + 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() *types_pb.RowNamespaceData { + return &types_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(), + }, + } +} + +// NewNamespacedSharesFromEDS extracts shares for a specific namespace from an EDS, considering +// each row independently. +func NewNamespacedSharesFromEDS( + 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 := NamespacedRowFromShares(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 +} + +// NamespacedRowFromShares extracts and constructs a RowNamespaceData from shares within the +// specified namespace. +func NamespacedRowFromShares(shares []share.Share, namespace share.Namespace, rowIndex int) (RowNamespaceData, error) { + var from, count int + for i := range len(shares) / 2 { + if namespace.Equals(share.GetNamespace(shares[i])) { + if count == 0 { + from = i + } + count++ + } + } + if count == 0 { + return RowNamespaceData{}, fmt.Errorf("no shares found in the namespace for row %d", rowIndex) + } + + namespacedShares := make([]share.Share, count) + copy(namespacedShares, shares[from:from+count]) + + tree := wrapper.NewErasuredNamespacedMerkleTree(uint64(len(shares)/2), uint(rowIndex)) + for _, shr := range shares { + if err := tree.Push(shr); err != nil { + return RowNamespaceData{}, fmt.Errorf("failed to build tree for row %d: %w", rowIndex, err) + } + } + + proof, err := tree.ProveRange(from, from+count) + if err != nil { + return RowNamespaceData{}, fmt.Errorf("failed to generate proof for row %d: %w", rowIndex, err) + } + + return RowNamespaceData{ + Shares: namespacedShares, + Proof: &proof, + }, nil +} + +func NamespacedRowFromProto(row *types_pb.RowNamespaceData) RowNamespaceData { + var proof nmt.Proof + if row.GetProof().GetLeafHash() != nil { + proof = nmt.NewAbsenceProof( + int(row.GetProof().GetStart()), + int(row.GetProof().GetEnd()), + row.GetProof().GetNodes(), + row.GetProof().GetLeafHash(), + row.GetProof().GetIsMaxNamespaceIgnored(), + ) + } else { + proof = nmt.NewInclusionProof( + int(row.GetProof().GetStart()), + int(row.GetProof().GetEnd()), + row.GetProof().GetNodes(), + row.GetProof().GetIsMaxNamespaceIgnored(), + ) + } + + return RowNamespaceData{ + Shares: SharesFromProto(row.GetShares()), + Proof: &proof, + } +} diff --git a/share/shwap/proto/types.pb.go b/share/shwap/proto/types.pb.go new file mode 100644 index 0000000000..3784e7d3b8 --- /dev/null +++ b/share/shwap/proto/types.pb.go @@ -0,0 +1,1114 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: share/pb/types.proto + +package types + +import ( + fmt "fmt" + pb "github.com/celestiaorg/nmt/pb" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type AxisType int32 + +const ( + AxisType_ROW AxisType = 0 + AxisType_COL AxisType = 1 +) + +var AxisType_name = map[int32]string{ + 0: "ROW", + 1: "COL", +} + +var AxisType_value = map[string]int32{ + "ROW": 0, + "COL": 1, +} + +func (x AxisType) String() string { + return proto.EnumName(AxisType_name, int32(x)) +} + +func (AxisType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_b405f12ecc363d82, []int{0} +} + +type Row_HalfSide int32 + +const ( + Row_LEFT Row_HalfSide = 0 + Row_RIGHT Row_HalfSide = 1 +) + +var Row_HalfSide_name = map[int32]string{ + 0: "LEFT", + 1: "RIGHT", +} + +var Row_HalfSide_value = map[string]int32{ + "LEFT": 0, + "RIGHT": 1, +} + +func (x Row_HalfSide) String() string { + return proto.EnumName(Row_HalfSide_name, int32(x)) +} + +func (Row_HalfSide) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_b405f12ecc363d82, []int{0, 0} +} + +type Row struct { + SharesHalf []*Share `protobuf:"bytes,1,rep,name=shares_half,json=sharesHalf,proto3" json:"shares_half,omitempty"` + HalfSide Row_HalfSide `protobuf:"varint,2,opt,name=half_side,json=halfSide,proto3,enum=Row_HalfSide" json:"half_side,omitempty"` +} + +func (m *Row) Reset() { *m = Row{} } +func (m *Row) String() string { return proto.CompactTextString(m) } +func (*Row) ProtoMessage() {} +func (*Row) Descriptor() ([]byte, []int) { + return fileDescriptor_b405f12ecc363d82, []int{0} +} +func (m *Row) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Row) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Row.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Row) XXX_Merge(src proto.Message) { + xxx_messageInfo_Row.Merge(m, src) +} +func (m *Row) XXX_Size() int { + return m.Size() +} +func (m *Row) XXX_DiscardUnknown() { + xxx_messageInfo_Row.DiscardUnknown(m) +} + +var xxx_messageInfo_Row proto.InternalMessageInfo + +func (m *Row) GetSharesHalf() []*Share { + if m != nil { + return m.SharesHalf + } + return nil +} + +func (m *Row) GetHalfSide() Row_HalfSide { + if m != nil { + return m.HalfSide + } + return Row_LEFT +} + +type Sample struct { + Share *Share `protobuf:"bytes,1,opt,name=share,proto3" json:"share,omitempty"` + Proof *pb.Proof `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` + ProofType AxisType `protobuf:"varint,3,opt,name=proof_type,json=proofType,proto3,enum=AxisType" json:"proof_type,omitempty"` +} + +func (m *Sample) Reset() { *m = Sample{} } +func (m *Sample) String() string { return proto.CompactTextString(m) } +func (*Sample) ProtoMessage() {} +func (*Sample) Descriptor() ([]byte, []int) { + return fileDescriptor_b405f12ecc363d82, []int{1} +} +func (m *Sample) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Sample) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Sample.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Sample) XXX_Merge(src proto.Message) { + xxx_messageInfo_Sample.Merge(m, src) +} +func (m *Sample) XXX_Size() int { + return m.Size() +} +func (m *Sample) XXX_DiscardUnknown() { + xxx_messageInfo_Sample.DiscardUnknown(m) +} + +var xxx_messageInfo_Sample proto.InternalMessageInfo + +func (m *Sample) GetShare() *Share { + if m != nil { + return m.Share + } + return nil +} + +func (m *Sample) GetProof() *pb.Proof { + if m != nil { + return m.Proof + } + return nil +} + +func (m *Sample) GetProofType() AxisType { + if m != nil { + return m.ProofType + } + return AxisType_ROW +} + +type RowNamespaceData struct { + Shares []*Share `protobuf:"bytes,1,rep,name=shares,proto3" json:"shares,omitempty"` + Proof *pb.Proof `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` +} + +func (m *RowNamespaceData) Reset() { *m = RowNamespaceData{} } +func (m *RowNamespaceData) String() string { return proto.CompactTextString(m) } +func (*RowNamespaceData) ProtoMessage() {} +func (*RowNamespaceData) Descriptor() ([]byte, []int) { + return fileDescriptor_b405f12ecc363d82, []int{2} +} +func (m *RowNamespaceData) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RowNamespaceData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RowNamespaceData.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RowNamespaceData) XXX_Merge(src proto.Message) { + xxx_messageInfo_RowNamespaceData.Merge(m, src) +} +func (m *RowNamespaceData) XXX_Size() int { + return m.Size() +} +func (m *RowNamespaceData) XXX_DiscardUnknown() { + xxx_messageInfo_RowNamespaceData.DiscardUnknown(m) +} + +var xxx_messageInfo_RowNamespaceData proto.InternalMessageInfo + +func (m *RowNamespaceData) GetShares() []*Share { + if m != nil { + return m.Shares + } + return nil +} + +func (m *RowNamespaceData) GetProof() *pb.Proof { + if m != nil { + return m.Proof + } + return nil +} + +type Share struct { + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *Share) Reset() { *m = Share{} } +func (m *Share) String() string { return proto.CompactTextString(m) } +func (*Share) ProtoMessage() {} +func (*Share) Descriptor() ([]byte, []int) { + return fileDescriptor_b405f12ecc363d82, []int{3} +} +func (m *Share) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Share) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Share.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Share) XXX_Merge(src proto.Message) { + xxx_messageInfo_Share.Merge(m, src) +} +func (m *Share) XXX_Size() int { + return m.Size() +} +func (m *Share) XXX_DiscardUnknown() { + xxx_messageInfo_Share.DiscardUnknown(m) +} + +var xxx_messageInfo_Share proto.InternalMessageInfo + +func (m *Share) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func init() { + proto.RegisterEnum("AxisType", AxisType_name, AxisType_value) + proto.RegisterEnum("Row_HalfSide", Row_HalfSide_name, Row_HalfSide_value) + proto.RegisterType((*Row)(nil), "Row") + proto.RegisterType((*Sample)(nil), "Sample") + proto.RegisterType((*RowNamespaceData)(nil), "RowNamespaceData") + proto.RegisterType((*Share)(nil), "Share") +} + +func init() { proto.RegisterFile("share/pb/types.proto", fileDescriptor_b405f12ecc363d82) } + +var fileDescriptor_b405f12ecc363d82 = []byte{ + // 369 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xcd, 0x6a, 0xdb, 0x40, + 0x14, 0x85, 0x35, 0x95, 0xa5, 0x4a, 0xd7, 0xad, 0x2b, 0x86, 0x2e, 0x44, 0x6b, 0x54, 0x23, 0x28, + 0x35, 0x86, 0x8e, 0xc0, 0x5e, 0x76, 0xd5, 0x7f, 0x07, 0x9c, 0x38, 0x8c, 0x0d, 0x21, 0xd9, 0x98, + 0x91, 0x35, 0xb6, 0x04, 0x72, 0x66, 0x90, 0x14, 0x14, 0x93, 0x97, 0xc8, 0x63, 0x65, 0xe9, 0x65, + 0x96, 0xc1, 0x7e, 0x91, 0xa0, 0x91, 0x1d, 0x42, 0x56, 0xd9, 0x7d, 0x73, 0xce, 0x1d, 0xee, 0x39, + 0x5c, 0xf8, 0x98, 0xc7, 0x2c, 0xe3, 0x81, 0x0c, 0x83, 0x62, 0x2d, 0x79, 0x4e, 0x64, 0x26, 0x0a, + 0xf1, 0xa9, 0x25, 0xc3, 0x40, 0x66, 0x42, 0x2c, 0xea, 0xb7, 0x7f, 0x03, 0x3a, 0x15, 0x25, 0xfe, + 0x06, 0x4d, 0x35, 0x9e, 0xcf, 0x62, 0x96, 0x2e, 0x5c, 0xd4, 0xd1, 0xbb, 0xcd, 0xbe, 0x49, 0x26, + 0x95, 0x46, 0xa1, 0xb6, 0x86, 0x2c, 0x5d, 0xe0, 0x1e, 0xd8, 0xd5, 0xc4, 0x2c, 0x4f, 0x22, 0xee, + 0xbe, 0xe9, 0xa0, 0x6e, 0xab, 0xff, 0x9e, 0x50, 0x51, 0x92, 0xca, 0x9d, 0x24, 0x11, 0xa7, 0x56, + 0xbc, 0x27, 0xff, 0x0b, 0x58, 0x07, 0x15, 0x5b, 0xd0, 0x18, 0xfd, 0xfd, 0x37, 0x75, 0x34, 0x6c, + 0x83, 0x41, 0x8f, 0xfe, 0x0f, 0xa7, 0x0e, 0xf2, 0x4b, 0x30, 0x27, 0x6c, 0x25, 0x53, 0x8e, 0xdb, + 0x60, 0xa8, 0x25, 0x2e, 0xea, 0xa0, 0x67, 0x9b, 0x6b, 0x11, 0x7f, 0x05, 0x43, 0x65, 0x56, 0x0b, + 0x9b, 0xfd, 0x0f, 0x64, 0xdf, 0x20, 0x24, 0xa7, 0x15, 0xd0, 0xda, 0xc5, 0x5d, 0x00, 0x05, 0xb3, + 0xaa, 0xb0, 0xab, 0xab, 0x70, 0x36, 0xf9, 0x79, 0x9d, 0xe4, 0xd3, 0xb5, 0xe4, 0xd4, 0x56, 0x66, + 0x85, 0xfe, 0x39, 0x38, 0x54, 0x94, 0x27, 0x6c, 0xc5, 0x73, 0xc9, 0xe6, 0xfc, 0x0f, 0x2b, 0x18, + 0xf6, 0xc0, 0xac, 0x7b, 0xbe, 0x68, 0xbf, 0x57, 0x5f, 0x19, 0xc2, 0xff, 0x0c, 0x86, 0xfa, 0x87, + 0x31, 0x34, 0x22, 0x56, 0x30, 0xd5, 0xe8, 0x1d, 0x55, 0xdc, 0x6b, 0x83, 0x75, 0x88, 0x83, 0xdf, + 0x82, 0x4e, 0xc7, 0x67, 0x8e, 0x56, 0xc1, 0xef, 0xf1, 0xc8, 0x41, 0xbf, 0x8e, 0xef, 0xb6, 0x1e, + 0xda, 0x6c, 0x3d, 0xf4, 0xb0, 0xf5, 0xd0, 0xed, 0xce, 0xd3, 0x36, 0x3b, 0x4f, 0xbb, 0xdf, 0x79, + 0xda, 0xc5, 0x60, 0x99, 0x14, 0xf1, 0x55, 0x48, 0xe6, 0x62, 0x15, 0xcc, 0x79, 0xca, 0xf3, 0x22, + 0x61, 0x22, 0x5b, 0x3e, 0xf1, 0xf7, 0x4b, 0x11, 0xf1, 0xe0, 0x70, 0xf0, 0x1f, 0xea, 0xe0, 0xa1, + 0xa9, 0x2e, 0x3c, 0x78, 0x0c, 0x00, 0x00, 0xff, 0xff, 0xec, 0x1b, 0x64, 0x91, 0x09, 0x02, 0x00, + 0x00, +} + +func (m *Row) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Row) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Row) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.HalfSide != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.HalfSide)) + i-- + dAtA[i] = 0x10 + } + if len(m.SharesHalf) > 0 { + for iNdEx := len(m.SharesHalf) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SharesHalf[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Sample) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Sample) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Sample) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProofType != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.ProofType)) + i-- + dAtA[i] = 0x18 + } + if m.Proof != nil { + { + size, err := m.Proof.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Share != nil { + { + size, err := m.Share.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RowNamespaceData) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RowNamespaceData) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RowNamespaceData) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Proof != nil { + { + size, err := m.Proof.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Shares) > 0 { + for iNdEx := len(m.Shares) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Shares[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Share) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Share) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Share) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Row) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.SharesHalf) > 0 { + for _, e := range m.SharesHalf { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.HalfSide != 0 { + n += 1 + sovTypes(uint64(m.HalfSide)) + } + return n +} + +func (m *Sample) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Share != nil { + l = m.Share.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Proof != nil { + l = m.Proof.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.ProofType != 0 { + n += 1 + sovTypes(uint64(m.ProofType)) + } + return n +} + +func (m *RowNamespaceData) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Shares) > 0 { + for _, e := range m.Shares { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.Proof != nil { + l = m.Proof.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Share) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Row) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Row: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Row: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SharesHalf", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SharesHalf = append(m.SharesHalf, &Share{}) + if err := m.SharesHalf[len(m.SharesHalf)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HalfSide", wireType) + } + m.HalfSide = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HalfSide |= Row_HalfSide(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Sample) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Sample: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Sample: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Share", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Share == nil { + m.Share = &Share{} + } + if err := m.Share.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proof == nil { + m.Proof = &pb.Proof{} + } + if err := m.Proof.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProofType", wireType) + } + m.ProofType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProofType |= AxisType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RowNamespaceData) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RowNamespaceData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RowNamespaceData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field halfShares", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Shares = append(m.Shares, &Share{}) + if err := m.Shares[len(m.Shares)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proof == nil { + m.Proof = &pb.Proof{} + } + if err := m.Proof.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Share) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Share: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Share: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/share/shwap/proto/types.proto b/share/shwap/proto/types.proto new file mode 100644 index 0000000000..a36f0f8130 --- /dev/null +++ b/share/shwap/proto/types.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; + +option go_package = "github.com/celestiaorg/celestia-node/share/shwap/proto;shwap"; + +import "pb/proof.proto"; // celestiaorg/nmt/pb/proof.proto + +message Row { + repeated Share shares_half = 1; + HalfSide half_side= 2; + + enum HalfSide { + LEFT = 0; + RIGHT = 1; + } +} + +message Sample { + Share share = 1; + proof.pb.Proof proof = 2; + AxisType proof_type = 3; +} + +message RowNamespaceData { + repeated Share shares = 1; + proof.pb.Proof proof = 2; +} + +message Share { + bytes data = 1; +} + +enum AxisType { + ROW = 0; + COL = 1; +} \ No newline at end of file diff --git a/share/shwap/row.go b/share/shwap/row.go new file mode 100644 index 0000000000..a136a27992 --- /dev/null +++ b/share/shwap/row.go @@ -0,0 +1,139 @@ +package shwap + +import ( + "bytes" + "fmt" + + "github.com/celestiaorg/celestia-app/pkg/wrapper" + "github.com/celestiaorg/rsmt2d" + + "github.com/celestiaorg/celestia-node/share" + types_pb "github.com/celestiaorg/celestia-node/share/shwap/proto" +) + +// RowSide enumerates the possible sides of a row within an Extended Data Square (EDS). +type RowSide int + +const ( + Left RowSide = iota // Left side of the row. + Right // Right side of the row. +) + +// Row represents a portion of a row in an EDS, either left or right half. +type Row struct { + halfShares []share.Share // halfShares holds the shares of either the left or right half of a row. + side RowSide // side indicates whether the row half is left or right. +} + +// NewRow creates a new Row with the specified shares and side. +func NewRow(halfShares []share.Share, side RowSide) Row { + return Row{ + halfShares: halfShares, + side: side, + } +} + +// 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 { + if len(r.halfShares) == 0 { + return fmt.Errorf("empty half row") + } + expectedShares := len(dah.RowRoots) / 2 + if len(r.halfShares) != expectedShares { + return fmt.Errorf("shares size doesn't match root size: %d != %d", len(r.halfShares), expectedShares) + } + if r.side != Left && r.side != Right { + return fmt.Errorf("invalid RowSide: %d", r.side) + } + + return r.VerifyRoot(dah, idx) +} + +// VerifyRoot verifies the integrity of the row's shares against the provided root hash for the +// given row index. +func (r Row) VerifyRoot(dah *share.Root, idx int) error { + shrs, err := r.Shares() + if err != nil { + return fmt.Errorf("while extending shares: %w", err) + } + + sqrLn := uint64(len(shrs) / 2) + tree := wrapper.NewErasuredNamespacedMerkleTree(sqrLn, uint(idx)) + for _, s := range shrs { + if err := tree.Push(s); err != nil { + return fmt.Errorf("while pushing shares to NMT: %w", err) + } + } + + root, err := tree.Root() + if err != nil { + return fmt.Errorf("while computing NMT root: %w", err) + } + + if !bytes.Equal(dah.RowRoots[idx], root) { + return fmt.Errorf("invalid root hash: %X != %X", root, dah.RowRoots[idx]) + } + 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() *types_pb.Row { + return &types_pb.Row{ + SharesHalf: SharesToProto(r.halfShares), + HalfSide: r.side.ToProto(), + } +} + +// RowFromProto converts a protobuf Row to a Row structure. +func RowFromProto(r *types_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() types_pb.Row_HalfSide { + if s == Left { + return types_pb.Row_LEFT + } + return types_pb.Row_RIGHT +} + +// sideFromProto converts a protobuf Row_HalfSide back to a RowSide. +func sideFromProto(side types_pb.Row_HalfSide) RowSide { + if side == types_pb.Row_LEFT { + return Left + } + return Right +} diff --git a/share/shwap/row_id.go b/share/shwap/row_id.go new file mode 100644 index 0000000000..beeae8ba1f --- /dev/null +++ b/share/shwap/row_id.go @@ -0,0 +1,80 @@ +package shwap + +import ( + "encoding/binary" + "fmt" + + "github.com/celestiaorg/celestia-node/share" +) + +// RowIDSize defines the size in bytes of RowID, consisting of the size of EdsID and 2 bytes for +// RowIndex. +const RowIDSize = EdsIDSize + 2 + +// RowID uniquely identifies a row in the data square of a blockchain block, combining block height +// with the row's index. +type RowID struct { + EdsID // Embedding EdsID to include the block height in RowID. + + RowIndex uint16 // RowIndex specifies the position of the row within the data square. +} + +// NewRowID creates a new RowID with the specified block height, row index, and validates it +// against the provided Root. It returns an error if the validation fails, ensuring the RowID +// conforms to expected constraints. +func NewRowID(height uint64, rowIdx uint16, root *share.Root) (RowID, error) { + rid := RowID{ + EdsID: EdsID{ + Height: height, + }, + RowIndex: rowIdx, + } + return rid, rid.Verify(root) +} + +// MarshalBinary encodes the RowID into a binary form for storage or network transmission. +func (rid RowID) MarshalBinary() []byte { + data := make([]byte, 0, RowIDSize) + return rid.appendTo(data) +} + +// 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) { + var rid RowID + if len(data) != RowIDSize { + return rid, fmt.Errorf("invalid RowID data length: expected %d, got %d", RowIDSize, len(data)) + } + eid, err := EdsIDFromBinary(data[:EdsIDSize]) + if err != nil { + return rid, fmt.Errorf("error decoding EdsID: %w", err) + } + rid.EdsID = eid + rid.RowIndex = binary.BigEndian.Uint16(data[EdsIDSize:]) + return rid, nil +} + +// Verify ensures the RowID's fields are valid given the specified root structure, particularly +// that the row index is within bounds. +func (rid RowID) Verify(root *share.Root) error { + if err := rid.EdsID.Verify(root); err != nil { + return err + } + + if root == nil || len(root.RowRoots) == 0 { + return fmt.Errorf("provided root is nil or empty") + } + + if int(rid.RowIndex) >= len(root.RowRoots) { + return fmt.Errorf("RowIndex out of bounds: %d >= %d", rid.RowIndex, len(root.RowRoots)) + } + + return nil +} + +// appendTo assists in binary encoding of RowID by appending the encoded fields to the given byte +// slice. +func (rid RowID) appendTo(data []byte) []byte { + data = rid.EdsID.appendTo(data) + return binary.BigEndian.AppendUint16(data, rid.RowIndex) +} diff --git a/share/shwap/row_id_test.go b/share/shwap/row_id_test.go new file mode 100644 index 0000000000..7c4edbf2e0 --- /dev/null +++ b/share/shwap/row_id_test.go @@ -0,0 +1,28 @@ +package shwap + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/edstest" +) + +func TestRowID(t *testing.T) { + square := edstest.RandEDS(t, 4) + root, err := share.NewRoot(square) + require.NoError(t, err) + + id, err := NewRowID(2, 1, root) + require.NoError(t, err) + + data := id.MarshalBinary() + idOut, err := RowIDFromBinary(data) + require.NoError(t, err) + assert.EqualValues(t, id, idOut) + + err = idOut.Verify(root) + require.NoError(t, err) +} diff --git a/share/shwap/sample.go b/share/shwap/sample.go new file mode 100644 index 0000000000..02e9a89ca0 --- /dev/null +++ b/share/shwap/sample.go @@ -0,0 +1,119 @@ +package shwap + +import ( + "crypto/sha256" + "fmt" + + "github.com/celestiaorg/celestia-app/pkg/wrapper" + "github.com/celestiaorg/nmt" + nmt_pb "github.com/celestiaorg/nmt/pb" + "github.com/celestiaorg/rsmt2d" + + "github.com/celestiaorg/celestia-node/share" + types_pb "github.com/celestiaorg/celestia-node/share/shwap/proto" +) + +// Sample represents a data share along with its Merkle proof, used to validate the share's +// inclusion in a data square. +type Sample struct { + share.Share // Embeds the share which includes the data with namespace. + Proof *nmt.Proof // Proof is the Merkle Proof validating the share's inclusion. + ProofType rsmt2d.Axis // ProofType indicates whether the proof is against a row or a column. +} + +// Validate checks the inclusion of the share using its Merkle proof under the specified root. +// Returns an error if the proof is invalid or does not correspond to the indicated proof type. +func (s *Sample) Validate(dah *share.Root, colIdx, rowIdx int) error { + if s.ProofType != rsmt2d.Row && s.ProofType != rsmt2d.Col { + return fmt.Errorf("invalid SampleProofType: %d", s.ProofType) + } + if !s.VerifyInclusion(dah, colIdx, rowIdx) { + return fmt.Errorf("share proof is invalid") + } + return nil +} + +// VerifyInclusion checks if the share is included in the given root hash at the specified indices. +func (s *Sample) VerifyInclusion(dah *share.Root, colIdx, rowIdx int) bool { + rootHash := share.RootHashForCoordinates(dah, s.ProofType, uint(colIdx), uint(rowIdx)) + size := len(dah.RowRoots) + isParity := colIdx >= size/2 || rowIdx >= size/2 + namespace := share.ParitySharesNamespace + if !isParity { + namespace = share.GetNamespace(s.Share) + } + + return s.Proof.VerifyInclusion( + sha256.New(), // Utilizes sha256, should be consistent throughout the application. + namespace.ToNMT(), + [][]byte{s.Share}, + rootHash, + ) +} + +// ToProto converts a Sample into its protobuf representation for serialization purposes. +func (s *Sample) ToProto() *types_pb.Sample { + return &types_pb.Sample{ + Share: &types_pb.Share{Data: s.Share}, + Proof: &nmt_pb.Proof{ + Start: int64(s.Proof.Start()), + End: int64(s.Proof.End()), + Nodes: s.Proof.Nodes(), + LeafHash: s.Proof.LeafHash(), + IsMaxNamespaceIgnored: s.Proof.IsMaxNamespaceIDIgnored(), + }, + ProofType: types_pb.AxisType(s.ProofType), + } +} + +// SampleFromEDS samples a share from an Extended Data Square based on the provided index and axis. +// This function generates a Merkle tree proof for the specified share. +func SampleFromEDS( + square *rsmt2d.ExtendedDataSquare, + proofType rsmt2d.Axis, + axisIdx, shrIdx int, +) (*Sample, error) { + var shrs [][]byte + switch proofType { + case rsmt2d.Row: + shrs = square.Row(uint(axisIdx)) + case rsmt2d.Col: + shrs = square.Col(uint(axisIdx)) + default: + return nil, fmt.Errorf("invalid proof type: %d", proofType) + } + + tree := wrapper.NewErasuredNamespacedMerkleTree(uint64(square.Width()/2), uint(axisIdx)) + for _, shr := range shrs { + err := tree.Push(shr) + if err != nil { + return nil, fmt.Errorf("while pushing shares to NMT: %w", err) + } + } + + prf, err := tree.ProveRange(shrIdx, shrIdx+1) + if err != nil { + return nil, fmt.Errorf("while proving range share over NMT: %w", err) + } + + return &Sample{ + Share: shrs[shrIdx], + Proof: &prf, + ProofType: proofType, + }, nil +} + +// SampleFromProto converts a protobuf Sample back into its domain model equivalent. +func SampleFromProto(s *types_pb.Sample) *Sample { + proof := nmt.NewInclusionProof( + int(s.GetProof().GetStart()), + int(s.GetProof().GetEnd()), + s.GetProof().GetNodes(), + s.GetProof().GetIsMaxNamespaceIgnored(), + ) + return &Sample{ + Share: ShareFromProto(s.GetShare()), + Proof: &proof, + ProofType: rsmt2d.Axis(s.GetProofType()), + } +} diff --git a/share/shwap/sample_id.go b/share/shwap/sample_id.go new file mode 100644 index 0000000000..a613f1c8b9 --- /dev/null +++ b/share/shwap/sample_id.go @@ -0,0 +1,92 @@ +package shwap + +import ( + "encoding/binary" + "fmt" + + "github.com/celestiaorg/celestia-node/share" +) + +// SampleIDSize defines the size of the SampleID in bytes, combining RowID size and 2 additional +// bytes for the ShareIndex. +const SampleIDSize = RowIDSize + 2 + +// SampleID uniquely identifies a specific sample within a row of an Extended Data Square (EDS). +type SampleID struct { + RowID // Embeds RowID to incorporate block height and row index. + + // ShareIndex specifies the index of the sample within the row. + ShareIndex uint16 +} + +// NewSampleID constructs a new SampleID using the provided block height, sample index, and a root +// structure for validation. It calculates the row and share index based on the sample index and +// the length of the row roots. +func NewSampleID(height uint64, smplIdx int, root *share.Root) (SampleID, error) { + if root == nil || len(root.RowRoots) == 0 { + return SampleID{}, fmt.Errorf("invalid root: root is nil or empty") + } + sqrLn := len(root.RowRoots) + rowIdx, shrIdx := uint16(smplIdx/sqrLn), uint16(smplIdx%sqrLn) + sid := SampleID{ + RowID: RowID{ + EdsID: EdsID{ + Height: height, + }, + RowIndex: rowIdx, + }, + ShareIndex: shrIdx, + } + + if err := sid.Verify(root); err != nil { + return SampleID{}, err + } + return sid, nil +} + +// MarshalBinary encodes SampleID into binary form. +// NOTE: Proto is avoided because +// * Its size is not deterministic which is required for IPLD. +// * No support for uint16 +func (sid SampleID) MarshalBinary() []byte { + data := make([]byte, 0, SampleIDSize) + return sid.appendTo(data) +} + +// SampleIDFromBinary deserializes a SampleID from binary data, ensuring the data length matches +// the expected size. +func SampleIDFromBinary(data []byte) (SampleID, error) { + if len(data) != SampleIDSize { + return SampleID{}, fmt.Errorf("invalid SampleID data length: expected %d, got %d", SampleIDSize, len(data)) + } + + rid, err := RowIDFromBinary(data[:RowIDSize]) + if err != nil { + return SampleID{}, fmt.Errorf("error decoding RowID: %w", err) + } + + shareIndex := binary.BigEndian.Uint16(data[RowIDSize:]) + return SampleID{RowID: rid, ShareIndex: shareIndex}, nil +} + +// Verify checks the validity of the SampleID by ensuring the ShareIndex is within the bounds of +// the square size. +func (sid SampleID) Verify(root *share.Root) error { + if err := sid.RowID.Verify(root); err != nil { + return err + } + + sqrLn := len(root.ColumnRoots) // Assumes ColumnRoots is valid and populated. + if int(sid.ShareIndex) >= sqrLn { + return fmt.Errorf("ShareIndex exceeds square size: %d >= %d", sid.ShareIndex, sqrLn) + } + + return nil +} + +// appendTo helps in constructing the binary representation by appending the encoded ShareIndex to +// the serialized RowID. +func (sid SampleID) appendTo(data []byte) []byte { + data = sid.RowID.appendTo(data) + return binary.BigEndian.AppendUint16(data, sid.ShareIndex) +} diff --git a/share/shwap/sample_id_test.go b/share/shwap/sample_id_test.go new file mode 100644 index 0000000000..053b35e57e --- /dev/null +++ b/share/shwap/sample_id_test.go @@ -0,0 +1,28 @@ +package shwap + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/edstest" +) + +func TestSampleID(t *testing.T) { + square := edstest.RandEDS(t, 4) + root, err := share.NewRoot(square) + require.NoError(t, err) + + id, err := NewSampleID(1, 1, root) + require.NoError(t, err) + + data := id.MarshalBinary() + idOut, err := SampleIDFromBinary(data) + require.NoError(t, err) + assert.EqualValues(t, id, idOut) + + err = idOut.Verify(root) + require.NoError(t, err) +} diff --git a/share/shwap/share.go b/share/shwap/share.go new file mode 100644 index 0000000000..b55bf104fa --- /dev/null +++ b/share/shwap/share.go @@ -0,0 +1,37 @@ +package shwap + +import ( + "github.com/celestiaorg/celestia-node/share" + types_pb "github.com/celestiaorg/celestia-node/share/shwap/proto" +) + +// ShareFromProto converts a protobuf Share object to the application's internal share +// representation. It returns nil if the input protobuf Share is nil, ensuring safe handling of nil +// values. +func ShareFromProto(s *types_pb.Share) share.Share { + if s == nil { + return nil + } + return s.Data +} + +// SharesToProto converts a slice of Shares from the application's internal representation to a +// slice of protobuf Share objects. This function allocates memory for the protobuf objects and +// copies data from the input slice. +func SharesToProto(shrs []share.Share) []*types_pb.Share { + protoShares := make([]*types_pb.Share, len(shrs)) + for i, shr := range shrs { + protoShares[i] = &types_pb.Share{Data: shr} + } + return protoShares +} + +// SharesFromProto converts a slice of protobuf Share objects to the application's internal slice +// of Shares. It ensures that each Share is correctly transformed using the ShareFromProto function. +func SharesFromProto(shrs []*types_pb.Share) []share.Share { + shares := make([]share.Share, len(shrs)) + for i, shr := range shrs { + shares[i] = ShareFromProto(shr) + } + return shares +} From 0e51bdee11c606b045aeba0c86af9d36517c39c3 Mon Sep 17 00:00:00 2001 From: Vlad <13818348+walldiss@users.noreply.github.com> Date: Thu, 9 May 2024 21:24:06 +0500 Subject: [PATCH 2/7] rename pb extact inclusionNamespace save some loop time --- share/shwap/namespaced_data.go | 12 ++++++++---- share/shwap/row.go | 18 +++++++++--------- share/shwap/sample.go | 33 ++++++++++++++++++++------------- share/shwap/share.go | 12 ++++++------ 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/share/shwap/namespaced_data.go b/share/shwap/namespaced_data.go index 65afa67687..af181c8bff 100644 --- a/share/shwap/namespaced_data.go +++ b/share/shwap/namespaced_data.go @@ -10,7 +10,7 @@ import ( "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" - types_pb "github.com/celestiaorg/celestia-node/share/shwap/proto" + pb "github.com/celestiaorg/celestia-node/share/shwap/proto" ) // NamespacedData stores collections of RowNamespaceData, each representing shares and their proofs @@ -88,8 +88,8 @@ func (rnd RowNamespaceData) VerifyInclusion(rowRoot []byte, namespace share.Name } // ToProto converts RowNamespaceData to its protobuf representation for serialization. -func (rnd RowNamespaceData) ToProto() *types_pb.RowNamespaceData { - return &types_pb.RowNamespaceData{ +func (rnd RowNamespaceData) ToProto() *pb.RowNamespaceData { + return &pb.RowNamespaceData{ Shares: SharesToProto(rnd.Shares), Proof: &nmt_pb.Proof{ Start: int64(rnd.Proof.Start()), @@ -140,6 +140,10 @@ func NamespacedRowFromShares(shares []share.Share, namespace share.Namespace, ro from = i } count++ + continue + } + if count > 0 { + break } } if count == 0 { @@ -167,7 +171,7 @@ func NamespacedRowFromShares(shares []share.Share, namespace share.Namespace, ro }, nil } -func NamespacedRowFromProto(row *types_pb.RowNamespaceData) RowNamespaceData { +func NamespacedRowFromProto(row *pb.RowNamespaceData) RowNamespaceData { var proof nmt.Proof if row.GetProof().GetLeafHash() != nil { proof = nmt.NewAbsenceProof( diff --git a/share/shwap/row.go b/share/shwap/row.go index a136a27992..e88a1db6e3 100644 --- a/share/shwap/row.go +++ b/share/shwap/row.go @@ -8,7 +8,7 @@ import ( "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" - types_pb "github.com/celestiaorg/celestia-node/share/shwap/proto" + pb "github.com/celestiaorg/celestia-node/share/shwap/proto" ) // RowSide enumerates the possible sides of a row within an Extended Data Square (EDS). @@ -92,15 +92,15 @@ func (r Row) Shares() ([]share.Share, error) { } // ToProto converts the Row to its protobuf representation. -func (r Row) ToProto() *types_pb.Row { - return &types_pb.Row{ +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 *types_pb.Row) Row { +func RowFromProto(r *pb.Row) Row { return Row{ halfShares: SharesFromProto(r.SharesHalf), side: sideFromProto(r.GetHalfSide()), @@ -123,16 +123,16 @@ func NewRowFromEDS(square *rsmt2d.ExtendedDataSquare, idx int, side RowSide) Row } // ToProto converts a RowSide to its protobuf representation. -func (s RowSide) ToProto() types_pb.Row_HalfSide { +func (s RowSide) ToProto() pb.Row_HalfSide { if s == Left { - return types_pb.Row_LEFT + return pb.Row_LEFT } - return types_pb.Row_RIGHT + return pb.Row_RIGHT } // sideFromProto converts a protobuf Row_HalfSide back to a RowSide. -func sideFromProto(side types_pb.Row_HalfSide) RowSide { - if side == types_pb.Row_LEFT { +func sideFromProto(side pb.Row_HalfSide) RowSide { + if side == pb.Row_LEFT { return Left } return Right diff --git a/share/shwap/sample.go b/share/shwap/sample.go index 02e9a89ca0..2975bcbf69 100644 --- a/share/shwap/sample.go +++ b/share/shwap/sample.go @@ -10,7 +10,7 @@ import ( "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" - types_pb "github.com/celestiaorg/celestia-node/share/shwap/proto" + pb "github.com/celestiaorg/celestia-node/share/shwap/proto" ) // Sample represents a data share along with its Merkle proof, used to validate the share's @@ -35,14 +35,9 @@ func (s *Sample) Validate(dah *share.Root, colIdx, rowIdx int) error { // VerifyInclusion checks if the share is included in the given root hash at the specified indices. func (s *Sample) VerifyInclusion(dah *share.Root, colIdx, rowIdx int) bool { - rootHash := share.RootHashForCoordinates(dah, s.ProofType, uint(colIdx), uint(rowIdx)) size := len(dah.RowRoots) - isParity := colIdx >= size/2 || rowIdx >= size/2 - namespace := share.ParitySharesNamespace - if !isParity { - namespace = share.GetNamespace(s.Share) - } - + namespace := inclusionNamespace(s.Share, colIdx, rowIdx, size) + rootHash := share.RootHashForCoordinates(dah, s.ProofType, uint(colIdx), uint(rowIdx)) return s.Proof.VerifyInclusion( sha256.New(), // Utilizes sha256, should be consistent throughout the application. namespace.ToNMT(), @@ -51,10 +46,22 @@ func (s *Sample) VerifyInclusion(dah *share.Root, colIdx, rowIdx int) bool { ) } +// inclusionNamespace returns the namespace for the share based on its position in the square. +// Shares from extended part of the square are considered parity shares. It means that +// parity shares are located outside of first quadrant of the square. According to the nmt +// specification, the parity shares are prefixed with the namespace of the parity shares. +func inclusionNamespace(sh share.Share, colIdx, rowIdx int, squareSize int) share.Namespace { + isParity := colIdx >= squareSize/2 || rowIdx >= squareSize/2 + if isParity { + return share.ParitySharesNamespace + } + return share.GetNamespace(sh) +} + // ToProto converts a Sample into its protobuf representation for serialization purposes. -func (s *Sample) ToProto() *types_pb.Sample { - return &types_pb.Sample{ - Share: &types_pb.Share{Data: s.Share}, +func (s *Sample) ToProto() *pb.Sample { + return &pb.Sample{ + Share: &pb.Share{Data: s.Share}, Proof: &nmt_pb.Proof{ Start: int64(s.Proof.Start()), End: int64(s.Proof.End()), @@ -62,7 +69,7 @@ func (s *Sample) ToProto() *types_pb.Sample { LeafHash: s.Proof.LeafHash(), IsMaxNamespaceIgnored: s.Proof.IsMaxNamespaceIDIgnored(), }, - ProofType: types_pb.AxisType(s.ProofType), + ProofType: pb.AxisType(s.ProofType), } } @@ -104,7 +111,7 @@ func SampleFromEDS( } // SampleFromProto converts a protobuf Sample back into its domain model equivalent. -func SampleFromProto(s *types_pb.Sample) *Sample { +func SampleFromProto(s *pb.Sample) *Sample { proof := nmt.NewInclusionProof( int(s.GetProof().GetStart()), int(s.GetProof().GetEnd()), diff --git a/share/shwap/share.go b/share/shwap/share.go index b55bf104fa..330cf830e9 100644 --- a/share/shwap/share.go +++ b/share/shwap/share.go @@ -2,13 +2,13 @@ package shwap import ( "github.com/celestiaorg/celestia-node/share" - types_pb "github.com/celestiaorg/celestia-node/share/shwap/proto" + pb "github.com/celestiaorg/celestia-node/share/shwap/proto" ) // ShareFromProto converts a protobuf Share object to the application's internal share // representation. It returns nil if the input protobuf Share is nil, ensuring safe handling of nil // values. -func ShareFromProto(s *types_pb.Share) share.Share { +func ShareFromProto(s *pb.Share) share.Share { if s == nil { return nil } @@ -18,17 +18,17 @@ func ShareFromProto(s *types_pb.Share) share.Share { // SharesToProto converts a slice of Shares from the application's internal representation to a // slice of protobuf Share objects. This function allocates memory for the protobuf objects and // copies data from the input slice. -func SharesToProto(shrs []share.Share) []*types_pb.Share { - protoShares := make([]*types_pb.Share, len(shrs)) +func SharesToProto(shrs []share.Share) []*pb.Share { + protoShares := make([]*pb.Share, len(shrs)) for i, shr := range shrs { - protoShares[i] = &types_pb.Share{Data: shr} + protoShares[i] = &pb.Share{Data: shr} } return protoShares } // SharesFromProto converts a slice of protobuf Share objects to the application's internal slice // of Shares. It ensures that each Share is correctly transformed using the ShareFromProto function. -func SharesFromProto(shrs []*types_pb.Share) []share.Share { +func SharesFromProto(shrs []*pb.Share) []share.Share { shares := make([]share.Share, len(shrs)) for i, shr := range shrs { shares[i] = ShareFromProto(shr) From 6d0e9c66f6bf8e5584d56437702c234aaf32e68d Mon Sep 17 00:00:00 2001 From: Vlad <13818348+walldiss@users.noreply.github.com> Date: Tue, 14 May 2024 17:03:48 +0500 Subject: [PATCH 3/7] improve validation for shwap types swap rowCol idx --- share/share.go | 10 ++++++- share/shwap/namespaced_data.go | 14 +++++++-- share/shwap/row.go | 3 ++ share/shwap/sample.go | 52 ++++++++++++++++++++-------------- share/shwap/sample_id.go | 8 ++---- share/shwap/sample_id_test.go | 2 +- share/shwap/share.go | 11 +++++++ 7 files changed, 69 insertions(+), 31 deletions(-) diff --git a/share/share.go b/share/share.go index f79e168022..e2f351e805 100644 --- a/share/share.go +++ b/share/share.go @@ -40,6 +40,14 @@ func GetData(s Share) []byte { return s[NamespaceSize:] } +// ValidateShare checks the size of a given share. +func ValidateShare(s Share) error { + if len(s) != Size { + return fmt.Errorf("invalid share size: %d", len(s)) + } + return nil +} + // ShareWithProof contains data with corresponding Merkle Proof type ShareWithProof struct { //nolint: revive // Share is a full data including namespace @@ -103,7 +111,7 @@ func NewSHA256Hasher() hash.Hash { } // RootHashForCoordinates returns the root hash for the given coordinates. -func RootHashForCoordinates(r *Root, axisType rsmt2d.Axis, colIdx, rowIdx uint) []byte { +func RootHashForCoordinates(r *Root, axisType rsmt2d.Axis, rowIdx, colIdx uint) []byte { if axisType == rsmt2d.Row { return r.RowRoots[rowIdx] } diff --git a/share/shwap/namespaced_data.go b/share/shwap/namespaced_data.go index af181c8bff..07230b77a8 100644 --- a/share/shwap/namespaced_data.go +++ b/share/shwap/namespaced_data.go @@ -56,9 +56,17 @@ func (ns NamespacedData) Verify(root *share.Root, namespace share.Namespace) err return nil } -func (rnd RowNamespaceData) Validate(dah *share.Root, rowIdx int, namespace share.Namespace) error { - if len(rnd.Shares) == 0 && rnd.Proof.IsEmptyProof() { - return fmt.Errorf("row contains no data or proof") +func (rnd RowNamespaceData) Validate(dah *share.Root, namespace share.Namespace, rowIdx int) error { + 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] diff --git a/share/shwap/row.go b/share/shwap/row.go index e88a1db6e3..d23130ef25 100644 --- a/share/shwap/row.go +++ b/share/shwap/row.go @@ -43,6 +43,9 @@ func (r Row) Validate(dah *share.Root, idx int) error { if len(r.halfShares) != expectedShares { return fmt.Errorf("shares size doesn't match root size: %d != %d", len(r.halfShares), expectedShares) } + if err := ValidateShares(r.halfShares); err != nil { + return fmt.Errorf("invalid shares: %w", err) + } if r.side != Left && r.side != Right { return fmt.Errorf("invalid RowSide: %d", r.side) } diff --git a/share/shwap/sample.go b/share/shwap/sample.go index 2975bcbf69..347658b81b 100644 --- a/share/shwap/sample.go +++ b/share/shwap/sample.go @@ -2,6 +2,7 @@ package shwap import ( "crypto/sha256" + "errors" "fmt" "github.com/celestiaorg/celestia-app/pkg/wrapper" @@ -23,21 +24,27 @@ type Sample struct { // Validate checks the inclusion of the share using its Merkle proof under the specified root. // Returns an error if the proof is invalid or does not correspond to the indicated proof type. -func (s *Sample) Validate(dah *share.Root, colIdx, rowIdx int) error { +func (s *Sample) Validate(dah *share.Root, rowIdx, colIdx int) error { + if err := share.ValidateShare(s.Share); err != nil { + return err + } + if s.Proof == nil { + return errors.New("nil proof") + } if s.ProofType != rsmt2d.Row && s.ProofType != rsmt2d.Col { return fmt.Errorf("invalid SampleProofType: %d", s.ProofType) } - if !s.VerifyInclusion(dah, colIdx, rowIdx) { + if !s.VerifyInclusion(dah, rowIdx, colIdx) { return fmt.Errorf("share proof is invalid") } return nil } // VerifyInclusion checks if the share is included in the given root hash at the specified indices. -func (s *Sample) VerifyInclusion(dah *share.Root, colIdx, rowIdx int) bool { +func (s *Sample) VerifyInclusion(dah *share.Root, rowIdx, colIdx int) bool { size := len(dah.RowRoots) - namespace := inclusionNamespace(s.Share, colIdx, rowIdx, size) - rootHash := share.RootHashForCoordinates(dah, s.ProofType, uint(colIdx), uint(rowIdx)) + namespace := inclusionNamespace(s.Share, rowIdx, colIdx, size) + rootHash := share.RootHashForCoordinates(dah, s.ProofType, uint(rowIdx), uint(colIdx)) return s.Proof.VerifyInclusion( sha256.New(), // Utilizes sha256, should be consistent throughout the application. namespace.ToNMT(), @@ -46,18 +53,6 @@ func (s *Sample) VerifyInclusion(dah *share.Root, colIdx, rowIdx int) bool { ) } -// inclusionNamespace returns the namespace for the share based on its position in the square. -// Shares from extended part of the square are considered parity shares. It means that -// parity shares are located outside of first quadrant of the square. According to the nmt -// specification, the parity shares are prefixed with the namespace of the parity shares. -func inclusionNamespace(sh share.Share, colIdx, rowIdx int, squareSize int) share.Namespace { - isParity := colIdx >= squareSize/2 || rowIdx >= squareSize/2 - if isParity { - return share.ParitySharesNamespace - } - return share.GetNamespace(sh) -} - // ToProto converts a Sample into its protobuf representation for serialization purposes. func (s *Sample) ToProto() *pb.Sample { return &pb.Sample{ @@ -78,14 +73,17 @@ func (s *Sample) ToProto() *pb.Sample { func SampleFromEDS( square *rsmt2d.ExtendedDataSquare, proofType rsmt2d.Axis, - axisIdx, shrIdx int, + rowIdx, colIdx int, ) (*Sample, error) { - var shrs [][]byte + var shrs []share.Share + var axisIdx, shrIdx int switch proofType { case rsmt2d.Row: - shrs = square.Row(uint(axisIdx)) + axisIdx, shrIdx = rowIdx, colIdx + shrs = square.Row(uint(rowIdx)) case rsmt2d.Col: - shrs = square.Col(uint(axisIdx)) + axisIdx, shrIdx = colIdx, rowIdx + shrs = square.Col(uint(colIdx)) default: return nil, fmt.Errorf("invalid proof type: %d", proofType) } @@ -124,3 +122,15 @@ func SampleFromProto(s *pb.Sample) *Sample { ProofType: rsmt2d.Axis(s.GetProofType()), } } + +// inclusionNamespace returns the namespace for the share based on its position in the square. +// Shares from extended part of the square are considered parity shares. It means that +// parity shares are located outside of first quadrant of the square. According to the nmt +// specification, the parity shares are prefixed with the namespace of the parity shares. +func inclusionNamespace(sh share.Share, rowIdx, colIdx, squareSize int) share.Namespace { + isParity := colIdx >= squareSize/2 || rowIdx >= squareSize/2 + if isParity { + return share.ParitySharesNamespace + } + return share.GetNamespace(sh) +} diff --git a/share/shwap/sample_id.go b/share/shwap/sample_id.go index a613f1c8b9..e2c2d5cd68 100644 --- a/share/shwap/sample_id.go +++ b/share/shwap/sample_id.go @@ -22,20 +22,18 @@ type SampleID struct { // NewSampleID constructs a new SampleID using the provided block height, sample index, and a root // structure for validation. It calculates the row and share index based on the sample index and // the length of the row roots. -func NewSampleID(height uint64, smplIdx int, root *share.Root) (SampleID, error) { +func NewSampleID(height uint64, rowIdx, colIdx int, root *share.Root) (SampleID, error) { if root == nil || len(root.RowRoots) == 0 { return SampleID{}, fmt.Errorf("invalid root: root is nil or empty") } - sqrLn := len(root.RowRoots) - rowIdx, shrIdx := uint16(smplIdx/sqrLn), uint16(smplIdx%sqrLn) sid := SampleID{ RowID: RowID{ EdsID: EdsID{ Height: height, }, - RowIndex: rowIdx, + RowIndex: uint16(rowIdx), }, - ShareIndex: shrIdx, + ShareIndex: uint16(colIdx), } if err := sid.Verify(root); err != nil { diff --git a/share/shwap/sample_id_test.go b/share/shwap/sample_id_test.go index 053b35e57e..6129aef996 100644 --- a/share/shwap/sample_id_test.go +++ b/share/shwap/sample_id_test.go @@ -15,7 +15,7 @@ func TestSampleID(t *testing.T) { root, err := share.NewRoot(square) require.NoError(t, err) - id, err := NewSampleID(1, 1, root) + id, err := NewSampleID(1, 1, 1, root) require.NoError(t, err) data := id.MarshalBinary() diff --git a/share/shwap/share.go b/share/shwap/share.go index 330cf830e9..da4ca94c96 100644 --- a/share/shwap/share.go +++ b/share/shwap/share.go @@ -1,6 +1,8 @@ package shwap import ( + "fmt" + "github.com/celestiaorg/celestia-node/share" pb "github.com/celestiaorg/celestia-node/share/shwap/proto" ) @@ -35,3 +37,12 @@ func SharesFromProto(shrs []*pb.Share) []share.Share { } return shares } + +func ValidateShares(shares []share.Share) error { + for i, shr := range shares { + if err := share.ValidateShare(shr); err != nil { + return fmt.Errorf("while validating share at index %d: %w", i, err) + } + } + return nil +} From 86564cf0b843ea5802fd826b520046b5a6d48dfc Mon Sep 17 00:00:00 2001 From: Vlad <13818348+walldiss@users.noreply.github.com> Date: Fri, 17 May 2024 12:04:44 +0500 Subject: [PATCH 4/7] validate empty proof --- share/shwap/namespaced_data.go | 15 ++++++++------- share/shwap/sample.go | 9 ++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/share/shwap/namespaced_data.go b/share/shwap/namespaced_data.go index 07230b77a8..c9be602e1a 100644 --- a/share/shwap/namespaced_data.go +++ b/share/shwap/namespaced_data.go @@ -1,7 +1,6 @@ package shwap import ( - "crypto/sha256" "fmt" "github.com/celestiaorg/celestia-app/pkg/wrapper" @@ -57,18 +56,20 @@ func (ns NamespacedData) Verify(root *share.Root, namespace share.Namespace) err } 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 for row %d", rowIdx) + } + if err := ValidateShares(rnd.Shares); err != nil { + return fmt.Errorf("invalid shares: %w", err) + } + 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) @@ -88,7 +89,7 @@ func (rnd RowNamespaceData) VerifyInclusion(rowRoot []byte, namespace share.Name leaves = append(leaves, append(namespaceBytes, shr...)) } return rnd.Proof.VerifyNamespace( - sha256.New(), + share.NewSHA256Hasher(), namespace.ToNMT(), leaves, rowRoot, diff --git a/share/shwap/sample.go b/share/shwap/sample.go index 347658b81b..470a4a4931 100644 --- a/share/shwap/sample.go +++ b/share/shwap/sample.go @@ -1,7 +1,6 @@ package shwap import ( - "crypto/sha256" "errors" "fmt" @@ -25,12 +24,12 @@ type Sample struct { // Validate checks the inclusion of the share using its Merkle proof under the specified root. // Returns an error if the proof is invalid or does not correspond to the indicated proof type. func (s *Sample) Validate(dah *share.Root, rowIdx, colIdx int) error { + if s.Proof == nil || s.Proof.IsEmptyProof() { + return errors.New("nil proof") + } if err := share.ValidateShare(s.Share); err != nil { return err } - if s.Proof == nil { - return errors.New("nil proof") - } if s.ProofType != rsmt2d.Row && s.ProofType != rsmt2d.Col { return fmt.Errorf("invalid SampleProofType: %d", s.ProofType) } @@ -46,7 +45,7 @@ func (s *Sample) VerifyInclusion(dah *share.Root, rowIdx, colIdx int) bool { namespace := inclusionNamespace(s.Share, rowIdx, colIdx, size) rootHash := share.RootHashForCoordinates(dah, s.ProofType, uint(rowIdx), uint(colIdx)) return s.Proof.VerifyInclusion( - sha256.New(), // Utilizes sha256, should be consistent throughout the application. + share.NewSHA256Hasher(), namespace.ToNMT(), [][]byte{s.Share}, rootHash, From 9b9b193c02b965b78788fd4540910c842402357f Mon Sep 17 00:00:00 2001 From: Wondertan Date: Wed, 22 May 2024 00:28:37 +0200 Subject: [PATCH 5/7] fix proto gen --- Makefile | 3 +- share/shwap/namespaced_data.go | 2 +- .../{proto/types.pb.go => pb/shwap.pb.go} | 214 +++++++++--------- .../{proto/types.proto => pb/shwap.proto} | 7 +- share/shwap/row.go | 2 +- share/shwap/sample.go | 2 +- share/shwap/share.go | 2 +- 7 files changed, 117 insertions(+), 115 deletions(-) rename share/shwap/{proto/types.pb.go => pb/shwap.pb.go} (77%) rename share/shwap/{proto/types.proto => pb/shwap.proto} (79%) diff --git a/Makefile b/Makefile index 000d01fa02..31197dc824 100644 --- a/Makefile +++ b/Makefile @@ -161,13 +161,14 @@ PB_CORE=$(shell go list -f {{.Dir}} -m github.com/tendermint/tendermint) PB_GOGO=$(shell go list -f {{.Dir}} -m github.com/gogo/protobuf) PB_CELESTIA_APP=$(shell go list -f {{.Dir}} -m github.com/celestiaorg/celestia-app) PB_NMT=$(shell go list -f {{.Dir}} -m github.com/celestiaorg/nmt) +PB_NODE=$(shell pwd) ## pb-gen: Generate protobuf code for all /pb/*.proto files in the project. pb-gen: @echo '--> Generating protobuf' @for dir in $(PB_PKGS); \ do for file in `find $$dir -type f -name "*.proto"`; \ - do protoc -I=. -I=${PB_CORE}/proto/ -I=${PB_GOGO} -I=${PB_CELESTIA_APP}/proto -I=${PB_NMT} --gogofaster_out=paths=source_relative:. $$file; \ + do protoc -I=. -I=${PB_CORE}/proto/ -I=${PB_NODE} -I=${PB_GOGO} -I=${PB_CELESTIA_APP}/proto -I=${PB_NMT} --gogofaster_out=paths=source_relative:. $$file; \ echo '-->' $$file; \ done; \ done; diff --git a/share/shwap/namespaced_data.go b/share/shwap/namespaced_data.go index 07230b77a8..542dbf833c 100644 --- a/share/shwap/namespaced_data.go +++ b/share/shwap/namespaced_data.go @@ -10,7 +10,7 @@ import ( "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" - pb "github.com/celestiaorg/celestia-node/share/shwap/proto" + "github.com/celestiaorg/celestia-node/share/shwap/pb" ) // NamespacedData stores collections of RowNamespaceData, each representing shares and their proofs diff --git a/share/shwap/proto/types.pb.go b/share/shwap/pb/shwap.pb.go similarity index 77% rename from share/shwap/proto/types.pb.go rename to share/shwap/pb/shwap.pb.go index 3784e7d3b8..000bf78ca7 100644 --- a/share/shwap/proto/types.pb.go +++ b/share/shwap/pb/shwap.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: share/pb/types.proto +// source: share/shwap/pb/shwap.proto -package types +package pb import ( fmt "fmt" @@ -45,7 +45,7 @@ func (x AxisType) String() string { } func (AxisType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_b405f12ecc363d82, []int{0} + return fileDescriptor_9431653f3c9f0bcb, []int{0} } type Row_HalfSide int32 @@ -70,19 +70,19 @@ func (x Row_HalfSide) String() string { } func (Row_HalfSide) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_b405f12ecc363d82, []int{0, 0} + return fileDescriptor_9431653f3c9f0bcb, []int{0, 0} } type Row struct { SharesHalf []*Share `protobuf:"bytes,1,rep,name=shares_half,json=sharesHalf,proto3" json:"shares_half,omitempty"` - HalfSide Row_HalfSide `protobuf:"varint,2,opt,name=half_side,json=halfSide,proto3,enum=Row_HalfSide" json:"half_side,omitempty"` + HalfSide Row_HalfSide `protobuf:"varint,2,opt,name=half_side,json=halfSide,proto3,enum=shwap.Row_HalfSide" json:"half_side,omitempty"` } func (m *Row) Reset() { *m = Row{} } func (m *Row) String() string { return proto.CompactTextString(m) } func (*Row) ProtoMessage() {} func (*Row) Descriptor() ([]byte, []int) { - return fileDescriptor_b405f12ecc363d82, []int{0} + return fileDescriptor_9431653f3c9f0bcb, []int{0} } func (m *Row) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -128,14 +128,14 @@ func (m *Row) GetHalfSide() Row_HalfSide { type Sample struct { Share *Share `protobuf:"bytes,1,opt,name=share,proto3" json:"share,omitempty"` Proof *pb.Proof `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - ProofType AxisType `protobuf:"varint,3,opt,name=proof_type,json=proofType,proto3,enum=AxisType" json:"proof_type,omitempty"` + ProofType AxisType `protobuf:"varint,3,opt,name=proof_type,json=proofType,proto3,enum=shwap.AxisType" json:"proof_type,omitempty"` } func (m *Sample) Reset() { *m = Sample{} } func (m *Sample) String() string { return proto.CompactTextString(m) } func (*Sample) ProtoMessage() {} func (*Sample) Descriptor() ([]byte, []int) { - return fileDescriptor_b405f12ecc363d82, []int{1} + return fileDescriptor_9431653f3c9f0bcb, []int{1} } func (m *Sample) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -194,7 +194,7 @@ func (m *RowNamespaceData) Reset() { *m = RowNamespaceData{} } func (m *RowNamespaceData) String() string { return proto.CompactTextString(m) } func (*RowNamespaceData) ProtoMessage() {} func (*RowNamespaceData) Descriptor() ([]byte, []int) { - return fileDescriptor_b405f12ecc363d82, []int{2} + return fileDescriptor_9431653f3c9f0bcb, []int{2} } func (m *RowNamespaceData) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -245,7 +245,7 @@ func (m *Share) Reset() { *m = Share{} } func (m *Share) String() string { return proto.CompactTextString(m) } func (*Share) ProtoMessage() {} func (*Share) Descriptor() ([]byte, []int) { - return fileDescriptor_b405f12ecc363d82, []int{3} + return fileDescriptor_9431653f3c9f0bcb, []int{3} } func (m *Share) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -282,42 +282,42 @@ func (m *Share) GetData() []byte { } func init() { - proto.RegisterEnum("AxisType", AxisType_name, AxisType_value) - proto.RegisterEnum("Row_HalfSide", Row_HalfSide_name, Row_HalfSide_value) - proto.RegisterType((*Row)(nil), "Row") - proto.RegisterType((*Sample)(nil), "Sample") - proto.RegisterType((*RowNamespaceData)(nil), "RowNamespaceData") - proto.RegisterType((*Share)(nil), "Share") + proto.RegisterEnum("shwap.AxisType", AxisType_name, AxisType_value) + proto.RegisterEnum("shwap.Row_HalfSide", Row_HalfSide_name, Row_HalfSide_value) + proto.RegisterType((*Row)(nil), "shwap.Row") + proto.RegisterType((*Sample)(nil), "shwap.Sample") + proto.RegisterType((*RowNamespaceData)(nil), "shwap.RowNamespaceData") + proto.RegisterType((*Share)(nil), "shwap.Share") } -func init() { proto.RegisterFile("share/pb/types.proto", fileDescriptor_b405f12ecc363d82) } +func init() { proto.RegisterFile("share/shwap/pb/shwap.proto", fileDescriptor_9431653f3c9f0bcb) } -var fileDescriptor_b405f12ecc363d82 = []byte{ - // 369 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xcd, 0x6a, 0xdb, 0x40, - 0x14, 0x85, 0x35, 0x95, 0xa5, 0x4a, 0xd7, 0xad, 0x2b, 0x86, 0x2e, 0x44, 0x6b, 0x54, 0x23, 0x28, - 0x35, 0x86, 0x8e, 0xc0, 0x5e, 0x76, 0xd5, 0x7f, 0x07, 0x9c, 0x38, 0x8c, 0x0d, 0x21, 0xd9, 0x98, - 0x91, 0x35, 0xb6, 0x04, 0x72, 0x66, 0x90, 0x14, 0x14, 0x93, 0x97, 0xc8, 0x63, 0x65, 0xe9, 0x65, - 0x96, 0xc1, 0x7e, 0x91, 0xa0, 0x91, 0x1d, 0x42, 0x56, 0xd9, 0x7d, 0x73, 0xce, 0x1d, 0xee, 0x39, - 0x5c, 0xf8, 0x98, 0xc7, 0x2c, 0xe3, 0x81, 0x0c, 0x83, 0x62, 0x2d, 0x79, 0x4e, 0x64, 0x26, 0x0a, - 0xf1, 0xa9, 0x25, 0xc3, 0x40, 0x66, 0x42, 0x2c, 0xea, 0xb7, 0x7f, 0x03, 0x3a, 0x15, 0x25, 0xfe, - 0x06, 0x4d, 0x35, 0x9e, 0xcf, 0x62, 0x96, 0x2e, 0x5c, 0xd4, 0xd1, 0xbb, 0xcd, 0xbe, 0x49, 0x26, - 0x95, 0x46, 0xa1, 0xb6, 0x86, 0x2c, 0x5d, 0xe0, 0x1e, 0xd8, 0xd5, 0xc4, 0x2c, 0x4f, 0x22, 0xee, - 0xbe, 0xe9, 0xa0, 0x6e, 0xab, 0xff, 0x9e, 0x50, 0x51, 0x92, 0xca, 0x9d, 0x24, 0x11, 0xa7, 0x56, - 0xbc, 0x27, 0xff, 0x0b, 0x58, 0x07, 0x15, 0x5b, 0xd0, 0x18, 0xfd, 0xfd, 0x37, 0x75, 0x34, 0x6c, - 0x83, 0x41, 0x8f, 0xfe, 0x0f, 0xa7, 0x0e, 0xf2, 0x4b, 0x30, 0x27, 0x6c, 0x25, 0x53, 0x8e, 0xdb, - 0x60, 0xa8, 0x25, 0x2e, 0xea, 0xa0, 0x67, 0x9b, 0x6b, 0x11, 0x7f, 0x05, 0x43, 0x65, 0x56, 0x0b, - 0x9b, 0xfd, 0x0f, 0x64, 0xdf, 0x20, 0x24, 0xa7, 0x15, 0xd0, 0xda, 0xc5, 0x5d, 0x00, 0x05, 0xb3, - 0xaa, 0xb0, 0xab, 0xab, 0x70, 0x36, 0xf9, 0x79, 0x9d, 0xe4, 0xd3, 0xb5, 0xe4, 0xd4, 0x56, 0x66, - 0x85, 0xfe, 0x39, 0x38, 0x54, 0x94, 0x27, 0x6c, 0xc5, 0x73, 0xc9, 0xe6, 0xfc, 0x0f, 0x2b, 0x18, - 0xf6, 0xc0, 0xac, 0x7b, 0xbe, 0x68, 0xbf, 0x57, 0x5f, 0x19, 0xc2, 0xff, 0x0c, 0x86, 0xfa, 0x87, - 0x31, 0x34, 0x22, 0x56, 0x30, 0xd5, 0xe8, 0x1d, 0x55, 0xdc, 0x6b, 0x83, 0x75, 0x88, 0x83, 0xdf, - 0x82, 0x4e, 0xc7, 0x67, 0x8e, 0x56, 0xc1, 0xef, 0xf1, 0xc8, 0x41, 0xbf, 0x8e, 0xef, 0xb6, 0x1e, - 0xda, 0x6c, 0x3d, 0xf4, 0xb0, 0xf5, 0xd0, 0xed, 0xce, 0xd3, 0x36, 0x3b, 0x4f, 0xbb, 0xdf, 0x79, - 0xda, 0xc5, 0x60, 0x99, 0x14, 0xf1, 0x55, 0x48, 0xe6, 0x62, 0x15, 0xcc, 0x79, 0xca, 0xf3, 0x22, - 0x61, 0x22, 0x5b, 0x3e, 0xf1, 0xf7, 0x4b, 0x11, 0xf1, 0xe0, 0x70, 0xf0, 0x1f, 0xea, 0xe0, 0xa1, - 0xa9, 0x2e, 0x3c, 0x78, 0x0c, 0x00, 0x00, 0xff, 0xff, 0xec, 0x1b, 0x64, 0x91, 0x09, 0x02, 0x00, - 0x00, +var fileDescriptor_9431653f3c9f0bcb = []byte{ + // 381 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x4f, 0x6b, 0xe2, 0x40, + 0x18, 0xc6, 0x33, 0x1b, 0xe3, 0xc6, 0x57, 0xd1, 0x30, 0x7b, 0x09, 0xee, 0x92, 0x95, 0xb0, 0x0b, + 0xb2, 0x60, 0xb2, 0xe8, 0x27, 0xd8, 0xbf, 0xb5, 0x60, 0x6b, 0x19, 0x85, 0x42, 0x2f, 0x61, 0x62, + 0x46, 0x13, 0x88, 0x9d, 0x21, 0x49, 0x49, 0x3d, 0xf7, 0xd0, 0x6b, 0x3f, 0x56, 0x8f, 0x1e, 0x7b, + 0x2c, 0xfa, 0x45, 0x4a, 0x26, 0xb1, 0x14, 0xda, 0x43, 0x6f, 0xbf, 0xcc, 0xf3, 0xcc, 0xbc, 0xcf, + 0x13, 0x5e, 0xe8, 0xa6, 0x21, 0x4d, 0x98, 0x9b, 0x86, 0x39, 0x15, 0xae, 0xf0, 0x4b, 0x70, 0x44, + 0xc2, 0x33, 0x8e, 0x35, 0xf9, 0xd1, 0x6d, 0x0b, 0xdf, 0x15, 0x09, 0xe7, 0xcb, 0xf2, 0xd8, 0xbe, + 0x45, 0xa0, 0x12, 0x9e, 0xe3, 0x01, 0x34, 0xe5, 0xe5, 0xd4, 0x0b, 0x69, 0xbc, 0x34, 0x51, 0x4f, + 0xed, 0x37, 0x87, 0x2d, 0xa7, 0x7c, 0x61, 0x56, 0x28, 0x04, 0x4a, 0xc3, 0x98, 0xc6, 0x4b, 0xfc, + 0x13, 0x1a, 0x85, 0xcf, 0x4b, 0xa3, 0x80, 0x99, 0x1f, 0x7a, 0xa8, 0xdf, 0x1e, 0x7e, 0xaa, 0xcc, + 0x84, 0xe7, 0x4e, 0xe1, 0x99, 0x45, 0x01, 0x23, 0x7a, 0x58, 0x91, 0xfd, 0x15, 0xf4, 0xc3, 0x29, + 0xd6, 0xa1, 0x36, 0xf9, 0xf7, 0x7f, 0x6e, 0x28, 0xb8, 0x01, 0x1a, 0x39, 0x3e, 0x1a, 0xcf, 0x0d, + 0x64, 0xdf, 0x20, 0xa8, 0xcf, 0xe8, 0x5a, 0xc4, 0x0c, 0xdb, 0xa0, 0xc9, 0x59, 0x26, 0xea, 0xa1, + 0x57, 0x31, 0x4a, 0x09, 0x7f, 0x07, 0x4d, 0xf6, 0x90, 0xd3, 0x9b, 0xc3, 0x8e, 0x53, 0xb5, 0xf2, + 0x9d, 0xb3, 0x02, 0x48, 0xa9, 0x62, 0x07, 0x40, 0x82, 0x97, 0x6d, 0x04, 0x33, 0x55, 0x99, 0xb4, + 0x53, 0xbd, 0xf7, 0xeb, 0x3a, 0x4a, 0xe7, 0x1b, 0xc1, 0x48, 0x43, 0x5a, 0x0a, 0xb4, 0x3d, 0x30, + 0x08, 0xcf, 0x4f, 0xe9, 0x9a, 0xa5, 0x82, 0x2e, 0xd8, 0x5f, 0x9a, 0x51, 0xfc, 0x0d, 0xea, 0x65, + 0xf5, 0x37, 0x7f, 0x4b, 0xa5, 0xbd, 0x33, 0x90, 0xfd, 0x19, 0x34, 0x79, 0x0f, 0x63, 0xa8, 0x05, + 0x34, 0xa3, 0xb2, 0x63, 0x8b, 0x48, 0xfe, 0xf1, 0x05, 0xf4, 0x43, 0x28, 0xfc, 0x11, 0x54, 0x32, + 0x3d, 0x37, 0x94, 0x02, 0xfe, 0x4c, 0x27, 0x06, 0xfa, 0x7d, 0x72, 0xbf, 0xb3, 0xd0, 0x76, 0x67, + 0xa1, 0xc7, 0x9d, 0x85, 0xee, 0xf6, 0x96, 0xb2, 0xdd, 0x5b, 0xca, 0xc3, 0xde, 0x52, 0x2e, 0x46, + 0xab, 0x28, 0x0b, 0xaf, 0x7c, 0x67, 0xc1, 0xd7, 0xee, 0x82, 0xc5, 0x2c, 0xcd, 0x22, 0xca, 0x93, + 0xd5, 0x33, 0x0f, 0x2e, 0x79, 0x50, 0xec, 0xc5, 0xcb, 0xed, 0xf0, 0xeb, 0x72, 0x03, 0x46, 0x4f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x67, 0xb6, 0xc0, 0x8b, 0x36, 0x02, 0x00, 0x00, } func (m *Row) Marshal() (dAtA []byte, err error) { @@ -341,7 +341,7 @@ func (m *Row) MarshalToSizedBuffer(dAtA []byte) (int, error) { var l int _ = l if m.HalfSide != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.HalfSide)) + i = encodeVarintShwap(dAtA, i, uint64(m.HalfSide)) i-- dAtA[i] = 0x10 } @@ -353,7 +353,7 @@ func (m *Row) MarshalToSizedBuffer(dAtA []byte) (int, error) { return 0, err } i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) + i = encodeVarintShwap(dAtA, i, uint64(size)) } i-- dAtA[i] = 0xa @@ -383,7 +383,7 @@ func (m *Sample) MarshalToSizedBuffer(dAtA []byte) (int, error) { var l int _ = l if m.ProofType != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.ProofType)) + i = encodeVarintShwap(dAtA, i, uint64(m.ProofType)) i-- dAtA[i] = 0x18 } @@ -394,7 +394,7 @@ func (m *Sample) MarshalToSizedBuffer(dAtA []byte) (int, error) { return 0, err } i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) + i = encodeVarintShwap(dAtA, i, uint64(size)) } i-- dAtA[i] = 0x12 @@ -406,7 +406,7 @@ func (m *Sample) MarshalToSizedBuffer(dAtA []byte) (int, error) { return 0, err } i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) + i = encodeVarintShwap(dAtA, i, uint64(size)) } i-- dAtA[i] = 0xa @@ -441,7 +441,7 @@ func (m *RowNamespaceData) MarshalToSizedBuffer(dAtA []byte) (int, error) { return 0, err } i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) + i = encodeVarintShwap(dAtA, i, uint64(size)) } i-- dAtA[i] = 0x12 @@ -454,7 +454,7 @@ func (m *RowNamespaceData) MarshalToSizedBuffer(dAtA []byte) (int, error) { return 0, err } i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) + i = encodeVarintShwap(dAtA, i, uint64(size)) } i-- dAtA[i] = 0xa @@ -486,15 +486,15 @@ func (m *Share) MarshalToSizedBuffer(dAtA []byte) (int, error) { if len(m.Data) > 0 { i -= len(m.Data) copy(dAtA[i:], m.Data) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i = encodeVarintShwap(dAtA, i, uint64(len(m.Data))) i-- dAtA[i] = 0xa } return len(dAtA) - i, nil } -func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { - offset -= sovTypes(v) +func encodeVarintShwap(dAtA []byte, offset int, v uint64) int { + offset -= sovShwap(v) base := offset for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -513,11 +513,11 @@ func (m *Row) Size() (n int) { if len(m.SharesHalf) > 0 { for _, e := range m.SharesHalf { l = e.Size() - n += 1 + l + sovTypes(uint64(l)) + n += 1 + l + sovShwap(uint64(l)) } } if m.HalfSide != 0 { - n += 1 + sovTypes(uint64(m.HalfSide)) + n += 1 + sovShwap(uint64(m.HalfSide)) } return n } @@ -530,14 +530,14 @@ func (m *Sample) Size() (n int) { _ = l if m.Share != nil { l = m.Share.Size() - n += 1 + l + sovTypes(uint64(l)) + n += 1 + l + sovShwap(uint64(l)) } if m.Proof != nil { l = m.Proof.Size() - n += 1 + l + sovTypes(uint64(l)) + n += 1 + l + sovShwap(uint64(l)) } if m.ProofType != 0 { - n += 1 + sovTypes(uint64(m.ProofType)) + n += 1 + sovShwap(uint64(m.ProofType)) } return n } @@ -551,12 +551,12 @@ func (m *RowNamespaceData) Size() (n int) { if len(m.Shares) > 0 { for _, e := range m.Shares { l = e.Size() - n += 1 + l + sovTypes(uint64(l)) + n += 1 + l + sovShwap(uint64(l)) } } if m.Proof != nil { l = m.Proof.Size() - n += 1 + l + sovTypes(uint64(l)) + n += 1 + l + sovShwap(uint64(l)) } return n } @@ -569,16 +569,16 @@ func (m *Share) Size() (n int) { _ = l l = len(m.Data) if l > 0 { - n += 1 + l + sovTypes(uint64(l)) + n += 1 + l + sovShwap(uint64(l)) } return n } -func sovTypes(x uint64) (n int) { +func sovShwap(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } -func sozTypes(x uint64) (n int) { - return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +func sozShwap(x uint64) (n int) { + return sovShwap(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } func (m *Row) Unmarshal(dAtA []byte) error { l := len(dAtA) @@ -588,7 +588,7 @@ func (m *Row) Unmarshal(dAtA []byte) error { var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -616,7 +616,7 @@ func (m *Row) Unmarshal(dAtA []byte) error { var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -629,11 +629,11 @@ func (m *Row) Unmarshal(dAtA []byte) error { } } if msglen < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } postIndex := iNdEx + msglen if postIndex < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if postIndex > l { return io.ErrUnexpectedEOF @@ -650,7 +650,7 @@ func (m *Row) Unmarshal(dAtA []byte) error { m.HalfSide = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -664,12 +664,12 @@ func (m *Row) Unmarshal(dAtA []byte) error { } default: iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) + skippy, err := skipShwap(dAtA[iNdEx:]) if err != nil { return err } if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF @@ -691,7 +691,7 @@ func (m *Sample) Unmarshal(dAtA []byte) error { var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -719,7 +719,7 @@ func (m *Sample) Unmarshal(dAtA []byte) error { var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -732,11 +732,11 @@ func (m *Sample) Unmarshal(dAtA []byte) error { } } if msglen < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } postIndex := iNdEx + msglen if postIndex < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if postIndex > l { return io.ErrUnexpectedEOF @@ -755,7 +755,7 @@ func (m *Sample) Unmarshal(dAtA []byte) error { var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -768,11 +768,11 @@ func (m *Sample) Unmarshal(dAtA []byte) error { } } if msglen < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } postIndex := iNdEx + msglen if postIndex < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if postIndex > l { return io.ErrUnexpectedEOF @@ -791,7 +791,7 @@ func (m *Sample) Unmarshal(dAtA []byte) error { m.ProofType = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -805,12 +805,12 @@ func (m *Sample) Unmarshal(dAtA []byte) error { } default: iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) + skippy, err := skipShwap(dAtA[iNdEx:]) if err != nil { return err } if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF @@ -832,7 +832,7 @@ func (m *RowNamespaceData) Unmarshal(dAtA []byte) error { var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -855,12 +855,12 @@ func (m *RowNamespaceData) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field halfShares", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType) } var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -873,11 +873,11 @@ func (m *RowNamespaceData) Unmarshal(dAtA []byte) error { } } if msglen < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } postIndex := iNdEx + msglen if postIndex < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if postIndex > l { return io.ErrUnexpectedEOF @@ -894,7 +894,7 @@ func (m *RowNamespaceData) Unmarshal(dAtA []byte) error { var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -907,11 +907,11 @@ func (m *RowNamespaceData) Unmarshal(dAtA []byte) error { } } if msglen < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } postIndex := iNdEx + msglen if postIndex < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if postIndex > l { return io.ErrUnexpectedEOF @@ -925,12 +925,12 @@ func (m *RowNamespaceData) Unmarshal(dAtA []byte) error { iNdEx = postIndex default: iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) + skippy, err := skipShwap(dAtA[iNdEx:]) if err != nil { return err } if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF @@ -952,7 +952,7 @@ func (m *Share) Unmarshal(dAtA []byte) error { var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -980,7 +980,7 @@ func (m *Share) Unmarshal(dAtA []byte) error { var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { - return ErrIntOverflowTypes + return ErrIntOverflowShwap } if iNdEx >= l { return io.ErrUnexpectedEOF @@ -993,11 +993,11 @@ func (m *Share) Unmarshal(dAtA []byte) error { } } if byteLen < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } postIndex := iNdEx + byteLen if postIndex < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if postIndex > l { return io.ErrUnexpectedEOF @@ -1009,12 +1009,12 @@ func (m *Share) Unmarshal(dAtA []byte) error { iNdEx = postIndex default: iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) + skippy, err := skipShwap(dAtA[iNdEx:]) if err != nil { return err } if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes + return ErrInvalidLengthShwap } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF @@ -1028,7 +1028,7 @@ func (m *Share) Unmarshal(dAtA []byte) error { } return nil } -func skipTypes(dAtA []byte) (n int, err error) { +func skipShwap(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 depth := 0 @@ -1036,7 +1036,7 @@ func skipTypes(dAtA []byte) (n int, err error) { var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { - return 0, ErrIntOverflowTypes + return 0, ErrIntOverflowShwap } if iNdEx >= l { return 0, io.ErrUnexpectedEOF @@ -1053,7 +1053,7 @@ func skipTypes(dAtA []byte) (n int, err error) { case 0: for shift := uint(0); ; shift += 7 { if shift >= 64 { - return 0, ErrIntOverflowTypes + return 0, ErrIntOverflowShwap } if iNdEx >= l { return 0, io.ErrUnexpectedEOF @@ -1069,7 +1069,7 @@ func skipTypes(dAtA []byte) (n int, err error) { var length int for shift := uint(0); ; shift += 7 { if shift >= 64 { - return 0, ErrIntOverflowTypes + return 0, ErrIntOverflowShwap } if iNdEx >= l { return 0, io.ErrUnexpectedEOF @@ -1082,14 +1082,14 @@ func skipTypes(dAtA []byte) (n int, err error) { } } if length < 0 { - return 0, ErrInvalidLengthTypes + return 0, ErrInvalidLengthShwap } iNdEx += length case 3: depth++ case 4: if depth == 0 { - return 0, ErrUnexpectedEndOfGroupTypes + return 0, ErrUnexpectedEndOfGroupShwap } depth-- case 5: @@ -1098,7 +1098,7 @@ func skipTypes(dAtA []byte) (n int, err error) { return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } if iNdEx < 0 { - return 0, ErrInvalidLengthTypes + return 0, ErrInvalidLengthShwap } if depth == 0 { return iNdEx, nil @@ -1108,7 +1108,7 @@ func skipTypes(dAtA []byte) (n int, err error) { } var ( - ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") + ErrInvalidLengthShwap = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowShwap = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupShwap = fmt.Errorf("proto: unexpected end of group") ) diff --git a/share/shwap/proto/types.proto b/share/shwap/pb/shwap.proto similarity index 79% rename from share/shwap/proto/types.proto rename to share/shwap/pb/shwap.proto index a36f0f8130..d7daea568a 100644 --- a/share/shwap/proto/types.proto +++ b/share/shwap/pb/shwap.proto @@ -1,6 +1,7 @@ +// Defined in CIP-19 https://github.com/celestiaorg/CIPs/blob/82aeb7dfc472105a11babffd548c730c899a3d24/cips/cip-19.md syntax = "proto3"; - -option go_package = "github.com/celestiaorg/celestia-node/share/shwap/proto;shwap"; +package shwap; +option go_package = "github.com/celestiaorg/celestia-node/share/shwap/pb"; import "pb/proof.proto"; // celestiaorg/nmt/pb/proof.proto @@ -32,4 +33,4 @@ message Share { enum AxisType { ROW = 0; COL = 1; -} \ No newline at end of file +} diff --git a/share/shwap/row.go b/share/shwap/row.go index d23130ef25..1570756740 100644 --- a/share/shwap/row.go +++ b/share/shwap/row.go @@ -8,7 +8,7 @@ import ( "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" - pb "github.com/celestiaorg/celestia-node/share/shwap/proto" + "github.com/celestiaorg/celestia-node/share/shwap/pb" ) // RowSide enumerates the possible sides of a row within an Extended Data Square (EDS). diff --git a/share/shwap/sample.go b/share/shwap/sample.go index 347658b81b..4423ae3629 100644 --- a/share/shwap/sample.go +++ b/share/shwap/sample.go @@ -11,7 +11,7 @@ import ( "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" - pb "github.com/celestiaorg/celestia-node/share/shwap/proto" + "github.com/celestiaorg/celestia-node/share/shwap/pb" ) // Sample represents a data share along with its Merkle proof, used to validate the share's diff --git a/share/shwap/share.go b/share/shwap/share.go index da4ca94c96..de15e15adb 100644 --- a/share/shwap/share.go +++ b/share/shwap/share.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/celestiaorg/celestia-node/share" - pb "github.com/celestiaorg/celestia-node/share/shwap/proto" + "github.com/celestiaorg/celestia-node/share/shwap/pb" ) // ShareFromProto converts a protobuf Share object to the application's internal share From 968d15552373b3446c38e5719f7a8fb315f558d6 Mon Sep 17 00:00:00 2001 From: Vlad <13818348+walldiss@users.noreply.github.com> Date: Wed, 22 May 2024 14:24:33 +0300 Subject: [PATCH 6/7] update file interface to use shwap types --- share/eds/utils.go | 14 ++--- share/ipld/get_shares.go | 5 +- share/ipld/get_shares_test.go | 10 ++-- share/store/file/axis_half.go | 19 ++++++ share/store/{ => file}/eds_file.go | 11 ++-- share/store/{ => file}/mem_file.go | 77 ++++++++++++++----------- share/store/{ => file}/mem_file_test.go | 13 ++--- 7 files changed, 87 insertions(+), 62 deletions(-) create mode 100644 share/store/file/axis_half.go rename share/store/{ => file}/eds_file.go (71%) rename share/store/{ => file}/mem_file.go (60%) rename share/store/{ => file}/mem_file_test.go (79%) diff --git a/share/eds/utils.go b/share/eds/utils.go index b897dd14b5..12f79e8fe7 100644 --- a/share/eds/utils.go +++ b/share/eds/utils.go @@ -121,24 +121,24 @@ func CollectSharesByNamespace( utils.SetStatusAndEnd(span, err) }() - rootCIDs := ipld.FilterRootByNamespace(root, namespace) - if len(rootCIDs) == 0 { + rowRoots, _, _ := share.FilterRootByNamespace(root, namespace) + if len(rowRoots) == 0 { return []share.NamespacedRow{}, nil } errGroup, ctx := errgroup.WithContext(ctx) - shares = make([]share.NamespacedRow, len(rootCIDs)) - for i, rootCID := range rootCIDs { + shares = make([]share.NamespacedRow, len(rowRoots)) + for i, rowRoot := range rowRoots { // shadow loop variables, to ensure correct values are captured - i, rootCID := i, rootCID + i, rowRoot := i, rowRoot errGroup.Go(func() error { - row, proof, err := ipld.GetSharesByNamespace(ctx, bg, rootCID, namespace, len(root.RowRoots)) + row, proof, err := ipld.GetSharesByNamespace(ctx, bg, rowRoot, namespace, len(root.RowRoots)) shares[i] = share.NamespacedRow{ Shares: row, Proof: proof, } if err != nil { - return fmt.Errorf("retrieving shares by namespace %s for row %x: %w", namespace.String(), rootCID, err) + return fmt.Errorf("retrieving shares by namespace %s for row %d: %w", namespace.String(), i, err) } return nil }) diff --git a/share/ipld/get_shares.go b/share/ipld/get_shares.go index 98db7012b5..2883e62761 100644 --- a/share/ipld/get_shares.go +++ b/share/ipld/get_shares.go @@ -44,12 +44,13 @@ func GetShares(ctx context.Context, bg blockservice.BlockGetter, root cid.Cid, s func GetSharesByNamespace( ctx context.Context, bGetter blockservice.BlockGetter, - root cid.Cid, + root []byte, namespace share.Namespace, maxShares int, ) ([]share.Share, *nmt.Proof, error) { + rootCid := MustCidFromNamespacedSha256(root) data := NewNamespaceData(maxShares, namespace, WithLeaves(), WithProofs()) - err := data.CollectLeavesByNamespace(ctx, bGetter, root) + err := data.CollectLeavesByNamespace(ctx, bGetter, rootCid) if err != nil { return nil, nil, err } diff --git a/share/ipld/get_shares_test.go b/share/ipld/get_shares_test.go index 2f5d630473..c5b606acee 100644 --- a/share/ipld/get_shares_test.go +++ b/share/ipld/get_shares_test.go @@ -174,8 +174,7 @@ func TestGetSharesByNamespace(t *testing.T) { rowRoots, err := eds.RowRoots() require.NoError(t, err) for _, row := range rowRoots { - rcid := MustCidFromNamespacedSha256(row) - rowShares, _, err := GetSharesByNamespace(ctx, bServ, rcid, namespace, len(rowRoots)) + rowShares, _, err := GetSharesByNamespace(ctx, bServ, row, namespace, len(rowRoots)) if errors.Is(err, ErrNamespaceOutsideRange) { continue } @@ -363,8 +362,7 @@ func TestGetSharesWithProofsByNamespace(t *testing.T) { rowRoots, err := eds.RowRoots() require.NoError(t, err) for _, row := range rowRoots { - rcid := MustCidFromNamespacedSha256(row) - rowShares, proof, err := GetSharesByNamespace(ctx, bServ, rcid, namespace, len(rowRoots)) + rowShares, proof, err := GetSharesByNamespace(ctx, bServ, row, namespace, len(rowRoots)) if namespace.IsOutsideRange(row, row) { require.ErrorIs(t, err, ErrNamespaceOutsideRange) continue @@ -386,7 +384,7 @@ func TestGetSharesWithProofsByNamespace(t *testing.T) { share.NewSHA256Hasher(), namespace.ToNMT(), leaves, - NamespacedSha256FromCID(rcid)) + row) require.True(t, verified) // verify inclusion @@ -394,7 +392,7 @@ func TestGetSharesWithProofsByNamespace(t *testing.T) { share.NewSHA256Hasher(), namespace.ToNMT(), rowShares, - NamespacedSha256FromCID(rcid)) + row) require.True(t, verified) } } diff --git a/share/store/file/axis_half.go b/share/store/file/axis_half.go new file mode 100644 index 0000000000..58b9306b85 --- /dev/null +++ b/share/store/file/axis_half.go @@ -0,0 +1,19 @@ +package file + +import ( + "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/shwap" +) + +type AxisHalf struct { + Shares []share.Share + IsParity bool +} + +func (a AxisHalf) ToRow() shwap.Row { + side := shwap.Left + if a.IsParity { + side = shwap.Right + } + return shwap.NewRow(a.Shares, side) +} diff --git a/share/store/eds_file.go b/share/store/file/eds_file.go similarity index 71% rename from share/store/eds_file.go rename to share/store/file/eds_file.go index 5d1eefb758..fadd1883a1 100644 --- a/share/store/eds_file.go +++ b/share/store/file/eds_file.go @@ -1,4 +1,4 @@ -package store +package file import ( "context" @@ -7,6 +7,7 @@ import ( "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/shwap" ) type EdsFile interface { @@ -14,11 +15,11 @@ type EdsFile interface { // Size returns square size of the file. Size() int // Share returns share and corresponding proof for the given axis and share index in this axis. - Share(ctx context.Context, x, y int) (*share.ShareWithProof, error) - // AxisHalf returns shares for the first half of the axis of the given type and index. - AxisHalf(ctx context.Context, axisType rsmt2d.Axis, axisIdx int) ([]share.Share, error) + Share(ctx context.Context, rowIdx, colIdx int) (*shwap.Sample, error) + // AxisHalf returns Shares for the first half of the axis of the given type and index. + AxisHalf(ctx context.Context, axisType rsmt2d.Axis, axisIdx int) (AxisHalf, error) // Data returns data for the given namespace and row index. - Data(ctx context.Context, namespace share.Namespace, rowIdx int) (share.NamespacedRow, error) + Data(ctx context.Context, namespace share.Namespace, rowIdx int) (shwap.RowNamespaceData, error) // EDS returns extended data square stored in the file. EDS(ctx context.Context) (*rsmt2d.ExtendedDataSquare, error) } diff --git a/share/store/mem_file.go b/share/store/file/mem_file.go similarity index 60% rename from share/store/mem_file.go rename to share/store/file/mem_file.go index 24f9cfd110..d3fefcb29b 100644 --- a/share/store/mem_file.go +++ b/share/store/file/mem_file.go @@ -1,4 +1,4 @@ -package store +package file import ( "context" @@ -9,6 +9,7 @@ import ( "github.com/celestiaorg/celestia-node/share" "github.com/celestiaorg/celestia-node/share/ipld" + "github.com/celestiaorg/celestia-node/share/shwap" ) var _ EdsFile = (*MemFile)(nil) @@ -27,12 +28,12 @@ func (f *MemFile) Size() int { func (f *MemFile) Share( _ context.Context, - x, y int, -) (*share.ShareWithProof, error) { + rowIdx, colIdx int, +) (*shwap.Sample, error) { axisType := rsmt2d.Row - axisIdx, shrIdx := y, x + axisIdx, shrIdx := rowIdx, colIdx - shares := f.axis(axisType, axisIdx) + shares := getAxis(f.Eds, axisType, axisIdx) tree := wrapper.NewErasuredNamespacedMerkleTree(uint64(f.Size()/2), uint(axisIdx)) for _, shr := range shares { err := tree.Push(shr) @@ -46,19 +47,41 @@ func (f *MemFile) Share( return nil, err } - return &share.ShareWithProof{ - Share: shares[shrIdx], - Proof: &proof, - Axis: axisType, + return &shwap.Sample{ + Share: shares[shrIdx], + Proof: &proof, + ProofType: axisType, }, nil } -func (f *MemFile) AxisHalf(_ context.Context, axisType rsmt2d.Axis, axisIdx int) ([]share.Share, error) { - return f.axis(axisType, axisIdx)[:f.Size()/2], nil +func (f *MemFile) AxisHalf(_ context.Context, axisType rsmt2d.Axis, axisIdx int) (AxisHalf, error) { + return AxisHalf{ + Shares: getAxis(f.Eds, axisType, axisIdx)[:f.Size()/2], + IsParity: false, + }, nil +} + +func (f *MemFile) Data(_ context.Context, namespace share.Namespace, rowIdx int) (shwap.RowNamespaceData, error) { + shares := getAxis(f.Eds, rsmt2d.Row, rowIdx) + return ndDataFromShares(shares, namespace, rowIdx) +} + +func (f *MemFile) EDS(_ context.Context) (*rsmt2d.ExtendedDataSquare, error) { + return f.Eds, nil } -func (f *MemFile) Data(_ context.Context, namespace share.Namespace, rowIdx int) (share.NamespacedRow, error) { - shares := f.axis(rsmt2d.Row, rowIdx) +func getAxis(eds *rsmt2d.ExtendedDataSquare, axisType rsmt2d.Axis, axisIdx int) []share.Share { + switch axisType { + case rsmt2d.Row: + return eds.Row(uint(axisIdx)) + case rsmt2d.Col: + return eds.Col(uint(axisIdx)) + default: + panic("unknown axis") + } +} + +func ndDataFromShares(shares []share.Share, namespace share.Namespace, rowIdx int) (shwap.RowNamespaceData, error) { bserv := ipld.NewMemBlockservice() batchAdder := ipld.NewNmtNodeAdder(context.TODO(), bserv, ipld.MaxSizeBatchOption(len(shares))) tree := wrapper.NewErasuredNamespacedMerkleTree(uint64(len(shares)/2), uint(rowIdx), @@ -66,42 +89,26 @@ func (f *MemFile) Data(_ context.Context, namespace share.Namespace, rowIdx int) for _, shr := range shares { err := tree.Push(shr) if err != nil { - return share.NamespacedRow{}, err + return shwap.RowNamespaceData{}, err } } root, err := tree.Root() if err != nil { - return share.NamespacedRow{}, err + return shwap.RowNamespaceData{}, err } err = batchAdder.Commit() if err != nil { - return share.NamespacedRow{}, err + return shwap.RowNamespaceData{}, err } - cid := ipld.MustCidFromNamespacedSha256(root) - row, proof, err := ipld.GetSharesByNamespace(context.TODO(), bserv, cid, namespace, len(shares)) + row, proof, err := ipld.GetSharesByNamespace(context.TODO(), bserv, root, namespace, len(shares)) if err != nil { - return share.NamespacedRow{}, err + return shwap.RowNamespaceData{}, err } - return share.NamespacedRow{ + return shwap.RowNamespaceData{ Shares: row, Proof: proof, }, nil } - -func (f *MemFile) EDS(_ context.Context) (*rsmt2d.ExtendedDataSquare, error) { - return f.Eds, nil -} - -func (f *MemFile) axis(axisType rsmt2d.Axis, axisIdx int) []share.Share { - switch axisType { - case rsmt2d.Row: - return f.Eds.Row(uint(axisIdx)) - case rsmt2d.Col: - return f.Eds.Col(uint(axisIdx)) - default: - panic("unknown axis") - } -} diff --git a/share/store/mem_file_test.go b/share/store/file/mem_file_test.go similarity index 79% rename from share/store/mem_file_test.go rename to share/store/file/mem_file_test.go index 9df1616afd..5dd6c87998 100644 --- a/share/store/mem_file_test.go +++ b/share/store/file/mem_file_test.go @@ -1,4 +1,4 @@ -package store +package file import ( "context" @@ -19,13 +19,12 @@ func TestMemFileShare(t *testing.T) { fl := &MemFile{Eds: eds} width := int(eds.Width()) - for x := 0; x < width; x++ { - for y := 0; y < width; y++ { - shr, err := fl.Share(context.TODO(), x, y) + for rowIdx := 0; rowIdx < width; rowIdx++ { + for colIdx := 0; colIdx < width; colIdx++ { + shr, err := fl.Share(context.TODO(), rowIdx, colIdx) require.NoError(t, err) - axishash := root.RowRoots[y] - ok := shr.Validate(axishash, x, y, width) + ok := shr.VerifyInclusion(root, rowIdx, colIdx) require.True(t, ok) } } @@ -45,7 +44,7 @@ func TestMemFileDate(t *testing.T) { if !namespace.IsOutsideRange(root, root) { nd, err := file.Data(context.Background(), namespace, i) require.NoError(t, err) - ok := nd.Verify(root, namespace) + ok := nd.VerifyInclusion(root, namespace) require.True(t, ok) } } From 9c6fba5fb04ea4004b240a3d4012307f212913f6 Mon Sep 17 00:00:00 2001 From: Vlad <13818348+walldiss@users.noreply.github.com> Date: Sat, 25 May 2024 00:35:36 +0300 Subject: [PATCH 7/7] update with latest changes --- share/availability.go | 17 ------ share/eds/utils.go | 10 ++-- share/root.go | 81 +++++++++++++++++++++++++++++ share/share.go | 48 ----------------- share/shwap/namespaced_data.go | 29 +++++------ share/shwap/namespaced_data_test.go | 12 ++--- 6 files changed, 106 insertions(+), 91 deletions(-) create mode 100644 share/root.go diff --git a/share/availability.go b/share/availability.go index f3511da450..3373a62276 100644 --- a/share/availability.go +++ b/share/availability.go @@ -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 diff --git a/share/eds/utils.go b/share/eds/utils.go index 12f79e8fe7..ac18b5c082 100644 --- a/share/eds/utils.go +++ b/share/eds/utils.go @@ -121,16 +121,16 @@ func CollectSharesByNamespace( utils.SetStatusAndEnd(span, err) }() - rowRoots, _, _ := share.FilterRootByNamespace(root, namespace) - if len(rowRoots) == 0 { + rowIdxs := share.RowsWithNamespace(root, namespace) + if len(rowIdxs) == 0 { return []share.NamespacedRow{}, nil } errGroup, ctx := errgroup.WithContext(ctx) - shares = make([]share.NamespacedRow, len(rowRoots)) - for i, rowRoot := range rowRoots { + shares = make([]share.NamespacedRow, len(rowIdxs)) + for i, rowIdx := range rowIdxs { // shadow loop variables, to ensure correct values are captured - i, rowRoot := i, rowRoot + i, rowRoot := i, root.RowRoots[rowIdx] errGroup.Go(func() error { row, proof, err := ipld.GetSharesByNamespace(ctx, bg, rowRoot, namespace, len(root.RowRoots)) shares[i] = share.NamespacedRow{ diff --git a/share/root.go b/share/root.go new file mode 100644 index 0000000000..4eca68695e --- /dev/null +++ b/share/root.go @@ -0,0 +1,81 @@ +package share + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "fmt" + "github.com/celestiaorg/celestia-app/pkg/da" + "hash" + + "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 +} + +// DataHash is a representation of the Root hash. +type DataHash []byte + +func (dh DataHash) Validate() error { + if len(dh) != 32 { + return fmt.Errorf("invalid hash size, expected 32, got %d", len(dh)) + } + return nil +} + +func (dh DataHash) String() string { + return fmt.Sprintf("%X", []byte(dh)) +} + +// IsEmptyRoot check whether DataHash corresponds to the root of an empty block EDS. +func (dh DataHash) IsEmptyRoot() bool { + return bytes.Equal(EmptyRoot().Hash(), dh) +} + +// MustDataHashFromString converts a hex string to a valid datahash. +func MustDataHashFromString(datahash string) DataHash { + dh, err := hex.DecodeString(datahash) + if err != nil { + panic(fmt.Sprintf("datahash conversion: passed string was not valid hex: %s", datahash)) + } + err = DataHash(dh).Validate() + if err != nil { + panic(fmt.Sprintf("datahash validation: passed hex string failed: %s", err)) + } + return dh +} + +// NewSHA256Hasher returns a new instance of a SHA-256 hasher. +func NewSHA256Hasher() hash.Hash { + return sha256.New() +} + +// RootHashForCoordinates returns the root hash for the given coordinates. +func RootHashForCoordinates(r *Root, axisType rsmt2d.Axis, rowIdx, colIdx uint) []byte { + if axisType == rsmt2d.Row { + return r.RowRoots[rowIdx] + } + return r.ColumnRoots[colIdx] +} + +// RowsWithNamespace returns indexes of rows, that might contain 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 idxs +} diff --git a/share/share.go b/share/share.go index e2f351e805..b97bab3589 100644 --- a/share/share.go +++ b/share/share.go @@ -1,11 +1,8 @@ package share import ( - "bytes" "crypto/sha256" - "encoding/hex" "fmt" - "hash" "github.com/celestiaorg/celestia-app/pkg/appconsts" "github.com/celestiaorg/nmt" @@ -72,48 +69,3 @@ func (s *ShareWithProof) Validate(rootHash []byte, x, y, edsSize int) bool { rootHash, ) } - -// DataHash is a representation of the Root hash. -type DataHash []byte - -func (dh DataHash) Validate() error { - if len(dh) != 32 { - return fmt.Errorf("invalid hash size, expected 32, got %d", len(dh)) - } - return nil -} - -func (dh DataHash) String() string { - return fmt.Sprintf("%X", []byte(dh)) -} - -// IsEmptyRoot check whether DataHash corresponds to the root of an empty block EDS. -func (dh DataHash) IsEmptyRoot() bool { - return bytes.Equal(EmptyRoot().Hash(), dh) -} - -// MustDataHashFromString converts a hex string to a valid datahash. -func MustDataHashFromString(datahash string) DataHash { - dh, err := hex.DecodeString(datahash) - if err != nil { - panic(fmt.Sprintf("datahash conversion: passed string was not valid hex: %s", datahash)) - } - err = DataHash(dh).Validate() - if err != nil { - panic(fmt.Sprintf("datahash validation: passed hex string failed: %s", err)) - } - return dh -} - -// NewSHA256Hasher returns a new instance of a SHA-256 hasher. -func NewSHA256Hasher() hash.Hash { - return sha256.New() -} - -// RootHashForCoordinates returns the root hash for the given coordinates. -func RootHashForCoordinates(r *Root, axisType rsmt2d.Axis, rowIdx, colIdx uint) []byte { - if axisType == rsmt2d.Row { - return r.RowRoots[rowIdx] - } - return r.ColumnRoots[colIdx] -} diff --git a/share/shwap/namespaced_data.go b/share/shwap/namespaced_data.go index 3f230f2e44..4e5acd5bce 100644 --- a/share/shwap/namespaced_data.go +++ b/share/shwap/namespaced_data.go @@ -16,6 +16,12 @@ import ( // within a namespace. type NamespacedData []RowNamespaceData +// RowNamespaceData holds shares and their corresponding proof for a single row within a namespace. +type RowNamespaceData struct { + Shares []share.Share `json:"shares"` // Shares within the namespace. + Proof *nmt.Proof `json:"proof"` // Proof of the shares' inclusion in the namespace. +} + // Flatten combines all shares from all rows within the namespace into a single slice. func (ns NamespacedData) Flatten() []share.Share { var shares []share.Share @@ -25,26 +31,19 @@ func (ns NamespacedData) Flatten() []share.Share { return shares } -// RowNamespaceData holds shares and their corresponding proof for a single row within a namespace. -type RowNamespaceData struct { - Shares []share.Share `json:"shares"` // Shares within the namespace. - Proof *nmt.Proof `json:"proof"` // Proof of the shares' inclusion in the namespace. -} - // Verify checks the integrity of the NamespacedData against a provided root and namespace. func (ns NamespacedData) Verify(root *share.Root, namespace share.Namespace) error { - rowRoots, _, _ := share.FilterRootByNamespace(root, namespace) + rowIdxs := share.RowsWithNamespace(root, namespace) - if len(rowRoots) != len(ns) { - return fmt.Errorf("expected %d rows, found %d rows", len(rowRoots), len(ns)) + if len(rowIdxs) != len(ns) { + return fmt.Errorf("expected %d rows, found %d rows", len(rowIdxs), len(ns)) } - for i, row := range ns { - if row.Proof == nil || len(row.Shares) == 0 { - return fmt.Errorf("row %d is missing proofs or shares", i) - } - if !row.VerifyInclusion(rowRoots[i], namespace) { - return fmt.Errorf("failed to verify row %d", i) + for i, rowIdx := range rowIdxs { + row := ns[i] + err := row.Validate(root, namespace, rowIdx) + if err != nil { + return fmt.Errorf("failed to validate row %d: %w", i, err) } } return nil diff --git a/share/shwap/namespaced_data_test.go b/share/shwap/namespaced_data_test.go index b5765763d5..bc698defc3 100644 --- a/share/shwap/namespaced_data_test.go +++ b/share/shwap/namespaced_data_test.go @@ -78,13 +78,13 @@ func TestValidateNamespacedRow(t *testing.T) { 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) + rowidxs := share.RowsWithNamespace(root, namespace) + require.Equal(t, len(rowidxs), len(nd)) + + for i, rowidx := range rowidxs { + row := nd[i] + err = row.Validate(root, namespace, rowidx) require.NoError(t, err) - idx++ } } }