1
+ use crate :: aggregation:: witgen:: { process, MultiBlockProcessResult } ;
1
2
use crate :: {
2
3
aggregation:: {
3
4
AssignedBarycentricEvaluationConfig , BarycentricEvaluationConfig , BlobDataConfig , RlcConfig ,
4
5
} ,
5
- blob:: { BatchData , PointEvaluationAssignments , N_BYTES_U256 } ,
6
+ blob:: { BatchData , PointEvaluationAssignments , N_BLOB_BYTES , N_BYTES_U256 } ,
6
7
param:: ConfigParams ,
7
8
BatchDataConfig , MAX_AGG_SNARKS ,
8
9
} ;
@@ -257,16 +258,16 @@ fn check_circuit(circuit: &BlobCircuit) -> Result<(), Vec<VerifyFailure>> {
257
258
258
259
#[ test]
259
260
fn blob_circuit_completeness ( ) {
260
- // single chunk in batch, but the chunk has a size of N_ROWS_DATA
261
- let full_blob = vec ! [
262
- // batch274 contains batch bytes that will produce a full blob
263
- hex :: decode (
264
- fs :: read_to_string ( "./data/test_batches/batch274.hex ")
265
- . expect ( "file path exists" )
266
- . trim ( ) ,
267
- )
268
- . expect ( "should load full blob batch bytes" ) ,
269
- ] ;
261
+ // Full blob test case
262
+ // batch274 contains batch bytes that will produce a full blob
263
+ let full_blob = hex :: decode (
264
+ fs :: read_to_string ( "./data/test_batches/batch274.hex" )
265
+ . expect ( "file path exists ")
266
+ . trim ( ) ,
267
+ )
268
+ . expect ( "should load full blob batch bytes" ) ;
269
+ // batch274 contains metadata
270
+ let segmented_full_blob_src = BatchData :: < MAX_AGG_SNARKS > :: segment_with_metadata ( full_blob ) ;
270
271
271
272
let all_empty_chunks: Vec < Vec < u8 > > = vec ! [ vec![ ] ; MAX_AGG_SNARKS ] ;
272
273
let one_chunk = vec ! [ vec![ 2 , 3 , 4 , 100 , 1 ] ] ;
@@ -288,8 +289,8 @@ fn blob_circuit_completeness() {
288
289
. chain ( std:: iter:: once ( vec ! [ 3 , 100 , 24 , 30 ] ) )
289
290
. collect :: < Vec < _ > > ( ) ;
290
291
291
- for blob in [
292
- full_blob ,
292
+ for ( idx , blob) in [
293
+ segmented_full_blob_src ,
293
294
one_chunk,
294
295
two_chunks,
295
296
max_chunks,
@@ -298,11 +299,113 @@ fn blob_circuit_completeness() {
298
299
nonempty_chunk_followed_by_empty_chunk,
299
300
empty_and_nonempty_chunks,
300
301
all_empty_except_last,
301
- ] {
302
- assert_eq ! ( check_data( BatchData :: from( & blob) ) , Ok ( ( ) ) , "{:?}" , blob) ;
302
+ ]
303
+ . into_iter ( )
304
+ . enumerate ( )
305
+ {
306
+ let batch_data = BatchData :: from ( & blob) ;
307
+
308
+ // First blob is purposely constructed to take full blob space
309
+ if idx == 0 {
310
+ let encoded_len = batch_data. get_encoded_batch_data_bytes ( ) . len ( ) ;
311
+ assert_eq ! (
312
+ encoded_len, N_BLOB_BYTES ,
313
+ "should be full blob: expected={N_BLOB_BYTES}, got={encoded_len}" ,
314
+ ) ;
315
+ }
316
+
317
+ assert_eq ! ( check_data( batch_data) , Ok ( ( ) ) , "{:?}" , blob) ;
303
318
}
304
319
}
305
320
321
+ #[ test]
322
+ fn zstd_encoding_consistency ( ) {
323
+ // Load test blob bytes
324
+ let blob_bytes = hex:: decode (
325
+ fs:: read_to_string ( "./data/test_blobs/blob005.hex" )
326
+ . expect ( "file path exists" )
327
+ . trim ( ) ,
328
+ )
329
+ . expect ( "should load blob bytes" ) ;
330
+
331
+ // Leave out most significant byte for compressed data
332
+ let mut compressed: Vec < u8 > = vec ! [ ] ;
333
+ for i in 0 ..blob_bytes. len ( ) / 32 {
334
+ for j in 1 ..32usize {
335
+ compressed. push ( blob_bytes[ i * 32 + j] ) ;
336
+ }
337
+ }
338
+
339
+ // Decode into original batch bytes
340
+ let MultiBlockProcessResult {
341
+ witness_rows : _w,
342
+ literal_bytes : _l,
343
+ fse_aux_tables : _f,
344
+ block_info_arr : _b,
345
+ sequence_info_arr : _s,
346
+ address_table_rows : _a,
347
+ sequence_exec_results,
348
+ } = process :: < Fr > ( & compressed, Value :: known ( Fr :: from ( 123456789 ) ) ) ;
349
+
350
+ // The decoded batch data consists of:
351
+ // - [0..182] bytes of metadata
352
+ // - [182..] remaining bytes of chunk data
353
+ let recovered_bytes = sequence_exec_results
354
+ . into_iter ( )
355
+ . flat_map ( |r| r. recovered_bytes )
356
+ . collect :: < Vec < u8 > > ( ) ;
357
+ let segmented_batch_data = BatchData :: < MAX_AGG_SNARKS > :: segment_with_metadata ( recovered_bytes) ;
358
+
359
+ // Re-encode into blob bytes
360
+ let re_encoded_batch_data: BatchData < MAX_AGG_SNARKS > = BatchData :: from ( & segmented_batch_data) ;
361
+ let re_encoded_blob_bytes = re_encoded_batch_data. get_encoded_batch_data_bytes ( ) ;
362
+
363
+ assert_eq ! ( compressed, re_encoded_blob_bytes, "Blob bytes must match" ) ;
364
+ }
365
+
366
+ #[ test]
367
+ fn zstd_encoding_consistency_from_batch ( ) {
368
+ // Load test batch bytes
369
+ // batch274 contains batch bytes that will produce a full blob
370
+ let batch_bytes = hex:: decode (
371
+ fs:: read_to_string ( "./data/test_batches/batch274.hex" )
372
+ . expect ( "file path exists" )
373
+ . trim ( ) ,
374
+ )
375
+ . expect ( "should load batch bytes" ) ;
376
+ let segmented_batch_bytes =
377
+ BatchData :: < MAX_AGG_SNARKS > :: segment_with_metadata ( batch_bytes. clone ( ) ) ;
378
+
379
+ // Re-encode into blob bytes
380
+ let encoded_batch_data: BatchData < MAX_AGG_SNARKS > = BatchData :: from ( & segmented_batch_bytes) ;
381
+ let encoded_blob_bytes = encoded_batch_data. get_encoded_batch_data_bytes ( ) ;
382
+
383
+ // full blob len sanity check
384
+ assert_eq ! (
385
+ encoded_blob_bytes. len( ) ,
386
+ N_BLOB_BYTES ,
387
+ "full blob is the correct len"
388
+ ) ;
389
+
390
+ // Decode into original batch bytes
391
+ let MultiBlockProcessResult {
392
+ witness_rows : _w,
393
+ literal_bytes : _l,
394
+ fse_aux_tables : _f,
395
+ block_info_arr : _b,
396
+ sequence_info_arr : _s,
397
+ address_table_rows : _a,
398
+ sequence_exec_results,
399
+ } = process :: < Fr > ( & encoded_blob_bytes, Value :: known ( Fr :: from ( 123456789 ) ) ) ;
400
+
401
+ let decoded_batch_bytes = sequence_exec_results
402
+ . into_iter ( )
403
+ . flat_map ( |r| r. recovered_bytes )
404
+ . collect :: < Vec < u8 > > ( ) ;
405
+
406
+ assert_eq ! ( batch_bytes, decoded_batch_bytes, "batch bytes must match" ) ;
407
+ }
408
+
306
409
fn generic_batch_data ( ) -> BatchData < MAX_AGG_SNARKS > {
307
410
BatchData :: from ( & vec ! [
308
411
vec![ 3 , 100 , 24 , 30 ] ,
0 commit comments