Skip to content

Commit e631dc3

Browse files
committed
move constants to advice and expose their hash
1 parent 4fc143e commit e631dc3

File tree

4 files changed

+132
-7
lines changed

4 files changed

+132
-7
lines changed

src/circuit_verifier/mod.rs

+93-7
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,44 @@ fn context_eval<E: MultiMillerLoop, R: io::Read>(
4141
instance_commitments: &[&[E::G1Affine]],
4242
t: &mut [&mut PoseidonChipRead<R, E::G1Affine>],
4343
circuit: &mut NativeScalarEccContext<E::G1Affine>,
44+
// Expose hash of constant value to instance to uniform the aggregator circuit
45+
constants_hasher: &mut PoseidonChipRead<R, E::G1Affine>,
4446
) -> Result<
4547
(
4648
Vec<AssignedPoint<E::G1Affine, E::Scalar>>,
4749
Vec<AssignedPoint<E::G1Affine, E::Scalar>>,
50+
AssignedValue<E::Scalar>,
4851
),
4952
UnsafeError,
5053
> {
5154
let mut it: Vec<(
5255
Option<AssignedPoint<E::G1Affine, E::Scalar>>,
5356
Option<AssignedValue<E::Scalar>>,
5457
)> = vec![];
55-
5658
let const_scalars = {
5759
c.const_scalars
5860
.iter()
59-
.map(|c| circuit.base_integer_chip().base_chip().assign_constant(*c))
61+
.map(|c| circuit.base_integer_chip().base_chip().assign(*c))
6062
.collect::<Vec<_>>()
6163
};
6264

65+
for c in const_scalars.iter() {
66+
constants_hasher.common_scalar(circuit, c);
67+
}
68+
6369
let const_points = {
6470
c.const_points
6571
.iter()
66-
.map(|c| circuit.assign_constant_point(&c.to_curve()))
72+
.map(|c| circuit.assign_point(&c.to_curve()))
6773
.collect::<Vec<_>>()
6874
};
6975

76+
for c in const_points.iter() {
77+
constants_hasher.common_point(circuit, c);
78+
}
79+
80+
let constants_hash = constants_hasher.squeeze(circuit);
81+
7082
let instance_commitments = {
7183
instance_commitments
7284
.iter()
@@ -214,6 +226,7 @@ fn context_eval<E: MultiMillerLoop, R: io::Read>(
214226
.map(|x| circuit.ecc_reduce(it[*x].0.as_ref().unwrap()))
215227
.collect(),
216228
instance_commitments.concat(),
229+
constants_hash,
217230
))
218231
}
219232

@@ -225,6 +238,9 @@ pub fn build_single_proof_verify_circuit<E: MultiMillerLoop + G2AffineBaseHelper
225238
hash: TranscriptHash,
226239
expose: Vec<[usize; 2]>,
227240
absorb: Vec<([usize; 3], [usize; 2])>, // the index of instance + the index of advices
241+
target_aggregator_constant_hash_instance_offset: Vec<([usize; 4])>, // (proof_index, layer_idx, instance_col, instance_row)
242+
all_constant_hash: &mut Vec<E::Scalar>,
243+
layer_idx: usize,
228244
) -> (AggregatorCircuit<E::G1Affine>, Vec<E::Scalar>)
229245
where
230246
NativeScalarEccContext<E::G1Affine>: PairingChipOps<E::G1Affine, E::Scalar>,
@@ -238,6 +254,9 @@ where
238254
vec![],
239255
expose,
240256
absorb,
257+
target_aggregator_constant_hash_instance_offset,
258+
all_constant_hash,
259+
layer_idx,
241260
)
242261
}
243262

@@ -249,7 +268,10 @@ pub fn build_aggregate_verify_circuit<E: MultiMillerLoop + G2AffineBaseHelper>(
249268
hash: TranscriptHash,
250269
commitment_check: Vec<[usize; 4]>,
251270
expose: Vec<[usize; 2]>,
252-
absorb: Vec<([usize; 3], [usize; 2])>, // the index of instance + the index of advices
271+
absorb: Vec<([usize; 3], [usize; 2])>, // the index of instance + the index of advices,
272+
target_aggregator_constant_hash_instance_offset: Vec<([usize; 4])>, // (proof_index, layer_idx, instance_col, instance_row)
273+
all_constant_hash: &mut Vec<E::Scalar>,
274+
layer_idx: usize,
253275
) -> (AggregatorCircuit<E::G1Affine>, Vec<E::Scalar>)
254276
where
255277
NativeScalarEccContext<E::G1Affine>: PairingChipOps<E::G1Affine, E::Scalar>,
@@ -267,6 +289,9 @@ where
267289
&commitment_check,
268290
&expose,
269291
&absorb,
292+
&target_aggregator_constant_hash_instance_offset,
293+
all_constant_hash,
294+
layer_idx,
270295
)
271296
.ok();
272297
rest_tries -= 1;
@@ -290,6 +315,12 @@ impl G2AffineBaseHelper for Bn256 {
290315
}
291316
}
292317

