halo2_base/utils/
halo2.rs1use std::collections::hash_map::Entry;
2
3use crate::ff::Field;
4use crate::halo2_proofs::{
5 circuit::{AssignedCell, Cell, Region, Value},
6 halo2curves::bn256::Bn256,
7 plonk::{Advice, Assigned, Circuit, Column, Fixed},
8 poly::kzg::commitment::ParamsKZG,
9};
10use crate::virtual_region::copy_constraints::{CopyConstraintManager, EXTERNAL_CELL_TYPE_ID};
11use crate::AssignedValue;
12
13pub use keygen::ProvingKeyGenerator;
14
15#[cfg(feature = "halo2-axiom")]
17pub type Halo2AssignedCell<'v, F> = AssignedCell<&'v Assigned<F>, F>;
18#[cfg(not(feature = "halo2-axiom"))]
20pub type Halo2AssignedCell<'v, F> = AssignedCell<Assigned<F>, F>;
21
22#[inline(always)]
24pub fn raw_assign_advice<'v, F: Field>(
25 region: &mut Region<F>,
26 column: Column<Advice>,
27 offset: usize,
28 value: Value<impl Into<Assigned<F>>>,
29) -> Halo2AssignedCell<'v, F> {
30 #[cfg(feature = "halo2-axiom")]
31 {
32 region.assign_advice(column, offset, value)
33 }
34 #[cfg(feature = "halo2-pse")]
35 {
36 let value = value.map(|a| Into::<Assigned<F>>::into(a));
37 region
38 .assign_advice(
39 || format!("assign advice {column:?} offset {offset}"),
40 column,
41 offset,
42 || value,
43 )
44 .unwrap()
45 }
46}
47
48#[inline(always)]
50pub fn raw_assign_fixed<F: Field>(
51 region: &mut Region<F>,
52 column: Column<Fixed>,
53 offset: usize,
54 value: F,
55) -> Cell {
56 #[cfg(feature = "halo2-axiom")]
57 {
58 region.assign_fixed(column, offset, value)
59 }
60 #[cfg(feature = "halo2-pse")]
61 {
62 region
63 .assign_fixed(
64 || format!("assign fixed {column:?} offset {offset}"),
65 column,
66 offset,
67 || Value::known(value),
68 )
69 .unwrap()
70 .cell()
71 }
72}
73
74#[inline(always)]
76pub fn raw_constrain_equal<F: Field>(region: &mut Region<F>, left: Cell, right: Cell) {
77 #[cfg(feature = "halo2-axiom")]
78 region.constrain_equal(left, right);
79 #[cfg(not(feature = "halo2-axiom"))]
80 region.constrain_equal(left, right).unwrap();
81}
82
83pub fn constrain_virtual_equals_external<F: Field + Ord>(
94 region: &mut Region<F>,
95 virtual_cell: AssignedValue<F>,
96 external_cell: Cell,
97 copy_manager: &mut CopyConstraintManager<F>,
98) {
99 let ctx_cell = virtual_cell.cell.unwrap();
100 match copy_manager.assigned_advices.entry(ctx_cell) {
101 Entry::Occupied(acell) => {
102 region.constrain_equal(*acell.get(), external_cell);
104 }
105 Entry::Vacant(assigned) => {
106 assert_eq!(ctx_cell.type_id, EXTERNAL_CELL_TYPE_ID);
108 assigned.insert(external_cell);
110 }
111 }
112}
113
114pub trait KeygenCircuitIntent<F: Field> {
120 type ConcreteCircuit: Circuit<F>;
122 type Pinning;
125
126 fn get_k(&self) -> u32;
129
130 fn build_keygen_circuit(self) -> Self::ConcreteCircuit;
134
135 fn get_pinning_after_keygen(
137 self,
138 kzg_params: &ParamsKZG<Bn256>,
139 circuit: &Self::ConcreteCircuit,
140 ) -> Self::Pinning;
141}
142
143mod keygen {
144 use crate::halo2_proofs::{
145 halo2curves::bn256::{Bn256, Fr, G1Affine},
146 plonk::{self, ProvingKey},
147 poly::{commitment::Params, kzg::commitment::ParamsKZG},
148 };
149
150 use super::KeygenCircuitIntent;
151
152 pub trait ProvingKeyGenerator {
154 fn create_pk_and_pinning(
156 self,
157 kzg_params: &ParamsKZG<Bn256>,
158 ) -> (ProvingKey<G1Affine>, serde_json::Value);
159 }
160
161 impl<CI> ProvingKeyGenerator for CI
162 where
163 CI: KeygenCircuitIntent<Fr> + Clone,
164 CI::Pinning: serde::Serialize,
165 {
166 fn create_pk_and_pinning(
167 self,
168 kzg_params: &ParamsKZG<Bn256>,
169 ) -> (ProvingKey<G1Affine>, serde_json::Value) {
170 assert_eq!(kzg_params.k(), self.get_k());
171 let circuit = self.clone().build_keygen_circuit();
172 #[cfg(feature = "halo2-axiom")]
173 let pk = plonk::keygen_pk2(kzg_params, &circuit, false).unwrap();
174 #[cfg(not(feature = "halo2-axiom"))]
175 let pk = {
176 let vk = plonk::keygen_vk_custom(kzg_params, &circuit, false).unwrap();
177 plonk::keygen_pk(kzg_params, vk, &circuit).unwrap()
178 };
179 let pinning = self.get_pinning_after_keygen(kzg_params, &circuit);
180 (pk, serde_json::to_value(pinning).unwrap())
181 }
182 }
183}