arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/crypto-primitives/src/signature/schnorr/constraints.rs
crypto-primitives/src/signature/schnorr/constraints.rsRaw
  1use crate::Vec;
  2use algebra_core::{Field, ProjectiveCurve};
  3use r1cs_core::{Namespace, SynthesisError};
  4use r1cs_std::prelude::*;
  5
  6use crate::signature::SigRandomizePkGadget;
  7
  8use core::{borrow::Borrow, marker::PhantomData};
  9
 10use crate::signature::schnorr::{Parameters, PublicKey, Schnorr};
 11use digest::Digest;
 12
 13type ConstraintF<C> = <<C as ProjectiveCurve>::BaseField as Field>::BasePrimeField;
 14
 15#[derive(Clone)]
 16pub struct ParametersVar<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
 17where
 18    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
 19{
 20    generator: GC,
 21    _curve: PhantomData<C>,
 22}
 23
 24#[derive(Derivative)]
 25#[derivative(
 26    Debug(bound = "C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>"),
 27    Clone(bound = "C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>")
 28)]
 29pub struct PublicKeyVar<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
 30where
 31    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
 32{
 33    pub_key: GC,
 34    #[doc(hidden)]
 35    _group: PhantomData<*const C>,
 36}
 37
 38pub struct SchnorrRandomizePkGadget<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
 39where
 40    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
 41{
 42    #[doc(hidden)]
 43    _group: PhantomData<*const C>,
 44    #[doc(hidden)]
 45    _group_gadget: PhantomData<*const GC>,
 46}
 47
 48impl<C, GC, D> SigRandomizePkGadget<Schnorr<C, D>, ConstraintF<C>>
 49    for SchnorrRandomizePkGadget<C, GC>
 50where
 51    C: ProjectiveCurve,
 52    GC: CurveVar<C, ConstraintF<C>>,
 53    D: Digest + Send + Sync,
 54    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
 55{
 56    type ParametersVar = ParametersVar<C, GC>;
 57    type PublicKeyVar = PublicKeyVar<C, GC>;
 58
 59    #[tracing::instrument(target = "r1cs", skip(parameters, public_key, randomness))]
 60    fn randomize(
 61        parameters: &Self::ParametersVar,
 62        public_key: &Self::PublicKeyVar,
 63        randomness: &[UInt8<ConstraintF<C>>],
 64    ) -> Result<Self::PublicKeyVar, SynthesisError> {
 65        let base = parameters.generator.clone();
 66        let randomness = randomness
 67            .iter()
 68            .flat_map(|b| b.to_bits_le().unwrap())
 69            .collect::<Vec<_>>();
 70        let rand_pk = &public_key.pub_key + &base.scalar_mul_le(randomness.iter())?;
 71        Ok(PublicKeyVar {
 72            pub_key: rand_pk,
 73            _group: PhantomData,
 74        })
 75    }
 76}
 77
 78impl<C, GC, D> AllocVar<Parameters<C, D>, ConstraintF<C>> for ParametersVar<C, GC>
 79where
 80    C: ProjectiveCurve,
 81    GC: CurveVar<C, ConstraintF<C>>,
 82    D: Digest,
 83    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
 84{
 85    fn new_variable<T: Borrow<Parameters<C, D>>>(
 86        cs: impl Into<Namespace<ConstraintF<C>>>,
 87        f: impl FnOnce() -> Result<T, SynthesisError>,
 88        mode: AllocationMode,
 89    ) -> Result<Self, SynthesisError> {
 90        let generator = GC::new_variable(cs, || f().map(|g| g.borrow().generator), mode)?;
 91        Ok(Self {
 92            generator,
 93            _curve: PhantomData,
 94        })
 95    }
 96}
 97
 98impl<C, GC> AllocVar<PublicKey<C>, ConstraintF<C>> for PublicKeyVar<C, GC>
 99where
100    C: ProjectiveCurve,
101    GC: CurveVar<C, ConstraintF<C>>,
102    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
103{
104    fn new_variable<T: Borrow<PublicKey<C>>>(
105        cs: impl Into<Namespace<ConstraintF<C>>>,
106        f: impl FnOnce() -> Result<T, SynthesisError>,
107        mode: AllocationMode,
108    ) -> Result<Self, SynthesisError> {
109        let pub_key = GC::new_variable(cs, f, mode)?;
110        Ok(Self {
111            pub_key,
112            _group: PhantomData,
113        })
114    }
115}
116
117impl<C, GC> EqGadget<ConstraintF<C>> for PublicKeyVar<C, GC>
118where
119    C: ProjectiveCurve,
120    GC: CurveVar<C, ConstraintF<C>>,
121    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
122{
123    #[inline]
124    fn is_eq(&self, other: &Self) -> Result<Boolean<ConstraintF<C>>, SynthesisError> {
125        self.pub_key.is_eq(&other.pub_key)
126    }
127
128    #[inline]
129    fn conditional_enforce_equal(
130        &self,
131        other: &Self,
132        condition: &Boolean<ConstraintF<C>>,
133    ) -> Result<(), SynthesisError> {
134        self.pub_key
135            .conditional_enforce_equal(&other.pub_key, condition)
136    }
137
138    #[inline]
139    fn conditional_enforce_not_equal(
140        &self,
141        other: &Self,
142        condition: &Boolean<ConstraintF<C>>,
143    ) -> Result<(), SynthesisError> {
144        self.pub_key
145            .conditional_enforce_not_equal(&other.pub_key, condition)
146    }
147}
148
149impl<C, GC> ToBytesGadget<ConstraintF<C>> for PublicKeyVar<C, GC>
150where
151    C: ProjectiveCurve,
152    GC: CurveVar<C, ConstraintF<C>>,
153    for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
154{
155    fn to_bytes(&self) -> Result<Vec<UInt8<ConstraintF<C>>>, SynthesisError> {
156        self.pub_key.to_bytes()
157    }
158}