use std::collections::hash_map::Entry;
use crate::ff::Field;
use crate::halo2_proofs::{
circuit::{AssignedCell, Cell, Region, Value},
halo2curves::bn256::Bn256,
plonk::{Advice, Assigned, Circuit, Column, Fixed},
poly::kzg::commitment::ParamsKZG,
};
use crate::virtual_region::copy_constraints::{CopyConstraintManager, EXTERNAL_CELL_TYPE_ID};
use crate::AssignedValue;
pub use keygen::ProvingKeyGenerator;
pub type Halo2AssignedCell<'v, F> = AssignedCell<&'v Assigned<F>, F>;
#[inline(always)]
pub fn raw_assign_advice<'v, F: Field>(
region: &mut Region<F>,
column: Column<Advice>,
offset: usize,
value: Value<impl Into<Assigned<F>>>,
) -> Halo2AssignedCell<'v, F> {
region.assign_advice(column, offset, value)
}
#[inline(always)]
pub fn raw_assign_fixed<F: Field>(
region: &mut Region<F>,
column: Column<Fixed>,
offset: usize,
value: F,
) -> Cell {
region.assign_fixed(column, offset, value)
}
#[inline(always)]
pub fn raw_constrain_equal<F: Field>(region: &mut Region<F>, left: Cell, right: Cell) {
region.constrain_equal(left, right);
}
pub fn constrain_virtual_equals_external<F: Field + Ord>(
region: &mut Region<F>,
virtual_cell: AssignedValue<F>,
external_cell: Cell,
copy_manager: &mut CopyConstraintManager<F>,
) {
let ctx_cell = virtual_cell.cell.unwrap();
match copy_manager.assigned_advices.entry(ctx_cell) {
Entry::Occupied(acell) => {
region.constrain_equal(*acell.get(), external_cell);
}
Entry::Vacant(assigned) => {
assert_eq!(ctx_cell.type_id, EXTERNAL_CELL_TYPE_ID);
assigned.insert(external_cell);
}
}
}
pub trait KeygenCircuitIntent<F: Field> {
type ConcreteCircuit: Circuit<F>;
type Pinning;
fn get_k(&self) -> u32;
fn build_keygen_circuit(self) -> Self::ConcreteCircuit;
fn get_pinning_after_keygen(
self,
kzg_params: &ParamsKZG<Bn256>,
circuit: &Self::ConcreteCircuit,
) -> Self::Pinning;
}
mod keygen {
use crate::halo2_proofs::{
halo2curves::bn256::{Bn256, Fr, G1Affine},
plonk::{self, ProvingKey},
poly::{commitment::Params, kzg::commitment::ParamsKZG},
};
use super::KeygenCircuitIntent;
pub trait ProvingKeyGenerator {
fn create_pk_and_pinning(
self,
kzg_params: &ParamsKZG<Bn256>,
) -> (ProvingKey<G1Affine>, serde_json::Value);
}
impl<CI> ProvingKeyGenerator for CI
where
CI: KeygenCircuitIntent<Fr> + Clone,
CI::Pinning: serde::Serialize,
{
fn create_pk_and_pinning(
self,
kzg_params: &ParamsKZG<Bn256>,
) -> (ProvingKey<G1Affine>, serde_json::Value) {
assert_eq!(kzg_params.k(), self.get_k());
let circuit = self.clone().build_keygen_circuit();
let pk = plonk::keygen_pk2(kzg_params, &circuit, false).unwrap();
let pinning = self.get_pinning_after_keygen(kzg_params, &circuit);
(pk, serde_json::to_value(pinning).unwrap())
}
}
}