use super::*;
pub mod input;
pub use self::input::*;
pub mod keccak_aggregator;
use crate::fsm_input_output::circuit_inputs::INPUT_OUTPUT_COMMITMENT_LENGTH;
use boojum::cs::implementations::prover::ProofConfig;
use boojum::cs::implementations::verifier::VerificationKey;
use boojum::cs::oracle::TreeHasher;
use boojum::cs::traits::circuit::ErasedBuilderForRecursiveVerifier;
use boojum::cs::traits::cs::ConstraintSystem;
use boojum::field::FieldExtension;
use boojum::field::SmallField;
use boojum::gadgets::boolean::Boolean;
use boojum::gadgets::num::Num;
use boojum::gadgets::recursion::allocated_proof::AllocatedProof;
use boojum::gadgets::recursion::allocated_vk::AllocatedVerificationKey;
use boojum::gadgets::recursion::circuit_pow::RecursivePoWRunner;
use boojum::gadgets::recursion::recursive_transcript::*;
use boojum::gadgets::recursion::recursive_tree_hasher::*;
use boojum::gadgets::traits::allocatable::CSAllocatable;
#[derive(Derivative, serde::Serialize, serde::Deserialize)]
#[derivative(Clone, Debug)]
#[serde(bound = "H::Output: serde::Serialize + serde::de::DeserializeOwned")]
pub struct InterblockRecursionConfig<
F: SmallField,
H: TreeHasher<F>,
EXT: FieldExtension<2, BaseField = F>,
> {
pub proof_config: ProofConfig,
pub verification_key: VerificationKey<F, H>,
pub capacity: usize,
pub _marker: std::marker::PhantomData<(F, H, EXT)>,
}
pub trait InputAggregationFunction<F: SmallField> {
type Params;
fn new<CS: ConstraintSystem<F>>(cs: &mut CS, params: Self::Params) -> Self;
fn aggregate_inputs<CS: ConstraintSystem<F>>(
&self,
cs: &mut CS,
inputs: &[Vec<Num<F>>],
validity_flags: &[Boolean<F>],
) -> Vec<Num<F>>;
}
pub fn interblock_recursion_function<
F: SmallField,
CS: ConstraintSystem<F> + 'static,
H: RecursiveTreeHasher<F, Num<F>>,
EXT: FieldExtension<2, BaseField = F>,
TR: RecursiveTranscript<
F,
CompatibleCap = <H::NonCircuitSimulator as TreeHasher<F>>::Output,
CircuitReflection = CTR,
>,
CTR: CircuitTranscript<
F,
CircuitCompatibleCap = <H as CircuitTreeHasher<F, Num<F>>>::CircuitOutput,
TransciptParameters = TR::TransciptParameters,
>,
POW: RecursivePoWRunner<F>,
AGG: InputAggregationFunction<F>,
>(
cs: &mut CS,
witness: InterblockRecursionCircuitInstanceWitness<F, H, EXT>,
config: InterblockRecursionConfig<F, H::NonCircuitSimulator, EXT>,
verifier_builder: Box<dyn ErasedBuilderForRecursiveVerifier<F, EXT, CS>>,
transcript_params: TR::TransciptParameters,
aggregation_params: AGG::Params,
) {
let InterblockRecursionCircuitInstanceWitness { proof_witnesses } = witness;
let mut proof_witnesses = proof_witnesses;
let InterblockRecursionConfig {
proof_config,
verification_key,
capacity,
..
} = config;
let r = cs as *mut CS;
assert_eq!(
verification_key.fixed_parameters.parameters,
verifier_builder.geometry()
);
let fixed_parameters = verification_key.fixed_parameters.clone();
let verifier = verifier_builder.create_recursive_verifier(cs);
let cs = unsafe { &mut *r };
let mut validity_flags = Vec::with_capacity(capacity);
let mut inputs = Vec::with_capacity(capacity);
let vk = AllocatedVerificationKey::allocate_constant(cs, verification_key);
for _ in 0..capacity {
let proof_witness = proof_witnesses.pop_front();
let proof = AllocatedProof::allocate_from_witness(
cs,
proof_witness,
&verifier,
&fixed_parameters,
&proof_config,
);
let (is_valid, public_inputs) = verifier.verify::<H, TR, CTR, POW>(
cs,
transcript_params.clone(),
&proof,
&fixed_parameters,
&proof_config,
&vk,
);
assert_eq!(public_inputs.len(), INPUT_OUTPUT_COMMITMENT_LENGTH);
assert_eq!(public_inputs.len(), fixed_parameters.num_public_inputs());
validity_flags.push(is_valid);
inputs.push(public_inputs);
}
let aggregator = AGG::new(cs, aggregation_params);
let aggregated_input = aggregator.aggregate_inputs(cs, &inputs, &validity_flags);
assert_eq!(aggregated_input.len(), INPUT_OUTPUT_COMMITMENT_LENGTH);
for el in aggregated_input.into_iter() {
use boojum::cs::gates::PublicInputGate;
let gate = PublicInputGate::new(el.get_variable());
gate.add_to_cs(cs);
}
}