liminal_ark_relations/
environment.rs

1use ark_std::vec::Vec;
2#[cfg(feature = "circuit")]
3use {
4    ark_poly::univariate::DensePolynomial,
5    ark_poly_commit::marlin_pc::MarlinKZG10,
6    ark_relations::r1cs::ConstraintSynthesizer,
7    ark_serialize::{CanonicalDeserialize, CanonicalSerialize},
8    ark_snark::SNARK,
9    ark_std::rand::{rngs::StdRng, SeedableRng},
10    blake2::Blake2s,
11};
12
13// For now, we can settle with these types.
14/// Common pairing engine.
15pub type PairingEngine = ark_bls12_381::Bls12_381;
16/// Common scalar field.
17pub type CircuitField = ark_bls12_381::Fr;
18#[cfg(feature = "circuit")]
19/// Variable in the Fr field
20pub type FpVar = ark_r1cs_std::fields::fp::FpVar<CircuitField>;
21
22// Systems with hardcoded parameters.
23#[cfg(feature = "circuit")]
24pub type Groth16 = ark_groth16::Groth16<PairingEngine>;
25#[cfg(feature = "circuit")]
26pub type GM17 = ark_gm17::GM17<PairingEngine>;
27#[cfg(feature = "circuit")]
28pub type MarlinPolynomialCommitment = MarlinKZG10<PairingEngine, DensePolynomial<CircuitField>>;
29#[cfg(feature = "circuit")]
30pub type Marlin = ark_marlin::Marlin<CircuitField, MarlinPolynomialCommitment, Blake2s>;
31
32/// Serialized keys.
33pub struct RawKeys {
34    pub pk: Vec<u8>,
35    pub vk: Vec<u8>,
36}
37
38#[cfg(feature = "circuit")]
39pub enum Error {
40    UniversalSystemVerificationError,
41    NonUniversalSystemVerificationError,
42}
43
44/// Common API for every proving system.
45#[cfg(feature = "circuit")]
46pub trait ProvingSystem {
47    type Proof: CanonicalSerialize + CanonicalDeserialize;
48    type ProvingKey: CanonicalSerialize + CanonicalDeserialize;
49    type VerifyingKey: CanonicalSerialize + CanonicalDeserialize;
50
51    /// Generates proof for `circuit` using proving key `pk`
52    fn prove<C: ConstraintSynthesizer<CircuitField>>(
53        pk: &Self::ProvingKey,
54        circuit: C,
55    ) -> Self::Proof;
56
57    // parametrize over Proving System
58    fn verify(
59        vk: &Self::VerifyingKey,
60        proof: &Self::Proof,
61        public_input: Vec<CircuitField>,
62    ) -> Result<bool, Error>;
63}
64
65/// Common API for every universal proving system.
66#[cfg(feature = "circuit")]
67pub trait UniversalSystem: ProvingSystem {
68    type Srs: CanonicalSerialize + CanonicalDeserialize;
69
70    /// Generates SRS.
71    fn generate_srs(num_constraints: usize, num_variables: usize, degree: usize) -> Self::Srs;
72
73    /// Generates proving and verifying key for `circuit` using `srs`.
74    fn generate_keys<C: ConstraintSynthesizer<CircuitField>>(
75        circuit: C,
76        srs: &Self::Srs,
77    ) -> (Self::ProvingKey, Self::VerifyingKey);
78}
79
80/// Common API for every non universal proving system.
81#[cfg(feature = "circuit")]
82pub trait NonUniversalSystem: ProvingSystem {
83    /// Generates proving and verifying key for `circuit`.
84    fn generate_keys<C: ConstraintSynthesizer<CircuitField>>(
85        circuit: C,
86    ) -> (Self::ProvingKey, Self::VerifyingKey);
87}
88
89#[cfg(feature = "circuit")]
90fn dummy_rng() -> StdRng {
91    StdRng::from_seed([0u8; 32])
92}
93
94// Unfortunately, Groth16, GM17 and Marlin don't have any common supertrait, and therefore,
95// we cannot provide any blanket implementation without running into damned `upstream crates may
96// add a new impl of trait` error (see https://github.com/rust-lang/rfcs/issues/2758).
97// Tfu. Disgusting.
98
99/// This macro takes a type `system` as the only argument and provides `ProvingSystem` and
100/// `NonUniversalSystem` implementations for it.
101///
102/// `system` should implement `SNARK<CircuitField>` trait.  
103#[cfg(feature = "circuit")]
104macro_rules! impl_non_universal_system_for_snark {
105    ($system:ty) => {
106        impl ProvingSystem for $system {
107            type Proof = <$system as SNARK<CircuitField>>::Proof;
108            type ProvingKey = <$system as SNARK<CircuitField>>::ProvingKey;
109            type VerifyingKey = <$system as SNARK<CircuitField>>::VerifyingKey;
110
111            fn prove<C: ConstraintSynthesizer<CircuitField>>(
112                pk: &Self::ProvingKey,
113                circuit: C,
114            ) -> Self::Proof {
115                let mut rng = dummy_rng();
116                <$system as SNARK<CircuitField>>::prove(pk, circuit, &mut rng)
117                    .expect("Failed to generate proof")
118            }
119
120            fn verify(
121                vk: &Self::VerifyingKey,
122                proof: &Self::Proof,
123                public_input: Vec<CircuitField>,
124            ) -> Result<bool, Error> {
125                <$system as SNARK<CircuitField>>::verify(vk, &*public_input, proof)
126                    .map_err(|_why| Error::NonUniversalSystemVerificationError)
127            }
128        }
129
130        impl NonUniversalSystem for $system {
131            fn generate_keys<C: ConstraintSynthesizer<CircuitField>>(
132                circuit: C,
133            ) -> (Self::ProvingKey, Self::VerifyingKey) {
134                let mut rng = dummy_rng();
135                <$system as SNARK<CircuitField>>::circuit_specific_setup(circuit, &mut rng)
136                    .expect("Failed to generate keys")
137            }
138        }
139    };
140}
141
142#[cfg(feature = "circuit")]
143impl_non_universal_system_for_snark!(Groth16);
144#[cfg(feature = "circuit")]
145impl_non_universal_system_for_snark!(GM17);
146
147#[cfg(feature = "circuit")]
148impl ProvingSystem for Marlin {
149    type Proof = ark_marlin::Proof<CircuitField, MarlinPolynomialCommitment>;
150    type ProvingKey = ark_marlin::IndexProverKey<CircuitField, MarlinPolynomialCommitment>;
151    type VerifyingKey = ark_marlin::IndexVerifierKey<CircuitField, MarlinPolynomialCommitment>;
152
153    fn prove<C: ConstraintSynthesizer<CircuitField>>(
154        pk: &Self::ProvingKey,
155        circuit: C,
156    ) -> Self::Proof {
157        let mut rng = dummy_rng();
158        Marlin::prove(pk, circuit, &mut rng).expect("Failed to generate proof")
159    }
160
161    fn verify(
162        vk: &Self::VerifyingKey,
163        proof: &Self::Proof,
164        public_input: Vec<CircuitField>,
165    ) -> Result<bool, Error> {
166        let mut rng = dummy_rng();
167        Marlin::verify(vk, public_input.as_slice(), proof, &mut rng)
168            .map_err(|_why| Error::UniversalSystemVerificationError)
169    }
170}
171
172#[cfg(feature = "circuit")]
173impl UniversalSystem for Marlin {
174    type Srs = ark_marlin::UniversalSRS<CircuitField, MarlinPolynomialCommitment>;
175
176    fn generate_srs(num_constraints: usize, num_variables: usize, degree: usize) -> Self::Srs {
177        let mut rng = dummy_rng();
178        Marlin::universal_setup(num_constraints, num_variables, degree, &mut rng)
179            .expect("Failed to generate SRS")
180    }
181
182    fn generate_keys<C: ConstraintSynthesizer<CircuitField>>(
183        circuit: C,
184        srs: &Self::Srs,
185    ) -> (Self::ProvingKey, Self::VerifyingKey) {
186        Marlin::index(srs, circuit).expect(
187            "Failed to generate keys from SRS (it might be the case, that the circuit is \
188                larger than the SRS allows).",
189        )
190    }
191}