Skip to content

Commit

Permalink
Ring VRF test vectors (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
davxy authored Jul 27, 2024
1 parent 6b07f6f commit 209b258
Show file tree
Hide file tree
Showing 7 changed files with 532 additions and 13 deletions.
128 changes: 128 additions & 0 deletions data/bandersnatch_ed_sha512_ell2_ring_vectors.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions data/bandersnatch_sw_sha512_tai_pedersen_vectors.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"comment": "Bandersnatch_SHA-512_TAI - vector-1",
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-1",
"sk": "3d6406500d4009fdf2604546093665911e753f2213570a29521fd88bc30ede18",
"pk": "fd72a90d1eeba6733824e76bb31991b8108d6562756b85f244333e3c7205225200",
"alpha": "",
Expand All @@ -16,7 +16,7 @@
"proof_sb": "6b2dbc4b088b21d732cc5193439b5186cddecb4ee12f8233cbe3057c06849216"
},
{
"comment": "Bandersnatch_SHA-512_TAI - vector-2",
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-2",
"sk": "8b9063872331dda4c3c282f7d813fb3c13e7339b7dc9635fdc764e32cc57cb15",
"pk": "e30eae606d21dff460cdaecfc9bfcd2e319628ccc0242f3ca21f2d5c940ba41680",
"alpha": "0a",
Expand All @@ -32,7 +32,7 @@
"proof_sb": "f05d631c7ae9fbc33ea4464af81188c1342f7c6aa127531e1f1bd203d608f613"
},
{
"comment": "Bandersnatch_SHA-512_TAI - vector-3",
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-3",
"sk": "6db187202f69e627e432296ae1d0f166ae6ac3c1222585b6ceae80ea07670b14",
"pk": "2a00e5a32e2f097858a1a4a73cf5c2fb4e6d375a4ea4cc3ae3e91660eade850c80",
"alpha": "",
Expand All @@ -48,7 +48,7 @@
"proof_sb": "07a177cf9a9d08282194c8cc0d856be3de2681c642ecd0cb95a014a82f7f5c11"
},
{
"comment": "Bandersnatch_SHA-512_TAI - vector-4",
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-4",
"sk": "b56cc204f1b6c2323709012cb16c72f3021035ce935fbe69b600a88d842c7407",
"pk": "4f29d79a27b9545d7223431eb6a63776949454b16e2ac0b7a959304ce3e52b6a00",
"alpha": "73616d706c65",
Expand All @@ -64,7 +64,7 @@
"proof_sb": "5b4d6ef3445d8dc8bcc38f44b3649d39fcb5c0b169c5085245f6903ef8ba940c"
},
{
"comment": "Bandersnatch_SHA-512_TAI - vector-5",
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-5",
"sk": "da36359bf1bfd1694d3ed359e7340bd02a6a5e54827d94db1384df29f5bdd302",
"pk": "e58e8ba2e99035fb7ae11fa14e2a609d6d13679278dac63ebee64ca8612ffa1480",
"alpha": "42616e646572736e6174636820766563746f72",
Expand All @@ -80,7 +80,7 @@
"proof_sb": "bd365d1ff09f59a9ad885bf3f71e81151747757788f6c07387f4100842784e13"
},
{
"comment": "Bandersnatch_SHA-512_TAI - vector-6",
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-6",
"sk": "da36359bf1bfd1694d3ed359e7340bd02a6a5e54827d94db1384df29f5bdd302",
"pk": "e58e8ba2e99035fb7ae11fa14e2a609d6d13679278dac63ebee64ca8612ffa1480",
"alpha": "42616e646572736e6174636820766563746f72",
Expand All @@ -96,7 +96,7 @@
"proof_sb": "9e989c2ae5177ef9505705cc144116f0b633693ca4fcdb85ec9b073fa06afb08"
},
{
"comment": "Bandersnatch_SHA-512_TAI - vector-7",
"comment": "Bandersnatch_SW_SHA-512_TAI - vector-7",
"sk": "35b877a25c394512292b82bdf8468e98eaf03c79c7fc9d53546dadc5fb75b500",
"pk": "7cba529a807bf602c84625fff28f4d1d836cf40a83f42d95c412f7b62ed9192900",
"alpha": "42616e646572736e6174636820766563746f72",
Expand Down
128 changes: 128 additions & 0 deletions data/bandersnatch_sw_sha512_tai_ring_vectors.json

Large diffs are not rendered by default.

Binary file added data/zcash-bls12-381-srs-2-11-uncompressed.bin
Binary file not shown.
175 changes: 170 additions & 5 deletions src/ring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,9 @@ where
#[cfg(test)]
pub(crate) mod testing {
use super::*;
use crate::testing::*;
use crate::{pedersen, testing as common};

pub const TEST_RING_SIZE: usize = 8;

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

let secret = Secret::<S>::from_seed(TEST_SEED);
let secret = Secret::<S>::from_seed(common::TEST_SEED);
let public = secret.public();
let input = Input::from(random_val(Some(rng)));
let input = Input::from(common::random_val(Some(rng)));
let output = secret.output(input);

let ring_size = ring_ctx.max_ring_size();

let prover_idx = 3;
let mut pks = random_vec::<AffinePoint<S>>(ring_size, Some(rng));
let mut pks = common::random_vec::<AffinePoint<S>>(ring_size, Some(rng));
pks[prover_idx] = public.0;

let prover_key = ring_ctx.prover_key(&pks);
Expand Down Expand Up @@ -370,4 +372,167 @@ pub(crate) mod testing {
};
($suite:ident, false) => {};
}

pub trait RingSuiteExt: RingSuite
where
BaseField<Self>: ark_ff::PrimeField,
CurveConfig<Self>: SWCurveConfig + Clone,
AffinePoint<Self>: SWMapping<CurveConfig<Self>>,
{
fn ring_context() -> &'static RingContext<Self>;
}

pub struct TestVector<S: RingSuite>
where
BaseField<S>: ark_ff::PrimeField,
CurveConfig<S>: SWCurveConfig + Clone,
AffinePoint<S>: SWMapping<CurveConfig<S>>,
{
pub pedersen: pedersen::testing::TestVector<S>,
pub ring_pks: Box<[AffinePoint<S>; TEST_RING_SIZE]>,
pub ring_proof: RingProof<S>,
}

impl<S: RingSuite> core::fmt::Debug for TestVector<S>
where
BaseField<S>: ark_ff::PrimeField,
CurveConfig<S>: SWCurveConfig + Clone,
AffinePoint<S>: SWMapping<CurveConfig<S>>,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("TestVector")
.field("pedersen", &self.pedersen)
.field("ring_proof", &"...")
.finish()
}
}

