snarkvm_synthesizer_snark/
lib.rs

1// Copyright 2024 Aleo Network Foundation
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#![forbid(unsafe_code)]
17#![allow(clippy::too_many_arguments)]
18#![warn(clippy::cast_possible_truncation)]
19#![cfg_attr(not(feature = "aleo-cli"), allow(unused_variables))]
20
21use console::network::{FiatShamir, prelude::*};
22use snarkvm_algorithms::{snark::varuna, traits::SNARK};
23
24use once_cell::sync::OnceCell;
25use std::sync::Arc;
26
27#[cfg(feature = "aleo-cli")]
28use colored::Colorize;
29
30type Varuna<N> = varuna::VarunaSNARK<<N as Environment>::PairingCurve, FiatShamir<N>, varuna::VarunaHidingMode>;
31
32mod certificate;
33pub use certificate::Certificate;
34
35mod proof;
36pub use proof::Proof;
37
38mod proving_key;
39pub use proving_key::ProvingKey;
40
41mod universal_srs;
42pub use universal_srs::UniversalSRS;
43
44mod verifying_key;
45pub use verifying_key::VerifyingKey;
46
47#[cfg(test)]
48pub(crate) mod test_helpers {
49    use super::*;
50    use circuit::{
51        environment::{Assignment, Circuit, Eject, Environment, Inject, Mode, One},
52        types::Field,
53    };
54    use console::{network::MainnetV0, prelude::One as _};
55    use snarkvm_algorithms::snark::varuna::VarunaVersion;
56
57    use once_cell::sync::OnceCell;
58
59    type CurrentNetwork = MainnetV0;
60
61    /// Compute 2^EXPONENT - 1, in a purposefully constraint-inefficient manner for testing.
62    fn create_example_circuit<E: Environment>() -> Field<E> {
63        let one = console::types::Field::<E::Network>::one();
64        let two = one + one;
65
66        const EXPONENT: u64 = 64;
67
68        // Compute 2^EXPONENT - 1, in a purposefully constraint-inefficient manner for testing.
69        let mut candidate = Field::<E>::new(Mode::Public, one);
70        let mut accumulator = Field::new(Mode::Private, two);
71        for _ in 0..EXPONENT {
72            candidate += &accumulator;
73            accumulator *= Field::new(Mode::Private, two);
74        }
75
76        assert_eq!((accumulator - Field::one()).eject_value(), candidate.eject_value());
77        assert_eq!(2, E::num_public());
78        assert_eq!(2 * EXPONENT + 1, E::num_private());
79        assert_eq!(EXPONENT, E::num_constraints());
80        assert!(E::is_satisfied());
81
82        candidate
83    }
84
85    /// Returns a sample assignment for the example circuit.
86    pub(crate) fn sample_assignment() -> Assignment<<Circuit as Environment>::BaseField> {
87        static INSTANCE: OnceCell<Assignment<<Circuit as Environment>::BaseField>> = OnceCell::new();
88        INSTANCE
89            .get_or_init(|| {
90                let _candidate_output = create_example_circuit::<Circuit>();
91                let assignment = Circuit::eject_assignment_and_reset();
92                assert_eq!(0, Circuit::num_constants());
93                assert_eq!(1, Circuit::num_public());
94                assert_eq!(0, Circuit::num_private());
95                assert_eq!(0, Circuit::num_constraints());
96                assignment
97            })
98            .clone()
99    }
100
101    /// Returns the sample circuit keys for the example circuit.
102    pub(crate) fn sample_keys() -> (ProvingKey<CurrentNetwork>, VerifyingKey<CurrentNetwork>) {
103        static INSTANCE: OnceCell<(ProvingKey<CurrentNetwork>, VerifyingKey<CurrentNetwork>)> = OnceCell::new();
104        INSTANCE
105            .get_or_init(|| {
106                let assignment = sample_assignment();
107                let srs = UniversalSRS::load().unwrap();
108                let (proving_key, verifying_key) = srs.to_circuit_key("test", &assignment).unwrap();
109                (proving_key, verifying_key)
110            })
111            .clone()
112    }
113
114    /// Returns a sample proof for the example circuit.
115    pub(crate) fn sample_proof() -> Proof<CurrentNetwork> {
116        static INSTANCE: OnceCell<Proof<CurrentNetwork>> = OnceCell::new();
117        INSTANCE
118            .get_or_init(|| {
119                let assignment = sample_assignment();
120                let (proving_key, _) = sample_keys();
121                proving_key.prove("test", VarunaVersion::V2, &assignment, &mut TestRng::default()).unwrap()
122            })
123            .clone()
124    }
125
126    /// Returns a sample certificate for the example circuit.
127    pub(super) fn sample_certificate() -> Certificate<CurrentNetwork> {
128        static INSTANCE: OnceCell<Certificate<CurrentNetwork>> = OnceCell::new();
129        INSTANCE
130            .get_or_init(|| {
131                let (proving_key, verifying_key) = sample_keys();
132                // Return the certificate.
133                Certificate::certify("test", &proving_key, &verifying_key).unwrap()
134            })
135            .clone()
136    }
137}
138
139#[cfg(test)]
140mod test {
141    use super::*;
142    use circuit::environment::{Circuit, Environment};
143    use console::network::MainnetV0;
144    use snarkvm_algorithms::snark::varuna::VarunaVersion;
145
146    type CurrentNetwork = MainnetV0;
147
148    #[test]
149    fn test_varuna() {
150        let assignment = crate::test_helpers::sample_assignment();
151
152        // Varuna setup, prove, and verify.
153        let srs = UniversalSRS::<CurrentNetwork>::load().unwrap();
154        let (proving_key, verifying_key) = srs.to_circuit_key("test", &assignment).unwrap();
155        let varuna_version = VarunaVersion::V2;
156        println!("Called circuit setup");
157
158        let proof = proving_key.prove("test", varuna_version, &assignment, &mut TestRng::default()).unwrap();
159        println!("Called prover");
160
161        let one = <Circuit as Environment>::BaseField::one();
162        assert!(verifying_key.verify("test", varuna_version, &[one, one], &proof));
163        println!("Called verifier");
164        println!("\nShould not verify (i.e. verifier messages should print below):");
165        assert!(!verifying_key.verify("test", varuna_version, &[one, one + one], &proof));
166        assert!(!verifying_key.verify("test", VarunaVersion::V1, &[one, one], &proof));
167    }
168
169    #[test]
170    fn test_varuna_verify_public_input_size() {
171        /// Creates a simple circuit: a * b.
172        fn create_assignment() -> circuit::Assignment<<CurrentNetwork as console::prelude::Environment>::Field> {
173            use circuit::{Inject, environment::Mode, types::Field};
174
175            // Ensure the circuit environment is clean.
176            Circuit::reset();
177
178            // Inject a field element.
179            let console_field = console::types::Field::<CurrentNetwork>::one();
180            let circuit_field_0 = Field::<Circuit>::new(Mode::Private, console_field);
181
182            // Inject another field element.
183            let console_field = console_field.double();
184            let circuit_field_1 = Field::<Circuit>::new(Mode::Private, console_field);
185
186            // Multiply the two field elements.
187            let _circuit_field_2 = circuit_field_0 * circuit_field_1;
188
189            // Eject the assignment.
190            Circuit::eject_assignment_and_reset()
191        }
192
193        let assignment = create_assignment();
194        assert_eq!(assignment.num_public(), 1);
195        assert_eq!(assignment.num_private(), 3);
196
197        let srs = UniversalSRS::<CurrentNetwork>::load().unwrap();
198        let (proving_key, verifying_key) = srs.to_circuit_key("test", &assignment).unwrap();
199        let varuna_version = VarunaVersion::V2;
200        println!("Called circuit setup");
201
202        let proof = proving_key.prove("test", varuna_version, &assignment, &mut TestRng::default()).unwrap();
203        println!("Called prover");
204
205        // Should pass.
206        let one = <Circuit as Environment>::BaseField::one();
207        assert!(verifying_key.verify("test", varuna_version, &[one], &proof));
208
209        // Should fail.
210        assert!(!verifying_key.verify("test", VarunaVersion::V1, &[one], &proof));
211        assert!(!verifying_key.verify("test", varuna_version, &[one, one], &proof));
212        assert!(!verifying_key.verify("test", varuna_version, &[one, one + one], &proof));
213        assert!(!verifying_key.verify("test", varuna_version, &[one, one, one], &proof));
214        assert!(!verifying_key.verify("test", varuna_version, &[one, one, one + one], &proof));
215        assert!(!verifying_key.verify("test", varuna_version, &[one, one, one, one], &proof));
216
217        println!("Called verifier");
218    }
219}