1use super::*;
27use utils::common::DomSep;
28use utils::straus::short_msm;
29
30pub trait TinySuite: Suite {}
34
35impl<T> TinySuite for T where T: Suite {}
36
37#[inline(always)]
38fn vrf_transcript<S: TinySuite>(
39 public: AffinePoint<S>,
40 ios: impl AsRef<[VrfIo<S>]>,
41 ad: impl AsRef<[u8]>,
42) -> (S::Transcript, VrfIo<S>) {
43 utils::vrf_transcript_with_schnorr(DomSep::TinyVrf, public, ios, ad)
44}
45
46#[derive(Debug, Clone)]
52pub struct Proof<S: TinySuite> {
53 pub c: ScalarField<S>,
55 pub s: ScalarField<S>,
57}
58
59impl<S: TinySuite> CanonicalSerialize for Proof<S> {
60 fn serialize_with_mode<W: ark_serialize::Write>(
61 &self,
62 mut writer: W,
63 compress: ark_serialize::Compress,
64 ) -> Result<(), ark_serialize::SerializationError> {
65 let scalar_len = ScalarField::<S>::MODULUS_BIT_SIZE.div_ceil(8) as usize;
66 if scalar_len < utils::common::CHALLENGE_LEN {
67 return Err(ark_serialize::SerializationError::InvalidData);
69 }
70 let mut c_buf = [0; 128];
71 self.c
72 .serialize_compressed(&mut c_buf[..])
73 .expect("c_buf is big enough");
74 let c_buf = &c_buf[..utils::common::CHALLENGE_LEN];
75 writer.write_all(c_buf)?;
76 self.s.serialize_with_mode(&mut writer, compress)?;
77 Ok(())
78 }
79
80 fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
81 utils::common::CHALLENGE_LEN + self.s.serialized_size(compress)
82 }
83}
84
85impl<S: TinySuite> CanonicalDeserialize for Proof<S> {
86 fn deserialize_with_mode<R: ark_serialize::Read>(
87 mut reader: R,
88 compress: ark_serialize::Compress,
89 validate: ark_serialize::Validate,
90 ) -> Result<Self, ark_serialize::SerializationError> {
91 let mut c_buf = [0u8; utils::common::CHALLENGE_LEN];
92 if reader.read_exact(&mut c_buf[..]).is_err() {
93 return Err(ark_serialize::SerializationError::InvalidData);
94 }
95 let c = ScalarField::<S>::from_le_bytes_mod_order(&c_buf);
96 let s = <ScalarField<S> as CanonicalDeserialize>::deserialize_with_mode(
97 &mut reader,
98 compress,
99 validate,
100 )?;
101 Ok(Proof { c, s })
102 }
103}
104
105impl<S: TinySuite> ark_serialize::Valid for Proof<S> {
106 fn check(&self) -> Result<(), ark_serialize::SerializationError> {
107 self.c.check()?;
108 self.s.check()?;
109 Ok(())
110 }
111}
112
113pub trait Prover<S: TinySuite> {
115 fn prove(&self, ios: impl AsRef<[VrfIo<S>]>, ad: impl AsRef<[u8]>) -> Proof<S>;
119}
120
121pub trait Verifier<S: TinySuite> {
133 fn verify(
139 &self,
140 ios: impl AsRef<[VrfIo<S>]>,
141 aux: impl AsRef<[u8]>,
142 proof: &Proof<S>,
143 ) -> Result<(), Error>;
144}
145
146impl<S: TinySuite> Prover<S> for Secret<S> {
147 fn prove(&self, ios: impl AsRef<[VrfIo<S>]>, ad: impl AsRef<[u8]>) -> Proof<S> {
157 let (t, io) = vrf_transcript::<S>(self.public.0, ios, ad);
158
159 let k = S::nonce(&self.scalar, Some(t.clone()));
160
161 let r = smul!(io.input.0, k).into_affine();
163
164 let c = S::challenge(&[&r], Some(t));
165 let s = k + c * self.scalar;
166 Proof { c, s }
167 }
168}
169
170impl<S: TinySuite> Verifier<S> for Public<S> {
171 fn verify(
177 &self,
178 ios: impl AsRef<[VrfIo<S>]>,
179 ad: impl AsRef<[u8]>,
180 proof: &Proof<S>,
181 ) -> Result<(), Error> {
182 let (t, io) = vrf_transcript::<S>(self.0, ios, ad);
183
184 let Proof { c, s } = proof;
185
186 let r = short_msm(&[io.input.0, io.output.0], &[*s, -*c], 2).into_affine();
188
189 let c_exp = S::challenge(&[&r], Some(t));
190 (c_exp == *c)
191 .then_some(())
192 .ok_or(Error::VerificationFailure)
193 }
194}
195
196#[cfg(test)]
197pub mod testing {
198 use super::*;
199 use crate::testing::{self as common, SuiteExt};
200
201 pub fn prove_verify<S: TinySuite>() {
202 let secret = Secret::<S>::from_seed(common::TEST_SEED);
203 let public = secret.public();
204 let input = Input::from_affine_unchecked(common::random_val(None));
205 let io = secret.vrf_io(input);
206
207 let proof = secret.prove(io, b"foo");
208 let result = public.verify(io, b"foo", &proof);
209 assert!(result.is_ok());
210 }
211
212 pub fn prove_verify_multi_empty<S: TinySuite>() {
213 let secret = Secret::<S>::from_seed(common::TEST_SEED);
214 let public = secret.public();
215
216 let ios: [VrfIo<S>; 0] = [];
217 let proof = secret.prove(ios, b"bar");
218
219 assert!(public.verify(ios, b"bar", &proof).is_ok());
220
221 assert!(public.verify(ios, b"baz", &proof).is_err());
223 }
224
225 pub fn prove_verify_multi_single<S: TinySuite>() {
227 let secret = Secret::<S>::from_seed(common::TEST_SEED);
228 let public = secret.public();
229 let input = Input::from_affine_unchecked(common::random_val(None));
230 let io = secret.vrf_io(input);
231
232 let proof_single = secret.prove(io, b"foo");
233 let proof_slice = secret.prove([io], b"foo");
234
235 let encode = |p: &tiny::Proof<S>| {
237 let mut buf = Vec::new();
238 p.serialize_compressed(&mut buf).unwrap();
239 buf
240 };
241 assert_eq!(encode(&proof_single), encode(&proof_slice));
242
243 assert!(public.verify(io, b"foo", &proof_slice).is_ok());
245 assert!(public.verify([io], b"foo", &proof_single).is_ok());
246 }
247
248 pub fn prove_verify_multi<S: TinySuite>() {
250 let secret = Secret::<S>::from_seed(common::TEST_SEED);
251 let public = secret.public();
252
253 let mut ios: Vec<VrfIo<S>> = (0..3u8)
254 .map(|i| {
255 let input = Input::new(&[i + 1]).unwrap();
256 secret.vrf_io(input)
257 })
258 .collect();
259 ios.push(VrfIo {
260 input: Input(S::Affine::generator()),
261 output: Output(public.0),
262 });
263
264 let proof = secret.prove(&ios[..], b"bar");
265 assert!(public.verify(&ios[..], b"bar", &proof).is_ok());
266
267 let mut bad_ios = ios.clone();
269 bad_ios[1].output = secret.output(ios[0].input);
270 assert!(public.verify(&bad_ios[..], b"bar", &proof).is_err());
271
272 let mut bad_ios = ios.clone();
274 bad_ios[0].input = ios[1].input;
275 assert!(public.verify(&bad_ios[..], b"bar", &proof).is_err());
276
277 assert!(public.verify(&ios[..], b"baz", &proof).is_err());
279 }
280
281 #[macro_export]
282 macro_rules! tiny_suite_tests {
283 ($suite:ty) => {
284 mod tiny {
285 use super::*;
286
287 #[test]
288 fn prove_verify() {
289 $crate::tiny::testing::prove_verify::<$suite>();
290 }
291
292 #[test]
293 fn prove_verify_multi_single() {
294 $crate::tiny::testing::prove_verify_multi_single::<$suite>();
295 }
296
297 #[test]
298 fn prove_verify_multi() {
299 $crate::tiny::testing::prove_verify_multi::<$suite>();
300 }
301
302 #[test]
303 fn prove_verify_multi_empty() {
304 $crate::tiny::testing::prove_verify_multi_empty::<$suite>();
305 }
306
307 $crate::test_vectors!($crate::tiny::testing::TestVector<$suite>);
308 }
309 };
310 }
311
312 pub struct TestVector<S: TinySuite> {
313 pub base: common::TestVector<S>,
314 pub c: ScalarField<S>,
315 pub s: ScalarField<S>,
316 }
317
318 impl<S: TinySuite> core::fmt::Debug for TestVector<S> {
319 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
320 let c = hex::encode(common::scalar_encode::<S>(&self.c));
321 let s = hex::encode(common::scalar_encode::<S>(&self.s));
322 f.debug_struct("TestVector")
323 .field("base", &self.base)
324 .field("proof_c", &c)
325 .field("proof_s", &s)
326 .finish()
327 }
328 }
329
330 impl<S> common::TestVectorTrait for TestVector<S>
331 where
332 S: TinySuite + SuiteExt + std::fmt::Debug,
333 {
334 fn name() -> String {
335 S::SUITE_NAME.to_string() + "_tiny"
336 }
337
338 fn new(comment: &str, seed: &[u8; 32], alpha: &[u8], ad: &[u8]) -> Self {
339 use super::Prover;
340 let base = common::TestVector::new(comment, seed, alpha, ad);
341 let io = VrfIo {
342 input: Input::from_affine_unchecked(base.h),
343 output: Output::from_affine_unchecked(base.gamma),
344 };
345 let sk = Secret::from_scalar(base.sk);
346 let proof: Proof<S> = sk.prove(io, ad);
347 Self {
348 base,
349 c: proof.c,
350 s: proof.s,
351 }
352 }
353
354 fn from_map(map: &common::TestVectorMap) -> Self {
355 let base = common::TestVector::from_map(map);
356 let c = common::scalar_decode::<S>(&map.get_bytes("proof_c"));
357 let s = common::scalar_decode::<S>(&map.get_bytes("proof_s"));
358 Self { base, c, s }
359 }
360
361 fn to_map(&self) -> common::TestVectorMap {
362 let buf = common::scalar_encode::<S>(&self.c);
363 let proof_c = &buf[..utils::common::CHALLENGE_LEN];
364 let items = [
365 ("proof_c", hex::encode(proof_c)),
366 ("proof_s", hex::encode(common::scalar_encode::<S>(&self.s))),
367 ];
368 let mut map = self.base.to_map();
369 items.into_iter().for_each(|(name, value)| {
370 map.0.insert(name.to_string(), value);
371 });
372 map
373 }
374
375 fn run(&self) {
376 self.base.run();
377 let io = VrfIo {
378 input: Input::<S>::from_affine_unchecked(self.base.h),
379 output: Output::from_affine_unchecked(self.base.gamma),
380 };
381 let sk = Secret::from_scalar(self.base.sk);
382 let proof = sk.prove(io, &self.base.ad);
383 assert_eq!(self.c, proof.c, "VRF proof challenge ('c') mismatch");
384 assert_eq!(self.s, proof.s, "VRF proof response ('s') mismatch");
385
386 let pk = Public(self.base.pk);
387 assert!(pk.verify(io, &self.base.ad, &proof).is_ok());
388 }
389 }
390}