@@ -123,36 +123,42 @@ impl BlobDataConfig {
123
123
let is_data = meta. query_selector ( config. data_selector ) ;
124
124
let is_boundary = meta. query_advice ( config. is_boundary , Rotation :: cur ( ) ) ;
125
125
let is_padding_next = meta. query_advice ( config. is_padding , Rotation :: next ( ) ) ;
126
+
126
127
let cond = is_data * is_boundary;
128
+
127
129
let len_next = meta. query_advice ( config. accumulator , Rotation :: next ( ) ) ;
128
- let preimage_rlc = meta. query_advice ( config. preimage_rlc , Rotation :: next ( ) ) ;
130
+ let preimage_rlc_next = meta. query_advice ( config. preimage_rlc , Rotation :: next ( ) ) ;
129
131
let byte_next = meta. query_advice ( config. byte , Rotation :: next ( ) ) ;
132
+
130
133
vec ! [
131
134
// if boundary followed by padding, length and preimage_rlc is 0.
132
135
cond. expr( ) * is_padding_next. expr( ) * len_next. expr( ) ,
133
- cond. expr( ) * is_padding_next. expr( ) * preimage_rlc . expr( ) ,
136
+ cond. expr( ) * is_padding_next. expr( ) * preimage_rlc_next . expr( ) ,
134
137
// if boundary not followed by padding, length resets to 1, preimage_rlc resets to
135
138
// the byte value.
136
139
cond. expr( ) * ( 1 . expr( ) - is_padding_next. expr( ) ) * ( len_next. expr( ) - 1 . expr( ) ) ,
137
140
cond. expr( )
138
141
* ( 1 . expr( ) - is_padding_next. expr( ) )
139
- * ( preimage_rlc - byte_next. expr( ) ) ,
142
+ * ( preimage_rlc_next - byte_next. expr( ) ) ,
140
143
]
141
144
} ) ;
142
145
143
146
meta. create_gate ( "BlobDataConfig (transition when no boundary)" , |meta| {
144
147
let is_data = meta. query_selector ( config. data_selector ) ;
145
148
let is_boundary = meta. query_advice ( config. is_boundary , Rotation :: cur ( ) ) ;
146
149
let is_padding = meta. query_advice ( config. is_padding , Rotation :: cur ( ) ) ;
147
- let chunk_idx_curr = meta. query_advice ( config. chunk_idx , Rotation :: cur ( ) ) ;
148
- let chunk_idx_next = meta. query_advice ( config. chunk_idx , Rotation :: next ( ) ) ;
150
+
149
151
// in the data section (not padding) when we traverse the same chunk.
150
152
let cond = is_data * ( 1 . expr ( ) - is_padding) * ( 1 . expr ( ) - is_boundary) ;
151
- let len_next = meta. query_advice ( config. accumulator , Rotation :: next ( ) ) ;
153
+
154
+ let chunk_idx_curr = meta. query_advice ( config. chunk_idx , Rotation :: cur ( ) ) ;
155
+ let chunk_idx_next = meta. query_advice ( config. chunk_idx , Rotation :: next ( ) ) ;
152
156
let len_curr = meta. query_advice ( config. accumulator , Rotation :: cur ( ) ) ;
153
- let preimage_rlc_next = meta. query_advice ( config. preimage_rlc , Rotation :: next ( ) ) ;
157
+ let len_next = meta. query_advice ( config. accumulator , Rotation :: next ( ) ) ;
154
158
let preimage_rlc_curr = meta. query_advice ( config. preimage_rlc , Rotation :: cur ( ) ) ;
159
+ let preimage_rlc_next = meta. query_advice ( config. preimage_rlc , Rotation :: next ( ) ) ;
155
160
let byte_next = meta. query_advice ( config. byte , Rotation :: next ( ) ) ;
161
+
156
162
vec ! [
157
163
// chunk idx unchanged.
158
164
cond. expr( ) * ( chunk_idx_next - chunk_idx_curr) ,
@@ -165,33 +171,43 @@ impl BlobDataConfig {
165
171
166
172
meta. create_gate ( "BlobDataConfig (boundary/padding/accumulator)" , |meta| {
167
173
let is_data = meta. query_selector ( config. data_selector ) ;
168
- let is_hash = meta. query_selector ( config. hash_selector ) ;
169
174
let is_boundary = meta. query_advice ( config. is_boundary , Rotation :: cur ( ) ) ;
170
175
let is_padding_curr = meta. query_advice ( config. is_padding , Rotation :: cur ( ) ) ;
171
176
let is_padding_next = meta. query_advice ( config. is_padding , Rotation :: next ( ) ) ;
172
177
let diff = is_padding_next - is_padding_curr. expr ( ) ;
173
- let accumulator = meta. query_advice ( config. accumulator , Rotation :: cur ( ) ) ;
174
178
175
179
vec ! [
176
- is_data. expr( ) * is_boundary. expr( ) * ( 1 . expr( ) - is_boundary. expr( ) ) ,
177
- is_hash. expr( ) * is_boundary. expr( ) ,
178
- is_data. expr( ) * is_padding_curr. expr( ) * ( 1 . expr( ) - is_padding_curr. expr( ) ) ,
180
+ // is_boundary is boolean.
181
+ is_boundary. expr( ) * ( 1 . expr( ) - is_boundary. expr( ) ) ,
182
+ // is_padding is boolean.
183
+ is_padding_curr. expr( ) * ( 1 . expr( ) - is_padding_curr. expr( ) ) ,
184
+ // is_padding is meaningful only for "chunk data" section, i.e.
185
+ // is_padding is 0 for other sections.
186
+ ( 1 . expr( ) - is_data. expr( ) ) * is_padding_curr. expr( ) ,
187
+ // is_padding transitions from 0 -> 1 only once
179
188
is_data * diff. expr( ) * ( 1 . expr( ) - diff. expr( ) ) ,
180
- is_hash. expr( ) * is_padding_curr. expr( ) ,
181
- is_hash * accumulator. expr( ) ,
182
189
]
183
190
} ) ;
184
191
185
192
// lookup to keccak table.
186
193
meta. lookup_any ( "BlobDataConfig (keccak table)" , |meta| {
187
194
let is_data = meta. query_selector ( config. data_selector ) ;
195
+ let is_hash = meta. query_selector ( config. hash_selector ) ;
196
+ let is_not_hash = 1 . expr ( ) - is_hash;
188
197
let is_boundary = meta. query_advice ( config. is_boundary , Rotation :: cur ( ) ) ;
189
- let cond = is_data * is_boundary;
198
+
199
+ // in the "metadata" or "chunk data" section, wherever is_boundary is set.
200
+ let cond = is_not_hash * is_boundary;
201
+
202
+ let accumulator = meta. query_advice ( config. accumulator , Rotation :: cur ( ) ) ;
203
+ let preimage_len =
204
+ is_data. expr ( ) * accumulator + ( 1 . expr ( ) - is_data) * N_ROWS_METADATA . expr ( ) ;
205
+
190
206
[
191
207
1 . expr ( ) , // q_enable
192
208
1 . expr ( ) , // is final
193
209
meta. query_advice ( config. preimage_rlc , Rotation :: cur ( ) ) , // input RLC
194
- meta . query_advice ( config . accumulator , Rotation :: cur ( ) ) , // input len
210
+ preimage_len , // input len
195
211
meta. query_advice ( config. digest_rlc , Rotation :: cur ( ) ) , // output RLC
196
212
]
197
213
. into_iter ( )
@@ -200,13 +216,15 @@ impl BlobDataConfig {
200
216
. collect ( )
201
217
} ) ;
202
218
203
- // TODO: lookup to keccak table for metadata bytes
204
219
205
220
// lookup for digest RLC to the hash section.
206
221
meta. lookup_any ( "BlobDataConfig (hash section)" , |meta| {
207
222
let is_data = meta. query_selector ( config. data_selector ) ;
208
223
let is_boundary = meta. query_advice ( config. is_boundary , Rotation :: cur ( ) ) ;
224
+
225
+ // in the "chunk data" section when we encounter a chunk boundary
209
226
let cond = is_data * is_boundary;
227
+
210
228
let hash_section_table = vec ! [
211
229
meta. query_selector( config. hash_selector) ,
212
230
meta. query_advice( config. chunk_idx, Rotation :: cur( ) ) ,
@@ -229,12 +247,20 @@ impl BlobDataConfig {
229
247
meta. lookup_any ( "BlobDataConfig (z := keccak(preimage_z))" , |meta| {
230
248
let is_hash = meta. query_selector ( config. hash_selector ) ;
231
249
let is_boundary = meta. query_advice ( config. is_boundary , Rotation :: cur ( ) ) ;
250
+
251
+ // when is_boundary is set in the "digest RLC" section.
252
+ // this is also the last row of the "digest RLC" section.
232
253
let cond = is_hash * is_boundary;
254
+
255
+ // - metadata_digest: 32 bytes
256
+ // - chunk[i].chunk_data_digest: 32 bytes each
257
+ let preimage_len = 32 . expr ( ) * ( MAX_AGG_SNARKS + 1 ) . expr ( ) ;
258
+
233
259
[
234
260
1 . expr ( ) , // q_enable
235
261
1 . expr ( ) , // is final
236
262
meta. query_advice ( config. preimage_rlc , Rotation :: cur ( ) ) , // input rlc
237
- 32 . expr ( ) * ( MAX_AGG_SNARKS + 1 ) . expr ( ) , // input len
263
+ preimage_len , // input len
238
264
meta. query_advice ( config. digest_rlc , Rotation :: cur ( ) ) , // output rlc
239
265
]
240
266
. into_iter ( )
@@ -447,27 +473,31 @@ impl BlobDataConfig {
447
473
}
448
474
region. constrain_equal ( num_nonempty_chunks. cell ( ) , num_chunks. cell ( ) ) ?;
449
475
450
- ////////////////////////////////////////////////////////////////////////////////
451
- ////////////////////////////////// CHUNK_DATA //////////////////////////////////
452
- ////////////////////////////////////////////////////////////////////////////////
453
-
454
- // the first data row has a length (accumulator) of 1.
455
- let row = assigned_rows. get ( N_ROWS_METADATA ) . unwrap ( ) ;
476
+ // on the last row of the "metadata" section we want to ensure the keccak table
477
+ // lookup would be enabled for the metadata digest
456
478
let one = {
457
479
let one =
458
480
rlc_config. load_private ( & mut region, & Fr :: one ( ) , & mut rlc_config_offset) ?;
459
481
let one_cell = rlc_config. one_cell ( one. cell ( ) . region_index ) ;
460
482
region. constrain_equal ( one. cell ( ) , one_cell) ?;
461
483
one
462
484
} ;
463
- let is_one = rlc_config. is_equal (
464
- & mut region,
465
- & row. accumulator ,
466
- & one,
467
- & mut rlc_config_offset,
485
+ region. constrain_equal (
486
+ assigned_rows
487
+ . get ( N_ROWS_METADATA - 1 )
488
+ . unwrap ( )
489
+ . is_boundary
490
+ . cell ( ) ,
491
+ one. cell ( ) ,
468
492
) ?;
469
- let is_not_one = rlc_config. not ( & mut region, & is_one, & mut rlc_config_offset) ?;
470
- rlc_config. enforce_zero ( & mut region, & is_not_one) ?;
493
+
494
+ ////////////////////////////////////////////////////////////////////////////////
495
+ ////////////////////////////////// CHUNK_DATA //////////////////////////////////
496
+ ////////////////////////////////////////////////////////////////////////////////
497
+
498
+ // the first data row has a length (accumulator) of 1.
499
+ let row = assigned_rows. get ( N_ROWS_METADATA ) . unwrap ( ) ;
500
+ region. constrain_equal ( row. accumulator . cell ( ) , one. cell ( ) ) ?;
471
501
472
502
let rows = assigned_rows
473
503
. iter ( )
@@ -524,13 +554,7 @@ impl BlobDataConfig {
524
554
let mut i_val = zero. clone ( ) ;
525
555
for row in rows. iter ( ) . skip ( 1 ) . take ( MAX_AGG_SNARKS ) {
526
556
i_val = rlc_config. add ( & mut region, & i_val, & one, & mut rlc_config_offset) ?;
527
- let diff = rlc_config. sub (
528
- & mut region,
529
- & row. chunk_idx ,
530
- & i_val,
531
- & mut rlc_config_offset,
532
- ) ?;
533
- rlc_config. enforce_zero ( & mut region, & diff) ?;
557
+ region. constrain_equal ( i_val. cell ( ) , row. chunk_idx . cell ( ) ) ?;
534
558
}
535
559
536
560
let r = rlc_config. read_challenge (
@@ -563,10 +587,12 @@ impl BlobDataConfig {
563
587
let blob_preimage_rlc_specified = & rows. last ( ) . unwrap ( ) . preimage_rlc ;
564
588
let blob_digest_rlc_specified = & rows. last ( ) . unwrap ( ) . digest_rlc ;
565
589
566
- // assert that metadata_digest which we get through lookup into keccak table is
567
- // equal to the one we assigned in hash section
590
+ // ensure that on the last row of this section the is_boundary is turned on
591
+ // which would enable the keccak table lookup for challenge_digest
592
+ region. constrain_equal ( rows. last ( ) . unwrap ( ) . is_boundary . cell ( ) , one. cell ( ) ) ?;
593
+
568
594
let metadata_digest_rlc_computed =
569
- & assigned_rows. get ( N_ROWS_METADATA ) . unwrap ( ) . digest_rlc ;
595
+ & assigned_rows. get ( N_ROWS_METADATA - 1 ) . unwrap ( ) . digest_rlc ;
570
596
let metadata_digest_rlc_specified = & rows. first ( ) . unwrap ( ) . digest_rlc ;
571
597
region. constrain_equal (
572
598
metadata_digest_rlc_computed. cell ( ) ,
@@ -606,13 +632,8 @@ impl BlobDataConfig {
606
632
& is_empty,
607
633
& mut rlc_config_offset,
608
634
) ?;
609
- let diff = rlc_config. sub (
610
- & mut region,
611
- & chunk_size_specified,
612
- & chunk_size_decoded,
613
- & mut rlc_config_offset,
614
- ) ?;
615
- rlc_config. enforce_zero ( & mut region, & diff) ?;
635
+ region
636
+ . constrain_equal ( chunk_size_specified. cell ( ) , chunk_size_decoded. cell ( ) ) ?;
616
637
617
638
chunk_digest_rlcs. push ( & row. digest_rlc ) ;
618
639
}
@@ -630,7 +651,7 @@ impl BlobDataConfig {
630
651
. skip ( N_ROWS_METADATA + N_ROWS_DATA + N_ROWS_DIGEST_RLC )
631
652
. take ( N_ROWS_DIGEST_BYTES )
632
653
. collect :: < Vec < _ > > ( ) ;
633
- for ( i, digest_rlc ) in std:: iter:: once ( metadata_digest_rlc_specified)
654
+ for ( i, digest_rlc_specified ) in std:: iter:: once ( metadata_digest_rlc_specified)
634
655
. chain ( chunk_digest_rlcs)
635
656
. chain ( std:: iter:: once ( blob_digest_rlc_specified) )
636
657
. enumerate ( )
@@ -646,13 +667,8 @@ impl BlobDataConfig {
646
667
. collect :: < Vec < _ > > ( ) ;
647
668
let digest_rlc_computed =
648
669
rlc_config. rlc ( & mut region, & digest_bytes, & r, & mut rlc_config_offset) ?;
649
- let diff = rlc_config. sub (
650
- & mut region,
651
- digest_rlc,
652
- & digest_rlc_computed,
653
- & mut rlc_config_offset,
654
- ) ?;
655
- rlc_config. enforce_zero ( & mut region, & diff) ?;
670
+ region
671
+ . constrain_equal ( digest_rlc_computed. cell ( ) , digest_rlc_specified. cell ( ) ) ?;
656
672
}
657
673
658
674
////////////////////////////////////////////////////////////////////////////////
0 commit comments