fullcodec_plonk/
circuit.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//! Tools & traits for PLONK circuits
8
9use crate::commitment_scheme::PublicParameters;
10use crate::constraint_system::TurboComposer;
11use crate::error::Error;
12use crate::proof_system::{Proof, Prover, ProverKey, Verifier, VerifierKey};
13#[cfg(feature = "canon")]
14use canonical_derive::Canon;
15use dusk_bls12_381::BlsScalar;
16use dusk_bytes::{DeserializableSlice, Serializable, Write};
17use dusk_jubjub::{JubJubAffine, JubJubExtended, JubJubScalar};
18use parity_scale_codec::{Decode, Encode};
19use sp_std::vec;
20use sp_std::vec::Vec;
21
22#[derive(Default, Debug, Clone, PartialEq, Decode, Encode)]
23#[cfg_attr(feature = "canon", derive(Canon))]
24/// Structure that represents a PLONK Circuit Public Input converted into it's
25/// &\[[`BlsScalar`]\] repr.
26pub struct PublicInputValue(pub(crate) Vec<BlsScalar>);
27
28impl From<BlsScalar> for PublicInputValue {
29    fn from(scalar: BlsScalar) -> Self {
30        Self(vec![scalar])
31    }
32}
33
34impl From<JubJubScalar> for PublicInputValue {
35    fn from(scalar: JubJubScalar) -> Self {
36        Self(vec![scalar.into()])
37    }
38}
39
40impl From<JubJubAffine> for PublicInputValue {
41    fn from(point: JubJubAffine) -> Self {
42        Self(vec![point.get_x(), point.get_y()])
43    }
44}
45
46impl From<JubJubExtended> for PublicInputValue {
47    fn from(point: JubJubExtended) -> Self {
48        JubJubAffine::from(point).into()
49    }
50}
51
52#[derive(Debug, Clone, PartialEq, Decode, Encode)]
53/// Collection of structs/objects that the Verifier will use in order to
54/// de/serialize data needed for Circuit proof verification.
55/// This structure can be seen as a link between the [`Circuit`] public input
56/// positions and the [`VerifierKey`] that the Verifier needs to use.
57pub struct VerifierData {
58    key: VerifierKey,
59    public_inputs_indexes: Vec<u32>,
60}
61
62impl VerifierData {
63    /// Creates a new `VerifierData` from a [`VerifierKey`] and the public
64    /// input positions of the circuit that it represents.
65    pub const fn new(
66        key: VerifierKey,
67        public_inputs_indexes: Vec<u32>,
68    ) -> Self {
69        Self {
70            key,
71            public_inputs_indexes,
72        }
73    }
74
75    /// Returns a reference to the contained [`VerifierKey`].
76    pub const fn key(&self) -> &VerifierKey {
77        &self.key
78    }
79
80    /// Returns a reference to the contained Public Input positions.
81    pub fn public_inputs_indexes(&self) -> &[u32] {
82        &self.public_inputs_indexes
83    }
84
85    /// Deserializes the `VerifierData` into a vector of bytes.
86    #[allow(unused_must_use)]
87    pub fn to_var_bytes(&self) -> Vec<u8> {
88        let mut buff = vec![
89            0u8;
90            VerifierKey::SIZE
91                + u32::SIZE
92                + self.public_inputs_indexes.len() * u32::SIZE
93        ];
94        let mut writer = &mut buff[..];
95
96        writer.write(&self.key.to_bytes());
97        writer.write(&(self.public_inputs_indexes.len() as u32).to_bytes());
98        self.public_inputs_indexes.iter().copied().for_each(|pos| {
99            // Omit the result since disk_bytes write can't fail here
100            // due to the fact that we're writing into a vector basically.
101            let _ = writer.write(&(pos as u32).to_bytes());
102        });
103
104        buff
105    }
106
107    /// Serializes `VerifierData` from a slice of bytes.
108    pub fn from_slice(mut buf: &[u8]) -> Result<Self, Error> {
109        let key = VerifierKey::from_reader(&mut buf)?;
110        let pos_num = u32::from_reader(&mut buf)? as usize;
111
112        let mut public_inputs_indexes = vec![];
113        for _ in 0..pos_num {
114            public_inputs_indexes.push(u32::from_reader(&mut buf)?);
115        }
116
117        Ok(Self {
118            key,
119            public_inputs_indexes,
120        })
121    }
122}
123
124/// Trait that should be implemented for any circuit function to provide to it
125/// the capabilities of automatically being able to generate, and verify proofs
126/// as well as compile the circuit.
127/// # Example
128///
129/// ```
130/// use fullcodec_plonk::prelude::*;
131/// use rand::SeedableRng;
132/// use rand_xorshift::XorShiftRng;
133///
134/// fn main() -> Result<(), Error> {
135/// // Implements a circuit that checks:
136/// // 1) a + b = c where C is a PI
137/// // 2) a <= 2^6
138/// // 3) b <= 2^5
139/// // 4) a * b = d where D is a PI
140/// // 5) JubJub::GENERATOR * e(JubJubScalar) = f where F is a PI
141/// #[derive(Debug, Default)]
142/// pub struct TestCircuit {
143///     a: BlsScalar,
144///     b: BlsScalar,
145///     c: BlsScalar,
146///     d: BlsScalar,
147///     e: JubJubScalar,
148///     f: JubJubAffine,
149/// }
150///
151/// impl Circuit for TestCircuit {
152///     const CIRCUIT_ID: [u8; 32] = [0xff; 32];
153///     fn gadget(
154///         &mut self,
155///         composer: &mut TurboComposer,
156///     ) -> Result<(), Error> {
157///         // Add fixed witness zero
158///         let zero = TurboComposer::constant_zero();
159///         let a = composer.append_witness(self.a);
160///         let b = composer.append_witness(self.b);
161///
162///         // Make first constraint a + b = c
163///         let constraint = Constraint::new()
164///             .left(1)
165///             .right(1)
166///             .public(-self.c)
167///             .a(a)
168///             .b(b);
169///
170///         composer.append_gate(constraint);
171///
172///         // Check that a and b are in range
173///         composer.component_range(a, 1 << 6);
174///         composer.component_range(b, 1 << 5);
175///
176///         // Make second constraint a * b = d
177///         let constraint = Constraint::new()
178///             .mult(1)
179///             .output(1)
180///             .public(-self.d)
181///             .a(a)
182///             .b(b);
183///
184///         composer.append_gate(constraint);
185///
186///         let e = composer.append_witness(self.e);
187///         let scalar_mul_result =
188///             composer.component_mul_generator(
189///                 e, dusk_jubjub::GENERATOR_EXTENDED,
190///             );
191///         // Apply the constrain
192///         composer
193///             .assert_equal_public_point(scalar_mul_result, self.f);
194///         Ok(())
195///     }
196///
197///     fn public_inputs(&self) -> Vec<PublicInputValue> {
198///         vec![self.c.into(), self.d.into(), self.f.into()]
199///     }
200///
201///     fn padded_gates(&self) -> usize {
202///         1 << 11
203///     }
204/// }
205///
206/// let rng = XorShiftRng::from_seed([
207/// 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37,
208/// 0x32, 0x54, 0x06, 0xbc, 0xe5,
209/// ]);
210///
211/// let pp = PublicParameters::setup(1 << 12, rng)?;
212/// // Initialize the circuit
213/// let mut circuit = TestCircuit::default();
214/// // Compile the circuit
215/// let (pk, vd) = circuit.compile(&pp)?;
216///
217/// // Prover POV
218/// let proof = {
219///     let mut circuit = TestCircuit {
220///         a: BlsScalar::from(20u64),
221///         b: BlsScalar::from(5u64),
222///         c: BlsScalar::from(25u64),
223///         d: BlsScalar::from(100u64),
224///         e: JubJubScalar::from(2u64),
225///         f: JubJubAffine::from(
226///             dusk_jubjub::GENERATOR_EXTENDED * JubJubScalar::from(2u64),
227///         ),
228///     };
229///
230///     circuit.prove(&pp, &pk, b"Test")
231/// }?;
232///
233/// // Verifier POV
234/// let public_inputs: Vec<PublicInputValue> = vec![
235///     BlsScalar::from(25u64).into(),
236///     BlsScalar::from(100u64).into(),
237///     JubJubAffine::from(
238///         dusk_jubjub::GENERATOR_EXTENDED * JubJubScalar::from(2u64),
239///     )
240///     .into(),
241/// ];
242///
243/// TestCircuit::verify(
244///     &pp,
245///     &vd,
246///     &proof,
247///     &public_inputs,
248///     b"Test",
249/// )
250/// }
251pub trait Circuit
252where
253    Self: Sized,
254{
255    /// Circuit identifier associated constant.
256    const CIRCUIT_ID: [u8; 32];
257
258    /// Gadget implementation used to fill the composer.
259    fn gadget(&mut self, composer: &mut TurboComposer) -> Result<(), Error>;
260
261    /// Compiles the circuit by using a function that returns a `Result`
262    /// with the `ProverKey`, `VerifierKey` and the circuit size.
263    fn compile(
264        &mut self,
265        pub_params: &PublicParameters,
266    ) -> Result<(ProverKey, VerifierData), Error> {
267        // Setup PublicParams
268        let (ck, _) = pub_params.trim(self.padded_gates())?;
269
270        // Generate & save `ProverKey` with some random values.
271        let mut prover = Prover::new(b"CircuitCompilation");
272
273        self.gadget(prover.composer_mut())?;
274
275        let public_inputs_indexes =
276            prover.composer_mut().public_input_indexes();
277
278        prover.preprocess(&ck)?;
279
280        // Generate & save `VerifierKey` with some random values.
281        let mut verifier = Verifier::new(b"CircuitCompilation");
282
283        self.gadget(verifier.composer_mut())?;
284
285        verifier.preprocess(&ck)?;
286
287        Ok((
288            prover
289                .prover_key
290                .expect("Unexpected error. Missing ProverKey in compilation"),
291            VerifierData::new(
292                verifier.verifier_key.expect(
293                    "Unexpected error. Missing VerifierKey in compilation",
294                ),
295                public_inputs_indexes,
296            ),
297        ))
298    }
299
300    /// Generates a proof using the provided `CircuitInputs` & `ProverKey`
301    /// instances.
302    fn prove(
303        &mut self,
304        pub_params: &PublicParameters,
305        prover_key: &ProverKey,
306        transcript_init: &'static [u8],
307    ) -> Result<Proof, Error> {
308        let (ck, _) = pub_params.trim(self.padded_gates())?;
309
310        // New Prover instance
311        let mut prover = Prover::new(transcript_init);
312
313        // Fill witnesses for Prover
314        self.gadget(prover.composer_mut())?;
315
316        // Add ProverKey to Prover
317        prover.prover_key = Some(prover_key.clone());
318        prover.prove(&ck)
319    }
320
321    /// Verify the provided proof for the compiled verifier data
322    fn verify(
323        pub_params: &PublicParameters,
324        verifier_data: &VerifierData,
325        proof: &Proof,
326        public_inputs: &[PublicInputValue],
327        transcript_init: &'static [u8],
328    ) -> Result<(), Error> {
329        let gates = verifier_data.key().padded_gates();
330        let pi_indexes = verifier_data.public_inputs_indexes();
331
332        let mut dense_pi = vec![BlsScalar::zero(); gates as usize];
333
334        public_inputs
335            .iter()
336            .map(|pi| pi.0.clone())
337            .flatten()
338            .zip(pi_indexes.iter().cloned())
339            .for_each(|(value, pos)| {
340                dense_pi[pos as usize] = -value;
341            });
342
343        let mut verifier = Verifier::new(transcript_init);
344
345        verifier.verifier_key.replace(*verifier_data.key());
346
347        let opening_key = pub_params.opening_key();
348
349        verifier.verify(proof, opening_key, &dense_pi)
350    }
351
352    /// Return the list of public inputs generated by the gadget
353    fn public_inputs(&self) -> Vec<PublicInputValue>;
354
355    /// Returns the Circuit size padded to the next power of two.
356    fn padded_gates(&self) -> usize;
357}