impl<S: RingSuiteExt + std::fmt::Debug + 'static> common::TestVectorTrait for TestVector<S>
where
BaseField<S>: ark_ff::PrimeField,
CurveConfig<S>: SWCurveConfig + Clone,
AffinePoint<S>: SWMapping<CurveConfig<S>>,
{
fn new(comment: &str, seed: &[u8], alpha: &[u8], salt: Option<&[u8]>, ad: &[u8]) -> Self {
use super::Prover;
let pedersen = pedersen::testing::TestVector::new(comment, seed, alpha, salt, ad);

let secret = Secret::<S>::from_scalar(pedersen.base.sk);
let public = secret.public();

let input = Input::<S>::from(pedersen.base.h);
let output = Output::from(pedersen.base.gamma);

let ring_ctx = <S as RingSuiteExt>::ring_context();

use ark_std::rand::SeedableRng;
let rng = &mut rand_chacha::ChaCha20Rng::from_seed([0x11; 32]);
let prover_idx = 3;
let mut ring_pks = common::random_vec::<AffinePoint<S>>(TEST_RING_SIZE, Some(rng));
ring_pks[prover_idx] = public.0;

let prover_key = ring_ctx.prover_key(&ring_pks);
let prover = ring_ctx.prover(prover_key, prover_idx);
let proof = secret.prove(input, output, ad, &prover);

{
// Just in case...
let mut p = (Vec::new(), Vec::new());
pedersen.proof.serialize_compressed(&mut p.0).unwrap();
proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
assert_eq!(p.0, p.1);
}

// TODO: also dump the verifier pks commitmet
Self {
pedersen,
ring_pks: crate::testing::vec_to_array(ring_pks).unwrap(),
ring_proof: proof.ring_proof,
}
}

fn from_map(map: &common::TestVectorMap) -> Self {
let pedersen = pedersen::testing::TestVector::from_map(map);

let ring_pks_raw = map.item_bytes("ring_pks");
let ring_pks =
<[AffinePoint<S>; TEST_RING_SIZE]>::deserialize_compressed(&ring_pks_raw[..])
.map(Box::new)
.unwrap();

let ring_proof_raw = map.item_bytes("ring_proof");
let ring_proof = RingProof::<S>::deserialize_compressed(&ring_proof_raw[..]).unwrap();

Self {
pedersen,
ring_pks,
ring_proof,
}
}

fn to_map(&self) -> common::TestVectorMap {
let mut map = self.pedersen.to_map();

let mut ring_pks_raw = Vec::new();
self.ring_pks
.serialize_compressed(&mut ring_pks_raw)
.unwrap();
let ring_pks_hex = hex::encode(ring_pks_raw);
map.0.insert("ring_pks".to_string(), ring_pks_hex);

let mut ring_proof_raw = Vec::new();
self.ring_proof
.serialize_compressed(&mut ring_proof_raw)
.unwrap();
let ring_proof_hex = hex::encode(ring_proof_raw);
map.0.insert("ring_proof".to_string(), ring_proof_hex);

map
}

fn run(&self) {
self.pedersen.run();

let input = Input::<S>::from(self.pedersen.base.h);
let output = Output::from(self.pedersen.base.gamma);
let secret = Secret::from_scalar(self.pedersen.base.sk);
let public = secret.public();
assert_eq!(public.0, self.pedersen.base.pk);

let ring_ctx = <S as RingSuiteExt>::ring_context();

let ring_pks = &*self.ring_pks;
let prover_idx = ring_pks.iter().position(|&pk| pk == public.0).unwrap();

let prover_key = ring_ctx.prover_key(ring_pks);
let prover = ring_ctx.prover(prover_key, prover_idx);

let verifier_key = ring_ctx.verifier_key(ring_pks);
let verifier = ring_ctx.verifier(verifier_key);

let proof = secret.prove(input, output, &self.pedersen.base.ad, &prover);

{
// Check if Pedersen proof matches
let mut p = (Vec::new(), Vec::new());
self.pedersen.proof.serialize_compressed(&mut p.0).unwrap();
proof.pedersen_proof.serialize_compressed(&mut p.1).unwrap();
assert_eq!(p.0, p.1);
}

// TODO
#[cfg(feature = "test-vectors")]
{
// Check if Ring proof matches
let mut p = (Vec::new(), Vec::new());
self.ring_proof.serialize_compressed(&mut p.0).unwrap();
proof.ring_proof.serialize_compressed(&mut p.1).unwrap();
assert_eq!(p.0, p.1);
}

assert!(
Public::verify(input, output, &self.pedersen.base.ad, &proof, &verifier).is_ok()
);
}
}
}
84 changes: 83 additions & 1 deletion src/suites/bandersnatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,47 @@ mod test_vectors_pedersen_ed {
}
}

