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 algebra::{groups::Group, Field};
  2use r1cs_core::{ConstraintSystem, SynthesisError};
  3use r1cs_std::prelude::*;
  4
  5use crate::signature::SigRandomizePkGadget;
  6
  7use core::{borrow::Borrow, marker::PhantomData};
  8
  9use crate::signature::schnorr::{SchnorrPublicKey, SchnorrSigParameters, SchnorrSignature};
 10use digest::Digest;
 11
 12pub struct SchnorrSigGadgetParameters<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>>
 13{
 14    generator: GG,
 15    _group:    PhantomData<*const G>,
 16    _engine:   PhantomData<*const ConstraintF>,
 17}
 18
 19impl<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> Clone
 20    for SchnorrSigGadgetParameters<G, ConstraintF, GG>
 21{
 22    fn clone(&self) -> Self {
 23        Self {
 24            generator: self.generator.clone(),
 25            _group:    PhantomData,
 26            _engine:   PhantomData,
 27        }
 28    }
 29}
 30
 31#[derive(Derivative)]
 32#[derivative(
 33    Debug(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
 34    Clone(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
 35    PartialEq(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
 36    Eq(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>")
 37)]
 38pub struct SchnorrSigGadgetPk<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
 39    pub_key: GG,
 40    #[doc(hidden)]
 41    _group:  PhantomData<*const G>,
 42    #[doc(hidden)]
 43    _engine: PhantomData<*const ConstraintF>,
 44}
 45
 46pub struct SchnorrRandomizePkGadget<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
 47    #[doc(hidden)]
 48    _group:        PhantomData<*const G>,
 49    #[doc(hidden)]
 50    _group_gadget: PhantomData<*const GG>,
 51    #[doc(hidden)]
 52    _engine:       PhantomData<*const ConstraintF>,
 53}
 54
 55impl<G, GG, D, ConstraintF> SigRandomizePkGadget<SchnorrSignature<G, D>, ConstraintF>
 56    for SchnorrRandomizePkGadget<G, ConstraintF, GG>
 57where
 58    G: Group,
 59    GG: GroupGadget<G, ConstraintF>,
 60    D: Digest + Send + Sync,
 61    ConstraintF: Field,
 62{
 63    type ParametersGadget = SchnorrSigGadgetParameters<G, ConstraintF, GG>;
 64    type PublicKeyGadget = SchnorrSigGadgetPk<G, ConstraintF, GG>;
 65
 66    fn check_randomization_gadget<CS: ConstraintSystem<ConstraintF>>(
 67        mut cs: CS,
 68        parameters: &Self::ParametersGadget,
 69        public_key: &Self::PublicKeyGadget,
 70        randomness: &[UInt8],
 71    ) -> Result<Self::PublicKeyGadget, SynthesisError> {
 72        let base = parameters.generator.clone();
 73        let randomness = randomness
 74            .iter()
 75            .flat_map(|b| b.into_bits_le())
 76            .collect::<Vec<_>>();
 77        let rand_pk = base.mul_bits(
 78            &mut cs.ns(|| "Compute Randomizer"),
 79            &public_key.pub_key,
 80            randomness.iter(),
 81        )?;
 82        Ok(SchnorrSigGadgetPk {
 83            pub_key: rand_pk,
 84            _group:  PhantomData,
 85            _engine: PhantomData,
 86        })
 87    }
 88}
 89
 90impl<G, ConstraintF, GG, D> AllocGadget<SchnorrSigParameters<G, D>, ConstraintF>
 91    for SchnorrSigGadgetParameters<G, ConstraintF, GG>
 92where
 93    G: Group,
 94    ConstraintF: Field,
 95    GG: GroupGadget<G, ConstraintF>,
 96    D: Digest,
 97{
 98    fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
 99    where
100        F: FnOnce() -> Result<T, SynthesisError>,
101        T: Borrow<SchnorrSigParameters<G, D>>,
102    {
103        let generator = GG::alloc_checked(cs, || f().map(|pp| pp.borrow().generator))?;
104        Ok(Self {
105            generator,
106            _engine: PhantomData,
107            _group: PhantomData,
108        })
109    }
110
111    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
112        cs: CS,
113        f: F,
114    ) -> Result<Self, SynthesisError>
115    where
116        F: FnOnce() -> Result<T, SynthesisError>,
117        T: Borrow<SchnorrSigParameters<G, D>>,
118    {
119        let generator = GG::alloc_input(cs, || f().map(|pp| pp.borrow().generator))?;
120        Ok(Self {
121            generator,
122            _engine: PhantomData,
123            _group: PhantomData,
124        })
125    }
126}
127
128impl<G, ConstraintF, GG> AllocGadget<SchnorrPublicKey<G>, ConstraintF>
129    for SchnorrSigGadgetPk<G, ConstraintF, GG>
130where
131    G: Group,
132    ConstraintF: Field,
133    GG: GroupGadget<G, ConstraintF>,
134{
135    fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
136    where
137        F: FnOnce() -> Result<T, SynthesisError>,
138        T: Borrow<SchnorrPublicKey<G>>,
139    {
140        let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
141        Ok(Self {
142            pub_key,
143            _engine: PhantomData,
144            _group: PhantomData,
145        })
146    }
147
148    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
149        cs: CS,
150        f: F,
151    ) -> Result<Self, SynthesisError>
152    where
153        F: FnOnce() -> Result<T, SynthesisError>,
154        T: Borrow<SchnorrPublicKey<G>>,
155    {
156        let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
157        Ok(Self {
158            pub_key,
159            _engine: PhantomData,
160            _group: PhantomData,
161        })
162    }
163}
164
165impl<G, ConstraintF, GG> ConditionalEqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
166where
167    G: Group,
168    ConstraintF: Field,
169    GG: GroupGadget<G, ConstraintF>,
170{
171    #[inline]
172    fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
173        &self,
174        mut cs: CS,
175        other: &Self,
176        condition: &Boolean,
177    ) -> Result<(), SynthesisError> {
178        self.pub_key.conditional_enforce_equal(
179            &mut cs.ns(|| "PubKey equality"),
180            &other.pub_key,
181            condition,
182        )?;
183        Ok(())
184    }
185
186    fn cost() -> usize {
187        <GG as ConditionalEqGadget<ConstraintF>>::cost()
188    }
189}
190
191impl<G, ConstraintF, GG> EqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
192where
193    G: Group,
194    ConstraintF: Field,
195    GG: GroupGadget<G, ConstraintF>,
196{
197}
198
199impl<G, ConstraintF, GG> ToBytesGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
200where
201    G: Group,
202    ConstraintF: Field,
203    GG: GroupGadget<G, ConstraintF>,
204{
205    fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
206        &self,
207        mut cs: CS,
208    ) -> Result<Vec<UInt8>, SynthesisError> {
209        self.pub_key.to_bytes(&mut cs.ns(|| "PubKey To Bytes"))
210    }
211
212    fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
213        &self,
214        mut cs: CS,
215    ) -> Result<Vec<UInt8>, SynthesisError> {
216        self.pub_key
217            .to_bytes_strict(&mut cs.ns(|| "PubKey To Bytes"))
218    }
219}