penumbra_sdk_keys/keys/fvk/
r1cs.rs1use ark_r1cs_std::prelude::*;
2use ark_relations::r1cs::SynthesisError;
3use decaf377::{
4 r1cs::{ElementVar, FqVar},
5 Element, Fq, Fr,
6};
7use decaf377_rdsa::{SpendAuth, VerificationKey, VerificationKeyBytes};
8use once_cell::sync::Lazy;
9
10fn generator() -> Element {
11 Element::GENERATOR
12}
13
14pub(crate) static SPENDAUTH_BASEPOINT: Lazy<Element> = Lazy::new(generator);
15
16pub struct RandomizedVerificationKey {
17 pub inner: ElementVar,
18}
19
20impl AllocVar<VerificationKey<SpendAuth>, Fq> for RandomizedVerificationKey {
21 fn new_variable<T: std::borrow::Borrow<VerificationKey<SpendAuth>>>(
22 cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
23 f: impl FnOnce() -> Result<T, SynthesisError>,
24 mode: ark_r1cs_std::prelude::AllocationMode,
25 ) -> Result<Self, SynthesisError> {
26 let ns = cs.into();
27 let cs = ns.cs();
28 let inner: VerificationKey<SpendAuth> = *f()?.borrow();
29 match mode {
30 AllocationMode::Constant => unimplemented!(),
31 AllocationMode::Input => {
32 let point = decaf377::Encoding(*inner.as_ref())
33 .vartime_decompress()
34 .map_err(|_| SynthesisError::MalformedVerifyingKey)?;
35 let element_var: ElementVar = AllocVar::new_input(cs, || Ok(point))?;
36 Ok(Self { inner: element_var })
37 }
38 AllocationMode::Witness => unimplemented!(),
39 }
40 }
41}
42
43impl R1CSVar<Fq> for RandomizedVerificationKey {
44 type Value = VerificationKey<SpendAuth>;
45
46 fn cs(&self) -> ark_relations::r1cs::ConstraintSystemRef<Fq> {
47 self.inner.cs()
48 }
49
50 fn value(&self) -> Result<Self::Value, SynthesisError> {
51 let point = self.inner.value()?;
52 let key_bytes = point.vartime_compress();
53 let verification_key_bytes: VerificationKeyBytes<SpendAuth> = key_bytes.0.into();
54 Ok(
55 VerificationKey::<SpendAuth>::try_from(verification_key_bytes)
56 .expect("should be able to convert from bytes"),
57 )
58 }
59}
60
61impl RandomizedVerificationKey {
62 pub fn compress_to_field(&self) -> Result<FqVar, SynthesisError> {
63 self.inner.compress_to_field()
64 }
65}
66
67impl EqGadget<Fq> for RandomizedVerificationKey {
68 fn is_eq(&self, other: &Self) -> Result<Boolean<Fq>, SynthesisError> {
69 let self_fq = self.inner.compress_to_field()?;
70 let other_fq = other.compress_to_field()?;
71 self_fq.is_eq(&other_fq)
72 }
73}
74
75pub struct AuthorizationKeyVar {
76 pub inner: ElementVar,
77}
78
79impl AllocVar<VerificationKey<SpendAuth>, Fq> for AuthorizationKeyVar {
80 fn new_variable<T: std::borrow::Borrow<VerificationKey<SpendAuth>>>(
81 cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
82 f: impl FnOnce() -> Result<T, SynthesisError>,
83 mode: ark_r1cs_std::prelude::AllocationMode,
84 ) -> Result<Self, SynthesisError> {
85 let ns = cs.into();
86 let cs = ns.cs();
87 let inner: VerificationKey<SpendAuth> = *f()?.borrow();
88 match mode {
89 AllocationMode::Constant => unimplemented!(),
90 AllocationMode::Input => unimplemented!(),
91 AllocationMode::Witness => {
92 let ak_point = decaf377::Encoding(*inner.as_ref())
93 .vartime_decompress()
94 .map_err(|_| SynthesisError::MalformedVerifyingKey)?;
95 let ak_element_var: ElementVar =
96 AllocVar::<Element, Fq>::new_witness(cs.clone(), || Ok(ak_point))?;
97
98 let identity = ElementVar::new_constant(cs, decaf377::Element::default())?;
100 identity.enforce_not_equal(&ak_element_var)?;
101 Ok(Self {
102 inner: ak_element_var,
103 })
104 }
105 }
106 }
107}
108
109impl R1CSVar<Fq> for AuthorizationKeyVar {
110 type Value = VerificationKey<SpendAuth>;
111
112 fn cs(&self) -> ark_relations::r1cs::ConstraintSystemRef<Fq> {
113 self.inner.cs()
114 }
115
116 fn value(&self) -> Result<Self::Value, SynthesisError> {
117 let point = self.inner.value()?;
118 let key_bytes = point.vartime_compress();
119 let verification_key_bytes: VerificationKeyBytes<SpendAuth> = key_bytes.0.into();
120 Ok(
121 VerificationKey::<SpendAuth>::try_from(verification_key_bytes)
122 .expect("should be able to convert from bytes"),
123 )
124 }
125}
126
127impl AuthorizationKeyVar {
128 pub fn randomize(
129 &self,
130 spend_auth_randomizer: &SpendAuthRandomizerVar,
131 ) -> Result<RandomizedVerificationKey, SynthesisError> {
132 let cs = self.inner.cs();
133 let spend_auth_basepoint_var = ElementVar::new_constant(cs, *SPENDAUTH_BASEPOINT)?;
134 let point = self.inner.clone()
135 + spend_auth_basepoint_var
136 .scalar_mul_le(spend_auth_randomizer.inner.to_bits_le()?.iter())?;
137 Ok(RandomizedVerificationKey { inner: point })
138 }
139}
140
141pub struct SpendAuthRandomizerVar {
142 inner: Vec<UInt8<Fq>>,
143}
144
145impl AllocVar<Fr, Fq> for SpendAuthRandomizerVar {
146 fn new_variable<T: std::borrow::Borrow<Fr>>(
147 cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
148 f: impl FnOnce() -> Result<T, SynthesisError>,
149 mode: ark_r1cs_std::prelude::AllocationMode,
150 ) -> Result<Self, SynthesisError> {
151 let ns = cs.into();
152 let cs = ns.cs();
153 let inner: Fr = *f()?.borrow();
154 match mode {
155 AllocationMode::Constant => unimplemented!(),
156 AllocationMode::Input => unimplemented!(),
157 AllocationMode::Witness => {
158 let spend_auth_randomizer_arr: [u8; 32] = inner.to_bytes();
159 Ok(Self {
160 inner: UInt8::new_witness_vec(cs, &spend_auth_randomizer_arr)?,
161 })
162 }
163 }
164 }
165}
166
167impl R1CSVar<Fq> for SpendAuthRandomizerVar {
168 type Value = Fr;
169
170 fn cs(&self) -> ark_relations::r1cs::ConstraintSystemRef<Fq> {
171 self.inner.cs()
172 }
173
174 fn value(&self) -> Result<Self::Value, SynthesisError> {
175 let mut bytes = [0u8; 32];
176 for (i, byte) in self.inner.iter().enumerate() {
177 bytes[i] = byte.value()?;
178 }
179 Ok(Fr::from_bytes_checked(&bytes).expect("can convert bytes to Fr"))
180 }
181}