From c9e4296416a4a6789c64baf536a5cc0bc96f9c2a Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Tue, 6 Oct 2020 18:06:22 +0200 Subject: [PATCH] implement randomized tests for proof verification --- src/groth16/tests/mod.rs | 218 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/src/groth16/tests/mod.rs b/src/groth16/tests/mod.rs index 3f7f5d448..0b29e4eed 100644 --- a/src/groth16/tests/mod.rs +++ b/src/groth16/tests/mod.rs @@ -1,5 +1,8 @@ use crate::bls::Engine; + use ff::{Field, PrimeField}; +use rand_core::SeedableRng; +use rand_xorshift::XorShiftRng; mod dummy_engine; use self::dummy_engine::*; @@ -436,3 +439,218 @@ fn test_create_batch_single() { assert!(verify_proof(&pvk, &proof, &[Fr::one()]).unwrap()); } } + +#[test] +fn test_verify_random_single() { + use crate::bls::{Bls12, Fr, G1Projective, G2Projective}; + use crate::groth16::{create_random_proof, generate_random_parameters, Proof}; + use groupy::{CurveAffine, CurveProjective}; + + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); + + let params = { + let c = XORDemo:: { + a: None, + b: None, + _marker: PhantomData, + }; + + generate_random_parameters::(c, &mut rng).unwrap() + }; + + let pvk = prepare_verifying_key(¶ms.vk); + + for _ in 0..50 { + let c = XORDemo { + a: Some(true), + b: Some(false), + _marker: PhantomData, + }; + + let proof = create_random_proof(c.clone(), ¶ms, &mut rng).unwrap(); + + // real proofs + assert!(verify_proof(&pvk, &proof, &[Fr::one()]).unwrap()); + + // mess up the inputs + { + assert!(!verify_proof(&pvk, &proof, &[Fr::random(&mut rng)]).unwrap()); + } + + // mess up the proof a little bit + { + let mut fake_proof = proof.clone(); + fake_proof.a = fake_proof.a.mul(Fr::random(&mut rng)).into_affine(); + assert!(!verify_proof(&pvk, &fake_proof, &[Fr::one()]).unwrap()); + } + + { + let mut fake_proof = proof.clone(); + fake_proof.b = fake_proof.b.mul(Fr::random(&mut rng)).into_affine(); + assert!(!verify_proof(&pvk, &fake_proof, &[Fr::one()]).unwrap()); + } + + { + let mut fake_proof = proof.clone(); + fake_proof.c = fake_proof.c.mul(Fr::random(&mut rng)).into_affine(); + assert!(!verify_proof(&pvk, &fake_proof, &[Fr::one()]).unwrap()); + } + + { + let mut fake_proof = proof.clone(); + let c = fake_proof.c; + fake_proof.c = fake_proof.a; + fake_proof.a = c; + assert!(!verify_proof(&pvk, &fake_proof, &[Fr::one()]).unwrap()); + } + + // entirely random proofs + { + let random_proof = Proof { + a: G1Projective::random(&mut rng).into_affine(), + b: G2Projective::random(&mut rng).into_affine(), + c: G1Projective::random(&mut rng).into_affine(), + }; + assert!(!verify_proof(&pvk, &random_proof, &[Fr::one()]).unwrap()); + } + } +} + +#[test] +fn test_verify_random_batch() { + use crate::bls::{Bls12, Fr, G1Projective, G2Projective}; + use crate::groth16::{ + create_random_proof_batch, generate_random_parameters, verify_proofs_batch, Proof, + }; + use groupy::{CurveAffine, CurveProjective}; + + let mut rng = XorShiftRng::from_seed([ + 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, + 0xe5, + ]); + + let params = { + let c = XORDemo:: { + a: None, + b: None, + _marker: PhantomData, + }; + + generate_random_parameters::(c, &mut rng).unwrap() + }; + + let pvk = prepare_verifying_key(¶ms.vk); + + let inputs = vec![vec![Fr::one()], vec![Fr::one()], vec![Fr::one()]]; + for _ in 0..50 { + let c = XORDemo { + a: Some(true), + b: Some(false), + _marker: PhantomData, + }; + + let proof = + create_random_proof_batch(vec![c.clone(), c.clone(), c.clone()], ¶ms, &mut rng) + .unwrap(); + + // real proofs + assert!( + verify_proofs_batch(&pvk, &mut rng, &[&proof[0], &proof[1], &proof[2]], &inputs) + .unwrap() + ); + + // mess up the inputs + { + let r = Fr::random(&mut rng); + assert!(!verify_proofs_batch( + &pvk, + &mut rng, + &[&proof[0], &proof[1], &proof[2]], + &[vec![r], vec![Fr::one()], vec![Fr::one()]], + ) + .unwrap()); + } + + // mess up the proof a little bit + { + let mut fake_proof = proof.clone(); + fake_proof[0].a = fake_proof[0].a.mul(Fr::random(&mut rng)).into_affine(); + assert!(!verify_proofs_batch( + &pvk, + &mut rng, + &[&fake_proof[0], &fake_proof[1], &fake_proof[2]], + &inputs + ) + .unwrap()); + } + + { + let mut fake_proof = proof.clone(); + fake_proof[1].b = fake_proof[1].b.mul(Fr::random(&mut rng)).into_affine(); + assert!(!verify_proofs_batch( + &pvk, + &mut rng, + &[&fake_proof[0], &fake_proof[1], &fake_proof[2]], + &inputs + ) + .unwrap()); + } + + { + let mut fake_proof = proof.clone(); + fake_proof[2].c = fake_proof[2].c.mul(Fr::random(&mut rng)).into_affine(); + assert!(!verify_proofs_batch( + &pvk, + &mut rng, + &[&fake_proof[0], &fake_proof[1], &fake_proof[2]], + &inputs + ) + .unwrap()); + } + + { + let mut fake_proof = proof.clone(); + let c = fake_proof[0].c; + fake_proof[0].c = fake_proof[0].a; + fake_proof[0].a = c; + assert!(!verify_proofs_batch( + &pvk, + &mut rng, + &[&fake_proof[0], &fake_proof[1], &fake_proof[2]], + &inputs + ) + .unwrap()); + } + + // entirely random proofs + { + let random_proof = [ + Proof { + a: G1Projective::random(&mut rng).into_affine(), + b: G2Projective::random(&mut rng).into_affine(), + c: G1Projective::random(&mut rng).into_affine(), + }, + Proof { + a: G1Projective::random(&mut rng).into_affine(), + b: G2Projective::random(&mut rng).into_affine(), + c: G1Projective::random(&mut rng).into_affine(), + }, + Proof { + a: G1Projective::random(&mut rng).into_affine(), + b: G2Projective::random(&mut rng).into_affine(), + c: G1Projective::random(&mut rng).into_affine(), + }, + ]; + assert!(!verify_proofs_batch( + &pvk, + &mut rng, + &[&random_proof[0], &random_proof[1], &random_proof[2],], + &inputs + ) + .unwrap()); + } + } +}