#[cfg(all(test, feature = "ring"))]
mod test_vectors_ring_ed {
use super::edwards::*;
use crate::testing;

type V = crate::ring::testing::TestVector<BandersnatchSha512Ell2>;

const TEST_VECTORS_FILE: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/data/bandersnatch_ed_sha512_ell2_ring_vectors.json"
);

impl crate::ring::testing::RingSuiteExt for BandersnatchSha512Ell2 {
fn ring_context() -> &'static RingContext {
use ark_serialize::CanonicalDeserialize;
use std::sync::OnceLock;
static RING_CTX: OnceLock<RingContext> = OnceLock::new();
RING_CTX.get_or_init(|| {
use std::{fs::File, io::Read};
let mut file = File::open(crate::testing::PCS_SRS_FILE).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
let pcs_params =
PcsParams::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
RingContext::from_srs(crate::ring::testing::TEST_RING_SIZE, pcs_params).unwrap()
})
}
}

#[test]
#[ignore = "test vectors generator"]
fn generate() {
testing::test_vectors_generate::<V>(TEST_VECTORS_FILE, "Bandersnatch_SHA-512_ELL2");
}

#[test]
fn process() {
testing::test_vectors_process::<V>(TEST_VECTORS_FILE);
}
}

#[cfg(test)]
mod test_vectors_ietf_sw {
use super::weierstrass::*;
Expand Down Expand Up @@ -332,7 +373,48 @@ mod test_vectors_pedersen_sw {
#[test]
#[ignore = "test vectors generator"]
fn generate() {
testing::test_vectors_generate::<V>(TEST_VECTORS_FILE, "Bandersnatch_SHA-512_TAI");
testing::test_vectors_generate::<V>(TEST_VECTORS_FILE, "Bandersnatch_SW_SHA-512_TAI");
}

#[test]
fn process() {
testing::test_vectors_process::<V>(TEST_VECTORS_FILE);
}
}

#[cfg(all(test, feature = "ring"))]
mod test_vectors_ring_sw {
use super::weierstrass::*;
use crate::testing;

type V = crate::ring::testing::TestVector<BandersnatchSha512Tai>;

const TEST_VECTORS_FILE: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/data/bandersnatch_sw_sha512_tai_ring_vectors.json"
);

impl crate::ring::testing::RingSuiteExt for BandersnatchSha512Tai {
fn ring_context() -> &'static RingContext {
use ark_serialize::CanonicalDeserialize;
use std::sync::OnceLock;
static RING_CTX: OnceLock<RingContext> = OnceLock::new();
RING_CTX.get_or_init(|| {
use std::{fs::File, io::Read};
let mut file = File::open(crate::testing::PCS_SRS_FILE).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
let pcs_params =
PcsParams::deserialize_uncompressed_unchecked(&mut &buf[..]).unwrap();
RingContext::from_srs(crate::ring::testing::TEST_RING_SIZE, pcs_params).unwrap()
})
}
}

