@@ -297,9 +297,9 @@ fn binary_k_fold_assigned(
297297 let inv_tw = omega_k_inv. powers ( ) . take ( 1usize << ( k - 1 ) ) . collect ( ) ;
298298 let half = RootF :: ONE . halve ( ) ;
299299
300- let mut x_pow = x ;
300+ let mut x_pow = base_chip . reduce_max_bits ( ctx , x ) ;
301301 let x_inv = invert_base_assigned ( ctx, base_chip, x) ;
302- let mut x_inv_pow = x_inv;
302+ let mut x_inv_pow = base_chip . reduce_max_bits ( ctx , x_inv) ;
303303
304304 for ( j, alpha) in alphas. iter ( ) . enumerate ( ) {
305305 let m = n >> ( j + 1 ) ;
@@ -318,7 +318,9 @@ fn binary_k_fold_assigned(
318318 values[ i] = ext_chip. add ( ctx, lo, fold) ;
319319 }
320320 x_pow = base_chip. square ( ctx, x_pow) ;
321+ x_pow = base_chip. reduce_max_bits ( ctx, x_pow) ;
321322 x_inv_pow = base_chip. square ( ctx, x_inv_pow) ;
323+ x_inv_pow = base_chip. reduce_max_bits ( ctx, x_inv_pow) ;
322324 }
323325 values[ 0 ]
324326}
@@ -380,9 +382,11 @@ fn constrain_merkle_path(
380382 let query_bits = query_bits. to_vec ( ) ;
381383
382384 for ( bit, & sibling) in query_bits. iter ( ) . zip ( merkle_path. siblings . iter ( ) ) {
383- let left_right = compress_bn254_digests ( ctx, ext_chip. range ( ) , cur, sibling) ;
384- let right_left = compress_bn254_digests ( ctx, ext_chip. range ( ) , sibling, cur) ;
385- cur = gate. select ( ctx, right_left, left_right, * bit) ;
385+ // Select input order first, then compress once (instead of compressing
386+ // both orderings and selecting after). Halves Poseidon2 calls per level.
387+ let left = gate. select ( ctx, sibling, cur, * bit) ;
388+ let right = gate. select ( ctx, cur, sibling, * bit) ;
389+ cur = compress_bn254_digests ( ctx, ext_chip. range ( ) , left, right) ;
386390 }
387391
388392 ctx. constrain_equal ( & cur, & root_digest) ;
@@ -580,6 +584,7 @@ pub(crate) fn constrain_whir_verification(
580584 mu_power_idx += 1 ;
581585 }
582586 }
587+
583588 let codeword_vals = codeword_vals. into_iter ( ) . flatten ( ) . collect :: < Vec < _ > > ( ) ;
584589 binary_k_fold_assigned ( ctx, ext_chip, codeword_vals, & alphas_round, zi_root)
585590 } else {
@@ -591,6 +596,7 @@ pub(crate) fn constrain_whir_verification(
591596 merkle_path,
592597 codeword_commitment_roots[ round_idx - 1 ] ,
593598 ) ;
599+
594600 let opened_values = merkle_path
595601 . leaf_values
596602 . iter ( )
@@ -650,19 +656,21 @@ pub(crate) fn constrain_whir_verification(
650656 let mut z0_pows = Vec :: with_capacity ( slc_len) ;
651657 z0_pows. push ( * z0) ;
652658 for _ in 1 ..slc_len {
653- let next = ext_chip. mul (
654- ctx,
655- * z0_pows. last ( ) . expect ( "z0 power sequence is non-empty" ) ,
656- * z0_pows. last ( ) . expect ( "z0 power sequence is non-empty" ) ,
657- ) ;
659+ let prev = z0_pows. last ( ) . unwrap ( ) ;
660+ let next = ext_chip. square ( ctx, * prev) ;
658661 z0_pows. push ( next) ;
659662 }
660- let z0_max = * z0_pows. last ( ) . expect ( "z0 power sequence is non-empty" ) ;
663+ let z0_max = * z0_pows. last ( ) . unwrap ( ) ;
664+ // Pre-reduce z0_pows so eq_mle doesn't redundantly reduce them.
665+ let z0_pows_reduced: Vec < _ > = z0_pows
666+ . iter ( )
667+ . map ( |p| ext_chip. reduce_max_bits ( ctx, * p) )
668+ . collect ( ) ;
661669 let eq = eval_eq_mle_assigned (
662670 ctx,
663671 ext_chip,
664672 alpha_slc,
665- & z0_pows [ ..z0_pows . len ( ) . saturating_sub ( 1 ) ] ,
673+ & z0_pows_reduced [ ..z0_pows_reduced . len ( ) . saturating_sub ( 1 ) ] ,
666674 ) ;
667675 let poly_eval = horner_eval_ext_poly_assigned ( ctx, ext_chip, final_poly, & z0_max) ;
668676 let term = ext_chip. mul ( ctx, * gamma, eq) ;
@@ -673,25 +681,34 @@ pub(crate) fn constrain_whir_verification(
673681
674682 profiler. push ( "query_point_evals" , ctx. advice . len ( ) ) ;
675683 let mut gamma_pow = ext_chip. mul ( ctx, * gamma, * gamma) ;
676- for zi in & zs_per_round[ round_idx] {
684+ for zi in zs_per_round[ round_idx] . iter ( ) {
677685 let mut zi_pows = Vec :: with_capacity ( slc_len) ;
678686 zi_pows. push ( * zi) ;
679687 for _ in 1 ..slc_len {
680- let next = ext_chip. base ( ) . mul (
681- ctx,
682- * zi_pows. last ( ) . expect ( "zi power sequence is non-empty" ) ,
683- * zi_pows. last ( ) . expect ( "zi power sequence is non-empty" ) ,
684- ) ;
688+ let prev = zi_pows. last ( ) . unwrap ( ) ;
689+ let next = ext_chip. base ( ) . square ( ctx, * prev) ;
685690 zi_pows. push ( next) ;
686691 }
687- let zi_max = * zi_pows. last ( ) . expect ( "zi power sequence is non-empty" ) ;
692+ // Pre-reduce zi_pows so eq_mle and poly eval don't redundantly reduce.
693+ let zi_pows_reduced: Vec < _ > = zi_pows
694+ . iter ( )
695+ . map ( |p| ext_chip. base ( ) . reduce_max_bits ( ctx, * p) )
696+ . collect ( ) ;
697+
688698 let eq = eval_eq_mle_ef_f_assigned (
689699 ctx,
690700 ext_chip,
691701 alpha_slc,
692- & zi_pows [ ..zi_pows . len ( ) . saturating_sub ( 1 ) ] ,
702+ & zi_pows_reduced [ ..zi_pows_reduced . len ( ) . saturating_sub ( 1 ) ] ,
693703 ) ;
694- let poly_eval = horner_eval_ext_poly_f_assigned ( ctx, ext_chip, final_poly, & zi_max) ;
704+
705+ let poly_eval = horner_eval_ext_poly_f_assigned (
706+ ctx,
707+ ext_chip,
708+ final_poly,
709+ zi_pows_reduced. last ( ) . unwrap ( ) ,
710+ ) ;
711+
695712 let term = ext_chip. mul ( ctx, gamma_pow, eq) ;
696713 let term = ext_chip. mul ( ctx, term, poly_eval) ;
697714 final_acc = ext_chip. add ( ctx, final_acc, term) ;
0 commit comments