318+
/* expose: expose target circuits' commitments to current aggregator circuits' instance
319+
* absorb: absorb target circuits' commitments to target aggregator circuits' instance
320+
* target_aggregator_constant_hash_instance: instance_offset of target_aggregator for constant_hash
321+
* prev_constant_hash: all previous constant_hash (hash of all circuits' constant values) of aggregators layer
322+
* layer_idx: current aggregator's layer index
323+
*/
293324
pub fn _build_aggregate_verify_circuit<E: MultiMillerLoop + G2AffineBaseHelper>(
294325
params: &ParamsVerifier<E>,
295326
vkey: &[&VerifyingKey<E::G1Affine>],
@@ -299,6 +330,9 @@ pub fn _build_aggregate_verify_circuit<E: MultiMillerLoop + G2AffineBaseHelper>(
299330
commitment_check: &Vec<[usize; 4]>,
300331
expose: &Vec<[usize; 2]>,
301332
absorb: &Vec<([usize; 3], [usize; 2])>, // the index of instance + the index of advices
333+
target_aggregator_constant_hash_instance_offset: &Vec<([usize; 4])>, // (proof_index, layer_idx, instance_col, instance_row)
334+
all_constant_hash: &mut Vec<E::Scalar>,
335+
layer_idx: usize,
302336
) -> Result<(AggregatorCircuit<E::G1Affine>, Vec<E::Scalar>), UnsafeError>
303337
where
304338
NativeScalarEccContext<E::G1Affine>: PairingChipOps<E::G1Affine, E::Scalar>,
@@ -330,7 +364,7 @@ where
330364
}
331365