#[test]
#[ignore = "test vectors generator"]
fn generate() {
testing::test_vectors_generate::<V>(TEST_VECTORS_FILE, "Bandersnatch_SW_SHA-512_TAI");
}

#[test]
Expand Down
16 changes: 16 additions & 0 deletions src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ use ark_std::{rand::RngCore, UniformRand};

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

// Zcash SRS file derived from (https://zfnd.org/conclusion-of-the-powers-of-tau-ceremony).
pub const PCS_SRS_FILE: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/data/zcash-bls12-381-srs-2-11-uncompressed.bin"
);

/// Generate a vector of random values.
pub fn random_vec<T: UniformRand>(n: usize, rng: Option<&mut dyn RngCore>) -> Vec<T> {
let mut local_rng = ark_std::test_rng();
Expand All @@ -21,6 +27,16 @@ pub fn random_val<T: UniformRand>(rng: Option<&mut dyn RngCore>) -> T {
T::rand(rng)
}

pub fn vec_to_array<T: core::fmt::Debug, const N: usize>(v: Vec<T>) -> Option<Box<[T; N]>> {
if v.len() != N {
return None;
}
// Safe because we checked the length
let boxed_slice = v.into_boxed_slice();
let boxed_array = boxed_slice.try_into().unwrap();
Some(boxed_array)
}

#[macro_export]
macro_rules! suite_tests {
($suite:ident, $build_ring:ident) => {
Expand Down

0 comments on commit 209b258

Please sign in to comment.