fullcodec_plonk/commitment_scheme/kzg10/
srs.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7//! The Public Parameters can also be referred to as the Structured Reference
8//! String (SRS).
9use super::key::{CommitKey, OpeningKey};
10use crate::{error::Error, util};
11use dusk_bls12_381::{G1Affine, G1Projective, G2Affine};
12use dusk_bytes::{DeserializableSlice, Serializable};
13use parity_scale_codec::{Decode, Encode};
14use rand_core::RngCore;
15use serde::{Deserialize, Serialize};
16use sp_std::vec;
17use sp_std::vec::Vec;
18
19/// The Public Parameters can also be referred to as the Structured Reference
20/// String (SRS). It is available to both the prover and verifier and allows the
21/// verifier to efficiently verify and make claims about polynomials up to and
22/// including a configured degree.
23#[derive(Debug, Clone, Encode, Decode, Serialize, Deserialize, PartialEq)]
24pub struct PublicParameters {
25    /// Key used to generate proofs for composed circuits.
26    pub(crate) commit_key: CommitKey,
27    /// Key used to verify proofs for composed circuits.
28    pub(crate) opening_key: OpeningKey,
29}
30
31impl PublicParameters {
32    /// Returns an untrimmed [`CommitKey`] reference contained in the
33    /// `PublicParameters` instance.
34    pub fn commit_key(&self) -> &CommitKey {
35        &self.commit_key
36    }
37
38    /// Returns an [`OpeningKey`] reference contained in the
39    /// `PublicParameters` instance.
40    pub fn opening_key(&self) -> &OpeningKey {
41        &self.opening_key
42    }
43
44    /// Setup generates the public parameters using a random number generator.
45    /// This method will in most cases be used for testing and exploration.
46    /// In reality, a `Trusted party` or a `Multiparty Computation` will be used
47    /// to generate the SRS. Returns an error if the configured degree is less
48    /// than one.
49    pub fn setup(
50        max_degree: usize,
51        mut rng: impl RngCore,
52    ) -> Result<PublicParameters, Error> {
53        // Cannot commit to constants
54        if max_degree < 1 {
55            return Err(Error::DegreeIsZero);
56        }
57
58        // Generate the secret scalar beta
59        let beta = util::random_scalar(&mut rng);
60
61        // Compute powers of beta up to and including beta^max_degree
62        let powers_of_beta = util::powers_of(&beta, max_degree);
63
64        // Powers of G1 that will be used to commit to a specified polynomial
65        let g = util::random_g1_point(&mut rng);
66        let powers_of_g: Vec<G1Projective> =
67            util::slow_multiscalar_mul_single_base(&powers_of_beta, g);
68        assert_eq!(powers_of_g.len(), max_degree + 1);
69
70        // Normalise all projective points
71        let mut normalised_g = vec![G1Affine::identity(); max_degree + 1];
72        G1Projective::batch_normalize(&powers_of_g, &mut normalised_g);
73
74        // Compute beta*G2 element and stored cached elements for verifying
75        // multiple proofs.
76        let h: G2Affine = util::random_g2_point(&mut rng).into();
77        let beta_h: G2Affine = (h * beta).into();
78
79        Ok(PublicParameters {
80            commit_key: CommitKey {
81                powers_of_g: normalised_g,
82            },
83            opening_key: OpeningKey::new(g.into(), h, beta_h),
84        })
85    }
86
87    /// Serialize the [`PublicParameters`] into bytes.
88    ///
89    /// This operation is designed to store the raw representation of the
90    /// contents of the PublicParameters. Therefore, the size of the bytes
91    /// outputed by this function is expected to be the double than the one
92    /// that [`PublicParameters::to_var_bytes`].
93    ///
94    /// # Note
95    /// This function should be used when we want to serialize the
96    /// PublicParameters allowing a really fast deserialization later.
97    /// This functions output should not be used by the regular
98    /// [`PublicParameters::from_slice`] fn.
99    pub fn to_raw_var_bytes(&self) -> Vec<u8> {
100        let mut bytes = self.opening_key.to_bytes().to_vec();
101        bytes.extend(&self.commit_key.to_raw_var_bytes());
102
103        bytes
104    }
105
106    /// Deserialize [`PublicParameters`] from a set of bytes created by
107    /// [`PublicParameters::to_raw_var_bytes`].
108    ///
109    /// The bytes source is expected to be trusted and no checks will be
110    /// performed reggarding the content of the points that the bytes
111    /// contain serialized.
112    ///
113    /// # Safety
114    /// This function will not produce any memory errors but can deal to the
115    /// generation of invalid or unsafe points/keys. To make sure this does not
116    /// happen, the inputed bytes must match the ones that were generated by
117    /// the encoding functions of this lib.
118    pub unsafe fn from_slice_unchecked(bytes: &[u8]) -> Self {
119        let opening_key = &bytes[..OpeningKey::SIZE];
120        let opening_key = OpeningKey::from_slice(opening_key)
121            .expect("Error at OpeningKey deserialization");
122
123        let commit_key = &bytes[OpeningKey::SIZE..];
124        let commit_key = CommitKey::from_slice_unchecked(commit_key);
125
126        Self {
127            commit_key,
128            opening_key,
129        }
130    }
131
132    /// Serialises a [`PublicParameters`] struct into a slice of bytes.
133    pub fn to_var_bytes(&self) -> Vec<u8> {
134        let mut bytes = self.opening_key.to_bytes().to_vec();
135        bytes.extend(self.commit_key.to_var_bytes().iter());
136        bytes
137    }
138
139    /// Deserialise a slice of bytes into a Public Parameter struct performing
140    /// security and consistency checks for each point that the bytes
141    /// contain.
142    ///
143    /// # Note
144    /// This function can be really slow if the [`PublicParameters`] have a
145    /// certain degree. If the bytes come from a trusted source such as a
146    /// local file, we recommend to use
147    /// [`PublicParameters::from_slice_unchecked`] and
148    /// [`PublicParameters::to_raw_var_bytes`].
149    pub fn from_slice(bytes: &[u8]) -> Result<PublicParameters, Error> {
150        if bytes.len() <= OpeningKey::SIZE {
151            return Err(Error::NotEnoughBytes);
152        }
153        let mut buf = bytes;
154        let opening_key = OpeningKey::from_reader(&mut buf)?;
155        let commit_key = CommitKey::from_slice(buf)?;
156
157        let pp = PublicParameters {
158            commit_key,
159            opening_key,
160        };
161
162        Ok(pp)
163    }
164
165    /// Trim truncates the [`PublicParameters`] to allow the prover to commit to
166    /// polynomials up to the and including the truncated degree.
167    /// Returns the [`CommitKey`] and [`OpeningKey`] used to generate and verify
168    /// proofs.
169    ///
170    /// Returns an error if the truncated degree is larger than the public
171    /// parameters configured degree.
172    pub fn trim(
173        &self,
174        truncated_degree: usize,
175    ) -> Result<(CommitKey, OpeningKey), Error> {
176        let truncated_prover_key =
177            self.commit_key.truncate(truncated_degree)?;
178        let opening_key = self.opening_key.clone();
179        Ok((truncated_prover_key, opening_key))
180    }
181
182    /// Max degree specifies the largest Polynomial
183    /// that this prover key can commit to.
184    pub fn max_degree(&self) -> usize {
185        self.commit_key.max_degree()
186    }
187}
188
189#[cfg(feature = "std")]
190#[cfg(test)]
191mod test {
192    use super::*;
193    use dusk_bls12_381::BlsScalar;
194    use rand_core::OsRng;
195
196    #[test]
197    fn test_powers_of() {
198        let x = BlsScalar::from(10u64);
199        let degree = 100u64;
200
201        let powers_of_x = util::powers_of(&x, degree as usize);
202
203        for (i, x_i) in powers_of_x.iter().enumerate() {
204            assert_eq!(*x_i, x.pow(&[i as u64, 0, 0, 0]))
205        }
206
207        let last_element = powers_of_x.last().unwrap();
208        assert_eq!(*last_element, x.pow(&[degree, 0, 0, 0]))
209    }
210
211    #[test]
212    fn test_serialise_deserialise_public_parameter() {
213        let pp = PublicParameters::setup(1 << 7, &mut OsRng).unwrap();
214
215        let got_pp = PublicParameters::from_slice(&pp.to_var_bytes()).unwrap();
216
217        assert_eq!(got_pp.commit_key.powers_of_g, pp.commit_key.powers_of_g);
218        assert_eq!(got_pp.opening_key.g, pp.opening_key.g);
219        assert_eq!(got_pp.opening_key.h, pp.opening_key.h);
220        assert_eq!(got_pp.opening_key.beta_h, pp.opening_key.beta_h);
221    }
222
223    #[test]
224    fn public_parameters_bytes_unchecked() {
225        let pp = PublicParameters::setup(1 << 7, &mut OsRng).unwrap();
226
227        let pp_p = unsafe {
228            let bytes = pp.to_raw_var_bytes();
229            PublicParameters::from_slice_unchecked(&bytes)
230        };
231
232        assert_eq!(pp.commit_key, pp_p.commit_key);
233        assert_eq!(pp.opening_key.g, pp_p.opening_key.g);
234        assert_eq!(pp.opening_key.h, pp_p.opening_key.h);
235        assert_eq!(pp.opening_key.beta_h, pp_p.opening_key.beta_h);
236    }
237}