halo2_axiom/poly/kzg/
strategy.rs

1use super::{
2    commitment::{KZGCommitmentScheme, ParamsKZG},
3    msm::DualMSM,
4};
5use crate::{
6    helpers::SerdeCurveAffine,
7    plonk::Error,
8    poly::{
9        commitment::Verifier,
10        strategy::{Guard, VerificationStrategy},
11    },
12};
13use ff::Field;
14use pairing::{Engine, MultiMillerLoop};
15use rand_core::OsRng;
16use std::fmt::Debug;
17
18/// Wrapper for linear verification accumulator
19#[derive(Debug, Clone)]
20pub struct GuardKZG<'params, E: MultiMillerLoop + Debug> {
21    pub(crate) msm_accumulator: DualMSM<'params, E>,
22}
23
24/// Define accumulator type as `DualMSM`
25impl<'params, E> Guard<KZGCommitmentScheme<E>> for GuardKZG<'params, E>
26where
27    E: MultiMillerLoop + Debug,
28    E::G1Affine: SerdeCurveAffine<ScalarExt = E::Fr, CurveExt = E::G1>,
29    E::G2Affine: SerdeCurveAffine,
30{
31    type MSMAccumulator = DualMSM<'params, E>;
32}
33
34/// KZG specific operations
35impl<'params, E: MultiMillerLoop + Debug> GuardKZG<'params, E> {
36    pub(crate) fn new(msm_accumulator: DualMSM<'params, E>) -> Self {
37        Self { msm_accumulator }
38    }
39}
40
41/// A verifier that checks multiple proofs in a batch
42#[derive(Clone, Debug)]
43pub struct AccumulatorStrategy<'params, E: Engine> {
44    pub(crate) msm_accumulator: DualMSM<'params, E>,
45}
46
47impl<'params, E: MultiMillerLoop + Debug> AccumulatorStrategy<'params, E> {
48    /// Constructs an empty batch verifier
49    pub fn new(params: &'params ParamsKZG<E>) -> Self {
50        AccumulatorStrategy {
51            msm_accumulator: DualMSM::new(params),
52        }
53    }
54
55    /// Constructs and initialized new batch verifier
56    pub fn with(msm_accumulator: DualMSM<'params, E>) -> Self {
57        AccumulatorStrategy { msm_accumulator }
58    }
59}
60
61/// A verifier that checks a single proof
62#[derive(Clone, Debug)]
63pub struct SingleStrategy<'params, E: Engine> {
64    pub(crate) msm: DualMSM<'params, E>,
65}
66
67impl<'params, E: MultiMillerLoop + Debug> SingleStrategy<'params, E> {
68    /// Constructs an empty batch verifier
69    pub fn new(params: &'params ParamsKZG<E>) -> Self {
70        SingleStrategy {
71            msm: DualMSM::new(params),
72        }
73    }
74}
75
76impl<
77        'params,
78        E: MultiMillerLoop + Debug,
79        V: Verifier<
80            'params,
81            KZGCommitmentScheme<E>,
82            MSMAccumulator = DualMSM<'params, E>,
83            Guard = GuardKZG<'params, E>,
84        >,
85    > VerificationStrategy<'params, KZGCommitmentScheme<E>, V> for AccumulatorStrategy<'params, E>
86where
87    E::G1Affine: SerdeCurveAffine<ScalarExt = E::Fr, CurveExt = E::G1>,
88    E::G2Affine: SerdeCurveAffine,
89{
90    type Output = Self;
91
92    fn new(params: &'params ParamsKZG<E>) -> Self {
93        AccumulatorStrategy::new(params)
94    }
95
96    fn process(
97        mut self,
98        f: impl FnOnce(V::MSMAccumulator) -> Result<V::Guard, Error>,
99    ) -> Result<Self::Output, Error> {
100        self.msm_accumulator.scale(E::Fr::random(OsRng));
101
102        // Guard is updated with new msm contributions
103        let guard = f(self.msm_accumulator)?;
104        Ok(Self {
105            msm_accumulator: guard.msm_accumulator,
106        })
107    }
108
109    fn finalize(self) -> bool {
110        self.msm_accumulator.check()
111    }
112}
113
114impl<
115        'params,
116        E: MultiMillerLoop + Debug,
117        V: Verifier<
118            'params,
119            KZGCommitmentScheme<E>,
120            MSMAccumulator = DualMSM<'params, E>,
121            Guard = GuardKZG<'params, E>,
122        >,
123    > VerificationStrategy<'params, KZGCommitmentScheme<E>, V> for SingleStrategy<'params, E>
124where
125    E::G1Affine: SerdeCurveAffine<ScalarExt = E::Fr, CurveExt = E::G1>,
126    E::G2Affine: SerdeCurveAffine,
127{
128    type Output = ();
129
130    fn new(params: &'params ParamsKZG<E>) -> Self {
131        Self::new(params)
132    }
133
134    fn process(
135        self,
136        f: impl FnOnce(V::MSMAccumulator) -> Result<V::Guard, Error>,
137    ) -> Result<Self::Output, Error> {
138        // Guard is updated with new msm contributions
139        let guard = f(self.msm)?;
140        let msm = guard.msm_accumulator;
141        if msm.check() {
142            Ok(())
143        } else {
144            Err(Error::ConstraintSystemFailure)
145        }
146    }
147
148    fn finalize(self) -> bool {
149        unreachable!();
150    }
151}