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 fn randomize(
60 parameters: &Self::ParametersVar,
61 public_key: &Self::PublicKeyVar,
62 randomness: &[UInt8<ConstraintF<C>>],
63 ) -> Result<Self::PublicKeyVar, SynthesisError> {
64 let base = parameters.generator.clone();
65 let randomness = randomness
66 .iter()
67 .flat_map(|b| b.into_bits_le())
68 .collect::<Vec<_>>();
69 let rand_pk = &public_key.pub_key + &base.mul_bits(randomness.iter())?;
70 Ok(PublicKeyVar {
71 pub_key: rand_pk,
72 _group: PhantomData,
73 })
74 }
75}
76
77impl<C, GC, D> AllocVar<Parameters<C, D>, ConstraintF<C>> for ParametersVar<C, GC>
78where
79 C: ProjectiveCurve,
80 GC: CurveVar<C, ConstraintF<C>>,
81 D: Digest,
82 for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
83{
84 fn new_variable<T: Borrow<Parameters<C, D>>>(
85 cs: impl Into<Namespace<ConstraintF<C>>>,
86 f: impl FnOnce() -> Result<T, SynthesisError>,
87 mode: AllocationMode,
88 ) -> Result<Self, SynthesisError> {
89 let generator = GC::new_variable(cs, || f().map(|g| g.borrow().generator), mode)?;
90 Ok(Self {
91 generator,
92 _curve: PhantomData,
93 })
94 }
95}
96
97impl<C, GC> AllocVar<PublicKey<C>, ConstraintF<C>> for PublicKeyVar<C, GC>
98where
99 C: ProjectiveCurve,
100 GC: CurveVar<C, ConstraintF<C>>,
101 for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
102{
103 fn new_variable<T: Borrow<PublicKey<C>>>(
104 cs: impl Into<Namespace<ConstraintF<C>>>,
105 f: impl FnOnce() -> Result<T, SynthesisError>,
106 mode: AllocationMode,
107 ) -> Result<Self, SynthesisError> {
108 let pub_key = GC::new_variable(cs, f, mode)?;
109 Ok(Self {
110 pub_key,
111 _group: PhantomData,
112 })
113 }
114}
115
116impl<C, GC> EqGadget<ConstraintF<C>> for PublicKeyVar<C, GC>
117where
118 C: ProjectiveCurve,
119 GC: CurveVar<C, ConstraintF<C>>,
120 for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
121{
122 #[inline]
123 fn is_eq(&self, other: &Self) -> Result<Boolean<ConstraintF<C>>, SynthesisError> {
124 self.pub_key.is_eq(&other.pub_key)
125 }
126
127 #[inline]
128 fn conditional_enforce_equal(
129 &self,
130 other: &Self,
131 condition: &Boolean<ConstraintF<C>>,
132 ) -> Result<(), SynthesisError> {
133 self.pub_key
134 .conditional_enforce_equal(&other.pub_key, condition)
135 }
136
137 #[inline]
138 fn conditional_enforce_not_equal(
139 &self,
140 other: &Self,
141 condition: &Boolean<ConstraintF<C>>,
142 ) -> Result<(), SynthesisError> {
143 self.pub_key
144 .conditional_enforce_not_equal(&other.pub_key, condition)
145 }
146}
147
148impl<C, GC> ToBytesGadget<ConstraintF<C>> for PublicKeyVar<C, GC>
149where
150 C: ProjectiveCurve,
151 GC: CurveVar<C, ConstraintF<C>>,
152 for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
153{
154 fn to_bytes(&self) -> Result<Vec<UInt8<ConstraintF<C>>>, SynthesisError> {
155 self.pub_key.to_bytes()
156 }
157}