use jevil::{Params, keygen, sign, verify};
use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
#[test]
fn flagship_round_trip_at_full_budget() {
let params = Params::new(3);
let mut rng = ChaCha20Rng::seed_from_u64(0);
let (pk, sk, cache) = keygen(&mut rng, params);
let msgs: Vec<Vec<u8>> = (0..params.n_star)
.map(|i| format!("multi-opening-msg-{i}").into_bytes())
.collect();
let sigs: Vec<_> = msgs
.iter()
.map(|m| sign(&sk, &pk, &cache, params, m))
.collect();
for (m, sig) in msgs.iter().zip(&sigs) {
verify(&pk, params, m, sig).expect("each of the n* signatures must verify");
}
}
#[test]
fn distinct_messages_produce_distinct_proofs() {
let params = Params::new(3);
let mut rng = ChaCha20Rng::seed_from_u64(0);
let (pk, sk, cache) = keygen(&mut rng, params);
let sig_a = sign(&sk, &pk, &cache, params, b"alpha");
let sig_b = sign(&sk, &pk, &cache, params, b"beta");
let sig_c = sign(&sk, &pk, &cache, params, b"gamma");
for (msg, sig) in [
(&b"alpha"[..], &sig_a),
(&b"beta"[..], &sig_b),
(&b"gamma"[..], &sig_c),
] {
verify(&pk, params, msg, sig).unwrap();
}
assert_ne!(sig_a.whir_proof, sig_b.whir_proof);
assert_ne!(sig_a.whir_proof, sig_c.whir_proof);
assert_ne!(sig_b.whir_proof, sig_c.whir_proof);
}
#[test]
fn distinct_seeds_produce_distinct_signatures() {
let params = Params::new(3);
let mut rng_a = ChaCha20Rng::seed_from_u64(0);
let mut rng_b = ChaCha20Rng::seed_from_u64(1);
let (pk_a, sk_a, cache_a) = keygen(&mut rng_a, params);
let (pk_b, sk_b, cache_b) = keygen(&mut rng_b, params);
let sig_a = sign(&sk_a, &pk_a, &cache_a, params, b"same-message");
let sig_b = sign(&sk_b, &pk_b, &cache_b, params, b"same-message");
verify(&pk_a, params, b"same-message", &sig_a).unwrap();
verify(&pk_b, params, b"same-message", &sig_b).unwrap();
assert_ne!(sig_a.whir_proof, sig_b.whir_proof);
assert_ne!(pk_a.root, pk_b.root);
}
#[test]
fn cross_verification_rejected() {
let params = Params::new(3);
let mut rng_a = ChaCha20Rng::seed_from_u64(0);
let mut rng_b = ChaCha20Rng::seed_from_u64(1);
let (pk_a, sk_a, cache_a) = keygen(&mut rng_a, params);
let (pk_b, _sk_b, _cache_b) = keygen(&mut rng_b, params);
let sig_a = sign(&sk_a, &pk_a, &cache_a, params, b"target");
verify(&pk_a, params, b"target", &sig_a).expect("sig_a verifies under pk_a");
verify(&pk_b, params, b"target", &sig_a).expect_err("sig_a must NOT verify under pk_b");
}
#[test]
fn deterministic_signatures_under_full_budget() {
let params = Params::new(3);
let (pk_1, sigs_1) = full_budget_run(params, 42);
let (pk_2, sigs_2) = full_budget_run(params, 42);
assert_eq!(pk_1.to_bytes(), pk_2.to_bytes());
assert_eq!(sigs_1.len(), sigs_2.len());
for (a, b) in sigs_1.iter().zip(&sigs_2) {
assert_eq!(a.to_bytes(), b.to_bytes());
}
}
fn full_budget_run(params: Params, seed: u64) -> (jevil::PublicKey, Vec<jevil::Signature>) {
let mut rng = ChaCha20Rng::seed_from_u64(seed);
let (pk, sk, cache) = keygen(&mut rng, params);
let sigs: Vec<_> = (0..params.n_star)
.map(|i| sign(&sk, &pk, &cache, params, format!("msg-{i}").as_bytes()))
.collect();
(pk, sigs)
}