1212// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313// See the License for the specific language governing permissions and
1414// limitations under the License.
15+
16+ mod record_shards;
17+
1518extern crate alloc;
1619
20+ use crate :: archiver:: record_shards:: RecordShards ;
1721use crate :: merkle_tree:: { MerkleTree , Witness } ;
18- use crate :: utils;
19- use crate :: utils:: { Gf16Element , GF_16_ELEMENT_BYTES } ;
22+ use crate :: utils:: GF_16_ELEMENT_BYTES ;
2023use alloc:: borrow:: Cow ;
2124use alloc:: collections:: VecDeque ;
2225use alloc:: vec;
2326use alloc:: vec:: Vec ;
2427use core:: cmp:: Ordering ;
25- use core:: iter;
2628use parity_scale_codec:: { Compact , CompactLen , Decode , Encode } ;
2729use reed_solomon_erasure:: galois_16:: ReedSolomon ;
2830use subspace_core_primitives:: objects:: {
@@ -135,6 +137,9 @@ pub enum ArchiverInstantiationError {
135137 error( "Segment size is not bigger than record size" )
136138 ) ]
137139 SegmentSizeTooSmall ,
140+ /// Segment size must be multiple of two
141+ #[ cfg_attr( feature = "thiserror" , error( "Segment size must be multiple of two" ) ) ]
142+ SegmentSizeNotMultipleOfTwo ,
138143 /// Segment size is not a multiple of record size
139144 #[ cfg_attr(
140145 feature = "thiserror" ,
@@ -220,6 +225,9 @@ impl Archiver {
220225 if segment_size <= record_size {
221226 return Err ( ArchiverInstantiationError :: SegmentSizeTooSmall ) ;
222227 }
228+ if segment_size % GF_16_ELEMENT_BYTES != 0 {
229+ return Err ( ArchiverInstantiationError :: SegmentSizeNotMultipleOfTwo ) ;
230+ }
223231 if segment_size % record_size != 0 {
224232 return Err ( ArchiverInstantiationError :: SegmentSizesNotMultipleOfRecordSize ) ;
225233 }
@@ -611,64 +619,54 @@ impl Archiver {
611619 }
612620 corrected_object_mapping
613621 } ;
614- let segment = {
615- let mut segment = segment. encode ( ) ;
616- // Add a few bytes of padding if needed to get constant size (caused by compact length
617- // encoding of scale codec)
618- assert ! ( self . segment_size >= segment. len( ) ) ;
619- segment. resize ( self . segment_size , 0u8 ) ;
620- segment
622+ let mut record_shards = {
623+ // Allocate record shards that can hold both data and parity record shards (hence `*2`)
624+ let mut record_shards =
625+ RecordShards :: new ( self . segment_size / self . record_size * 2 , self . record_size ) ;
626+ segment. encode_to ( & mut record_shards) ;
627+ record_shards
621628 } ;
622629
623- let data_shards: Vec < Vec < Gf16Element > > = segment
624- . chunks_exact ( self . record_size )
625- . map ( utils:: slice_to_arrays)
626- . collect ( ) ;
627-
628630 drop ( segment) ;
629631
630- let mut parity_shards: Vec < Vec < Gf16Element > > =
631- iter:: repeat ( vec ! [ Gf16Element :: default ( ) ; self . record_size / 2 ] )
632- . take ( data_shards. len ( ) )
633- . collect ( ) ;
632+ let mut record_shards_slices = record_shards. as_mut_slices ( ) ;
634633
635634 // Apply erasure coding to to create parity shards/records
636635 self . reed_solomon
637- . encode_sep ( & data_shards , & mut parity_shards )
638- . expect ( "Encoding is running with fixed parameters and should never fail" ) ;
636+ . encode ( & mut record_shards_slices )
637+ . expect ( "Encoding is running with fixed parameters and should never fail; qed " ) ;
639638
640- let mut pieces = vec ! [ 0u8 ; ( data_shards. len( ) + parity_shards. len( ) ) * PIECE_SIZE ] ;
641- // Combine data and parity records back into flat vector of pieces (witness part of piece is
642- // still zeroes after this and is filled later)
643- pieces
644- . chunks_exact_mut ( PIECE_SIZE )
645- . zip ( data_shards. into_iter ( ) . chain ( parity_shards) )
646- . flat_map ( |( piece, shard) | {
647- piece
648- . chunks_exact_mut ( GF_16_ELEMENT_BYTES )
649- . zip ( shard. into_iter ( ) )
650- } )
651- . for_each ( |( piece_chunk, shard_chunk) | {
652- piece_chunk. copy_from_slice ( & shard_chunk) ;
653- } ) ;
639+ let mut pieces = FlatPieces :: new ( record_shards_slices. len ( ) ) ;
640+ drop ( record_shards_slices) ;
654641
655642 // Build a Merkle tree over all records
656643 let merkle_tree = MerkleTree :: from_data (
657- pieces
658- . chunks_exact ( PIECE_SIZE )
659- . map ( |piece| & piece[ ..self . record_size ] ) ,
644+ record_shards
645+ . as_bytes ( )
646+ . as_ref ( )
647+ . chunks_exact ( self . record_size ) ,
660648 ) ;
661649
662- // Fill witnesses (Merkle proofs) in pieces created earlier
650+ // Combine data and parity records back into flat vector of pieces along with corresponding
651+ // witnesses (Merkle proofs) created above.
663652 pieces
664- . chunks_exact_mut ( PIECE_SIZE )
653+ . as_pieces_mut ( )
665654 . enumerate ( )
666- . for_each ( |( position, piece) | {
667- let witness = merkle_tree
668- . get_witness ( position)
669- . expect ( "We use the same indexes as during Merkle tree creation; qed" ) ;
670-
671- piece[ self . record_size ..] . copy_from_slice ( & witness) ;
655+ . zip (
656+ record_shards
657+ . as_bytes ( )
658+ . as_ref ( )
659+ . chunks_exact ( self . record_size ) ,
660+ )
661+ . for_each ( |( ( position, piece) , shard_chunk) | {
662+ let ( record_part, witness_part) = piece. split_at_mut ( self . record_size ) ;
663+
664+ record_part. copy_from_slice ( shard_chunk) ;
665+ witness_part. copy_from_slice (
666+ & merkle_tree
667+ . get_witness ( position)
668+ . expect ( "We use the same indexes as during Merkle tree creation; qed" ) ,
669+ ) ;
672670 } ) ;
673671
674672 // Now produce root block
@@ -689,9 +687,7 @@ impl Archiver {
689687
690688 ArchivedSegment {
691689 root_block,
692- pieces : pieces
693- . try_into ( )
694- . expect ( "Pieces length is correct as created above; qed" ) ,
690+ pieces,
695691 object_mapping,
696692 }
697693 }
0 commit comments