ark-r1cs-std/crypto-primitives/src/signature/schnorr/constraints.rs
crypto-primitives/src/signature/schnorr/constraints.rsRaw
1use algebra_core::{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}