penumbra_sdk_asset/asset/
r1cs.rs

1use ark_r1cs_std::prelude::*;
2use ark_relations::r1cs::SynthesisError;
3use decaf377::{
4    r1cs::{ElementVar, FqVar},
5    Fq,
6};
7
8use crate::asset::Id;
9
10use super::VALUE_GENERATOR_DOMAIN_SEP;
11
12#[derive(Clone)]
13pub struct AssetIdVar {
14    pub asset_id: FqVar,
15}
16
17impl AllocVar<Id, Fq> for AssetIdVar {
18    fn new_variable<T: std::borrow::Borrow<Id>>(
19        cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
20        f: impl FnOnce() -> Result<T, SynthesisError>,
21        mode: ark_r1cs_std::prelude::AllocationMode,
22    ) -> Result<Self, SynthesisError> {
23        let ns = cs.into();
24        let cs = ns.cs();
25        let asset_id: Id = *f()?.borrow();
26        let inner_asset_id_var = FqVar::new_variable(cs, || Ok(asset_id.0), mode)?;
27        Ok(Self {
28            asset_id: inner_asset_id_var,
29        })
30    }
31}
32
33impl R1CSVar<Fq> for AssetIdVar {
34    type Value = Id;
35
36    fn cs(&self) -> ark_relations::r1cs::ConstraintSystemRef<Fq> {
37        self.asset_id.cs()
38    }
39
40    fn value(&self) -> Result<Self::Value, SynthesisError> {
41        let asset_id_fq = self.asset_id.value()?;
42        Ok(Id(asset_id_fq))
43    }
44}
45
46impl AssetIdVar {
47    pub fn value_generator(&self) -> Result<ElementVar, SynthesisError> {
48        let cs = self.cs();
49        let value_generator_domain_sep =
50            FqVar::new_constant(cs.clone(), *VALUE_GENERATOR_DOMAIN_SEP)?;
51        let hashed_asset_id =
52            poseidon377::r1cs::hash_1(cs, &value_generator_domain_sep, self.asset_id.clone())?;
53        ElementVar::encode_to_curve(&hashed_asset_id)
54    }
55}
56
57impl EqGadget<Fq> for AssetIdVar {
58    fn is_eq(&self, other: &Self) -> Result<Boolean<Fq>, SynthesisError> {
59        self.asset_id.is_eq(&other.asset_id)
60    }
61}