// -*- 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
#![allow(non_snake_case)]
extern crate bincode;
extern crate curve25519_dalek;
extern crate serde;
extern crate sha2;
#[macro_use]
extern crate zkp;
use self::sha2::Sha512;
use curve25519_dalek::constants as dalek_constants;
use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;
use zkp::Transcript;
define_proof! {dleq, "DLEQ Example Proof", (x), (A, B, H), (G) : A = (x * G), B = (x * H) }
#[test]
fn create_and_verify_compact() {
// Prover's scope
let (proof, points) = {
let H = RistrettoPoint::hash_from_bytes::(b"A VRF input, for instance");
let x = Scalar::from(89327492234u64).invert();
let A = &x * &dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let B = &x * &H;
let mut transcript = Transcript::new(b"DLEQTest");
dleq::prove_compact(
&mut transcript,
dleq::ProveAssignments {
x: &x,
A: &A,
B: &B,
G: &dalek_constants::RISTRETTO_BASEPOINT_POINT,
H: &H,
},
)
};
// Serialize and parse bincode representation
let proof_bytes = bincode::serialize(&proof).unwrap();
let parsed_proof: dleq::CompactProof = bincode::deserialize(&proof_bytes).unwrap();
// Verifier logic
let mut transcript = Transcript::new(b"DLEQTest");
assert!(dleq::verify_compact(
&parsed_proof,
&mut transcript,
dleq::VerifyAssignments {
A: &points.A,
B: &points.B,
G: &dalek_constants::RISTRETTO_BASEPOINT_COMPRESSED,
H: &RistrettoPoint::hash_from_bytes::(b"A VRF input, for instance").compress(),
},
)
.is_ok());
}
#[test]
fn create_and_verify_batchable() {
// identical to above but with batchable proofs
// Prover's scope
let (proof, points) = {
let H = RistrettoPoint::hash_from_bytes::(b"A VRF input, for instance");
let x = Scalar::from(89327492234u64).invert();
let A = &x * &dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let B = &x * &H;
let mut transcript = Transcript::new(b"DLEQTest");
dleq::prove_batchable(
&mut transcript,
dleq::ProveAssignments {
x: &x,
A: &A,
B: &B,
G: &dalek_constants::RISTRETTO_BASEPOINT_POINT,
H: &H,
},
)
};
// Serialize and parse bincode representation
let proof_bytes = bincode::serialize(&proof).unwrap();
let parsed_proof: dleq::BatchableProof = bincode::deserialize(&proof_bytes).unwrap();
// Verifier logic
let mut transcript = Transcript::new(b"DLEQTest");
assert!(dleq::verify_batchable(
&parsed_proof,
&mut transcript,
dleq::VerifyAssignments {
A: &points.A,
B: &points.B,
G: &dalek_constants::RISTRETTO_BASEPOINT_COMPRESSED,
H: &RistrettoPoint::hash_from_bytes::(b"A VRF input, for instance").compress(),
},
)
.is_ok());
}
#[test]
fn create_batch_and_batch_verify() {
let messages = [
"One message",
"Another message",
"A third message",
"A fourth message",
];
// Prover's scope
let (proofs, pubkeys, vrf_outputs) = {
let mut proofs = vec![];
let mut pubkeys = vec![];
let mut vrf_outputs = vec![];
for (i, message) in messages.iter().enumerate() {
let H = RistrettoPoint::hash_from_bytes::(message.as_bytes());
let x = Scalar::from(89327492234u64) * Scalar::from((i + 1) as u64);
let A = &x * &dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let B = &x * &H;
let mut transcript = Transcript::new(b"DLEQTest");
let (proof, points) = dleq::prove_batchable(
&mut transcript,
dleq::ProveAssignments {
x: &x,
A: &A,
B: &B,
G: &dalek_constants::RISTRETTO_BASEPOINT_POINT,
H: &H,
},
);
proofs.push(proof);
pubkeys.push(points.A);
vrf_outputs.push(points.B);
}
(proofs, pubkeys, vrf_outputs)
};
// Verifier logic
let mut transcripts = vec![Transcript::new(b"DLEQTest"); messages.len()];
assert!(dleq::batch_verify(
&proofs,
transcripts.iter_mut().collect(),
dleq::BatchVerifyAssignments {
A: pubkeys,
B: vrf_outputs,
H: messages
.iter()
.map(
|message| RistrettoPoint::hash_from_bytes::(message.as_bytes())
.compress()
)
.collect(),
G: dalek_constants::RISTRETTO_BASEPOINT_COMPRESSED,
},
)
.is_ok());
}