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