Skip to content
This repository was archived by the owner on Mar 29, 2025. It is now read-only.

Commit 209b258

Browse files
authoredJul 27, 2024
Ring VRF test vectors (#28)
1 parent 6b07f6f commit 209b258

7 files changed

+532
-13
lines changed
 

‎data/bandersnatch_ed_sha512_ell2_ring_vectors.json

+128
Large diffs are not rendered by default.

‎data/bandersnatch_sw_sha512_tai_pedersen_vectors.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[
22
{
3-
"comment": "Bandersnatch_SHA-512_TAI - vector-1",
3+
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-1",
44
"sk": "3d6406500d4009fdf2604546093665911e753f2213570a29521fd88bc30ede18",
55
"pk": "fd72a90d1eeba6733824e76bb31991b8108d6562756b85f244333e3c7205225200",
66
"alpha": "",
@@ -16,7 +16,7 @@
1616
"proof_sb": "6b2dbc4b088b21d732cc5193439b5186cddecb4ee12f8233cbe3057c06849216"
1717
},
1818
{
19-
"comment": "Bandersnatch_SHA-512_TAI - vector-2",
19+
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-2",
2020
"sk": "8b9063872331dda4c3c282f7d813fb3c13e7339b7dc9635fdc764e32cc57cb15",
2121
"pk": "e30eae606d21dff460cdaecfc9bfcd2e319628ccc0242f3ca21f2d5c940ba41680",
2222
"alpha": "0a",
@@ -32,7 +32,7 @@
3232
"proof_sb": "f05d631c7ae9fbc33ea4464af81188c1342f7c6aa127531e1f1bd203d608f613"
3333
},
3434
{
35-
"comment": "Bandersnatch_SHA-512_TAI - vector-3",
35+
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-3",
3636
"sk": "6db187202f69e627e432296ae1d0f166ae6ac3c1222585b6ceae80ea07670b14",
3737
"pk": "2a00e5a32e2f097858a1a4a73cf5c2fb4e6d375a4ea4cc3ae3e91660eade850c80",
3838
"alpha": "",
@@ -48,7 +48,7 @@
4848
"proof_sb": "07a177cf9a9d08282194c8cc0d856be3de2681c642ecd0cb95a014a82f7f5c11"
4949
},
5050
{
51-
"comment": "Bandersnatch_SHA-512_TAI - vector-4",
51+
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-4",
5252
"sk": "b56cc204f1b6c2323709012cb16c72f3021035ce935fbe69b600a88d842c7407",
5353
"pk": "4f29d79a27b9545d7223431eb6a63776949454b16e2ac0b7a959304ce3e52b6a00",
5454
"alpha": "73616d706c65",
@@ -64,7 +64,7 @@
6464
"proof_sb": "5b4d6ef3445d8dc8bcc38f44b3649d39fcb5c0b169c5085245f6903ef8ba940c"
6565
},
6666
{
67-
"comment": "Bandersnatch_SHA-512_TAI - vector-5",
67+
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-5",
6868
"sk": "da36359bf1bfd1694d3ed359e7340bd02a6a5e54827d94db1384df29f5bdd302",
6969
"pk": "e58e8ba2e99035fb7ae11fa14e2a609d6d13679278dac63ebee64ca8612ffa1480",
7070
"alpha": "42616e646572736e6174636820766563746f72",
@@ -80,7 +80,7 @@
8080
"proof_sb": "bd365d1ff09f59a9ad885bf3f71e81151747757788f6c07387f4100842784e13"
8181
},
8282
{
83-
"comment": "Bandersnatch_SHA-512_TAI - vector-6",
83+
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-6",
8484
"sk": "da36359bf1bfd1694d3ed359e7340bd02a6a5e54827d94db1384df29f5bdd302",
8585
"pk": "e58e8ba2e99035fb7ae11fa14e2a609d6d13679278dac63ebee64ca8612ffa1480",
8686
"alpha": "42616e646572736e6174636820766563746f72",
@@ -96,7 +96,7 @@
9696
"proof_sb": "9e989c2ae5177ef9505705cc144116f0b633693ca4fcdb85ec9b073fa06afb08"
9797
},
9898
{
99-
"comment": "Bandersnatch_SHA-512_TAI - vector-7",
99+
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-7",
100100
"sk": "35b877a25c394512292b82bdf8468e98eaf03c79c7fc9d53546dadc5fb75b500",
101101
"pk": "7cba529a807bf602c84625fff28f4d1d836cf40a83f42d95c412f7b62ed9192900",
102102
"alpha": "42616e646572736e6174636820766563746f72",

‎data/bandersnatch_sw_sha512_tai_ring_vectors.json

+128
Large diffs are not rendered by default.
576 KB
Binary file not shown.

‎src/ring.rs

+170-5
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,9 @@ where
309309
#[cfg(test)]
310310
pub(crate) mod testing {
311311
use super::*;
312-
use crate::testing::*;
312+
use crate::{pedersen, testing as common};
313+
314+
pub const TEST_RING_SIZE: usize = 8;
313315

314316
pub fn prove_verify<S: RingSuite>()
315317
where
@@ -318,17 +320,17 @@ pub(crate) mod testing {
318320
AffinePoint<S>: utils::te_sw_map::SWMapping<CurveConfig<S>>,
319321
{
320322
let rng = &mut ark_std::test_rng();
321-
let ring_ctx = RingContext::<S>::from_rand(512, rng);
323+
let ring_ctx = RingContext::<S>::from_rand(TEST_RING_SIZE, rng);
322324

323-
let secret = Secret::<S>::from_seed(TEST_SEED);
325+
let secret = Secret::<S>::from_seed(common::TEST_SEED);
324326
let public = secret.public();
325-
let input = Input::from(random_val(Some(rng)));
327+
let input = Input::from(common::random_val(Some(rng)));
326328
let output = secret.output(input);
327329

328330
let ring_size = ring_ctx.max_ring_size();
329331

330332
let prover_idx = 3;
331-
let mut pks = random_vec::<AffinePoint<S>>(ring_size, Some(rng));
333+
let mut pks = common::random_vec::<AffinePoint<S>>(ring_size, Some(rng));
332334
pks[prover_idx] = public.0;
333335

334336
let prover_key = ring_ctx.prover_key(&pks);
@@ -370,4 +372,167 @@ pub(crate) mod testing {
370372
};
371373
($suite:ident, false) => {};
372374
}
375+
376+
pub trait RingSuiteExt: RingSuite
377+
where
378+
BaseField<Self>: ark_ff::PrimeField,
379+
CurveConfig<Self>: SWCurveConfig + Clone,
380+
AffinePoint<Self>: SWMapping<CurveConfig<Self>>,
381+
{
382+
fn ring_context() -> &'static RingContext<Self>;
383+
}
384+
385+
pub struct TestVector<S: RingSuite>
386+
where
387+
BaseField<S>: ark_ff::PrimeField,
388+
CurveConfig<S>: SWCurveConfig + Clone,
389+
AffinePoint<S>: SWMapping<CurveConfig<S>>,
390+
{
391+
pub pedersen: pedersen::testing::TestVector<S>,
392+
pub ring_pks: Box<[AffinePoint<S>; TEST_RING_SIZE]>,
393+
pub ring_proof: RingProof<S>,
394+
}
395+
396+
impl<S: RingSuite> core::fmt::Debug for TestVector<S>
397+
where
398+
BaseField<S>: ark_ff::PrimeField,
399+
CurveConfig<S>: SWCurveConfig + Clone,
400+
AffinePoint<S>: SWMapping<CurveConfig<S>>,
401+
{
402+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
403+
f.debug_struct("TestVector")
404+
.field("pedersen", &self.pedersen)
405+
.field("ring_proof", &"...")
406+
.finish()
407+
}
408+
}
409+
410+
impl<S: RingSuiteExt + std::fmt::Debug + 'static> common::TestVectorTrait for TestVector<S>
411+
where
412+
BaseField<S>: ark_ff::PrimeField,
413+
CurveConfig<S>: SWCurveConfig + Clone,
414+
AffinePoint<S>: SWMapping<CurveConfig<S>>,
415+
{
416+
fn new(comment: &str, seed: &[u8], alpha: &[u8], salt: Option<&[u8]>, ad: &[u8]) -> Self {
417+
use super::Prover;
418+
let pedersen = pedersen::testing::TestVector::new(comment, seed, alpha, salt, ad);
419+
420+
let secret = Secret::<S>::from_scalar(pedersen.base.sk);
421+
let public = secret.public();
422+
423+
let input = Input::<S>::from(pedersen.base.h);
424+
let output = Output::from(pedersen.base.gamma);
425+
426+
let ring_ctx = <S as RingSuiteExt>::ring_context();
427+
428+
use ark_std::rand::SeedableRng;
429+
let rng = &mut rand_chacha::ChaCha20Rng::from_seed([0x11; 32]);
430+
let prover_idx = 3;
431+
let mut ring_pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
432+
ring_pks[prover_idx] = public.0;
433+
434+
let prover_key = ring_ctx.prover_key(&ring_pks);
435+
let prover = ring_ctx.prover(prover_key, prover_idx);
436+
let proof = secret.prove(input, output, ad, &prover);
437+
438+
{
439+
// Just in case...
440+
let mut p = (Vec::new(), Vec::new());
441+
pedersen.proof.serialize_compressed(&mut p.0).unwrap();
442+
proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
443+
assert_eq!(p.0, p.1);
444+
}
445+
446+
// TODO: also dump the verifier pks commitmet
447+
Self {
448+
pedersen,
449+
ring_pks: crate::testing::vec_to_array(ring_pks).unwrap(),
450+
ring_proof: proof.ring_proof,
451+
}
452+
}
453+
454+
fn from_map(map: &common::TestVectorMap) -> Self {
455+
let pedersen = pedersen::testing::TestVector::from_map(map);
456+
457+
let ring_pks_raw = map.item_bytes("ring_pks");
458+
let ring_pks =
459+
<[AffinePoint<S>; TEST_RING_SIZE]>::deserialize_compressed(&ring_pks_raw[..])
460+
.map(Box::new)
461+
.unwrap();
462+
463+
let ring_proof_raw = map.item_bytes("ring_proof");
464+
let ring_proof = RingProof::<S>::deserialize_compressed(&ring_proof_raw[..]).unwrap();
465+
466+
Self {
467+
pedersen,
468+
ring_pks,
469+
ring_proof,
470+
}
471+
}
472+
473+
fn to_map(&self) -> common::TestVectorMap {
474+
let mut map = self.pedersen.to_map();
475+
476+
let mut ring_pks_raw = Vec::new();
477+
self.ring_pks
478+
.serialize_compressed(&mut ring_pks_raw)
479+
.unwrap();
480+
let ring_pks_hex = hex::encode(ring_pks_raw);
481+
map.0.insert("ring_pks".to_string(), ring_pks_hex);
482+
483+
let mut ring_proof_raw = Vec::new();
484+
self.ring_proof
485+
.serialize_compressed(&mut ring_proof_raw)
486+
.unwrap();
487+
let ring_proof_hex = hex::encode(ring_proof_raw);
488+
map.0.insert("ring_proof".to_string(), ring_proof_hex);
489+
490+
map
491+
}
492+
493+
fn run(&self) {
494+
self.pedersen.run();
495+
496+
let input = Input::<S>::from(self.pedersen.base.h);
497+
let output = Output::from(self.pedersen.base.gamma);
498+
let secret = Secret::from_scalar(self.pedersen.base.sk);
499+
let public = secret.public();
500+
assert_eq!(public.0, self.pedersen.base.pk);
501+
502+
let ring_ctx = <S as RingSuiteExt>::ring_context();
503+
504+
let ring_pks = &*self.ring_pks;
505+
let prover_idx = ring_pks.iter().position(|&pk| pk == public.0).unwrap();
506+
507+
let prover_key = ring_ctx.prover_key(ring_pks);
508+
let prover = ring_ctx.prover(prover_key, prover_idx);
509+
510+
let verifier_key = ring_ctx.verifier_key(ring_pks);
511+
let verifier = ring_ctx.verifier(verifier_key);
512+
513+
let proof = secret.prove(input, output, &self.pedersen.base.ad, &prover);
514+
515+
{
516+
// Check if Pedersen proof matches
517+
let mut p = (Vec::new(), Vec::new());
518+
self.pedersen.proof.serialize_compressed(&mut p.0).unwrap();
519+
proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
520+
assert_eq!(p.0, p.1);
521+
}
522+
523+
// TODO
524+
#[cfg(feature = "test-vectors")]
525+
{
526+
// Check if Ring proof matches
527+
let mut p = (Vec::new(), Vec::new());
528+
self.ring_proof.serialize_compressed(&mut p.0).unwrap();
529+
proof.ring_proof.serialize_compressed(&mut p.1).unwrap();
530+
assert_eq!(p.0, p.1);
531+
}
532+
533+
assert!(
534+
Public::verify(input, output, &self.pedersen.base.ad, &proof, &verifier).is_ok()
535+
);
536+
}
537+
}
373538
}

‎src/suites/bandersnatch.rs

+83-1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,47 @@ mod test_vectors_pedersen_ed {
293293
}
294294
}
295295

296+
#[cfg(all(test, feature = "ring"))]
297+
mod test_vectors_ring_ed {
298+
use super::edwards::*;
299+
use crate::testing;
300+
301+
type V = crate::ring::testing::TestVector<BandersnatchSha512Ell2>;
302+
303+
const TEST_VECTORS_FILE: &str = concat!(
304+
env!("CARGO_MANIFEST_DIR"),
305+
"/data/bandersnatch_ed_sha512_ell2_ring_vectors.json"
306+
);
307+
308+
impl crate::ring::testing::RingSuiteExt for BandersnatchSha512Ell2 {
309+
fn ring_context() -> &'static RingContext {
310+
use ark_serialize::CanonicalDeserialize;
311+
use std::sync::OnceLock;
312+
static RING_CTX: OnceLock<RingContext> = OnceLock::new();
313+
RING_CTX.get_or_init(|| {
314+
use std::{fs::File, io::Read};
315+
let mut file = File::open(crate::testing::PCS_SRS_FILE).unwrap();
316+
let mut buf = Vec::new();
317+
file.read_to_end(&mut buf).unwrap();
318+
let pcs_params =
319+
PcsParams::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
320+
RingContext::from_srs(crate::ring::testing::TEST_RING_SIZE, pcs_params).unwrap()
321+
})
322+
}
323+
}
324+
325+
#[test]
326+
#[ignore = "test vectors generator"]
327+
fn generate() {
328+
testing::test_vectors_generate::<V>(TEST_VECTORS_FILE, "Bandersnatch_SHA-512_ELL2");
329+
}
330+
331+
#[test]
332+
fn process() {
333+
testing::test_vectors_process::<V>(TEST_VECTORS_FILE);
334+
}
335+
}
336+
296337
#[cfg(test)]
297338
mod test_vectors_ietf_sw {
298339
use super::weierstrass::*;
@@ -332,7 +373,48 @@ mod test_vectors_pedersen_sw {
332373
#[test]
333374
#[ignore = "test vectors generator"]
334375
fn generate() {
335-
testing::test_vectors_generate::<V>(TEST_VECTORS_FILE, "Bandersnatch_SHA-512_TAI");
376+
testing::test_vectors_generate::<V>(TEST_VECTORS_FILE, "Bandersnatch_SW_SHA-512_TAI");
377+
}
378+
379+
#[test]
380+
fn process() {
381+
testing::test_vectors_process::<V>(TEST_VECTORS_FILE);
382+
}
383+
}
384+
385+
#[cfg(all(test, feature = "ring"))]
386+
mod test_vectors_ring_sw {
387+
use super::weierstrass::*;
388+
use crate::testing;
389+
390+
type V = crate::ring::testing::TestVector<BandersnatchSha512Tai>;
391+
392+
const TEST_VECTORS_FILE: &str = concat!(
393+
env!("CARGO_MANIFEST_DIR"),
394+
"/data/bandersnatch_sw_sha512_tai_ring_vectors.json"
395+
);
396+
397+
impl crate::ring::testing::RingSuiteExt for BandersnatchSha512Tai {
398+
fn ring_context() -> &'static RingContext {
399+
use ark_serialize::CanonicalDeserialize;
400+
use std::sync::OnceLock;
401+
static RING_CTX: OnceLock<RingContext> = OnceLock::new();
402+
RING_CTX.get_or_init(|| {
403+
use std::{fs::File, io::Read};
404+
let mut file = File::open(crate::testing::PCS_SRS_FILE).unwrap();
405+
let mut buf = Vec::new();
406+
file.read_to_end(&mut buf).unwrap();
407+
let pcs_params =
408+
PcsParams::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
409+
RingContext::from_srs(crate::ring::testing::TEST_RING_SIZE, pcs_params).unwrap()
410+
})
411+
}
412+
}
413+
414+
#[test]
415+
#[ignore = "test vectors generator"]
416+
fn generate() {
417+
testing::test_vectors_generate::<V>(TEST_VECTORS_FILE, "Bandersnatch_SW_SHA-512_TAI");
336418
}
337419

338420
#[test]

‎src/testing.rs

+16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ use ark_std::{rand::RngCore, UniformRand};
77

88
pub const TEST_SEED: &[u8] = b"seed";
99

10+
// Zcash SRS file derived from (https://zfnd.org/conclusion-of-the-powers-of-tau-ceremony).
11+
pub const PCS_SRS_FILE: &str = concat!(
12+
env!("CARGO_MANIFEST_DIR"),
13+
"/data/zcash-bls12-381-srs-2-11-uncompressed.bin"
14+
);
15+
1016
/// Generate a vector of random values.
1117
pub fn random_vec<T: UniformRand>(n: usize, rng: Option<&mut dyn RngCore>) -> Vec<T> {
1218
let mut local_rng = ark_std::test_rng();
@@ -21,6 +27,16 @@ pub fn random_val<T: UniformRand>(rng: Option<&mut dyn RngCore>) -> T {
2127
T::rand(rng)
2228
}
2329

30+
pub fn vec_to_array<T: core::fmt::Debug, const N: usize>(v: Vec<T>) -> Option<Box<[T; N]>> {
31+
if v.len() != N {
32+
return None;
33+
}
34+
// Safe because we checked the length
35+
let boxed_slice = v.into_boxed_slice();
36+
let boxed_array = boxed_slice.try_into().unwrap();
37+
Some(boxed_array)
38+
}
39+
2440
#[macro_export]
2541
macro_rules! suite_tests {
2642
($suite:ident, $build_ring:ident) => {

0 commit comments

Comments
 (0)
This repository has been archived.