penumbra_sdk_proof_params/
lib.rs

1#![deny(clippy::unwrap_used)]
2#![allow(clippy::redundant_static_lifetimes)]
3// Requires nightly.
4#![cfg_attr(docsrs, feature(doc_auto_cfg))]
5
6use anyhow::{bail, Result};
7use ark_groth16::{PreparedVerifyingKey, ProvingKey, VerifyingKey};
8use ark_serialize::CanonicalDeserialize;
9use decaf377::Bls12_377;
10use once_cell::sync::{Lazy, OnceCell};
11use std::ops::Deref;
12
13/// The length of our Groth16 proofs in bytes.
14pub const GROTH16_PROOF_LENGTH_BYTES: usize = 192;
15
16mod traits;
17
18pub use traits::{
19    generate_constraint_matrices, generate_prepared_test_parameters, generate_test_parameters,
20    DummyWitness, ProvingKeyExt, VerifyingKeyExt,
21};
22
23/// A wrapper around a proving key that can be lazily loaded.
24///
25/// One instance of this struct is created for each proving key.
26///
27/// The behavior of those instances is controlled by the `bundled-proving-keys`
28/// feature. When the feature is enabled, the proving key data is bundled into
29/// the binary at compile time, and the proving key is loaded from the bundled
30/// data on first use.  When the feature is not enabled, the proving key must be
31/// loaded using `try_load` prior to its first use.
32///
33/// The `bundled-proving-keys` feature needs access to proving keys at build
34/// time.  When pulling the crate as a dependency, these may not be available.
35/// To address this, the `download-proving-keys` feature will download them from
36/// the network at build time. All proving keys are checked against hardcoded hashes
37/// to ensure they have not been tampered with.
38#[derive(Debug, Default)]
39pub struct LazyProvingKey {
40    pk_id: &'static str,
41    inner: OnceCell<ProvingKey<Bls12_377>>,
42}
43
44impl LazyProvingKey {
45    // Not making this pub means only the statically defined proving keys can exist.
46    fn new(pk_id: &'static str) -> Self {
47        LazyProvingKey {
48            pk_id,
49            inner: OnceCell::new(),
50        }
51    }
52
53    /// Attempt to load the proving key from the given bytes.
54    ///
55    /// The provided bytes are validated against a hardcoded hash of the expected proving key,
56    /// so passing the wrong proving key will fail.
57    ///
58    /// If the proving key is already loaded, this method is a no-op.
59    pub fn try_load(&self, bytes: &[u8]) -> Result<&ProvingKey<Bls12_377>> {
60        self.inner.get_or_try_init(|| {
61            let pk = ProvingKey::deserialize_uncompressed_unchecked(bytes)?;
62
63            let pk_id = pk.debug_id();
64            if pk_id != self.pk_id {
65                bail!(
66                    "proving key ID mismatch: expected {}, loaded {}",
67                    self.pk_id,
68                    pk_id
69                );
70            }
71
72            Ok(pk)
73        })
74    }
75
76    /// Attempt to load the proving key from the given bytes.
77    ///
78    /// This method bypasses the validation checks against the hardcoded
79    /// hash of the expected proving key.
80    pub fn try_load_unchecked(&self, bytes: &[u8]) -> Result<&ProvingKey<Bls12_377>> {
81        self.inner.get_or_try_init(|| {
82            let pk = ProvingKey::deserialize_uncompressed_unchecked(bytes)?;
83
84            Ok(pk)
85        })
86    }
87}
88
89impl Deref for LazyProvingKey {
90    type Target = ProvingKey<Bls12_377>;
91
92    fn deref(&self) -> &Self::Target {
93        self.inner.get().expect("Proving key cannot be loaded!")
94    }
95}
96
97// Note: Conditionally load the proving key objects if the
98// bundled-proving-keys is present.
99
100/// Proving key for the spend proof.
101pub static SPEND_PROOF_PROVING_KEY: Lazy<LazyProvingKey> = Lazy::new(|| {
102    let spend_proving_key = LazyProvingKey::new(spend::PROVING_KEY_ID);
103
104    #[cfg(feature = "bundled-proving-keys")]
105    spend_proving_key
106        .try_load(include_bytes!("gen/spend_pk.bin"))
107        .expect("bundled proving key is valid");
108
109    spend_proving_key
110});
111
112/// Verification key for the spend proof.
113pub static SPEND_PROOF_VERIFICATION_KEY: Lazy<PreparedVerifyingKey<Bls12_377>> =
114    Lazy::new(|| spend_verification_parameters().into());
115
116pub mod spend {
117    include!("gen/spend_id.rs");
118}
119
120/// Proving key for the output proof.
121pub static OUTPUT_PROOF_PROVING_KEY: Lazy<LazyProvingKey> = Lazy::new(|| {
122    let output_proving_key = LazyProvingKey::new(output::PROVING_KEY_ID);
123
124    #[cfg(feature = "bundled-proving-keys")]
125    output_proving_key
126        .try_load(include_bytes!("gen/output_pk.bin"))
127        .expect("bundled proving key is valid");
128
129    output_proving_key
130});
131
132/// Verification key for the output proof.
133pub static OUTPUT_PROOF_VERIFICATION_KEY: Lazy<PreparedVerifyingKey<Bls12_377>> =
134    Lazy::new(|| output_verification_parameters().into());
135
136pub mod output {
137    include!("gen/output_id.rs");
138}
139
140/// Proving key for the swap proof.
141pub static SWAP_PROOF_PROVING_KEY: Lazy<LazyProvingKey> = Lazy::new(|| {
142    let swap_proving_key = LazyProvingKey::new(swap::PROVING_KEY_ID);
143
144    #[cfg(feature = "bundled-proving-keys")]
145    swap_proving_key
146        .try_load(include_bytes!("gen/swap_pk.bin"))
147        .expect("bundled proving key is valid");
148
149    swap_proving_key
150});
151
152/// Verification key for the swap proof.
153pub static SWAP_PROOF_VERIFICATION_KEY: Lazy<PreparedVerifyingKey<Bls12_377>> =
154    Lazy::new(|| swap_verification_parameters().into());
155
156pub mod swap {
157    include!("gen/swap_id.rs");
158}
159
160/// Proving key for the swap claim proof.
161pub static SWAPCLAIM_PROOF_PROVING_KEY: Lazy<LazyProvingKey> = Lazy::new(|| {
162    let swapclaim_proving_key = LazyProvingKey::new(swapclaim::PROVING_KEY_ID);
163
164    #[cfg(feature = "bundled-proving-keys")]
165    swapclaim_proving_key
166        .try_load(include_bytes!("gen/swapclaim_pk.bin"))
167        .expect("bundled proving key is valid");
168
169    swapclaim_proving_key
170});
171
172/// Verification key for the swap claim proof.
173pub static SWAPCLAIM_PROOF_VERIFICATION_KEY: Lazy<PreparedVerifyingKey<Bls12_377>> =
174    Lazy::new(|| swapclaim_verification_parameters().into());
175
176pub mod swapclaim {
177    include!("gen/swapclaim_id.rs");
178}
179
180/// Proving key for the convert proof.
181pub static CONVERT_PROOF_PROVING_KEY: Lazy<LazyProvingKey> = Lazy::new(|| {
182    let convert_proving_key = LazyProvingKey::new(convert::PROVING_KEY_ID);
183
184    #[cfg(feature = "bundled-proving-keys")]
185    convert_proving_key
186        .try_load(include_bytes!("gen/convert_pk.bin"))
187        .expect("bundled proving key is valid");
188
189    convert_proving_key
190});
191
192/// Verification key for the convert proof.
193pub static CONVERT_PROOF_VERIFICATION_KEY: Lazy<PreparedVerifyingKey<Bls12_377>> =
194    Lazy::new(|| convert_verification_parameters().into());
195
196pub mod convert {
197    include!("gen/convert_id.rs");
198}
199
200/// Proving key for the delegator vote proof.
201pub static DELEGATOR_VOTE_PROOF_PROVING_KEY: Lazy<LazyProvingKey> = Lazy::new(|| {
202    let delegator_vote_proving_key = LazyProvingKey::new(delegator_vote::PROVING_KEY_ID);
203
204    #[cfg(feature = "bundled-proving-keys")]
205    delegator_vote_proving_key
206        .try_load(include_bytes!("gen/delegator_vote_pk.bin"))
207        .expect("bundled proving key is valid");
208
209    delegator_vote_proving_key
210});
211
212/// Verification key for the delegator vote proof.
213pub static DELEGATOR_VOTE_PROOF_VERIFICATION_KEY: Lazy<PreparedVerifyingKey<Bls12_377>> =
214    Lazy::new(|| delegator_vote_verification_parameters().into());
215
216pub mod delegator_vote {
217    include!("gen/delegator_vote_id.rs");
218}
219
220/// Proving key for the nullifier derivation proof.
221pub static NULLIFIER_DERIVATION_PROOF_PROVING_KEY: Lazy<LazyProvingKey> = Lazy::new(|| {
222    let nullifier_proving_key = LazyProvingKey::new(nullifier_derivation::PROVING_KEY_ID);
223
224    #[cfg(feature = "bundled-proving-keys")]
225    nullifier_proving_key
226        .try_load(include_bytes!("gen/nullifier_derivation_pk.bin"))
227        .expect("bundled proving key is valid");
228
229    nullifier_proving_key
230});
231
232/// Verification key for the delegator vote proof.
233pub static NULLIFIER_DERIVATION_PROOF_VERIFICATION_KEY: Lazy<PreparedVerifyingKey<Bls12_377>> =
234    Lazy::new(|| nullifier_derivation_verification_parameters().into());
235
236pub mod nullifier_derivation {
237    include!("gen/nullifier_derivation_id.rs");
238}
239
240// Note: Here we are using `CanonicalDeserialize::deserialize_uncompressed_unchecked` as the
241// parameters are being loaded from a trusted source (our source code).
242
243fn spend_verification_parameters() -> VerifyingKey<Bls12_377> {
244    let vk_params = include_bytes!("gen/spend_vk.param");
245    VerifyingKey::deserialize_uncompressed_unchecked(&vk_params[..])
246        .expect("can deserialize VerifyingKey")
247}
248
249fn output_verification_parameters() -> VerifyingKey<Bls12_377> {
250    let vk_params = include_bytes!("gen/output_vk.param");
251    VerifyingKey::deserialize_uncompressed_unchecked(&vk_params[..])
252        .expect("can deserialize VerifyingKey")
253}
254
255fn swap_verification_parameters() -> VerifyingKey<Bls12_377> {
256    let vk_params = include_bytes!("gen/swap_vk.param");
257    VerifyingKey::deserialize_uncompressed_unchecked(&vk_params[..])
258        .expect("can deserialize VerifyingKey")
259}
260
261fn swapclaim_verification_parameters() -> VerifyingKey<Bls12_377> {
262    let vk_params = include_bytes!("gen/swapclaim_vk.param");
263    VerifyingKey::deserialize_uncompressed_unchecked(&vk_params[..])
264        .expect("can deserialize VerifyingKey")
265}
266
267fn convert_verification_parameters() -> VerifyingKey<Bls12_377> {
268    let vk_params = include_bytes!("gen/convert_vk.param");
269    VerifyingKey::deserialize_uncompressed_unchecked(&vk_params[..])
270        .expect("can deserialize VerifyingKey")
271}
272
273fn delegator_vote_verification_parameters() -> VerifyingKey<Bls12_377> {
274    let vk_params = include_bytes!("gen/delegator_vote_vk.param");
275    VerifyingKey::deserialize_uncompressed_unchecked(&vk_params[..])
276        .expect("can deserialize VerifyingKey")
277}
278
279fn nullifier_derivation_verification_parameters() -> VerifyingKey<Bls12_377> {
280    let vk_params = include_bytes!("gen/nullifier_derivation_vk.param");
281    VerifyingKey::deserialize_uncompressed_unchecked(&vk_params[..])
282        .expect("can deserialize VerifyingKey")
283}