use crate::{
backend::Frontend,
crypto::{GeneratesRandom, HashPRG, Hasher, PseudoRandomGenerator, Seed},
prover::{
challenge::{ChallengeGenerator, PartyVec},
proof::Response,
views::ViewCommitment,
},
verifier::replay::{ViewReplayError, ViewReplayerBackend, WordPairPool},
word::Words,
};
use zeroize::Zeroizing;
#[derive(Debug)]
pub struct Verifier<'a, H: Hasher, PV: PseudoRandomGenerator, S: Seed, WPP: WordPairPool> {
expected_output: &'a Words,
challenge_hasher: H,
challenges: PartyVec,
num_iters_ingested: usize,
_marker: core::marker::PhantomData<(PV, S, WPP)>,
}
impl<'a, H: Hasher, PV: PseudoRandomGenerator, S: Seed, WPP: WordPairPool>
Verifier<'a, H, PV, S, WPP>
{
pub fn new(expected_output: &'a Words) -> Self {
return Self {
expected_output,
challenge_hasher: H::new(),
challenges: PartyVec::new(),
num_iters_ingested: 0,
_marker: core::marker::PhantomData,
};
}
pub fn num_iters_ingested(&self) -> usize {
return self.num_iters_ingested;
}
pub fn next_iter<'b, 'c>(
&'c mut self,
response: &'b Response<H::Digest, S>,
) -> VerifyingIteration<'a, 'b, 'c, H, PV, S, WPP> {
self.challenges.push(response.challenge());
let view_replayer =
ViewReplayerBackend::<H, PV, S, WPP>::new(response).into_view_replayer();
return VerifyingIteration {
verifier: self,
view_replayer,
};
}
pub fn finalize(mut self) -> bool {
let challenge_entropy = Zeroizing::new(self.challenge_hasher.finalize().as_ref().to_vec());
let mut challenge_generator =
ChallengeGenerator::new(HashPRG::<H>::new(&challenge_entropy));
for challenge in &self.challenges {
if challenge_generator.next() != challenge {
return false;
}
}
return true;
}
fn ingest_commitments(&mut self, commitments: &[ViewCommitment<H::Digest>; 3]) {
let challenge_hasher = &mut self.challenge_hasher;
for commitment in commitments {
challenge_hasher.update(commitment.digest().as_ref());
commitment.output_share().update_hasher(challenge_hasher);
}
self.num_iters_ingested += 1;
}
}
#[derive(Debug)]
pub struct VerifyingIteration<
'a: 'b,
'b,
'c,
H: Hasher,
PV: PseudoRandomGenerator,
S: Seed,
WPP: WordPairPool,
> {
verifier: &'c mut Verifier<'a, H, PV, S, WPP>,
view_replayer: Frontend<ViewReplayerBackend<'b, H, PV, S, WPP>>,
}
impl<'a, 'b, 'c, H: Hasher, PV: PseudoRandomGenerator, S: Seed, WPP: WordPairPool>
VerifyingIteration<'a, 'b, 'c, H, PV, S, WPP>
{
pub fn view_replayer(&self) -> &Frontend<ViewReplayerBackend<'b, H, PV, S, WPP>> {
return &self.view_replayer;
}
pub fn finalize(self) -> Result<[ViewCommitment<H::Digest>; 3], ViewReplayError> {
let this = core::mem::ManuallyDrop::new(self);
let verifier = unsafe { core::ptr::read(&this.verifier) };
let view_replayer = unsafe { core::ptr::read(&this.view_replayer) };
let view_commitments = view_replayer.finalize_with_arg(verifier.expected_output)?;
verifier.ingest_commitments(&view_commitments);
return Ok(view_commitments);
}
}
impl<'a, 'b, 'c, H: Hasher, PV: PseudoRandomGenerator, S: Seed, WPP: WordPairPool> Drop
for VerifyingIteration<'a, 'b, 'c, H, PV, S, WPP>
{
fn drop(&mut self) {
panic!("Verifying iteration was dropped before being finalized.")
}
}