| 13 | use crate::bn254::fq2::Fq2; |
| 14 | |
| 15 | pub(crate) fn chunk_msm( |
| 16 | input_ks: Vec<ark_ff::BigInt<4>>, |
| 17 | qs: Vec<ark_bn254::G1Affine>, |
| 18 | ) -> Vec<(ark_bn254::G1Affine, bool, Script, Vec<Hint>)> { |
| 19 | assert_eq!(qs.len(), NUM_PUBS); |
| 20 | assert_eq!(input_ks.len(), NUM_PUBS); |
| 21 | let num_pubs = input_ks.len(); |
| 22 | |
| 23 | let ks = input_ks |
| 24 | .iter() |
| 25 | .map(|x| { |
| 26 | if *x < ark_bn254::Fr::MODULUS { |
| 27 | *x |
| 28 | } else { |
| 29 | ark_ff::BigInt::<4>::from(1u64) |
| 30 | } |
| 31 | }) |
| 32 | .collect::<Vec<ark_ff::BigInt<4>>>(); |
| 33 | |
| 34 | let chunks = msm::g1_multi_scalar_mul(qs.clone(), ks.into_iter().map(|f| f.into()).collect()); |
| 35 | |
| 36 | // [G1AccDashHash, G1AccHash, k0, k1, k2] |
| 37 | // [hints, G1Acc] |
| 38 | |
| 39 | let mut chunk_scripts = vec![]; |
| 40 | for (msm_tap_index, (chunk, variable_index)) in chunks.iter().enumerate() { |
| 41 | let ops_script = if msm_tap_index == 0 { |
| 42 | script! { |
| 43 | { G1Affine::push( ark_bn254::G1Affine::new_unchecked(ark_bn254::Fq::ZERO, ark_bn254::Fq::ZERO))} |
| 44 | { Fr::fromaltstack()} |
| 45 | |
| 46 | { Fr::copy(0)} |
| 47 | { Fr::is_valid() } |
| 48 | |
| 49 | // [hints, G1Acc, k, 0/1] |
| 50 | OP_IF |
| 51 | // [hints, G1Acc, k] |
| 52 | {chunk.1.clone()} |
| 53 | // [G1Acc, G1AccDash] |
| 54 | {Fq2::roll(2)} {Fq2::drop()} |
| 55 | //M: [G1AccDash] |
| 56 | //A: [G1AccDashHash] |
| 57 | {1} |
| 58 | OP_ELSE |
| 59 | // [G1Acc, k] |
| 60 | {Fr::drop()} |
| 61 | {G1Affine::drop()} |
| 62 | // [] [G1AccDashHash] |
| 63 | {Fq::push(ark_bn254::Fq::ONE)} |
| 64 | {Fq::push(ark_bn254::Fq::ZERO)} |
| 65 | //M: [Mock_G1AccDash] |
| 66 | //A: [G1AccDashHash] |
| 67 | {0} |
| 68 | OP_ENDIF |
| 69 | } |
| 70 | } else { |
| 71 | script! { |
| 72 | // [hints, G1Acc] [G1AccDashHash, G1AccHash] |