1use super::concat;
7use crate::{simple::TrancheIndex, Entropy, TicketId};
8use ark_vrf::{
9 reexports::ark_serialize::{CanonicalDeserialize, CanonicalSerialize},
10 suites::bandersnatch::{self, AffinePoint, Secret as SecretImpl},
11};
12use codec::{Decode, Encode, MaxEncodedLen};
13use jam_types::{AnyVec, OpaqueBandersnatchPublic, TicketAttempt};
14
15pub use ark_vrf::Error;
16
17const SCALAR_SERIALIZED_SIZE: usize = 32;
18const POINT_SERIALIZED_SIZE: usize = 32;
19
20pub const PUBLIC_SERIALIZED_SIZE: usize = POINT_SERIALIZED_SIZE;
21pub const PREOUT_SERIALIZED_SIZE: usize = POINT_SERIALIZED_SIZE;
22
23const ERR_MSG: &str = "object length is constant and checked by test; qed";
24
25type Seed = [u8; SCALAR_SERIALIZED_SIZE];
27
28#[derive(Clone, Copy, PartialEq, Eq, Hash, Encode, Decode, MaxEncodedLen, Default)]
30pub struct Public(pub [u8; PUBLIC_SERIALIZED_SIZE]);
31
32impl Public {
33 pub fn is_valid(&self) -> bool {
34 AffinePoint::deserialize_compressed_unchecked(&self.0[..]).is_ok()
35 }
36}
37
38impl std::fmt::Debug for Public {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(f, "{:?}", AnyVec(self.0.to_vec()))
41 }
42}
43
44impl std::fmt::Display for Public {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(f, "{}", AnyVec(self.0.to_vec()))
47 }
48}
49
50impl From<OpaqueBandersnatchPublic> for Public {
51 fn from(opaque: OpaqueBandersnatchPublic) -> Self {
52 Self(opaque.0)
53 }
54}
55impl From<Public> for OpaqueBandersnatchPublic {
56 fn from(public: Public) -> Self {
57 Self(public.0)
58 }
59}
60
61#[derive(Clone)]
63pub struct Secret(SecretImpl);
64
65impl Secret {
66 pub fn new(rng: &mut impl rand::CryptoRng) -> Self {
68 Self::from_seed(rand::Rng::random(rng))
69 }
70
71 pub fn from_seed(seed: Seed) -> Self {
73 Self(SecretImpl::from_seed(&seed))
74 }
75
76 pub fn public(&self) -> Public {
78 let public = self.0.public();
79 let mut raw = [0; PUBLIC_SERIALIZED_SIZE];
80 public.serialize_compressed(raw.as_mut_slice()).expect(ERR_MSG);
81 Public(raw)
82 }
83
84 pub fn generate() -> Self {
86 Self::new(&mut rand::rng())
87 }
88}
89
90pub enum Message {
92 TicketSeal(Entropy, TicketAttempt),
94 FallbackSeal(Entropy),
96 Entropy(TicketId),
98 AuditInitial(Entropy),
100 AuditSubsequent(Entropy, jam_types::WorkReportHash, TrancheIndex),
102}
103
104impl Message {
105 pub fn using_encoded<R>(&self, f: impl FnOnce(&[u8]) -> R) -> R {
107 match self {
108 Self::TicketSeal(entropy, attempt) =>
109 f(concat(&mut [0; 15 + 32 + 1], &[b"jam_ticket_seal", &entropy.0, &[*attempt]])),
110 Self::FallbackSeal(entropy) =>
111 f(concat(&mut [0; 17 + 32], &[b"jam_fallback_seal", &entropy.0])),
112 Self::Entropy(ticket_id) =>
113 f(concat(&mut [0; 11 + 32], &[b"jam_entropy", &ticket_id.0])),
114 Self::AuditInitial(entropy_source) =>
115 f(concat(&mut [0; 9 + 32], &[b"jam_audit", &entropy_source.0])),
116 Self::AuditSubsequent(entropy_source, report, index) => f(concat(
117 &mut [0; 9 + 64 + 1],
118 &[b"jam_audit", &entropy_source.0, &report.0, &[*index]],
119 )),
120 }
121 }
122}
123
124#[inline(always)]
126fn vrf_input(message: &Message) -> bandersnatch::Input {
127 message
128 .using_encoded(|enc| bandersnatch::Input::new(enc).expect("Elligator2 H2C is infallible"))
129}
130
131pub mod vrf {
133 use super::*;
134 use ark_vrf::ietf::{Prover, Verifier};
135 use codec::ConstEncodedLen;
136
137 pub(crate) const PROOF_SERIALIZED_SIZE: usize = 64;
138 pub const SIGNATURE_SERIALIZED_SIZE: usize = PREOUT_SERIALIZED_SIZE + PROOF_SERIALIZED_SIZE;
139
140 #[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
142 pub struct Signature(pub [u8; SIGNATURE_SERIALIZED_SIZE]);
143
144 impl ConstEncodedLen for Signature {}
145
146 impl Signature {
147 pub fn vrf_output(&self) -> Entropy {
149 bandersnatch::Output::deserialize_compressed_unchecked(
150 &self.0[..PREOUT_SERIALIZED_SIZE],
151 )
152 .map(|p| {
153 let mut raw = [0u8; 32];
154 raw.copy_from_slice(&p.hash()[..32]);
155 Entropy(raw)
156 })
157 .unwrap_or_default()
158 }
159
160 pub fn vrf_verify(
162 &self,
163 message: &Message,
164 aux_data: &[u8],
165 public: &Public,
166 ) -> Result<(), Error> {
167 public.vrf_verify(message, aux_data, self)
168 }
169 }
170
171 impl Secret {
172 pub fn vrf_sign(&self, message: &Message, aux_data: &[u8]) -> Signature {
176 let input = vrf_input(message);
177 let output = self.0.output(input);
178 let proof = self.0.prove(input, output, aux_data);
179 let mut raw = [0_u8; SIGNATURE_SERIALIZED_SIZE];
180 output.serialize_compressed(&mut raw[..PREOUT_SERIALIZED_SIZE]).expect(ERR_MSG);
181 proof.serialize_compressed(&mut raw[PREOUT_SERIALIZED_SIZE..]).expect(ERR_MSG);
182 Signature(raw)
183 }
184
185 pub fn vrf_output(&self, message: &Message) -> Entropy {
187 let input = vrf_input(message);
188 let hash = self.0.output(input).hash();
189 let mut raw = [0u8; 32];
190 raw.copy_from_slice(&hash[..32]);
191 Entropy(raw)
192 }
193 }
194
195 impl Public {
196 pub fn vrf_verify(
198 &self,
199 message: &Message,
200 aux_data: &[u8],
201 signature: &Signature,
202 ) -> Result<(), Error> {
203 let public = bandersnatch::Public::deserialize_compressed_unchecked(self.0.as_ref())
204 .map_err(|_| Error::InvalidData)?;
205 let output = bandersnatch::Output::deserialize_compressed_unchecked(
206 &signature.0[..PREOUT_SERIALIZED_SIZE],
207 )
208 .map_err(|_| Error::InvalidData)?;
209 let proof = bandersnatch::IetfProof::deserialize_compressed_unchecked(
210 &signature.0[PREOUT_SERIALIZED_SIZE..],
211 )
212 .map_err(|_| Error::InvalidData)?;
213 let input = vrf_input(message);
214 public.verify(input, output, aux_data, &proof)
215 }
216 }
217
218 impl AsRef<[u8]> for Public {
219 fn as_ref(&self) -> &[u8] {
220 &self.0
221 }
222 }
223}
224
225pub mod ring_vrf {
226 use super::*;
227 use ark_vrf::ring::{Prover, Verifier};
228 pub use bandersnatch::{RingBatchItem, RingBatchVerifier, RingProver, RingVerifier};
229 use bandersnatch::{RingCommitment as RingCommitmentImpl, RingProofParams};
230
231 pub const RING_COMMITMENT_SERIALIZED_SIZE: usize = 144;
232
233 pub const RING_PROOF_SERIALIZED_SIZE: usize = 752;
234
235 pub const RING_SIGNATURE_SERIALIZED_SIZE: usize =
236 PREOUT_SERIALIZED_SIZE + RING_PROOF_SERIALIZED_SIZE;
237
238 #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode, MaxEncodedLen)]
239 pub struct RingCommitment(pub [u8; RING_COMMITMENT_SERIALIZED_SIZE]);
240
241 #[derive(Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
243 pub struct Signature(pub [u8; RING_SIGNATURE_SERIALIZED_SIZE]);
244
245 impl Signature {
246 pub fn ring_vrf_verify(
251 &self,
252 message: &Message,
253 aux_data: &[u8],
254 verifier: &RingVerifier,
255 ) -> Result<(), Error> {
256 let output = bandersnatch::Output::deserialize_compressed_unchecked(
257 &self.0[..PREOUT_SERIALIZED_SIZE],
258 )
259 .map_err(|_| Error::InvalidData)?;
260 let proof = bandersnatch::RingProof::deserialize_compressed_unchecked(
261 &self.0[PREOUT_SERIALIZED_SIZE..],
262 )
263 .map_err(|_| Error::InvalidData)?;
264 let input = vrf_input(message);
265 bandersnatch::Public::verify(input, output, aux_data, &proof, verifier)
266 }
267
268 pub fn ring_vrf_prepare(
274 &self,
275 message: &Message,
276 aux_data: &[u8],
277 batch_verifier: &RingBatchVerifier,
278 ) -> Result<RingBatchItem, Error> {
279 let output = bandersnatch::Output::deserialize_compressed_unchecked(
280 &self.0[..PREOUT_SERIALIZED_SIZE],
281 )
282 .map_err(|_| Error::InvalidData)?;
283 let proof = bandersnatch::RingProof::deserialize_compressed_unchecked(
284 &self.0[PREOUT_SERIALIZED_SIZE..],
285 )
286 .map_err(|_| Error::InvalidData)?;
287 let input = vrf_input(message);
288 Ok(batch_verifier.prepare(input, output, aux_data, &proof))
289 }
290
291 pub fn vrf_output(&self) -> Entropy {
293 bandersnatch::Output::deserialize_compressed_unchecked(
294 &self.0[..PREOUT_SERIALIZED_SIZE],
295 )
296 .map(|p| {
297 let mut raw = [0u8; 32];
298 raw.copy_from_slice(&p.hash()[..32]);
299 Entropy(raw)
300 })
301 .unwrap_or_default()
302 }
303 }
304
305 impl Secret {
306 pub fn ring_vrf_sign(
310 &self,
311 message: &Message,
312 aux_data: &[u8],
313 prover: &RingProver,
314 ) -> Signature {
315 let input = vrf_input(message);
316 let output = self.0.output(input);
317 let proof = self.0.prove(input, output, aux_data, prover);
318 let mut raw = [0_u8; RING_SIGNATURE_SERIALIZED_SIZE];
319 output.serialize_compressed(&mut raw[..PREOUT_SERIALIZED_SIZE]).expect(ERR_MSG);
320 proof.serialize_compressed(&mut raw[PREOUT_SERIALIZED_SIZE..]).expect(ERR_MSG);
321 Signature(raw)
322 }
323 }
324
325 #[derive(Clone)]
327 pub struct RingContext;
328
329 impl RingContext {
330 pub fn params() -> &'static RingProofParams {
332 use std::sync::OnceLock;
333 static PARAMS: OnceLock<RingProofParams> = OnceLock::new();
334 PARAMS.get_or_init(|| {
335 use bandersnatch::PcsParams;
336 let buf = include_bytes!(concat!(
338 env!("CARGO_MANIFEST_DIR"),
339 "/data/zcash-srs-2-11-uncompressed.bin"
340 ));
341 let pcs_params = PcsParams::deserialize_uncompressed_unchecked(&mut &buf[..])
342 .expect("Error deserializing PcsParam");
343 RingProofParams::from_pcs_params(jam_types::val_count() as usize, pcs_params)
344 .expect("Error constructing RingProofParams from PcsParams")
345 })
346 }
347
348 pub fn prover(public_keys: &[Public], public_index: usize) -> RingProver {
352 let params = Self::params();
353 let pks = public_to_affine(public_keys);
354 let prover_key = params.prover_key(&pks);
355 params.prover(prover_key, public_index)
356 }
357
358 pub fn verifier(public_keys: &[Public]) -> RingVerifier {
362 let params = Self::params();
363 let pks = public_to_affine(public_keys);
364 let verifier_key = params.verifier_key(&pks);
365 params.verifier(verifier_key)
366 }
367
368 pub fn commitment(public_keys: &[Public]) -> RingCommitment {
372 let params = Self::params();
373 let pks = public_to_affine(public_keys);
374 let verifier_key = params.verifier_key(&pks);
375 let commitment = verifier_key.commitment();
376 let mut raw = [0; RING_COMMITMENT_SERIALIZED_SIZE];
377 commitment.serialize_compressed(&mut raw[..]).expect(ERR_MSG);
378 RingCommitment(raw)
379 }
380
381 pub fn verifier_from_commitment(commitment: RingCommitment) -> Result<RingVerifier, Error> {
383 let params = Self::params();
384 let mut raw = &commitment.0[..];
385 let commitment = RingCommitmentImpl::deserialize_compressed_unchecked(&mut raw)
386 .map_err(|_| Error::InvalidData)?;
387 let verifier_key = params.verifier_key_from_commitment(commitment);
388 Ok(params.verifier(verifier_key))
389 }
390 }
391
392 #[inline(always)]
397 fn public_to_affine(pks: &[Public]) -> Vec<AffinePoint> {
398 pks.iter()
399 .map(|pk| {
400 AffinePoint::deserialize_compressed_unchecked(&pk.0[..])
401 .unwrap_or(RingProofParams::padding_point())
402 })
403 .collect()
404 }
405}
406
407#[cfg(all(test, feature = "full-test-suite"))]
408mod tests {
409 #![allow(clippy::unwrap_used)]
410 use super::{ring_vrf::*, vrf::*, *};
411 use crate::NewNull;
412 use ring_vrf::RING_COMMITMENT_SERIALIZED_SIZE;
413
414 const SEED_SERIALIZED_SIZE: usize = 32;
415 const RING_KEYSET_SIZE: usize = 1023;
416
417 const DEV_SEED: [u8; SEED_SERIALIZED_SIZE] = [0xcb; SEED_SERIALIZED_SIZE];
418
419 #[allow(dead_code)]
420 fn serialize<T: CanonicalSerialize>(obj: &T) -> Vec<u8> {
421 let mut buf = Vec::new();
422 obj.serialize_compressed(&mut buf).unwrap();
423 buf
424 }
425
426 #[test]
427 fn backend_assumptions_check() {
428 use ark_vrf::reexports::ark_std;
429 use bandersnatch::RingProofParams;
430 const EXPECTED_DOMAIN_OVERHEAD: usize = 257;
431
432 let ctx = RingProofParams::from_seed(RING_KEYSET_SIZE, [0; 32]);
433
434 let expected_domain_size = 1 << ark_std::log2(RING_KEYSET_SIZE + EXPECTED_DOMAIN_OVERHEAD);
435 assert_eq!(ctx.max_ring_size(), expected_domain_size - EXPECTED_DOMAIN_OVERHEAD);
436
437 let pks: Vec<_> =
438 (0..16).map(|i| SecretImpl::from_seed(&[i as u8; 32]).public().0).collect();
439
440 let secret = SecretImpl::from_seed(&[0u8; 32]);
441
442 let public = secret.public();
443 assert_eq!(public.compressed_size(), PUBLIC_SERIALIZED_SIZE);
444
445 let input = vrf_input(&Message::FallbackSeal(Default::default()));
446 let output = secret.output(input);
447 assert_eq!(output.compressed_size(), PREOUT_SERIALIZED_SIZE);
448
449 let prover_key = ctx.prover_key(&pks);
450 let prover = ctx.prover(prover_key, 0);
451
452 let verifier_key = ctx.verifier_key(&pks);
453 let commitment = verifier_key.commitment();
454 assert_eq!(commitment.compressed_size(), RING_COMMITMENT_SERIALIZED_SIZE);
455
456 let ietf_proof = {
457 use ark_vrf::ietf::Prover;
458 secret.prove(input, output, [])
459 };
460 assert_eq!(ietf_proof.compressed_size(), PROOF_SERIALIZED_SIZE);
461
462 let ring_proof = {
463 use ark_vrf::ring::Prover;
464 secret.prove(input, output, [], &prover)
465 };
466 assert_eq!(ring_proof.compressed_size(), RING_PROOF_SERIALIZED_SIZE);
467
468 let padding_raw = [
471 0x92, 0xca, 0x79, 0xe6, 0x1d, 0xd9, 0x0c, 0x15, 0x73, 0xa8, 0x69, 0x3f, 0x19, 0x9b,
472 0xf6, 0xe1, 0xe8, 0x68, 0x35, 0xcc, 0x71, 0x5c, 0xdc, 0xf9, 0x3f, 0x5e, 0xf2, 0x22,
473 0x56, 0x00, 0x23, 0xaa,
474 ];
475 let padding_point = AffinePoint::deserialize_compressed(&padding_raw[..]).unwrap();
476 assert_eq!(RingProofParams::padding_point(), padding_point);
477 }
478
479 fn encode_decode<T: Encode + Decode + PartialEq + std::fmt::Debug>(expected_len: usize) {
480 let obj = T::new_null();
481 let buf = obj.encode();
482 assert_eq!(buf.len(), expected_len);
483 let dec = T::decode(&mut buf.as_slice()).unwrap();
484 assert_eq!(obj, dec);
485 }
486
487 #[test]
488 fn codec_works() {
489 encode_decode::<Public>(PUBLIC_SERIALIZED_SIZE);
490 encode_decode::<vrf::Signature>(SIGNATURE_SERIALIZED_SIZE);
491 encode_decode::<ring_vrf::Signature>(RING_SIGNATURE_SERIALIZED_SIZE);
492 }
493
494 #[test]
495 fn vrf_sign_verify() {
496 let secret = Secret::from_seed(DEV_SEED);
497 let public = secret.public();
498
499 let input = Message::FallbackSeal(Default::default());
500 let ad = b"data";
501
502 let signature = secret.vrf_sign(&input, ad);
503
504 assert!(public.vrf_verify(&input, ad, &signature).is_ok());
505
506 assert!(public.vrf_verify(&input, b"bad", &signature).is_err());
508
509 assert!(public
511 .vrf_verify(&Message::FallbackSeal([1; 32].into()), ad, &signature)
512 .is_err());
513 }
514
515 #[test]
516 fn vrf_output_hash_matches() {
517 let secret = Secret::from_seed(DEV_SEED);
518
519 let input = Message::FallbackSeal(Default::default());
520 let signature = secret.vrf_sign(&input, b"data");
521
522 let output1 = secret.vrf_output(&input);
523 let output2 = signature.vrf_output();
524 assert_eq!(output1, output2);
525 }
526
527 #[test]
528 fn ring_vrf_sign_verify() {
529 let mut pks: Vec<_> = (0..16).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
530 assert!(pks.len() <= RING_KEYSET_SIZE);
531
532 let secret = Secret::from_seed(DEV_SEED);
533
534 let input = Message::FallbackSeal(Default::default());
535 let ad = b"data";
536
537 let prover_index = 3;
539 pks[prover_index] = secret.public();
540
541 let prover = RingContext::prover(&pks, prover_index);
542 let signature = secret.ring_vrf_sign(&input, ad, &prover);
543
544 let verifier = RingContext::verifier(&pks);
545 assert!(signature.ring_vrf_verify(&input, ad, &verifier).is_ok());
546
547 assert!(signature.ring_vrf_verify(&input, b"bad", &verifier).is_err());
549
550 assert!(signature
552 .ring_vrf_verify(&Message::FallbackSeal([1; 32].into()), ad, &verifier)
553 .is_err());
554 }
555
556 #[test]
557 fn ring_vrf_sign_verify_with_out_of_ring_key() {
558 let pks: Vec<_> = (0..16).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
559 let secret = Secret::from_seed(DEV_SEED);
560
561 let input = Message::FallbackSeal(Default::default());
562 let ad = b"data";
563
564 let prover = RingContext::prover(&pks, 0);
566 let signature = secret.ring_vrf_sign(&input, ad, &prover);
567
568 let verifier = RingContext::verifier(&pks);
569 assert!(signature.ring_vrf_verify(&input, ad, &verifier).is_err());
570 }
571
572 #[test]
573 fn ring_vrf_batch_verify() {
574 let mut pks: Vec<_> = (0..16).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
575 assert!(pks.len() <= RING_KEYSET_SIZE);
576
577 let secrets = [
578 Secret::from_seed(DEV_SEED),
579 Secret::from_seed([0xab; SEED_SERIALIZED_SIZE]),
580 Secret::from_seed([0xcd; SEED_SERIALIZED_SIZE]),
581 ];
582 let indices = [3, 7, 12];
583 for (i, secret) in secrets.iter().enumerate() {
584 pks[indices[i]] = secret.public();
585 }
586
587 let messages = [
588 Message::FallbackSeal(Default::default()),
589 Message::FallbackSeal([1; 32].into()),
590 Message::FallbackSeal([2; 32].into()),
591 ];
592 let ad = b"data";
593
594 let signatures: Vec<_> = secrets
595 .iter()
596 .enumerate()
597 .map(|(i, secret)| {
598 let prover = RingContext::prover(&pks, indices[i]);
599 secret.ring_vrf_sign(&messages[i], ad, &prover)
600 })
601 .collect();
602
603 let verifier = RingContext::verifier(&pks);
605 let mut batch = RingBatchVerifier::new(verifier);
606 for (i, sig) in signatures.iter().enumerate() {
607 let item = sig.ring_vrf_prepare(&messages[i], ad, &batch).unwrap();
608 batch.push_prepared(item);
609 }
610 assert!(batch.verify().is_ok());
611
612 let verifier = RingContext::verifier(&pks);
614 let mut batch = RingBatchVerifier::new(verifier);
615 for (i, sig) in signatures.iter().enumerate() {
616 let msg = if i == 2 { &messages[0] } else { &messages[i] };
617 let item = sig.ring_vrf_prepare(msg, ad, &batch).unwrap();
618 batch.push_prepared(item);
619 }
620 assert!(batch.verify().is_err());
621 }
622
623 #[test]
624 fn ring_vrf_make_bytes_matches() {
625 let mut pks: Vec<_> = (0..16).map(|i| Secret::from_seed([i as u8; 32]).public()).collect();
626 assert!(pks.len() <= RING_KEYSET_SIZE);
627
628 let secret = Secret::from_seed(DEV_SEED);
629
630 let prover_index = 3;
632 pks[prover_index] = secret.public();
633
634 let input = Message::FallbackSeal(Default::default());
635
636 let prover = RingContext::prover(&pks, prover_index);
637 let signature = secret.ring_vrf_sign(&input, b"data", &prover);
638
639 let output1 = secret.vrf_output(&input);
640 let output2 = signature.vrf_output();
641 assert_eq!(output1, output2);
642 }
643}