diff --git a/blob/blob.go b/blob/blob.go index a51b17e..9c6b980 100644 --- a/blob/blob.go +++ b/blob/blob.go @@ -25,9 +25,12 @@ const ProtoIndexWrapperTypeID = "INDX" // MaxShareVersion is the maximum value a share version can be. See: [shares.MaxShareVersion]. const MaxShareVersion = 127 +// SignerSize is the size of the signer in bytes. +const SignerSize = 20 + // Blob (stands for binary large object) is a core type that represents data // to be submitted to the Celestia network alongside an accompanying namespace -// and optional signer (for proving the signer of the blob) +// and optional signer (for proving the author of the blob) type Blob struct { namespace ns.Namespace data []byte @@ -37,13 +40,31 @@ type Blob struct { // New creates a new coretypes.Blob from the provided data after performing // basic stateless checks over it. -func New(ns ns.Namespace, data []byte, shareVersion uint8, signer []byte) *Blob { +func New(ns ns.Namespace, data []byte, shareVersion uint8, signer []byte) (*Blob, error) { + if shareVersion == 0 && signer != nil { + return nil, errors.New("share version 0 does not support signer") + } + if shareVersion == 1 && len(signer) != SignerSize { + return nil, errors.New("share version 1 requires signer of size 20 bytes") + } return &Blob{ namespace: ns, data: data, shareVersion: shareVersion, signer: signer, + }, nil +} + +func NewV0(ns ns.Namespace, data []byte) *Blob { + blob, err := New(ns, data, 0, nil) + if err != nil { + panic(err) } + return blob +} + +func NewV1(ns ns.Namespace, data []byte, signer []byte) (*Blob, error) { + return New(ns, data, 1, signer) } // NewFromProto creates a Blob from the proto format and performs @@ -62,12 +83,12 @@ func NewFromProto(pb *BlobProto) (*Blob, error) { if err != nil { return nil, fmt.Errorf("invalid namespace: %w", err) } - return &Blob{ - namespace: ns, - data: pb.Data, - shareVersion: uint8(pb.ShareVersion), - signer: pb.Signer, - }, nil + return New( + ns, + pb.Data, + uint8(pb.ShareVersion), + pb.Signer, + ) } // Namespace returns the namespace of the blob diff --git a/inclusion/commitment_test.go b/inclusion/commitment_test.go index 7aec190..51c43b4 100644 --- a/inclusion/commitment_test.go +++ b/inclusion/commitment_test.go @@ -72,6 +72,7 @@ func TestCreateCommitment(t *testing.T) { expected []byte expectErr bool shareVersion uint8 + signer []byte } tests := []test{ { @@ -81,6 +82,14 @@ func TestCreateCommitment(t *testing.T) { expected: []byte{0x31, 0xf5, 0x15, 0x6d, 0x5d, 0xb9, 0xa7, 0xf5, 0xb4, 0x3b, 0x29, 0x7a, 0x14, 0xc0, 0x70, 0xc2, 0xcc, 0x4e, 0xf3, 0xd6, 0x9d, 0x87, 0xed, 0x8, 0xad, 0xdd, 0x21, 0x6d, 0x9b, 0x9f, 0xa1, 0x18}, shareVersion: shares.ShareVersionZero, }, + { + name: "blob of one share with signer succeeds", + namespace: ns1, + blob: bytes.Repeat([]byte{0xFF}, shares.AvailableBytesFromSparseShares(2)-blob.SignerSize), + expected: []byte{0x88, 0x3c, 0x74, 0x6, 0x4e, 0x8e, 0x26, 0x27, 0xad, 0x58, 0x8, 0x38, 0x9f, 0x1f, 0x19, 0x24, 0x19, 0x4c, 0x1a, 0xe2, 0x3c, 0x7d, 0xf9, 0x62, 0xc8, 0xd5, 0x6d, 0xf0, 0x62, 0xa9, 0x2b, 0x2b}, + shareVersion: shares.ShareVersionOne, + signer: bytes.Repeat([]byte{1}, blob.SignerSize), + }, { name: "blob with unsupported share version should return error", namespace: ns1, @@ -91,7 +100,8 @@ func TestCreateCommitment(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - blob := blob.New(tt.namespace, tt.blob, tt.shareVersion, nil) + blob, err := blob.New(tt.namespace, tt.blob, tt.shareVersion, tt.signer) + require.NoError(t, err) res, err := inclusion.CreateCommitment(blob, twoLeafMerkleRoot, defaultSubtreeRootThreshold) if tt.expectErr { assert.Error(t, err) diff --git a/internal/test/factory.go b/internal/test/factory.go index b8abb80..5c13a8d 100644 --- a/internal/test/factory.go +++ b/internal/test/factory.go @@ -38,13 +38,21 @@ func RandomBytes(size int) []byte { return b } -func GenerateBlobTxWithNamespace(namespaces []namespace.Namespace, blobSizes []int) []byte { +func GenerateBlobTxWithNamespace(namespaces []namespace.Namespace, blobSizes []int, version uint8) []byte { blobs := make([]*blob.Blob, len(blobSizes)) if len(namespaces) != len(blobSizes) { panic("number of namespaces should match number of blob sizes") } + var err error + var signer []byte + if version == shares.ShareVersionOne { + signer = RandomBytes(blob.SignerSize) + } for i, size := range blobSizes { - blobs[i] = blob.New(namespaces[i], RandomBytes(size), shares.DefaultShareVersion, nil) + blobs[i], err = blob.New(namespaces[i], RandomBytes(size), version, signer) + if err != nil { + panic(err) + } } blobTx, err := blob.MarshalBlobTx(MockPFB(toUint32(blobSizes)), blobs...) if err != nil { @@ -54,7 +62,7 @@ func GenerateBlobTxWithNamespace(namespaces []namespace.Namespace, blobSizes []i } func GenerateBlobTx(blobSizes []int) []byte { - return GenerateBlobTxWithNamespace(Repeat(DefaultTestNamespace, len(blobSizes)), blobSizes) + return GenerateBlobTxWithNamespace(Repeat(DefaultTestNamespace, len(blobSizes)), blobSizes, shares.DefaultShareVersion) } func GenerateBlobTxs(numTxs, blobsPerPfb, blobSize int) [][]byte { diff --git a/shares/parse.go b/shares/parse.go index 6f37ec1..cb527ff 100644 --- a/shares/parse.go +++ b/shares/parse.go @@ -36,13 +36,7 @@ func ParseShares(shares []Share, ignorePadding bool) ([]ShareSequence, error) { currentSequence := ShareSequence{} for _, share := range shares { - if err := share.Validate(); err != nil { - return sequences, err - } - isStart, err := share.IsSequenceStart() - if err != nil { - return sequences, err - } + isStart := share.IsSequenceStart() ns, err := share.Namespace() if err != nil { return sequences, err diff --git a/shares/parse_sparse_shares.go b/shares/parse_sparse_shares.go index b0a5adb..e44460a 100644 --- a/shares/parse_sparse_shares.go +++ b/shares/parse_sparse_shares.go @@ -13,6 +13,7 @@ type sequence struct { shareVersion uint8 data []byte sequenceLen uint32 + signer []byte } // parseSparseShares iterates through rawShares and parses out individual @@ -25,10 +26,7 @@ func parseSparseShares(shares []Share, supportedShareVersions []uint8) (blobs [] sequences := make([]sequence, 0) for _, share := range shares { - version, err := share.Version() - if err != nil { - return nil, err - } + version := share.Version() if !bytes.Contains(supportedShareVersions, []byte{version}) { return nil, fmt.Errorf("unsupported share version %v is not present in supported share versions %v", version, supportedShareVersions) } @@ -41,16 +39,8 @@ func parseSparseShares(shares []Share, supportedShareVersions []uint8) (blobs [] continue } - isStart, err := share.IsSequenceStart() - if err != nil { - return nil, err - } - - if isStart { - sequenceLen, err := share.SequenceLen() - if err != nil { - return nil, err - } + if share.IsSequenceStart() { + sequenceLen := share.SequenceLen() data, err := share.RawData() if err != nil { return nil, err @@ -64,6 +54,7 @@ func parseSparseShares(shares []Share, supportedShareVersions []uint8) (blobs [] shareVersion: version, data: data, sequenceLen: sequenceLen, + signer: GetSigner(share), }) } else { // continuation share if len(sequences) == 0 { @@ -81,7 +72,11 @@ func parseSparseShares(shares []Share, supportedShareVersions []uint8) (blobs [] for _, sequence := range sequences { // trim any padding from the end of the sequence sequence.data = sequence.data[:sequence.sequenceLen] - blobs = append(blobs, blob.New(sequence.ns, sequence.data, sequence.shareVersion, nil)) + blob, err := blob.New(sequence.ns, sequence.data, sequence.shareVersion, sequence.signer) + if err != nil { + return nil, err + } + blobs = append(blobs, blob) } return blobs, nil diff --git a/shares/parse_sparse_shares_test.go b/shares/parse_sparse_shares_test.go index b47c60b..7aca801 100644 --- a/shares/parse_sparse_shares_test.go +++ b/shares/parse_sparse_shares_test.go @@ -155,13 +155,25 @@ func Test_parseSparseSharesWithNamespacedPadding(t *testing.T) { require.Equal(t, blobs, pblobs) } +func Test_parseShareVersionOne(t *testing.T) { + v1blob, err := blob.NewV1(ns.MustNewV0(bytes.Repeat([]byte{1}, ns.NamespaceVersionZeroIDSize)), []byte("data"), bytes.Repeat([]byte{1}, blob.SignerSize)) + require.NoError(t, err) + v1shares, err := SplitBlobs(v1blob) + require.NoError(t, err) + + parsedBlobs, err := parseSparseShares(v1shares, SupportedShareVersions) + require.NoError(t, err) + require.Equal(t, v1blob, parsedBlobs[0]) + require.Len(t, parsedBlobs, 1) +} + func generateRandomBlobWithNamespace(namespace ns.Namespace, size int) *blob.Blob { data := make([]byte, size) _, err := crand.Read(data) if err != nil { panic(err) } - return blob.New(namespace, data, ShareVersionZero, nil) + return blob.NewV0(namespace, data) } func generateRandomBlob(dataSize int) *blob.Blob { diff --git a/shares/parse_test.go b/shares/parse_test.go index 079611a..d9a985c 100644 --- a/shares/parse_test.go +++ b/shares/parse_test.go @@ -31,9 +31,6 @@ func TestParseShares(t *testing.T) { blobTwoStart := blobTwoShares[0] blobTwoContinuation := blobTwoShares[1] - // invalidShare is longer than the length of a valid share - invalidShare := Share{data: append(generateRawShare(t, ns1, true, 1), []byte{0}...)} - // tooLargeSequenceLen is a single share with too large of a sequence len // because it takes more than one share to store a sequence of 1000 bytes tooLargeSequenceLen := generateRawShare(t, ns1, true, uint32(1000)) @@ -116,13 +113,6 @@ func TestParseShares(t *testing.T) { }, expectErr: false, }, - { - name: "one share with invalid size", - shares: []Share{invalidShare}, - ignorePadding: false, - want: []ShareSequence{}, - expectErr: true, - }, { name: "blob one start followed by blob two continuation", shares: []Share{blobOneStart, blobTwoContinuation}, diff --git a/shares/share_builder.go b/shares/share_builder.go index e52aa6a..0adcd17 100644 --- a/shares/share_builder.go +++ b/shares/share_builder.go @@ -168,6 +168,17 @@ func (b *Builder) WriteSequenceLen(sequenceLen uint32) error { return nil } +// WriteSigner writes the signer's information to the share. +func (b *Builder) WriteSigner(signer []byte) { + // only write the signer if it is the first share and the share version is 1 + if b == nil || !b.isFirstShare || b.shareVersion != ShareVersionOne { + return + } + // NOTE: we don't check whether previous data has already been expected + // like the sequence length (we just assume it has) + b.rawShareData = append(b.rawShareData, signer...) +} + // FlipSequenceStart flips the sequence start indicator of the share provided func (b *Builder) FlipSequenceStart() { infoByteIndex := b.indexOfInfoBytes() diff --git a/shares/share_builder_test.go b/shares/share_builder_test.go index 1268f57..6ca2b0e 100644 --- a/shares/share_builder_test.go +++ b/shares/share_builder_test.go @@ -137,9 +137,7 @@ func TestShareBuilderWriteSequenceLen(t *testing.T) { share, err := tc.builder.Build() require.NoError(t, err) - length, err := share.SequenceLen() - require.NoError(t, err) - + length := share.SequenceLen() assert.Equal(t, tc.wantLen, length) }) } diff --git a/shares/share_sequence.go b/shares/share_sequence.go index c8a0c21..d11e288 100644 --- a/shares/share_sequence.go +++ b/shares/share_sequence.go @@ -38,7 +38,7 @@ func (s ShareSequence) SequenceLen() (uint32, error) { return 0, fmt.Errorf("invalid sequence length because share sequence %v has no shares", s) } firstShare := s.Shares[0] - return firstShare.SequenceLen() + return firstShare.SequenceLen(), nil } // validSequenceLen extracts the sequenceLen written to the first share @@ -84,10 +84,7 @@ func (s ShareSequence) isPadding() (bool, error) { // firstShare and returns the number of shares needed to store a sequence of // that length. func numberOfSharesNeeded(firstShare Share) (sharesUsed int, err error) { - sequenceLen, err := firstShare.SequenceLen() - if err != nil { - return 0, err - } + sequenceLen := firstShare.SequenceLen() isCompact, err := firstShare.IsCompactShare() if err != nil { diff --git a/shares/shares.go b/shares/shares.go index 4612339..3ff884b 100644 --- a/shares/shares.go +++ b/shares/shares.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "fmt" + "github.com/celestiaorg/go-square/blob" "github.com/celestiaorg/go-square/namespace" ) @@ -14,33 +15,14 @@ type Share struct { data []byte } -func (s *Share) Namespace() (namespace.Namespace, error) { - if len(s.data) < namespace.NamespaceSize { - panic(fmt.Sprintf("share %s is too short to contain a namespace", s)) - } - return namespace.From(s.data[:namespace.NamespaceSize]) -} - -func (s *Share) InfoByte() (InfoByte, error) { - if len(s.data) < namespace.NamespaceSize+ShareInfoBytes { - return 0, fmt.Errorf("share %s is too short to contain an info byte", s) - } - // the info byte is the first byte after the namespace - unparsed := s.data[namespace.NamespaceSize] - return ParseInfoByte(unparsed) -} - func NewShare(data []byte) (*Share, error) { if err := validateSize(data); err != nil { return nil, err } + // TODO: we should also validate namespace return &Share{data}, nil } -func (s *Share) Validate() error { - return validateSize(s.data) -} - func validateSize(data []byte) error { if len(data) != ShareSize { return fmt.Errorf("share data must be %d bytes, got %d", ShareSize, len(data)) @@ -48,23 +30,26 @@ func validateSize(data []byte) error { return nil } -func (s *Share) Len() int { - return len(s.data) +// Namespace returns the shares namespace +// TODO: we could validate it the namespace in the constructor +// and then return the bytes without needing to validate it every time +func (s *Share) Namespace() (namespace.Namespace, error) { + return namespace.NewFromBytes(s.data[:namespace.NamespaceSize]) } -func (s *Share) Version() (uint8, error) { - infoByte, err := s.InfoByte() - if err != nil { - return 0, err - } - return infoByte.Version(), nil +func (s *Share) InfoByte() InfoByte { + // the info byte is the first byte after the namespace + unparsed := s.data[namespace.NamespaceSize] + return InfoByte(unparsed) +} + +func (s *Share) Version() uint8 { + infoByte := s.InfoByte() + return infoByte.Version() } func (s *Share) DoesSupportVersions(supportedShareVersions []uint8) error { - ver, err := s.Version() - if err != nil { - return err - } + ver := s.Version() if !bytes.Contains(supportedShareVersions, []byte{ver}) { return fmt.Errorf("unsupported share version %v is not present in the list of supported share versions %v", ver, supportedShareVersions) } @@ -72,12 +57,9 @@ func (s *Share) DoesSupportVersions(supportedShareVersions []uint8) error { } // IsSequenceStart returns true if this is the first share in a sequence. -func (s *Share) IsSequenceStart() (bool, error) { - infoByte, err := s.InfoByte() - if err != nil { - return false, err - } - return infoByte.IsSequenceStart(), nil +func (s *Share) IsSequenceStart() bool { + infoByte := s.InfoByte() + return infoByte.IsSequenceStart() } // IsCompactShare returns true if this is a compact share. @@ -90,33 +72,38 @@ func (s Share) IsCompactShare() (bool, error) { return isCompact, nil } +// GetSigner returns the signer of the share, if the +// share is not of type v1 and is not the first share in a sequence +// it returns nil +func GetSigner(share Share) []byte { + infoByte := share.InfoByte() + if infoByte.Version() != ShareVersionOne { + return nil + } + if !infoByte.IsSequenceStart() { + return nil + } + startIndex := namespace.NamespaceSize + ShareInfoBytes + SequenceLenBytes + endIndex := startIndex + blob.SignerSize + return share.data[startIndex:endIndex] +} + // SequenceLen returns the sequence length of this *share and optionally an // error. It returns 0, nil if this is a continuation share (i.e. doesn't // contain a sequence length). -func (s *Share) SequenceLen() (sequenceLen uint32, err error) { - isSequenceStart, err := s.IsSequenceStart() - if err != nil { - return 0, err - } - if !isSequenceStart { - return 0, nil +func (s *Share) SequenceLen() uint32 { + if !s.IsSequenceStart() { + return 0 } start := namespace.NamespaceSize + ShareInfoBytes end := start + SequenceLenBytes - if len(s.data) < end { - return 0, fmt.Errorf("share %s with length %d is too short to contain a sequence length", - s, len(s.data)) - } - return binary.BigEndian.Uint32(s.data[start:end]), nil + return binary.BigEndian.Uint32(s.data[start:end]) } // IsPadding returns whether this *share is padding or not. func (s *Share) IsPadding() (bool, error) { - isNamespacePadding, err := s.isNamespacePadding() - if err != nil { - return false, err - } + isNamespacePadding := s.isNamespacePadding() isTailPadding, err := s.isTailPadding() if err != nil { return false, err @@ -128,17 +115,8 @@ func (s *Share) IsPadding() (bool, error) { return isNamespacePadding || isTailPadding || isPrimaryReservedPadding, nil } -func (s *Share) isNamespacePadding() (bool, error) { - isSequenceStart, err := s.IsSequenceStart() - if err != nil { - return false, err - } - sequenceLen, err := s.SequenceLen() - if err != nil { - return false, err - } - - return isSequenceStart && sequenceLen == 0, nil +func (s *Share) isNamespacePadding() bool { + return s.IsSequenceStart() && s.SequenceLen() == 0 } func (s *Share) isTailPadding() (bool, error) { @@ -162,23 +140,21 @@ func (s *Share) ToBytes() []byte { } // RawData returns the raw share data. The raw share data does not contain the -// namespace ID, info byte, sequence length, or reserved bytes. -func (s *Share) RawData() (rawData []byte, err error) { - if len(s.data) < s.rawDataStartIndex() { - return rawData, fmt.Errorf("share %s is too short to contain raw data", s) +// namespace ID, info byte, sequence length and if they exist: the reserved bytes +// and signer. +func (s *Share) RawData() ([]byte, error) { + startingIndex, err := s.rawDataStartIndex() + if err != nil { + return nil, err } - - return s.data[s.rawDataStartIndex():], nil + return s.data[startingIndex:], nil } -func (s *Share) rawDataStartIndex() int { - isStart, err := s.IsSequenceStart() - if err != nil { - panic(err) - } +func (s *Share) rawDataStartIndex() (int, error) { + isStart := s.IsSequenceStart() isCompact, err := s.IsCompactShare() if err != nil { - panic(err) + return 0, err } index := namespace.NamespaceSize + ShareInfoBytes @@ -188,7 +164,10 @@ func (s *Share) rawDataStartIndex() int { if isCompact { index += ShareReservedBytes } - return index + if s.Version() == ShareVersionOne { + index += blob.SignerSize + } + return index, nil } // RawDataUsingReserved returns the raw share data while taking reserved bytes into account. @@ -212,10 +191,7 @@ func (s *Share) RawDataUsingReserved() (rawData []byte, err error) { // rawDataStartIndexUsingReserved returns the start index of raw data while accounting for // reserved bytes, if it exists in the share. func (s *Share) rawDataStartIndexUsingReserved() (int, error) { - isStart, err := s.IsSequenceStart() - if err != nil { - return 0, err - } + isStart := s.IsSequenceStart() isCompact, err := s.IsCompactShare() if err != nil { return 0, err @@ -225,6 +201,9 @@ func (s *Share) rawDataStartIndexUsingReserved() (int, error) { if isStart { index += SequenceLenBytes } + if s.Version() == ShareVersionOne { + index += blob.SignerSize + } if isCompact { reservedBytes, err := ParseReservedBytes(s.data[index : index+ShareReservedBytes]) diff --git a/shares/shares_test.go b/shares/shares_test.go index 1681977..da4e29e 100644 --- a/shares/shares_test.go +++ b/shares/shares_test.go @@ -14,7 +14,6 @@ func TestSequenceLen(t *testing.T) { name string share Share wantLen uint32 - wantErr bool } firstShare := append(bytes.Repeat([]byte{1}, namespace.NamespaceSize), []byte{ @@ -36,58 +35,32 @@ func TestSequenceLen(t *testing.T) { 1, // info byte 0, 0, 0, 10, // sequence len }...) - noInfoByte := namespace.TxNamespace.Bytes() - noSequenceLen := append(namespace.TxNamespace.Bytes(), - []byte{ - 1, // info byte - }...) testCases := []testCase{ { name: "first share", share: Share{data: firstShare}, wantLen: 10, - wantErr: false, }, { name: "first share with long sequence", share: Share{data: firstShareWithLongSequence}, wantLen: 323, - wantErr: false, }, { name: "continuation share", share: Share{data: continuationShare}, wantLen: 0, - wantErr: false, }, { name: "compact share", share: Share{data: compactShare}, wantLen: 10, - wantErr: false, - }, - { - name: "no info byte returns error", - share: Share{data: noInfoByte}, - wantLen: 0, - wantErr: true, - }, - { - name: "no sequence len returns error", - share: Share{data: noSequenceLen}, - wantLen: 0, - wantErr: true, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - length, err := tc.share.SequenceLen() - - if tc.wantErr { - assert.Error(t, err) - return - } + length := tc.share.SequenceLen() if tc.wantLen != length { t.Errorf("want %d, got %d", tc.wantLen, length) } @@ -97,10 +70,9 @@ func TestSequenceLen(t *testing.T) { func TestRawData(t *testing.T) { type testCase struct { - name string - share Share - want []byte - wantErr bool + name string + share Share + want []byte } sparseNamespaceID := namespace.MustNewV0(bytes.Repeat([]byte{0x1}, namespace.NamespaceVersionZeroIDSize)) firstSparseShare := append( @@ -129,15 +101,6 @@ func TestRawData(t *testing.T) { 0, 0, 0, 0, // reserved bytes 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // data }...) - noSequenceLen := append(namespace.TxNamespace.Bytes(), - []byte{ - 1, // info byte - }...) - notEnoughSequenceLenBytes := append(namespace.TxNamespace.Bytes(), - []byte{ - 1, // info byte - 0, 0, 10, // sequence len - }...) testCases := []testCase{ { name: "first sparse share", @@ -159,25 +122,12 @@ func TestRawData(t *testing.T) { share: Share{data: continuationCompactShare}, want: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, }, - { - name: "no sequence len returns error", - share: Share{data: noSequenceLen}, - wantErr: true, - }, - { - name: "not enough sequence len bytes returns error", - share: Share{data: notEnoughSequenceLenBytes}, - wantErr: true, - }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { rawData, err := tc.share.RawData() - if tc.wantErr { - assert.Error(t, err) - return - } + require.NoError(t, err) assert.Equal(t, tc.want, rawData) }) } @@ -222,12 +172,10 @@ func TestIsCompactShare(t *testing.T) { func TestIsPadding(t *testing.T) { type testCase struct { - name string - share Share - want bool - wantErr bool + name string + share Share + want bool } - emptyShare := Share{} blobShare, _ := zeroPadIfNecessary( append( ns1.Bytes(), @@ -243,11 +191,6 @@ func TestIsPadding(t *testing.T) { require.NoError(t, err) testCases := []testCase{ - { - name: "empty share", - share: emptyShare, - wantErr: true, - }, { name: "blob share", share: Share{data: blobShare}, @@ -273,10 +216,6 @@ func TestIsPadding(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { got, err := tc.share.IsPadding() - if tc.wantErr { - assert.Error(t, err) - return - } require.NoError(t, err) assert.Equal(t, tc.want, got) }) diff --git a/shares/sparse_shares_test.go b/shares/sparse_shares_test.go index 7d22886..bd07f0e 100644 --- a/shares/sparse_shares_test.go +++ b/shares/sparse_shares_test.go @@ -41,8 +41,7 @@ func TestSparseShareContainsInfoByte(t *testing.T) { err := sss.Write(blob) assert.NoError(t, err) shares := sss.Export() - got, err := shares[tc.shareIndex].InfoByte() - require.NoError(t, err) + got := shares[tc.shareIndex].InfoByte() assert.Equal(t, tc.expected, got) }) } diff --git a/shares/split_sparse_shares.go b/shares/split_sparse_shares.go index 9cbc6ad..bae30d3 100644 --- a/shares/split_sparse_shares.go +++ b/shares/split_sparse_shares.go @@ -36,9 +36,12 @@ func (sss *SparseShareSplitter) Write(blob *blob.Blob) error { if err := b.WriteSequenceLen(uint32(len(rawData))); err != nil { return err } + // add the signer to the first share for v1 share versions only + if blob.ShareVersion() == ShareVersionOne { + b.WriteSigner(blob.Signer()) + } for rawData != nil { - rawDataLeftOver := b.AddData(rawData) if rawDataLeftOver == nil { // Just call it on the latest share @@ -80,10 +83,7 @@ func (sss *SparseShareSplitter) WriteNamespacePaddingShares(count int) error { if err != nil { return err } - lastBlobInfo, err := lastBlob.InfoByte() - if err != nil { - return err - } + lastBlobInfo := lastBlob.InfoByte() nsPaddingShares, err := NamespacePaddingShares(lastBlobNs, lastBlobInfo.Version(), count) if err != nil { return err diff --git a/shares/split_sparse_shares_test.go b/shares/split_sparse_shares_test.go index 8546a03..f834ef6 100644 --- a/shares/split_sparse_shares_test.go +++ b/shares/split_sparse_shares_test.go @@ -7,6 +7,7 @@ import ( "github.com/celestiaorg/go-square/blob" "github.com/celestiaorg/go-square/namespace" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestSparseShareSplitter tests that the spare share splitter can split blobs @@ -14,12 +15,14 @@ import ( func TestSparseShareSplitter(t *testing.T) { ns1 := namespace.MustNewV0(bytes.Repeat([]byte{1}, namespace.NamespaceVersionZeroIDSize)) ns2 := namespace.MustNewV0(bytes.Repeat([]byte{2}, namespace.NamespaceVersionZeroIDSize)) + signer := bytes.Repeat([]byte{1}, blob.SignerSize) - blob1 := blob.New(ns1, []byte("data1"), ShareVersionZero, nil) - blob2 := blob.New(ns2, []byte("data2"), ShareVersionZero, nil) + blob1 := blob.NewV0(ns1, []byte("data1")) + blob2, err := blob.NewV1(ns2, []byte("data2"), signer) + require.NoError(t, err) sss := NewSparseShareSplitter() - err := sss.Write(blob1) + err = sss.Write(blob1) assert.NoError(t, err) err = sss.Write(blob2) @@ -27,11 +30,16 @@ func TestSparseShareSplitter(t *testing.T) { got := sss.Export() assert.Len(t, got, 2) + + assert.Equal(t, ShareVersionZero, got[0].Version()) + assert.Equal(t, ShareVersionOne, got[1].Version()) + assert.Equal(t, signer, GetSigner(got[1])) + assert.Nil(t, GetSigner(got[0])) // this is v0 so should not have any signer attached } func TestWriteNamespacePaddingShares(t *testing.T) { ns1 := namespace.MustNewV0(bytes.Repeat([]byte{1}, namespace.NamespaceVersionZeroIDSize)) - blob1 := newBlob(ns1, ShareVersionZero) + blob1 := blob.NewV0(ns1, []byte("data1")) sss := NewSparseShareSplitter() @@ -50,11 +58,6 @@ func TestWriteNamespacePaddingShares(t *testing.T) { assert.True(t, isPadding) // verify that the padding share has the same share version as blob1 - info, err := got[1].InfoByte() - assert.NoError(t, err) - assert.Equal(t, info.Version(), ShareVersionZero) -} - -func newBlob(ns namespace.Namespace, shareVersion uint8) *blob.Blob { - return blob.New(ns, []byte("data"), shareVersion, nil) + version := got[1].Version() + assert.Equal(t, version, ShareVersionZero) } diff --git a/square/builder_test.go b/square/builder_test.go index 4efd3a8..81e038f 100644 --- a/square/builder_test.go +++ b/square/builder_test.go @@ -338,7 +338,7 @@ func generateBlobTxsWithNamespaces(namespaces []namespace.Namespace, blobSizes [ counter := 0 for i := 0; i < len(txs); i++ { n := namespaces[counter : counter+len(blobSizes[i])] - txs[i] = test.GenerateBlobTxWithNamespace(n, blobSizes[i]) + txs[i] = test.GenerateBlobTxWithNamespace(n, blobSizes[i], shares.ShareVersionZero) counter += len(blobSizes[i]) } return txs