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}