Skip to content

Commit 3886067

Browse files
authored
Optimize Static Verifier alpha pow computation (#1250)
1 parent 37f0b55 commit 3886067

File tree

5 files changed

+53
-4
lines changed

5 files changed

+53
-4
lines changed

extensions/native/compiler/src/constraints/halo2/baby_bear.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ impl BabyBearChip {
8080
r
8181
}
8282

83+
/// Reduce max_bits if possible. This function doesn't guarantee that the actual value is within BabyBear.
84+
pub fn reduce_max_bits(&self, ctx: &mut Context<Fr>, a: AssignedBabyBear) -> AssignedBabyBear {
85+
if a.max_bits > BABYBEAR_MAX_BITS {
86+
self.reduce(ctx, a)
87+
} else {
88+
a
89+
}
90+
}
91+
8392
pub fn add(
8493
&self,
8594
ctx: &mut Context<Fr>,
@@ -527,4 +536,18 @@ impl BabyBearExt4Chip {
527536
);
528537
c
529538
}
539+
540+
pub fn reduce_max_bits(
541+
&self,
542+
ctx: &mut Context<Fr>,
543+
a: AssignedBabyBearExt4,
544+
) -> AssignedBabyBearExt4 {
545+
AssignedBabyBearExt4(
546+
a.0.into_iter()
547+
.map(|x| self.base.reduce_max_bits(ctx, x))
548+
.collect::<Vec<_>>()
549+
.try_into()
550+
.unwrap(),
551+
)
552+
}
530553
}

extensions/native/compiler/src/constraints/halo2/compiler.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,14 @@ impl<C: Config + Debug> Halo2ConstraintCompiler<C> {
408408
);
409409
exts.insert(b.0, x);
410410
}
411+
DslIr::CircuitFeltReduce(a) => {
412+
let x = f_chip.reduce_max_bits(ctx, felts[&a.0]);
413+
felts.insert(a.0, x);
414+
}
415+
DslIr::CircuitExtReduce(a) => {
416+
let x = ext_chip.reduce_max_bits(ctx, exts[&a.0]);
417+
exts.insert(a.0, x);
418+
}
411419
DslIr::CycleTrackerStart(_name) => {
412420
#[cfg(feature = "bench-metrics")]
413421
cell_tracker.start(_name);
@@ -482,6 +490,8 @@ fn is_babybear_ir<C: Config>(ir: &DslIr<C>) -> bool {
482490
| DslIr::AssertEqFI(_, _)
483491
| DslIr::WitnessFelt(_, _)
484492
| DslIr::CircuitFelts2Ext(_, _)
493+
| DslIr::CircuitFeltReduce(_)
494+
| DslIr::CircuitExtReduce(_)
485495
| DslIr::ImmE(_, _)
486496
| DslIr::AddE(_, _, _)
487497
| DslIr::AddEF(_, _, _)

extensions/native/compiler/src/ir/instructions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,10 @@ pub enum DslIr<C: Config> {
248248
CircuitExt2Felt([Felt<C::F>; 4], Ext<C::F, C::EF>),
249249
/// Converts a slice of felts to an ext. Should only be used when target is a circuit.
250250
CircuitFelts2Ext([Felt<C::F>; 4], Ext<C::F, C::EF>),
251+
/// Halo2 only. Reduce a Felt so later computation becomes cheaper.
252+
CircuitFeltReduce(Felt<C::F>),
253+
/// Halo2 only. Reduce an Ext so later computation becomes cheaper.
254+
CircuitExtReduce(Ext<C::F, C::EF>),
251255
/// FriReducedOpening(alpha, curr_alpha_pow, at_x_array, at_z_array, result)
252256
FriReducedOpening(
253257
Ext<C::F, C::EF>,

extensions/native/compiler/src/ir/utils.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,10 @@ impl<C: Config> Builder<C> {
175175
.push(DslIr::CircuitExt2Felt([a, b, c, d], value));
176176
[a, b, c, d]
177177
}
178+
pub fn felt_reduce_circuit(&mut self, value: Felt<C::F>) {
179+
self.operations.push(DslIr::CircuitFeltReduce(value));
180+
}
181+
pub fn ext_reduce_circuit(&mut self, value: Ext<C::F, C::EF>) {
182+
self.operations.push(DslIr::CircuitExtReduce(value));
183+
}
178184
}

extensions/native/recursion/src/fri/two_adic_pcs.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ pub fn verify_two_adic_pcs<C: Config>(
4848
let log_blowup = config.log_blowup;
4949
let blowup = config.blowup;
5050
let alpha = challenger.sample_ext(builder);
51+
if builder.flags.static_only {
52+
builder.ext_reduce_circuit(alpha);
53+
}
5154

5255
builder.cycle_tracker_start("stage-d-verifier-verify");
5356
let betas: Array<C, Ext<C::F, C::EF>> = builder.array(proof.commit_phase_commits.len());
@@ -232,7 +235,7 @@ pub fn verify_two_adic_pcs<C: Config>(
232235
let p_at_z = builder.get(&ps_at_z, t);
233236
builder.assign(&n, n * alpha + (p_at_z - p_at_x));
234237
}
235-
builder.assign(&cur_ro, cur_ro + cur_alpha_pow * n / (z - x));
238+
builder.assign(&cur_ro, cur_ro + n / (z - x) * cur_alpha_pow);
236239
builder.assign(&cur_alpha_pow, cur_alpha_pow * mat_alpha_pow);
237240
} else {
238241
// TODO: this is just for testing the correctness. Will remove later.
@@ -396,13 +399,16 @@ fn compute_round_alpha_pows<C: Config>(
396399
let mat_alpha_pow: Ext<_, _> = if builder.flags.static_only {
397400
let width = width.value();
398401
assert!(width < 1 << MAX_LOG_WIDTH);
399-
let mut ret = C::EF::ONE.cons();
402+
let mut expr = C::EF::ONE.cons();
400403
for i in 0..MAX_LOG_WIDTH {
401404
if width & (1 << i) != 0 {
402-
ret *= builder.get(&pow_of_alpha, i);
405+
expr *= builder.get(&pow_of_alpha, i);
403406
}
404407
}
405-
builder.eval(ret)
408+
let ret: Ext<_, _> = builder.eval(expr);
409+
// Minimize max_bits so following computation becomes cheaper.
410+
builder.ext_reduce_circuit(ret);
411+
ret
406412
} else {
407413
let width = width.get_var();
408414
// This is dynamic only so safe to cast.

0 commit comments

Comments
 (0)