use dusk_poseidon::{decrypt, decrypt_gadget};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use dusk_jubjub::GENERATOR;
use dusk_plonk::prelude::*;
use ff::Field;
use rand::rngs::StdRng;
use rand::SeedableRng;
use std::ops::Mul;
const CAPACITY: usize = 11;
const MESSAGE_CAPACITY: usize = 2;
const CIPHER_SIZE: usize = MESSAGE_CAPACITY + 1;
#[derive(Default)]
pub struct CipherDecrypt {
shared: JubJubAffine,
nonce: BlsScalar,
cipher: PoseidonCipher,
}
impl CipherDecrypt {
pub fn random(rng: &mut StdRng) -> Self {
let shared = GENERATOR
.to_niels()
.mul(&JubJubScalar::random(&mut *rng))
.into();
let nonce = BlsScalar::random(&mut *rng);
let message =
[BlsScalar::random(&mut *rng), BlsScalar::random(&mut *rng)];
let cipher = PoseidonCipher::encrypt(&message, &shared, &nonce);
Self {
shared,
nonce,
cipher,
}
}
}
impl Circuit for CipherDecrypt {
fn circuit(&self, composer: &mut Composer) -> Result<(), Error> {
let shared = composer.append_point(self.shared);
let nonce = composer.append_witness(self.nonce);
let mut cipher_circuit = [Composer::ZERO; CIPHER_SIZE];
self.cipher
.cipher()
.iter()
.zip(cipher_circuit.iter_mut())
.for_each(|(cipher_scalar, cipher_witness)| {
*cipher_witness = composer.append_witness(*cipher_scalar);
});
decrypt_gadget(composer, &shared, nonce, &cipher_circuit);
Ok(())
}
}
fn bench_cipher_decryption(c: &mut Criterion) {
let label = b"cipher decryption benchmark";
let mut rng = StdRng::seed_from_u64(0xc001);
let pp = PublicParameters::setup(1 << CAPACITY, &mut rng).unwrap();
let (prover, verifier) = Compiler::compile::<CipherDecrypt>(&pp, label)
.expect("Circuit should compile successfully");
let mut proof = Proof::default();
let public_inputs = Vec::new();
let circuit = CipherDecrypt::random(&mut rng);
c.bench_function("cipher decryption native", |b| {
b.iter(|| {
PoseidonCipher::decrypt(
black_box(&circuit.cipher),
black_box(&circuit.shared),
black_box(&circuit.nonce),
);
})
});
c.bench_function("cipher decryption proof generation", |b| {
b.iter(|| {
(proof, _) = prover
.prove(&mut rng, black_box(&circuit))
.expect("Proof generation should succeed");
})
});
c.bench_function("cipher decryption proof verification", |b| {
b.iter(|| {
verifier
.verify(black_box(&proof), &public_inputs)
.expect("Proof verification should succeed");
})
});
}
criterion_group! {
name = benches;
config = Criterion::default().sample_size(10);
targets = bench_cipher_decryption
}
criterion_main!(benches);