penumbra_sdk_keys/address/
r1cs.rs1use crate::Address;
2use ark_ff::ToConstraintField;
3use ark_r1cs_std::prelude::*;
4use ark_relations::r1cs::SynthesisError;
5use decaf377::{
6 r1cs::{ElementVar, FqVar},
7 Element, Fq,
8};
9
10#[derive(Clone)]
11pub struct AddressVar {
12 pub diversified_generator: ElementVar,
13 pub transmission_key: ElementVar,
14 pub clue_key: FqVar,
15}
16
17impl AddressVar {
18 pub fn diversified_generator(&self) -> ElementVar {
19 self.diversified_generator.clone()
20 }
21
22 pub fn transmission_key(&self) -> ElementVar {
23 self.transmission_key.clone()
24 }
25
26 pub fn clue_key(&self) -> FqVar {
27 self.clue_key.clone()
28 }
29}
30
31impl AllocVar<Address, Fq> for AddressVar {
32 fn new_variable<T: std::borrow::Borrow<Address>>(
33 cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
34 f: impl FnOnce() -> Result<T, SynthesisError>,
35 mode: ark_r1cs_std::prelude::AllocationMode,
36 ) -> Result<Self, SynthesisError> {
37 let ns = cs.into();
38 let cs = ns.cs();
39 let address: Address = f()?.borrow().to_owned();
40
41 let diversified_generator: ElementVar = AllocVar::<Element, Fq>::new_variable(
42 cs.clone(),
43 || Ok(address.diversified_generator()),
44 mode,
45 )?;
46 let identity = ElementVar::new_constant(cs.clone(), decaf377::Element::default())?;
48 identity.enforce_not_equal(&diversified_generator)?;
49
50 let element_transmission_key = decaf377::Encoding(address.transmission_key().0)
51 .vartime_decompress()
52 .map_err(|_| SynthesisError::AssignmentMissing)?;
53 let transmission_key: ElementVar = AllocVar::<Element, Fq>::new_variable(
54 cs.clone(),
55 || Ok(element_transmission_key),
56 mode,
57 )?;
58 let clue_key = FqVar::new_variable(
59 cs,
60 || Ok(Fq::from_le_bytes_mod_order(&address.clue_key().0[..])),
61 mode,
62 )?;
63
64 Ok(Self {
65 diversified_generator,
66 transmission_key,
67 clue_key,
68 })
69 }
70}
71
72impl ToConstraintField<Fq> for Address {
76 fn to_field_elements(&self) -> Option<Vec<Fq>> {
77 let mut elements = Vec::new();
78 elements.extend(self.diversified_generator().to_field_elements()?);
79 let transmission_key_fq = decaf377::Encoding(self.transmission_key().0)
80 .vartime_decompress()
81 .expect("transmission key is valid decaf377 Element");
82 elements.extend([transmission_key_fq.vartime_compress_to_field()]);
83 elements.extend(Fq::from_bytes_checked(&self.clue_key().0));
84 Some(elements)
85 }
86}