use super::*;
use crate::boojum::cs::implementations::verifier::{SizeCalculator, VerificationKeyCircuitGeometry};
use crate::boojum::field::goldilocks::{GoldilocksExt2 as GLExt2, GoldilocksField as GL};
#[derive(Clone, Default, Debug)]
pub(crate) struct ConstantsHolder {
pub(crate) quotient_degree: usize,
pub(crate) num_lookup_subarguments: usize,
pub(crate) num_variable_polys: usize,
pub(crate) num_witness_polys: usize,
pub(crate) num_constant_polys: usize,
pub(crate) num_multiplicities_polys: usize,
pub(crate) num_copy_permutation_polys: usize,
pub(crate) num_lookup_table_setup_polys: usize,
pub(crate) num_intermediate_partial_product_relations: usize,
pub(crate) total_num_gate_terms_for_specialized_columns: usize,
pub(crate) total_num_gate_terms_for_general_purpose_columns: usize,
pub(crate) total_num_lookup_argument_terms: usize,
pub(crate) total_num_terms: usize,
pub(crate) witness_leaf_size: usize,
pub(crate) stage_2_leaf_size: usize,
pub(crate) quotient_leaf_size: usize,
pub(crate) setup_leaf_size: usize,
pub(crate) num_poly_values_at_z: usize,
pub(crate) num_poly_values_at_z_omega: usize,
pub(crate) num_poly_values_at_zero: usize,
pub(crate) num_public_inputs: usize,
pub(crate) new_pow_bits: usize,
pub(crate) num_fri_repetitions: usize,
pub(crate) fri_folding_schedule: Vec<usize>,
pub(crate) final_expected_degree: usize,
pub(crate) total_num_challenges_for_fri_quotiening: usize,
}
impl ConstantsHolder {
pub fn generate<E: Engine, CS: ConstraintSystem<E>>(proof_config: &ProofConfig, verifier: &WrapperVerifier<E, CS>, fixed_parameters: &VerificationKeyCircuitGeometry) -> Self {
assert_eq!(verifier.parameters, fixed_parameters.parameters);
assert_eq!(verifier.lookup_parameters, fixed_parameters.lookup_parameters);
assert!(proof_config.fri_folding_schedule.is_none());
assert_eq!(fixed_parameters.cap_size, proof_config.merkle_tree_cap_size);
assert_eq!(fixed_parameters.fri_lde_factor, proof_config.fri_lde_factor,);
let mut result = Self::default();
result.quotient_degree = SizeCalculator::<GL, 2, GLExt2>::quotient_degree(fixed_parameters);
result.num_lookup_subarguments = SizeCalculator::<GL, 2, GLExt2>::num_sublookup_arguments(&verifier.parameters, &verifier.lookup_parameters);
result.num_variable_polys = SizeCalculator::<GL, 2, GLExt2>::num_variable_polys(&verifier.parameters, verifier.total_num_variables_for_specialized_columns);
result.num_witness_polys = SizeCalculator::<GL, 2, GLExt2>::num_witness_polys(&verifier.parameters, verifier.total_num_witnesses_for_specialized_columns);
result.num_constant_polys = SizeCalculator::<GL, 2, GLExt2>::num_constant_polys(&verifier.parameters, fixed_parameters, verifier.total_num_constants_for_specialized_columns);
result.num_multiplicities_polys =
SizeCalculator::<GL, 2, GLExt2>::num_multipicities_polys(&verifier.lookup_parameters, fixed_parameters.total_tables_len as usize, fixed_parameters.domain_size);
result.num_copy_permutation_polys = result.num_variable_polys;
result.num_lookup_table_setup_polys = SizeCalculator::<GL, 2, GLExt2>::num_lookup_table_setup_polys(&verifier.lookup_parameters);
result.witness_leaf_size = SizeCalculator::<GL, 2, GLExt2>::witness_leaf_size(
&verifier.parameters,
&verifier.lookup_parameters,
fixed_parameters,
verifier.total_num_variables_for_specialized_columns,
verifier.total_num_witnesses_for_specialized_columns,
);
result.stage_2_leaf_size = SizeCalculator::<GL, 2, GLExt2>::stage_2_leaf_size(
&verifier.parameters,
&verifier.lookup_parameters,
fixed_parameters,
verifier.total_num_variables_for_specialized_columns,
);
result.quotient_leaf_size = SizeCalculator::<GL, 2, GLExt2>::quotient_leaf_size(fixed_parameters);
result.setup_leaf_size = SizeCalculator::<GL, 2, GLExt2>::setup_leaf_size(
&verifier.parameters,
&verifier.lookup_parameters,
fixed_parameters,
verifier.total_num_variables_for_specialized_columns,
verifier.total_num_constants_for_specialized_columns,
);
result.total_num_lookup_argument_terms = result.num_lookup_subarguments + result.num_multiplicities_polys;
use crate::boojum::cs::implementations::copy_permutation::num_intermediate_partial_product_relations;
result.num_intermediate_partial_product_relations = num_intermediate_partial_product_relations(result.num_copy_permutation_polys, result.quotient_degree);
result.compute_num_gate_terms(verifier);
result.compute_total_num_terms();
result.compute_num_poly_values_at_z(fixed_parameters);
result.compute_num_poly_values_at_z_omega();
result.compute_num_poly_values_at_zero();
result.num_public_inputs = fixed_parameters.public_inputs_locations.len();
result.compute_fri_parameters(fixed_parameters, proof_config);
result.compute_total_num_challenges_for_fri_quotiening(verifier);
result
}
fn compute_num_gate_terms<E: Engine, CS: ConstraintSystem<E>>(&mut self, verifier: &WrapperVerifier<E, CS>) {
assert_eq!(verifier.evaluators_over_specialized_columns.len(), verifier.gate_type_ids_for_specialized_columns.len());
self.total_num_gate_terms_for_specialized_columns = verifier
.evaluators_over_specialized_columns
.iter()
.zip(verifier.gate_type_ids_for_specialized_columns.iter())
.map(|(evaluator, gate_type_id)| {
let placement_strategy = verifier.placement_strategies.get(gate_type_id).copied().expect("gate must be allowed");
let num_repetitions = match placement_strategy {
GatePlacementStrategy::UseSpecializedColumns { num_repetitions, .. } => num_repetitions,
_ => unreachable!(),
};
assert_eq!(evaluator.num_repetitions_on_row, num_repetitions);
let terms_per_repetition = evaluator.num_quotient_terms;
terms_per_repetition * num_repetitions
})
.sum();
self.total_num_gate_terms_for_general_purpose_columns = verifier
.evaluators_over_general_purpose_columns
.iter()
.map(|evaluator| evaluator.total_quotient_terms_over_all_repetitions)
.sum();
}
fn compute_total_num_terms(&mut self) {
self.total_num_terms = self.total_num_lookup_argument_terms + self.total_num_gate_terms_for_specialized_columns + self.total_num_gate_terms_for_general_purpose_columns + 1 + 1 + self.num_intermediate_partial_product_relations; }
fn compute_num_poly_values_at_z(&mut self, fixed_parameters: &VerificationKeyCircuitGeometry) {
let expected_lookup_polys_total = if fixed_parameters.lookup_parameters.lookup_is_allowed() {
self.num_lookup_subarguments + self.num_multiplicities_polys * 2 + fixed_parameters.lookup_parameters.lookup_width() + 1 } else {
0
};
self.num_poly_values_at_z = self.num_variable_polys + self.num_witness_polys +
self.num_constant_polys + self.num_copy_permutation_polys +
1 + self.num_intermediate_partial_product_relations + expected_lookup_polys_total + self.quotient_degree; }
fn compute_num_poly_values_at_z_omega(&mut self) {
self.num_poly_values_at_z_omega = 1;
}
fn compute_num_poly_values_at_zero(&mut self) {
self.num_poly_values_at_zero = self.num_lookup_subarguments + self.num_multiplicities_polys;
}
fn compute_total_num_challenges_for_fri_quotiening<E: Engine, CS: ConstraintSystem<E>>(&mut self, verifier: &WrapperVerifier<E, CS>) {
let expected_lookup_polys_total = if verifier.lookup_parameters.lookup_is_allowed() {
self.num_lookup_subarguments + self.num_multiplicities_polys * 2 + verifier.lookup_parameters.lookup_width() + 1 } else {
0
};
let num_poly_values_at_z = self.num_variable_polys + self.num_witness_polys +
self.num_constant_polys + self.num_copy_permutation_polys +
1 + self.num_intermediate_partial_product_relations + expected_lookup_polys_total + self.quotient_degree;
let mut total_num_challenges = 0;
total_num_challenges += num_poly_values_at_z;
total_num_challenges += 1;
total_num_challenges += self.total_num_lookup_argument_terms;
total_num_challenges += self.num_public_inputs;
self.total_num_challenges_for_fri_quotiening = total_num_challenges;
}
fn compute_fri_parameters(&mut self, fixed_parameters: &VerificationKeyCircuitGeometry, proof_config: &ProofConfig) {
let (
new_pow_bits, num_queries, interpolation_log2s_schedule, final_expected_degree,
) = crate::boojum::cs::implementations::prover::compute_fri_schedule(
proof_config.security_level as u32,
proof_config.merkle_tree_cap_size,
proof_config.pow_bits,
fixed_parameters.fri_lde_factor.trailing_zeros(),
fixed_parameters.domain_size.trailing_zeros(),
);
let mut expected_degree = fixed_parameters.domain_size;
for interpolation_degree_log2 in interpolation_log2s_schedule.iter() {
expected_degree >>= interpolation_degree_log2;
}
assert_eq!(final_expected_degree, expected_degree as usize);
self.new_pow_bits = new_pow_bits as usize;
self.num_fri_repetitions = num_queries;
self.fri_folding_schedule = interpolation_log2s_schedule;
self.final_expected_degree = final_expected_degree;
}
}