use std::marker::PhantomData;
use halo2_base::{
gates::circuit::BaseCircuitParams,
gates::{circuit::BaseConfig, flex_gate::BasicGateConfig},
halo2_proofs::{
plonk::{Challenge, ConstraintSystem, FirstPhase, SecondPhase},
poly::Rotation,
},
utils::ScalarField,
};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
pub mod builder;
pub mod instructions;
#[derive(Clone, Debug)]
pub struct PureRlcConfig<F: ScalarField> {
pub basic_gates: Vec<BasicGateConfig<F>>,
pub gamma: Challenge,
pub usable_rows: usize,
_marker: PhantomData<F>,
}
impl<F: ScalarField> PureRlcConfig<F> {
pub fn configure(meta: &mut ConstraintSystem<F>, k: usize, num_advice_col: usize) -> Self {
let basic_gates = (0..num_advice_col)
.map(|_| {
let a = meta.advice_column_in(SecondPhase);
meta.enable_equality(a);
let q = meta.selector();
BasicGateConfig::new(q, a)
})
.collect_vec();
let gamma = meta.challenge_usable_after(FirstPhase);
for gate in &basic_gates {
meta.create_gate("RLC computation", |meta| {
let q = meta.query_selector(gate.q_enable);
let rlc_prev = meta.query_advice(gate.value, Rotation::cur());
let val = meta.query_advice(gate.value, Rotation::next());
let rlc_curr = meta.query_advice(gate.value, Rotation(2));
let gamma = meta.query_challenge(gamma);
vec![q * (rlc_prev * gamma + val - rlc_curr)]
});
}
log::info!("Poisoned rows after RlcConfig::configure {}", meta.minimum_rows());
let usable_rows = (1usize << k) - meta.minimum_rows();
Self { basic_gates, gamma, usable_rows, _marker: PhantomData }
}
}
#[derive(Clone, Default, Hash, Debug, Serialize, Deserialize)]
pub struct RlcCircuitParams {
pub base: BaseCircuitParams,
pub num_rlc_columns: usize,
}
#[derive(Clone, Debug)]
pub struct RlcConfig<F: ScalarField> {
pub base: BaseConfig<F>,
pub rlc: PureRlcConfig<F>,
}
impl<F: ScalarField> RlcConfig<F> {
pub fn configure(meta: &mut ConstraintSystem<F>, params: RlcCircuitParams) -> Self {
let k = params.base.k;
let mut base = BaseConfig::configure(meta, params.base);
let rlc = PureRlcConfig::configure(meta, k, params.num_rlc_columns);
base.set_usable_rows(rlc.usable_rows);
RlcConfig { base, rlc }
}
pub fn basic_gates(&self, phase: usize) -> Vec<BasicGateConfig<F>> {
self.base.gate().basic_gates[phase].clone()
}
pub fn set_usable_rows(&mut self, usable_rows: usize) {
self.base.set_usable_rows(usable_rows);
self.rlc.usable_rows = usable_rows;
}
}