proof_of_sql/proof_primitive/dory/
setup.rs

1use super::{G1Affine, G2Affine, PublicParameters, GT};
2use crate::{base::impl_serde_for_ark_serde_unchecked, utils::log};
3use alloc::vec::Vec;
4use ark_ec::pairing::{Pairing, PairingOutput};
5use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
6use itertools::MultiUnzip;
7use num_traits::One;
8#[cfg(feature = "std")]
9use std::{
10    fs::File,
11    io::{BufReader, BufWriter, Error, Read, Write},
12    path::Path,
13};
14
15/// The transparent setup information that the prover must know to create a proof.
16/// This is public knowledge and must match with the verifier's setup information.
17/// See Section 3.3 of <https://eprint.iacr.org/2020/1274.pdf> for details.
18///
19///
20/// Note:
21/// We use nu = m and k = m-i or m-j.
22/// This indexing is more convenient for coding because lengths of the arrays used are typically 2^k rather than 2^i or 2^j.
23pub struct ProverSetup<'a> {
24    /// `Gamma_1[k]` = Γ_1,(m-k) in the Dory paper.
25    pub(super) Gamma_1: Vec<&'a [G1Affine]>,
26    /// `Gamma_2[k]` = Γ_2,(m-k) in the Dory paper.
27    pub(super) Gamma_2: Vec<&'a [G2Affine]>,
28    /// `H_1` = `H_1` in the Dory paper. This could be used for blinding, but is currently only used in the Fold-Scalars algorithm.
29    pub(super) H_1: G1Affine,
30    /// `H_2` = `H_2` in the Dory paper. This could be used for blinding, but is currently only used in the Fold-Scalars algorithm.
31    pub(super) H_2: G2Affine,
32    /// `Gamma_2_fin` = `Gamma_2,fin` in the Dory paper.
33    pub(super) Gamma_2_fin: G2Affine,
34    /// `max_nu` is the maximum nu that this setup will work for
35    pub(super) max_nu: usize,
36    /// The handle to the `blitzar` `Gamma_1` instances.
37    #[cfg(feature = "blitzar")]
38    blitzar_handle:
39        blitzar::compute::MsmHandle<blitzar::compute::ElementP2<ark_bls12_381::g1::Config>>,
40}
41
42impl<'a> ProverSetup<'a> {
43    /// Create a new `ProverSetup` from the public parameters.
44    /// # Panics
45    /// Panics if the length of `Gamma_1` or `Gamma_2` is not equal to `2^max_nu`.
46    pub(super) fn new(
47        Gamma_1: &'a [G1Affine],
48        Gamma_2: &'a [G2Affine],
49        H_1: G1Affine,
50        H_2: G2Affine,
51        Gamma_2_fin: G2Affine,
52        max_nu: usize,
53    ) -> Self {
54        assert_eq!(Gamma_1.len(), 1 << max_nu);
55        assert_eq!(Gamma_2.len(), 1 << max_nu);
56        #[cfg(feature = "blitzar")]
57        let blitzar_handle = blitzar::compute::MsmHandle::new(
58            &Gamma_1.iter().copied().map(Into::into).collect::<Vec<_>>(),
59        );
60        let (Gamma_1, Gamma_2): (Vec<_>, Vec<_>) = (0..=max_nu)
61            .map(|k| (&Gamma_1[..1 << k], &Gamma_2[..1 << k]))
62            .unzip();
63        ProverSetup {
64            Gamma_1,
65            Gamma_2,
66            H_1,
67            H_2,
68            Gamma_2_fin,
69            max_nu,
70            #[cfg(feature = "blitzar")]
71            blitzar_handle,
72        }
73    }
74
75    /// Create a new `ProverSetup` from the public parameters and blitzar handle
76    /// # Panics
77    /// Panics if the length of `Gamma_1` or `Gamma_2` is not equal to `2^max_nu`.
78    #[must_use]
79    #[cfg(feature = "blitzar")]
80    pub fn from_public_parameters_and_blitzar_handle(
81        public_parameters: &'a PublicParameters,
82        blitzar_handle: blitzar::compute::MsmHandle<
83            blitzar::compute::ElementP2<ark_bls12_381::g1::Config>,
84        >,
85    ) -> Self {
86        let Gamma_1: &'a [G1Affine] = &public_parameters.Gamma_1;
87        let Gamma_2: &'a [G2Affine] = &public_parameters.Gamma_2;
88        let H_1 = public_parameters.H_1;
89        let H_2 = public_parameters.H_2;
90        let Gamma_2_fin = public_parameters.Gamma_2_fin;
91        let max_nu = public_parameters.max_nu;
92        assert_eq!(Gamma_1.len(), 1 << max_nu);
93        assert_eq!(Gamma_2.len(), 1 << max_nu);
94
95        let (Gamma_1, Gamma_2): (Vec<_>, Vec<_>) = (0..=max_nu)
96            .map(|k| (&Gamma_1[..1 << k], &Gamma_2[..1 << k]))
97            .unzip();
98        ProverSetup {
99            Gamma_1,
100            Gamma_2,
101            H_1,
102            H_2,
103            Gamma_2_fin,
104            max_nu,
105            #[cfg(feature = "blitzar")]
106            blitzar_handle,
107        }
108    }
109
110    /// Gets the `MSMHandle` for this setup
111    #[must_use]
112    #[cfg(feature = "blitzar")]
113    pub fn blitzar_handle(
114        self,
115    ) -> blitzar::compute::MsmHandle<blitzar::compute::ElementP2<ark_bls12_381::g1::Config>> {
116        self.blitzar_handle
117    }
118
119    #[cfg(feature = "blitzar")]
120    #[tracing::instrument(name = "ProverSetup::blitzar_msm", level = "debug", skip_all)]
121    pub(super) fn blitzar_msm(
122        &self,
123        res: &mut [blitzar::compute::ElementP2<ark_bls12_381::g1::Config>],
124        element_num_bytes: u32,
125        scalars: &[u8],
126    ) {
127        log::log_memory_usage("Start");
128
129        self.blitzar_handle.msm(res, element_num_bytes, scalars);
130    }
131
132    #[cfg(feature = "blitzar")]
133    #[tracing::instrument(name = "ProverSetup::blitzar_packed_msm", level = "debug", skip_all)]
134    pub(super) fn blitzar_packed_msm(
135        &self,
136        res: &mut [blitzar::compute::ElementP2<ark_bls12_381::g1::Config>],
137        output_bit_table: &[u32],
138        scalars: &[u8],
139    ) {
140        log::log_memory_usage("Start");
141
142        self.blitzar_handle
143            .packed_msm(res, output_bit_table, scalars);
144    }
145
146    #[cfg(feature = "blitzar")]
147    #[tracing::instrument(name = "ProverSetup::blitzar_vlen_msm", level = "debug", skip_all)]
148    pub(super) fn blitzar_vlen_msm(
149        &self,
150        res: &mut [blitzar::compute::ElementP2<ark_bls12_381::g1::Config>],
151        output_bit_table: &[u32],
152        output_lengths: &[u32],
153        scalars: &[u8],
154    ) {
155        log::log_memory_usage("Start");
156
157        self.blitzar_handle
158            .vlen_msm(res, output_bit_table, output_lengths, scalars);
159    }
160}
161
162impl<'a> From<&'a PublicParameters> for ProverSetup<'a> {
163    fn from(value: &'a PublicParameters) -> Self {
164        Self::new(
165            &value.Gamma_1,
166            &value.Gamma_2,
167            value.H_1,
168            value.H_2,
169            value.Gamma_2_fin,
170            value.max_nu,
171        )
172    }
173}
174
175/// The transparent setup information that the verifier must know to verify a proof.
176/// This is public knowledge and must match with the prover's setup information.
177/// See Section 3.3 of <https://eprint.iacr.org/2020/1274.pdf> for details.
178///
179///
180/// Note:
181/// We use nu = m and k = m-i or m-j.
182/// This indexing is more convenient for coding because lengths of the arrays used are typically 2^k rather than 2^i or 2^j.
183#[derive(CanonicalSerialize, CanonicalDeserialize, PartialEq, Eq, Debug, Clone)]
184pub struct VerifierSetup {
185    /// `Delta_1L[k]` = Δ_1L,(m-k) in the Dory paper, so `Delta_1L[0]` is unused. Note, this is the same as `Delta_2L`.
186    pub(super) Delta_1L: Vec<GT>,
187    /// `Delta_1R[k]` = Δ_1R,(m-k) in the Dory paper, so `Delta_1R[0]` is unused.
188    pub(super) Delta_1R: Vec<GT>,
189    /// `Delta_2L[k]` = Δ_2L,(m-k) in the Dory paper, so `Delta_2L[0]` is unused. Note, this is the same as `Delta_1L`.
190    pub(super) Delta_2L: Vec<GT>,
191    /// `Delta_2R[k]` = Δ_2R,(m-k) in the Dory paper, so `Delta_2R[0]` is unused.
192    pub(super) Delta_2R: Vec<GT>,
193    /// `chi[k]` = χ,(m-k) in the Dory paper.
194    pub(super) chi: Vec<GT>,
195    /// `Gamma_1_0` is the `Γ_1` used in Scalar-Product algorithm in the Dory paper.
196    pub(super) Gamma_1_0: G1Affine,
197    /// `Gamma_2_0` is the `Γ_2` used in Scalar-Product algorithm in the Dory paper.
198    pub(super) Gamma_2_0: G2Affine,
199    /// `H_1` = `H_1` in the Dory paper. This could be used for blinding, but is currently only used in the Fold-Scalars algorithm.
200    pub(super) H_1: G1Affine,
201    /// `H_2` = `H_2` in the Dory paper. This could be used for blinding, but is currently only used in the Fold-Scalars algorithm.
202    pub(super) H_2: G2Affine,
203    /// `H_T` = `H_T` in the Dory paper.
204    pub(super) H_T: GT,
205    /// `Gamma_2_fin` = `Gamma_2,fin` in the Dory paper.
206    pub(super) Gamma_2_fin: G2Affine,
207    /// `max_nu` is the maximum nu that this setup will work for
208    pub(super) max_nu: usize,
209}
210
211impl_serde_for_ark_serde_unchecked!(VerifierSetup);
212
213impl VerifierSetup {
214    /// Create a new `VerifierSetup` from the public parameters.
215    /// # Panics
216    /// Panics if the length of `Gamma_1_nu` is not equal to `2^max_nu`.
217    /// Panics if the length of `Gamma_2_nu` is not equal to `2^max_nu`.
218    pub(super) fn new(
219        Gamma_1_nu: &[G1Affine],
220        Gamma_2_nu: &[G2Affine],
221        H_1: G1Affine,
222        H_2: G2Affine,
223        Gamma_2_fin: G2Affine,
224        max_nu: usize,
225    ) -> Self {
226        assert_eq!(Gamma_1_nu.len(), 1 << max_nu);
227        assert_eq!(Gamma_2_nu.len(), 1 << max_nu);
228        let (Delta_1L_2L, Delta_1R, Delta_2R, chi): (Vec<_>, Vec<_>, Vec<_>, Vec<_>) = (0..=max_nu)
229            .map(|k| {
230                if k == 0 {
231                    (
232                        PairingOutput(One::one()),
233                        PairingOutput(One::one()),
234                        PairingOutput(One::one()),
235                        Pairing::pairing(Gamma_1_nu[0], Gamma_2_nu[0]),
236                    )
237                } else {
238                    (
239                        Pairing::multi_pairing(
240                            &Gamma_1_nu[..1 << (k - 1)],
241                            &Gamma_2_nu[..1 << (k - 1)],
242                        ),
243                        Pairing::multi_pairing(
244                            &Gamma_1_nu[1 << (k - 1)..1 << k],
245                            &Gamma_2_nu[..1 << (k - 1)],
246                        ),
247                        Pairing::multi_pairing(
248                            &Gamma_1_nu[..1 << (k - 1)],
249                            &Gamma_2_nu[1 << (k - 1)..1 << k],
250                        ),
251                        Pairing::multi_pairing(&Gamma_1_nu[..1 << k], &Gamma_2_nu[..1 << k]),
252                    )
253                }
254            })
255            .multiunzip();
256        Self {
257            Delta_1L: Delta_1L_2L.clone(),
258            Delta_1R,
259            Delta_2L: Delta_1L_2L,
260            Delta_2R,
261            chi,
262            Gamma_1_0: Gamma_1_nu[0],
263            Gamma_2_0: Gamma_2_nu[0],
264            H_1,
265            H_2,
266            H_T: Pairing::pairing(H_1, H_2),
267            Gamma_2_fin,
268            max_nu,
269        }
270    }
271
272    #[cfg(feature = "std")]
273    /// Function to save `VerifierSetup` to a file in binary form
274    pub fn save_to_file(&self, path: &Path) -> std::io::Result<()> {
275        // Create or open the file at the specified path
276
277        let file = File::create(path)?;
278        let mut writer = BufWriter::new(file);
279
280        // Serialize the PublicParameters struct into the file
281        let mut serialized_data = Vec::new();
282        self.serialize_with_mode(&mut serialized_data, Compress::No)
283            .map_err(|e| Error::other(format!("{e}")))?;
284
285        // Write serialized bytes to the file
286        writer.write_all(&serialized_data)?;
287        writer.flush()?;
288        Ok(())
289    }
290
291    #[cfg(feature = "std")]
292    /// Function to load `VerifierSetup` from a file in binary form
293    pub fn load_from_file(path: &Path) -> std::io::Result<Self> {
294        // Open the file at the specified path
295
296        let file = File::open(path)?;
297        let mut reader = BufReader::new(file);
298
299        // Read the serialized data from the file
300        let mut serialized_data = Vec::new();
301        reader.read_to_end(&mut serialized_data)?;
302
303        // Deserialize the data into a PublicParameters instance
304        Self::deserialize_with_mode(&mut &serialized_data[..], Compress::No, Validate::No)
305            .map_err(|e| Error::other(format!("{e}")))
306    }
307}
308
309impl From<&PublicParameters> for VerifierSetup {
310    fn from(value: &PublicParameters) -> Self {
311        Self::new(
312            &value.Gamma_1,
313            &value.Gamma_2,
314            value.H_1,
315            value.H_2,
316            value.Gamma_2_fin,
317            value.max_nu,
318        )
319    }
320}