332366
let c = EvalContext::translate(&targets[..]);
333-
let (pl, mut il) = match hash {
367+
let (pl, mut il, assigned_constant_hash) = match hash {
334368
TranscriptHash::Poseidon => {
335369
let mut t = vec![];
336370
for i in 0..proofs.len() {
@@ -341,6 +375,9 @@ where
341375
let it = PoseidonRead::init(&empty[..]);
342376
t.push(PoseidonChipRead::init(it, &mut ctx));
343377

378+
let mut constant_hasher =
379+
PoseidonChipRead::init(PoseidonRead::init(&empty[..]), &mut ctx);
380+
344381
context_eval::<E, _>(
345382
c,
346383
&instance_commitments
@@ -349,15 +386,57 @@ where
349386
.collect::<Vec<_>>()[..],
350387
&mut t.iter_mut().collect::<Vec<_>>(),
351388
&mut ctx,
389+
&mut constant_hasher,
352390
)?
353391
}
354392
_ => unreachable!(),
355393
};
356394

395+
let mut hashes = vec![];
396+
// assign for constant_hashes
397+
for h in all_constant_hash.iter() {
398+
let v = ctx.base_integer_chip().base_chip().assign(*h);
399+
hashes.push(v);
400+
}
401+
402+
if layer_idx < hashes.len() {
403+
ctx.base_integer_chip()
404+
.base_chip()
405+
.assert_equal(&hashes[layer_idx], &assigned_constant_hash);
406+
} else {
407+
all_constant_hash.push(assigned_constant_hash.val);
408+
hashes.push(assigned_constant_hash);
409+
}
410+
357411
for check in pl[0..absorb_start_idx].chunks(2).skip(1) {
358412
ctx.ecc_assert_equal(&check[0], &check[1]);
359413
}
360414

415+
// il[target_aggregator_circuit's hash instance col] -= msm(params[?..? + target_layer_index + 1], hashes[0..target_aggregator_circuit_layer_index + 1])
416+
for [proof_index, layer_idx, instance_col, instance_row_start] in
417+
target_aggregator_constant_hash_instance_offset
418+
{
419+
let mut instance_index = *instance_col;
420+
for i in instances[0..*proof_index].iter() {
421+
instance_index += i.len()
422+
}
423+
let mut points = vec![];
424+
let mut scalars = vec![];
425+
for i in 0..*layer_idx {
426+
points.push(
427+
ctx.assign_constant_point(&params.g_lagrange[i + instance_row_start].to_curve()),
428+
);
429+
scalars.push(hashes[i]);
430+
}
431+
432+
let msm_c = ctx.msm(&points, &scalars);
433+
let diff_commit = ctx.ecc_neg(&msm_c);
434+
let instance_commit = il[instance_index].clone();
435+
let instance_commit_curv = ctx.to_point_with_curvature(instance_commit);
436+
let update_commit = ctx.ecc_add(&instance_commit_curv, &diff_commit);
437+
il[instance_index] = update_commit;
438+
}
439+
361440
for (i, c) in pl[absorb_start_idx..expose_start_idx].iter().enumerate() {
362441
let encoded_c = ctx.ecc_encode(c);
363442
let [proof_index, instance_offset, g_index] = absorb[i].0;
@@ -442,13 +521,17 @@ where
442521
ctx.check_pairing(&[(&pl[0], &assigned_s_g2), (&pl[1], &assigned_g2)]);
443522
}
444523

445-
let assigned_instances = vec![&il[..], &pl[expose_start_idx..pl.len()]]
524+
let mut assigned_instances = vec![&il[..], &pl[expose_start_idx..pl.len()]]
446525
.concat()
447526
.iter()
448527
.map(|p| ctx.ecc_encode(p))
449528
.collect::<Vec<_>>()
450529
.concat();
451530

531+
assigned_instances.append(&mut hashes);
532+
533+
assigned_instances.push(assigned_constant_hash);
534+
452535
for ai in assigned_instances.iter() {
453536
ctx.0
454537
.ctx
@@ -461,7 +544,10 @@ where
461544

462545
let instances = assigned_instances.iter().map(|x| x.val).collect::<Vec<_>>();
463546
let ctx: Context<_> = ctx.into();
464-
println!("offset {} {} {}", ctx.base_offset, ctx. range_offset, ctx.select_offset);
547+
println!(
548+
"offset {} {} {}",
549+
ctx.base_offset, ctx.range_offset, ctx.select_offset
550+
);
465551

466552
Ok((
467553
AggregatorCircuit::new(

src/circuits/utils.rs

+9
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ pub fn run_circuit_unsafe_full_pass<
234234
expose: Vec<[usize; 2]>,
235235
absorb: Vec<([usize; 3], [usize; 2])>,
236236
force_create_proof: bool,
237+
target_aggregator_constant_hash_instance_offset: Vec<([usize; 4])>, // (circuit_idx, layer_idx, instance_col, instance_row)
238+
all_constant_hash: &mut Vec<E::Scalar>,
239+
layer_idx: usize,
237240
) -> Option<(AggregatorCircuit<E::G1Affine>, Vec<E::Scalar>)>
238241
where
239242
NativeScalarEccContext<E::G1Affine>: PairingChipOps<E::G1Affine, E::Scalar>,
@@ -342,6 +345,9 @@ where
342345
hash,
343346
expose.clone(),
344347
absorb.clone(),
348+
target_aggregator_constant_hash_instance_offset.clone(),
349+
all_constant_hash,
350+
layer_idx.clone(),
345351
);
346352
const K: u32 = 21;
347353
let prover = MockProver::run(K, &circuit, vec![instances]).unwrap();
@@ -379,6 +385,9 @@ where
379385
commitment_check,
380386
expose,
381387
absorb,
388+
target_aggregator_constant_hash_instance_offset,
389+
all_constant_hash,
390+
layer_idx,
382391
);
383392
end_timer!(timer);
384393

src/lib.rs

+18
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ fn test_single_one_pass() {
3535
vec![],
3636
vec![],
3737
true,
38+
vec![],
39+
&mut vec![],
40+
0,
3841
);
3942
}
4043

@@ -64,6 +67,9 @@ fn test_single_one_pass_with_verify_circuit() {
6467
vec![],
6568
vec![],
6669
true,
70+
vec![],
71+
&mut vec![],
72+
0,
6773
)
6874
.unwrap();
6975

@@ -78,6 +84,9 @@ fn test_single_one_pass_with_verify_circuit() {
7884
vec![],
7985
vec![],
8086
true,
87+
vec![],
88+
&mut vec![],
89+
0,
8190
);
8291
}
8392

@@ -107,6 +116,9 @@ fn test_single_one_pass_poseidon() {
107116
vec![],
108117
vec![],
109118
true,
119+
vec![],
120+
&mut vec![],
121+
0,
110122
);
111123
}
112124

@@ -137,6 +149,9 @@ fn test_multi_one_pass() {
137149
vec![],
138150
vec![],
139151
true,
152+
vec![],
153+
&mut vec![],
154+
0,
140155
);
141156
}
142157

@@ -167,5 +182,8 @@ fn test_multi_one_pass_poseidon() {
167182
vec![],
168183
vec![],
169184
true,
185+
vec![],
186+
&mut vec![],
187+
0,
170188
);
171189
}

src/solidity_verifier/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ pub fn test_twice_verify_circuit_diff() {
230230
vec![],
231231
vec![],
232232
true,
233+
vec![],
234+
&mut vec![],
235+
0,
233236
)
234237
.unwrap();
235238

@@ -246,6 +249,9 @@ pub fn test_twice_verify_circuit_diff() {
246249
vec![],
247250
vec![],
248251
true,
252+
vec![],
253+
&mut vec![],
254+
0,
249255
)
250256
.unwrap();
251257

@@ -344,6 +350,9 @@ pub fn test_solidity_render() {
344350
vec![],
345351
vec![],
346352
true,
353+
vec![],
354+
&mut vec![],
355+
0,
347356
)
348357
.unwrap();
349358

@@ -359,6 +368,9 @@ pub fn test_solidity_render() {
359368
vec![],
360369
vec![],
361370
true,
371+
vec![],
372+
&mut vec![],
373+
0,
362374
);
363375

364376
let params = load_or_build_unsafe_params::<Bn256>(

0 commit comments

Comments
 (0)