// -*- coding: utf-8; mode: rust; -*- // // To the extent possible under law, the authors have waived all // copyright and related or neighboring rights to zkp, // using the Creative Commons "CC0" public domain dedication. See // for full // details. // // Authors: // - Henry de Valence #![feature(test)] #![allow(non_snake_case)] extern crate bincode; extern crate curve25519_dalek; extern crate serde; #[macro_use] extern crate serde_derive; extern crate sha2; #[macro_use] extern crate zkp; extern crate test; use test::Bencher; use self::sha2::Sha512; use curve25519_dalek::constants as dalek_constants; use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; use zkp::toolbox::{batch_verifier::BatchVerifier, prover::Prover, verifier::Verifier, SchnorrCS}; use zkp::Transcript; #[allow(non_snake_case)] fn dleq_statement( cs: &mut CS, x: CS::ScalarVar, A: CS::PointVar, B: CS::PointVar, G: CS::PointVar, H: CS::PointVar, ) { cs.constrain(A, vec![(x, G)]); cs.constrain(B, vec![(x, H)]); } #[bench] fn create_compact_dleq(b: &mut Bencher) { let G = dalek_constants::RISTRETTO_BASEPOINT_POINT; let H = RistrettoPoint::hash_from_bytes::(G.compress().as_bytes()); let x = Scalar::from(89327492234u64); let A = G * x; let B = H * x; b.iter(|| { let mut transcript = Transcript::new(b"DLEQTest"); let mut prover = Prover::new(b"DLEQProof", &mut transcript); let var_x = prover.allocate_scalar(b"x", x); let (var_G, _) = prover.allocate_point(b"G", G); let (var_H, _) = prover.allocate_point(b"H", H); let (var_A, _cmpr_A) = prover.allocate_point(b"A", A); let (var_B, _cmpr_B) = prover.allocate_point(b"B", B); dleq_statement(&mut prover, var_x, var_A, var_B, var_G, var_H); prover.prove_compact() }); } #[bench] fn verify_compact_dleq(b: &mut Bencher) { let G = dalek_constants::RISTRETTO_BASEPOINT_POINT; let H = RistrettoPoint::hash_from_bytes::(G.compress().as_bytes()); let (proof, cmpr_A, cmpr_B) = { let x = Scalar::from(89327492234u64); let A = G * x; let B = H * x; let mut transcript = Transcript::new(b"DLEQTest"); let mut prover = Prover::new(b"DLEQProof", &mut transcript); // XXX committing var names to transcript forces ordering (?) let var_x = prover.allocate_scalar(b"x", x); let (var_G, _) = prover.allocate_point(b"G", G); let (var_H, _) = prover.allocate_point(b"H", H); let (var_A, cmpr_A) = prover.allocate_point(b"A", A); let (var_B, cmpr_B) = prover.allocate_point(b"B", B); dleq_statement(&mut prover, var_x, var_A, var_B, var_G, var_H); (prover.prove_compact(), cmpr_A, cmpr_B) }; let cmpr_G = G.compress(); let cmpr_H = H.compress(); b.iter(|| { let mut transcript = Transcript::new(b"DLEQTest"); let mut verifier = Verifier::new(b"DLEQProof", &mut transcript); let var_x = verifier.allocate_scalar(b"x"); let var_G = verifier.allocate_point(b"G", cmpr_G).unwrap(); let var_H = verifier.allocate_point(b"H", cmpr_H).unwrap(); let var_A = verifier.allocate_point(b"A", cmpr_A).unwrap(); let var_B = verifier.allocate_point(b"B", cmpr_B).unwrap(); dleq_statement(&mut verifier, var_x, var_A, var_B, var_G, var_H); verifier.verify_compact(&proof) }); } #[bench] fn create_batchable_dleq(b: &mut Bencher) { let G = dalek_constants::RISTRETTO_BASEPOINT_POINT; let H = RistrettoPoint::hash_from_bytes::(G.compress().as_bytes()); let x = Scalar::from(89327492234u64); let A = G * x; let B = H * x; b.iter(|| { let mut transcript = Transcript::new(b"DLEQTest"); let mut prover = Prover::new(b"DLEQProof", &mut transcript); let var_x = prover.allocate_scalar(b"x", x); let (var_G, _) = prover.allocate_point(b"G", G); let (var_H, _) = prover.allocate_point(b"H", H); let (var_A, _cmpr_A) = prover.allocate_point(b"A", A); let (var_B, _cmpr_B) = prover.allocate_point(b"B", B); dleq_statement(&mut prover, var_x, var_A, var_B, var_G, var_H); prover.prove_batchable() }); } #[bench] fn verify_batchable_dleq(b: &mut Bencher) { let G = dalek_constants::RISTRETTO_BASEPOINT_POINT; let H = RistrettoPoint::hash_from_bytes::(G.compress().as_bytes()); let (proof, cmpr_A, cmpr_B) = { let x = Scalar::from(89327492234u64); let A = G * x; let B = H * x; let mut transcript = Transcript::new(b"DLEQTest"); let mut prover = Prover::new(b"DLEQProof", &mut transcript); let var_x = prover.allocate_scalar(b"x", x); let (var_G, _) = prover.allocate_point(b"G", G); let (var_H, _) = prover.allocate_point(b"H", H); let (var_A, cmpr_A) = prover.allocate_point(b"A", A); let (var_B, cmpr_B) = prover.allocate_point(b"B", B); dleq_statement(&mut prover, var_x, var_A, var_B, var_G, var_H); (prover.prove_batchable(), cmpr_A, cmpr_B) }; let cmpr_G = G.compress(); let cmpr_H = H.compress(); b.iter(|| { let mut transcript = Transcript::new(b"DLEQTest"); let mut verifier = Verifier::new(b"DLEQProof", &mut transcript); let var_x = verifier.allocate_scalar(b"x"); let var_G = verifier.allocate_point(b"G", cmpr_G).unwrap(); let var_H = verifier.allocate_point(b"H", cmpr_H).unwrap(); let var_A = verifier.allocate_point(b"A", cmpr_A).unwrap(); let var_B = verifier.allocate_point(b"B", cmpr_B).unwrap(); dleq_statement(&mut verifier, var_x, var_A, var_B, var_G, var_H); verifier.verify_batchable(&proof) }); } fn batch_verify_batchable_dleq_helper(batch_size: usize, b: &mut Bencher) { let G = dalek_constants::RISTRETTO_BASEPOINT_POINT; let H = RistrettoPoint::hash_from_bytes::(G.compress().as_bytes()); let mut proofs = Vec::new(); let mut cmpr_As = Vec::new(); let mut cmpr_Bs = Vec::new(); for j in 0..batch_size { let (proof, cmpr_A, cmpr_B) = { let x = Scalar::from((j as u64) + 89327492234u64); let A = G * x; let B = H * x; let mut transcript = Transcript::new(b"DLEQBatchTest"); let mut prover = Prover::new(b"DLEQProof", &mut transcript); // XXX committing var names to transcript forces ordering (?) let var_x = prover.allocate_scalar(b"x", x); let (var_G, _) = prover.allocate_point(b"G", G); let (var_H, _) = prover.allocate_point(b"H", H); let (var_A, cmpr_A) = prover.allocate_point(b"A", A); let (var_B, cmpr_B) = prover.allocate_point(b"B", B); dleq_statement(&mut prover, var_x, var_A, var_B, var_G, var_H); (prover.prove_batchable(), cmpr_A, cmpr_B) }; proofs.push(proof); cmpr_As.push(cmpr_A); cmpr_Bs.push(cmpr_B); } b.iter(|| { let mut transcripts = vec![Transcript::new(b"DLEQBatchTest"); batch_size]; let transcript_refs = transcripts.iter_mut().collect(); let mut verifier = BatchVerifier::new(b"DLEQProof", batch_size, transcript_refs).unwrap(); let var_x = verifier.allocate_scalar(b"x"); let var_G = verifier.allocate_static_point(b"G", G.compress()).unwrap(); let var_H = verifier.allocate_static_point(b"H", H.compress()).unwrap(); let var_A = verifier .allocate_instance_point(b"A", cmpr_As.clone()) .unwrap(); let var_B = verifier .allocate_instance_point(b"B", cmpr_Bs.clone()) .unwrap(); dleq_statement(&mut verifier, var_x, var_A, var_B, var_G, var_H); assert!(verifier.verify_batchable(&proofs).is_ok()); }); } #[bench] fn batch_verify_batchable_dleq_1(b: &mut Bencher) { batch_verify_batchable_dleq_helper(1, b) } #[bench] fn batch_verify_batchable_dleq_4(b: &mut Bencher) { batch_verify_batchable_dleq_helper(4, b) } #[bench] fn batch_verify_batchable_dleq_16(b: &mut Bencher) { batch_verify_batchable_dleq_helper(16, b) } #[bench] fn batch_verify_batchable_dleq_64(b: &mut Bencher) { batch_verify_batchable_dleq_helper(64, b) }