use ark_ec::pairing::Pairing;
use ark_ec::twisted_edwards::{Affine, TECurveConfig};
use ark_ec::CurveGroup;
use ark_std::rand::RngCore;
use w3f_pcs::pcs::kzg::params::KzgVerifierKey;
use w3f_pcs::pcs::kzg::KZG;
use w3f_pcs::pcs::PCS;
use w3f_plonk_common::kzg_acc::KzgAccumulator;
use w3f_plonk_common::piop::VerifierPiop;
use w3f_plonk_common::transcript::PlonkTranscript;
use w3f_plonk_common::verifier::Challenges;
use crate::piop::PiopVerifier;
use crate::ring_verifier::RingVerifier;
use crate::RingProof;
pub struct BatchItem<E, J>
where
E: Pairing,
J: TECurveConfig<BaseField = E::ScalarField>,
{
piop: PiopVerifier<E::ScalarField, <KZG<E> as PCS<E::ScalarField>>::C, Affine<J>>,
proof: RingProof<E::ScalarField, KZG<E>>,
challenges: Challenges<E::ScalarField>,
entropy: [u8; 32],
}
impl<E, J> BatchItem<E, J>
where
E: Pairing,
J: TECurveConfig<BaseField = E::ScalarField>,
{
pub fn new<T>(
verifier: &RingVerifier<E::ScalarField, KZG<E>, J, T>,
proof: RingProof<E::ScalarField, KZG<E>>,
result: Affine<J>,
) -> Self
where
T: PlonkTranscript<E::ScalarField, KZG<E>>,
{
let (challenges, mut rng) = verifier.plonk_verifier.restore_challenges(
&result,
&proof,
PiopVerifier::<E::ScalarField, <KZG<E> as PCS<_>>::C, Affine<J>>::N_COLUMNS + 1,
PiopVerifier::<E::ScalarField, <KZG<E> as PCS<_>>::C, Affine<J>>::N_CONSTRAINTS,
);
let seed = verifier.piop_params.seed;
let seed_plus_result = (seed + result).into_affine();
let domain_at_zeta = verifier.piop_params.domain.evaluate(challenges.zeta);
let piop = PiopVerifier::<_, _, Affine<J>>::init(
domain_at_zeta,
verifier.fixed_columns_committed.clone(),
proof.column_commitments.clone(),
proof.columns_at_zeta.clone(),
(seed.x, seed.y),
(seed_plus_result.x, seed_plus_result.y),
);
let mut entropy = [0_u8; 32];
rng.fill_bytes(&mut entropy);
Self {
piop,
proof,
challenges,
entropy,
}
}
}
pub struct BatchVerifier<E: Pairing, T>
where
T: PlonkTranscript<E::ScalarField, KZG<E>>,
{
acc: KzgAccumulator<E>,
transcript: T,
}
impl<E: Pairing, T> BatchVerifier<E, T>
where
T: PlonkTranscript<E::ScalarField, KZG<E>>,
{
pub fn new(kzg_vk: KzgVerifierKey<E>, transcript: T) -> Self {
Self {
acc: KzgAccumulator::<E>::new(kzg_vk),
transcript,
}
}
pub fn push<J>(
&mut self,
verifier: &RingVerifier<E::ScalarField, KZG<E>, J, T>,
proof: RingProof<E::ScalarField, KZG<E>>,
result: Affine<J>,
) where
J: TECurveConfig<BaseField = E::ScalarField>,
{
self.push_prepared(BatchItem::new(verifier, proof, result));
}
pub fn push_prepared<J>(&mut self, item: BatchItem<E, J>)
where
J: TECurveConfig<BaseField = E::ScalarField>,
{
let mut ts = self.transcript.clone();
ts._add_serializable(b"batch-entropy", &item.entropy);
self.acc
.accumulate(item.piop, item.proof, item.challenges, &mut ts.to_rng());
}
pub fn verify(&self) -> bool {
self.acc.verify()
}
}