use crate::{
circuit::Circuit,
crypto::{Hasher, PseudoRandomGenerator, Seed},
prover::proof::Proof,
verifier::{
Verifier,
replay::{ViewReplayError, WordPairPool},
},
word::Words,
};
pub fn verify<C: Circuit, H: Hasher, PV: PseudoRandomGenerator, S: Seed, WPP: WordPairPool>(
circuit: &C,
expected_output: &Words,
proof: &Proof<H::Digest, S>,
) -> Result<bool, ViewReplayError> {
let mut verifier: Verifier<H, PV, S, WPP> = Verifier::new(expected_output);
for response in proof {
let iter = verifier.next_iter(response);
circuit.exec(iter.view_replayer());
iter.finalize()?;
}
return Ok(verifier.finalize());
}
#[cfg(feature = "rayon")]
pub fn par_verify<C: Circuit, H: Hasher, PV: PseudoRandomGenerator, S: Seed, WPP: WordPairPool>(
circuit: &C,
expected_output: &Words,
proof: &Proof<H::Digest, S>,
) -> Result<bool, ViewReplayError>
where
C: Sync,
H::Digest: Send + Sync,
S: Send + Sync,
{
use crate::{
crypto::HashPRG,
prover::challenge::{ChallengeGenerator, PartyVec},
};
use alloc::vec::Vec;
use rayon::prelude::*;
let mut challenges = PartyVec::with_capacity(proof.len());
for response in proof {
challenges.push(response.challenge());
}
let replay_results: Vec<_> = proof
.into_par_iter()
.map(|response| {
use crate::verifier::replay::ViewReplayerBackend;
let view_replayer =
ViewReplayerBackend::<H, PV, S, WPP>::new(response).into_view_replayer();
circuit.exec(&view_replayer);
view_replayer.finalize_with_arg(expected_output)
})
.collect();
let mut challenge_hasher = H::new();
for res in replay_results {
let view_commitments = res?;
for commitment in view_commitments {
challenge_hasher.update(commitment.digest().as_ref());
commitment
.output_share()
.update_hasher(&mut challenge_hasher);
}
}
let challenge_entropy = challenge_hasher.finalize();
let mut challenge_generator =
ChallengeGenerator::new(HashPRG::<H>::new(challenge_entropy.as_ref()));
for challenge in &challenges {
if challenge_generator.next() != challenge {
return Ok(false);
}
}
return Ok(true);
}