halo2_axiom/poly/kzg/
msm.rs
1use std::fmt::Debug;
2
3use super::commitment::ParamsKZG;
4use crate::{
5 arithmetic::{best_multiexp, parallelize, CurveAffine},
6 poly::commitment::MSM,
7};
8use group::{Curve, Group};
9use pairing::{Engine, MillerLoopResult, MultiMillerLoop};
10
11#[derive(Clone, Default, Debug)]
13pub struct MSMKZG<E: Engine> {
14 pub(crate) scalars: Vec<E::Fr>,
15 pub(crate) bases: Vec<E::G1>,
16}
17
18impl<E: Engine> MSMKZG<E> {
19 pub fn new() -> Self {
21 MSMKZG {
22 scalars: vec![],
23 bases: vec![],
24 }
25 }
26
27 pub fn combine_with_base(&mut self, base: E::Fr) {
29 use ff::Field;
30 let mut acc = E::Fr::ONE;
31 if !self.scalars.is_empty() {
32 for scalar in self.scalars.iter_mut().rev() {
33 *scalar *= &acc;
34 acc *= base;
35 }
36 }
37 }
38}
39
40impl<E> MSM<E::G1Affine> for MSMKZG<E>
41where
42 E: Engine + Debug,
43 E::G1Affine: CurveAffine<ScalarExt = E::Fr, CurveExt = E::G1>,
44{
45 fn append_term(&mut self, scalar: E::Fr, point: E::G1) {
46 self.scalars.push(scalar);
47 self.bases.push(point);
48 }
49
50 fn add_msm(&mut self, other: &Self) {
51 self.scalars.extend(other.scalars().iter());
52 self.bases.extend(other.bases().iter());
53 }
54
55 fn scale(&mut self, factor: E::Fr) {
56 if !self.scalars.is_empty() {
57 parallelize(&mut self.scalars, |scalars, _| {
58 for other_scalar in scalars {
59 *other_scalar *= &factor;
60 }
61 })
62 }
63 }
64
65 fn check(&self) -> bool {
66 bool::from(self.eval().is_identity())
67 }
68
69 fn eval(&self) -> E::G1 {
70 use group::prime::PrimeCurveAffine;
71 let mut bases = vec![E::G1Affine::identity(); self.scalars.len()];
72 E::G1::batch_normalize(&self.bases, &mut bases);
73 best_multiexp(&self.scalars, &bases)
74 }
75
76 fn bases(&self) -> Vec<E::G1> {
77 self.bases.clone()
78 }
79
80 fn scalars(&self) -> Vec<E::Fr> {
81 self.scalars.clone()
82 }
83}
84
85#[derive(Debug, Clone)]
87pub(crate) struct PreMSM<E: Engine> {
88 projectives_msms: Vec<MSMKZG<E>>,
89}
90
91impl<E: Engine + Debug> PreMSM<E> {
92 pub(crate) fn new() -> Self {
93 PreMSM {
94 projectives_msms: vec![],
95 }
96 }
97
98 pub(crate) fn normalize(self) -> MSMKZG<E> {
99 let (scalars, bases) = self
100 .projectives_msms
101 .into_iter()
102 .map(|msm| (msm.scalars, msm.bases))
103 .unzip::<_, _, Vec<_>, Vec<_>>();
104
105 MSMKZG {
106 scalars: scalars.into_iter().flatten().collect(),
107 bases: bases.into_iter().flatten().collect(),
108 }
109 }
110
111 pub(crate) fn add_msm(&mut self, other: MSMKZG<E>) {
112 self.projectives_msms.push(other);
113 }
114}
115
116impl<'params, E: MultiMillerLoop + Debug> From<&'params ParamsKZG<E>> for DualMSM<'params, E> {
117 fn from(params: &'params ParamsKZG<E>) -> Self {
118 DualMSM::new(params)
119 }
120}
121
122#[derive(Debug, Clone)]
124pub struct DualMSM<'a, E: Engine> {
125 pub(crate) params: &'a ParamsKZG<E>,
126 pub(crate) left: MSMKZG<E>,
127 pub(crate) right: MSMKZG<E>,
128}
129
130impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E> {
131 pub fn new(params: &'a ParamsKZG<E>) -> Self {
133 Self {
134 params,
135 left: MSMKZG::new(),
136 right: MSMKZG::new(),
137 }
138 }
139}
140
141impl<'a, E: MultiMillerLoop + Debug> DualMSM<'a, E>
142where
143 E::G1Affine: CurveAffine<ScalarExt = E::Fr, CurveExt = E::G1>,
144{
145 pub fn scale(&mut self, e: E::Fr) {
147 self.left.scale(e);
148 self.right.scale(e);
149 }
150
151 pub fn add_msm(&mut self, other: Self) {
153 self.left.add_msm(&other.left);
154 self.right.add_msm(&other.right);
155 }
156
157 pub fn check(self) -> bool {
159 let s_g2_prepared = E::G2Prepared::from(self.params.s_g2);
160 let n_g2_prepared = E::G2Prepared::from(-self.params.g2);
161
162 let left = self.left.eval();
163 let right = self.right.eval();
164
165 let (term_1, term_2) = (
166 (&left.into(), &s_g2_prepared),
167 (&right.into(), &n_g2_prepared),
168 );
169 let terms = &[term_1, term_2];
170
171 bool::from(
172 E::multi_miller_loop(&terms[..])
173 .final_exponentiation()
174 .is_identity(),
175 )
176 }
177}