Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

Commit 5d0aec5

Browse files
authored
keccak lookup for metadata row and minor fixes (#1162)
1 parent 836aac1 commit 5d0aec5

File tree

1 file changed

+72
-56
lines changed

1 file changed

+72
-56
lines changed

aggregator/src/aggregation/blob_data.rs

Lines changed: 72 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -123,36 +123,42 @@ impl BlobDataConfig {
123123
let is_data = meta.query_selector(config.data_selector);
124124
let is_boundary = meta.query_advice(config.is_boundary, Rotation::cur());
125125
let is_padding_next = meta.query_advice(config.is_padding, Rotation::next());
126+
126127
let cond = is_data * is_boundary;
128+
127129
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());
129131
let byte_next = meta.query_advice(config.byte, Rotation::next());
132+
130133
vec![
131134
// if boundary followed by padding, length and preimage_rlc is 0.
132135
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(),
134137
// if boundary not followed by padding, length resets to 1, preimage_rlc resets to
135138
// the byte value.
136139
cond.expr() * (1.expr() - is_padding_next.expr()) * (len_next.expr() - 1.expr()),
137140
cond.expr()
138141
* (1.expr() - is_padding_next.expr())
139-
* (preimage_rlc - byte_next.expr()),
142+
* (preimage_rlc_next - byte_next.expr()),
140143
]
141144
});
142145

143146
meta.create_gate("BlobDataConfig (transition when no boundary)", |meta| {
144147
let is_data = meta.query_selector(config.data_selector);
145148
let is_boundary = meta.query_advice(config.is_boundary, Rotation::cur());
146149
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+
149151
// in the data section (not padding) when we traverse the same chunk.
150152
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());
152156
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());
154158
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());
155160
let byte_next = meta.query_advice(config.byte, Rotation::next());
161+
156162
vec![
157163
// chunk idx unchanged.
158164
cond.expr() * (chunk_idx_next - chunk_idx_curr),
@@ -165,33 +171,43 @@ impl BlobDataConfig {
165171

166172
meta.create_gate("BlobDataConfig (boundary/padding/accumulator)", |meta| {
167173
let is_data = meta.query_selector(config.data_selector);
168-
let is_hash = meta.query_selector(config.hash_selector);
169174
let is_boundary = meta.query_advice(config.is_boundary, Rotation::cur());
170175
let is_padding_curr = meta.query_advice(config.is_padding, Rotation::cur());
171176
let is_padding_next = meta.query_advice(config.is_padding, Rotation::next());
172177
let diff = is_padding_next - is_padding_curr.expr();
173-
let accumulator = meta.query_advice(config.accumulator, Rotation::cur());
174178

175179
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
179188
is_data * diff.expr() * (1.expr() - diff.expr()),
180-
is_hash.expr() * is_padding_curr.expr(),
181-
is_hash * accumulator.expr(),
182189
]
183190
});
184191

185192
// lookup to keccak table.
186193
meta.lookup_any("BlobDataConfig (keccak table)", |meta| {
187194
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;
188197
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+
190206
[
191207
1.expr(), // q_enable
192208
1.expr(), // is final
193209
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
195211
meta.query_advice(config.digest_rlc, Rotation::cur()), // output RLC
196212
]
197213
.into_iter()
@@ -200,13 +216,15 @@ impl BlobDataConfig {
200216
.collect()
201217
});
202218

203-
// TODO: lookup to keccak table for metadata bytes
204219

205220
// lookup for digest RLC to the hash section.
206221
meta.lookup_any("BlobDataConfig (hash section)", |meta| {
207222
let is_data = meta.query_selector(config.data_selector);
208223
let is_boundary = meta.query_advice(config.is_boundary, Rotation::cur());
224+
225+
// in the "chunk data" section when we encounter a chunk boundary
209226
let cond = is_data * is_boundary;
227+
210228
let hash_section_table = vec![
211229
meta.query_selector(config.hash_selector),
212230
meta.query_advice(config.chunk_idx, Rotation::cur()),
@@ -229,12 +247,20 @@ impl BlobDataConfig {
229247
meta.lookup_any("BlobDataConfig (z := keccak(preimage_z))", |meta| {
230248
let is_hash = meta.query_selector(config.hash_selector);
231249
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.
232253
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+
233259
[
234260
1.expr(), // q_enable
235261
1.expr(), // is final
236262
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
238264
meta.query_advice(config.digest_rlc, Rotation::cur()), // output rlc
239265
]
240266
.into_iter()
@@ -447,27 +473,31 @@ impl BlobDataConfig {
447473
}
448474
region.constrain_equal(num_nonempty_chunks.cell(), num_chunks.cell())?;
449475

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
456478
let one = {
457479
let one =
458480
rlc_config.load_private(&mut region, &Fr::one(), &mut rlc_config_offset)?;
459481
let one_cell = rlc_config.one_cell(one.cell().region_index);
460482
region.constrain_equal(one.cell(), one_cell)?;
461483
one
462484
};
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(),
468492
)?;
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())?;
471501

472502
let rows = assigned_rows
473503
.iter()
@@ -524,13 +554,7 @@ impl BlobDataConfig {
524554
let mut i_val = zero.clone();
525555
for row in rows.iter().skip(1).take(MAX_AGG_SNARKS) {
526556
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())?;
534558
}
535559

536560
let r = rlc_config.read_challenge(
@@ -563,10 +587,12 @@ impl BlobDataConfig {
563587
let blob_preimage_rlc_specified = &rows.last().unwrap().preimage_rlc;
564588
let blob_digest_rlc_specified = &rows.last().unwrap().digest_rlc;
565589

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+
568594
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;
570596
let metadata_digest_rlc_specified = &rows.first().unwrap().digest_rlc;
571597
region.constrain_equal(
572598
metadata_digest_rlc_computed.cell(),
@@ -606,13 +632,8 @@ impl BlobDataConfig {
606632
&is_empty,
607633
&mut rlc_config_offset,
608634
)?;
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())?;
616637

617638
chunk_digest_rlcs.push(&row.digest_rlc);
618639
}
@@ -630,7 +651,7 @@ impl BlobDataConfig {
630651
.skip(N_ROWS_METADATA + N_ROWS_DATA + N_ROWS_DIGEST_RLC)
631652
.take(N_ROWS_DIGEST_BYTES)
632653
.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)
634655
.chain(chunk_digest_rlcs)
635656
.chain(std::iter::once(blob_digest_rlc_specified))
636657
.enumerate()
@@ -646,13 +667,8 @@ impl BlobDataConfig {
646667
.collect::<Vec<_>>();
647668
let digest_rlc_computed =
648669
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())?;
656672
}
657673

658674
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)