use crate::{
backend::Frontend,
crypto::{GeneratesRandom, Hasher, PseudoRandomGenerator, Seed},
prover::views::{
ViewBuilderBackend, ViewCommitment, WordTriplePool, collectors::ViewCommitmentsRelayer,
},
};
use alloc::vec::Vec;
use zeroize::Zeroizing;
#[derive(Debug)]
pub struct ChallengeBuilder<
H: Hasher,
PS: PseudoRandomGenerator,
PV: PseudoRandomGenerator,
S: Seed,
WTP: WordTriplePool,
> {
num_iters_ingested: usize,
seed_prg: PS,
challenge_hasher: H,
_marker: core::marker::PhantomData<(PV, S, WTP)>,
}
impl<H: Hasher, PS: PseudoRandomGenerator, PV: PseudoRandomGenerator, S: Seed, WTP: WordTriplePool>
ChallengeBuilder<H, PS, PV, S, WTP>
{
pub fn new(seed_entropy: &[u8]) -> Self {
return ChallengeBuilder {
seed_prg: PS::new(seed_entropy),
challenge_hasher: H::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(&'_ mut self) -> ChallengeBuildingIteration<'_, H, PS, PV, S, WTP> {
let seeds: Zeroizing<[S; 3]> = Zeroizing::new(self.seed_prg.next());
return ChallengeBuildingIteration {
challenge_builder: self,
view_builder: ViewBuilderBackend::new(seeds).into_view_builder(),
};
}
pub fn finalize(mut self) -> Zeroizing<Vec<u8>> {
let challenge_entropy = Zeroizing::new(self.challenge_hasher.finalize().as_ref().to_vec());
return challenge_entropy;
}
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 ChallengeBuildingIteration<
'a,
H: Hasher,
PS: PseudoRandomGenerator,
PV: PseudoRandomGenerator,
S: Seed,
WTP: WordTriplePool,
> {
challenge_builder: &'a mut ChallengeBuilder<H, PS, PV, S, WTP>,
view_builder: Frontend<ViewBuilderBackend<H, PV, S, ViewCommitmentsRelayer<H::Digest, S>, WTP>>,
}
impl<
'a,
H: Hasher,
PS: PseudoRandomGenerator,
PV: PseudoRandomGenerator,
S: Seed,
WTP: WordTriplePool,
> ChallengeBuildingIteration<'a, H, PS, PV, S, WTP>
{
pub fn view_builder(
&self,
) -> &Frontend<ViewBuilderBackend<H, PV, S, ViewCommitmentsRelayer<H::Digest, S>, WTP>> {
return &self.view_builder;
}
pub fn finalize(self) {
let this = core::mem::ManuallyDrop::new(self);
let challenge_builder = unsafe { core::ptr::read(&this.challenge_builder) };
let view_builder = unsafe { core::ptr::read(&this.view_builder) };
let view_commitments = view_builder.finalize();
challenge_builder.ingest_commitments(&view_commitments);
}
}
impl<
'a,
H: Hasher,
PS: PseudoRandomGenerator,
PV: PseudoRandomGenerator,
S: Seed,
WTP: WordTriplePool,
> Drop for ChallengeBuildingIteration<'a, H, PS, PV, S, WTP>
{
fn drop(&mut self) {
panic!("Challenge building iteration was dropped before being finalized.")
}
}