@@ -255,42 +255,83 @@ func NewPartSetFromData(data []byte, partSize uint32) (ops *PartSet, err error)
255
255
ops .proofs = make ([]merkle.Proof , total )
256
256
for i := uint32 (0 ); i < total ; i ++ {
257
257
ops .proofs [i ] = * proofs [i ]
258
- ops .partsBitArray .SetIndex (int (i ), true )
259
258
}
259
+ ops .partsBitArray .Fill ()
260
260
ops .count = total
261
261
ops .byteSize = int64 (len (data ))
262
262
263
263
return ops , nil
264
264
}
265
265
266
+ // newPartSetFromChunks creates a new PartSet from given data chunks, and other data.
267
+ func newPartSetFromChunks (chunks [][]byte , root cmtbytes.HexBytes , proofs []* merkle.Proof , partSize int ) (* PartSet , error ) {
268
+ total := len (chunks )
269
+ if total != len (proofs ) {
270
+ return nil , fmt .Errorf ("chunks and proofs have different lengths: %d != %d" , len (chunks ), len (proofs ))
271
+ }
272
+ if root == nil {
273
+ return nil , fmt .Errorf ("root is nil" )
274
+ }
275
+
276
+ // create a new partset using the new parity parts.
277
+ ps := NewPartSetFromHeader (PartSetHeader {
278
+ Total : uint32 (total ),
279
+ Hash : root ,
280
+ }, uint32 (partSize ))
281
+
282
+ // access ps directly, without mutex, because we know it is not used elsewhere
283
+ for i := 0 ; i < total ; i ++ {
284
+ start := i * partSize
285
+ end := start + len (chunks [i ])
286
+
287
+ // Ensure we don't exceed buffer bounds
288
+ if end > len (ps .buffer ) {
289
+ return nil , fmt .Errorf ("part data exceeds buffer bounds" )
290
+ }
291
+
292
+ copy (ps .buffer [start :end ], chunks [i ])
293
+ ps .proofs [i ] = * proofs [i ]
294
+ }
295
+ ps .partsBitArray .Fill ()
296
+ ps .count = uint32 (total )
297
+ ps .lastPartSize = len (chunks [total - 1 ])
298
+ ps .byteSize = int64 (len (ps .buffer ))
299
+ return ps , nil
300
+ }
301
+
266
302
// Encode Extend erasure encodes the block parts. Only the original parts should be
267
303
// provided. The parity data is formed into its own PartSet and returned
268
304
// alongside the length of the last part. The length of the last part is
269
305
// necessary because the last part may be padded with zeros after decoding. These zeros must be removed before computi
270
306
func Encode (ops * PartSet , partSize uint32 ) (* PartSet , int , error ) {
271
- chunks := make ([][]byte , 2 * ops .Total ())
272
- for i := range chunks {
273
- if i < int (ops .Total ()) {
274
- chunks [i ] = ops .GetPart (i ).Bytes .Bytes ()
275
- continue
276
- }
277
- chunks [i ] = make ([]byte , partSize )
307
+ total := int (ops .Total ())
308
+ chunks := make ([][]byte , 2 * total )
309
+ ops .mtx .Lock ()
310
+ for i := range total {
311
+ chunks [i ] = ops .getPartBytes (i )
312
+ }
313
+ ops .mtx .Unlock ()
314
+
315
+ ps := int (partSize )
316
+ parityBuffer := make ([]byte , total * ps ) // allocate once, only slice later
317
+ for i := 0 ; i < total ; i ++ {
318
+ chunks [total + i ] = parityBuffer [i * ps : (i + 1 )* ps ]
278
319
}
279
320
280
321
// pad ONLY the last chunk and not the part with zeros if necessary AFTER the root has been generated
281
- lastLen := len (ops .GetPart ( int ( ops . Total () - 1 )). Bytes . Bytes ( ))
322
+ lastLen := len (ops .GetPartBytes ( total - 1 ))
282
323
if lastLen < int (partSize ) {
283
324
padded := make ([]byte , partSize )
284
- count := copy (padded , chunks [ops . Total () - 1 ])
285
- if count < len (chunks [ops . Total () - 1 ]) {
325
+ count := copy (padded , chunks [total - 1 ])
326
+ if count < len (chunks [total - 1 ]) {
286
327
return nil , 0 , fmt .Errorf ("copy failed of unpadded part with index %d: %d < %d" , ops .Total ()- 1 , count , len (chunks [ops .Total ()- 1 ]))
287
328
}
288
- chunks [ops . Total () - 1 ] = padded
329
+ chunks [total - 1 ] = padded
289
330
}
290
331
291
332
// init an encoder if it is not already initialized using the original
292
333
// number of parts.
293
- enc , err := reedsolomon .New (int ( ops . Total ()), int ( ops . Total ()) )
334
+ enc , err := reedsolomon .New (total , total )
294
335
if err != nil {
295
336
return nil , 0 , err
296
337
}
@@ -302,26 +343,12 @@ func Encode(ops *PartSet, partSize uint32) (*PartSet, int, error) {
302
343
}
303
344
304
345
// only the parity data is needed for the new partset.
305
- chunks = chunks [ops . Total () :]
346
+ chunks = chunks [total :]
306
347
eroot , eproofs := merkle .ParallelProofsFromByteSlices (chunks )
307
348
308
- // create a new partset using the new parity parts.
309
- eps := NewPartSetFromHeader (PartSetHeader {
310
- Total : ops .Total (),
311
- Hash : eroot ,
312
- }, partSize )
313
- for i := uint32 (0 ); i < ops .Total (); i ++ {
314
- added , err := eps .AddPart (& Part {
315
- Index : i ,
316
- Bytes : chunks [i ],
317
- Proof : * eproofs [i ],
318
- })
319
- if err != nil {
320
- return nil , 0 , err
321
- }
322
- if ! added {
323
- return nil , 0 , fmt .Errorf ("couldn't add parity part %d" , i )
324
- }
349
+ eps , err := newPartSetFromChunks (chunks , eroot , eproofs , ps )
350
+ if err != nil {
351
+ return nil , 0 , err
325
352
}
326
353
return eps , lastLen , nil
327
354
}
@@ -541,9 +568,6 @@ func (ps *PartSet) addPart(part *Part) (bool, error) {
541
568
return false , errors .New ("nil part" )
542
569
}
543
570
544
- ps .mtx .Lock ()
545
- defer ps .mtx .Unlock ()
546
-
547
571
// Invalid part index
548
572
if part .Index >= ps .total {
549
573
return false , ErrPartSetUnexpectedIndex
@@ -563,18 +587,22 @@ func (ps *PartSet) addPart(part *Part) (bool, error) {
563
587
return false , fmt .Errorf ("part data exceeds buffer bounds" )
564
588
}
565
589
566
- copy ( ps .buffer [ start : end ], part . Bytes )
590
+ ps .mtx . Lock ( )
567
591
592
+ copy (ps .buffer [start :end ], part .Bytes )
568
593
ps .proofs [part .Index ] = part .Proof
569
594
570
595
// Track last part size if this is the last part
571
596
if part .Index == ps .total - 1 {
572
597
ps .lastPartSize = len (part .Bytes )
573
598
}
574
-
575
- ps .partsBitArray .SetIndex (int (part .Index ), true )
576
599
ps .count ++
577
600
ps .byteSize += int64 (len (part .Bytes ))
601
+
602
+ ps .mtx .Unlock ()
603
+
604
+ ps .partsBitArray .SetIndex (int (part .Index ), true )
605
+
578
606
return true , nil
579
607
}
580
608
@@ -632,8 +660,6 @@ func (ps *PartSet) GetPart(index int) *Part {
632
660
}
633
661
634
662
func (ps * PartSet ) HasPart (index int ) bool {
635
- ps .mtx .Lock ()
636
- defer ps .mtx .Unlock ()
637
663
return ps .partsBitArray .GetIndex (index )
638
664
}
639
665
0 commit comments