diff --git a/examples/blake2f.rs b/examples/blake2f.rs index b459bfba..558461ce 100644 --- a/examples/blake2f.rs +++ b/examples/blake2f.rs @@ -7,7 +7,7 @@ use chiquito::{ CircuitContext, StepTypeSetupContext, StepTypeWGHandler, }, plonkish::{ - backend::halo2::{halo2_verify, Halo2Provable}, + backend::halo2_legacy::{chiquitoSuperCircuit2Halo2, ChiquitoHalo2SuperCircuit}, compiler::{ cell_manager::{MaxWidthCellManager, SingleRowCellManager}, config, @@ -18,7 +18,10 @@ use chiquito::{ poly::ToExpr, sbpir::query::Queriable, }; -use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField}; +use halo2_proofs::{ + dev::MockProver, + halo2curves::{bn256::Fr, group::ff::PrimeField}, +}; use std::{fmt::Write, hash::Hash}; pub const IV_LEN: usize = 8; @@ -1394,7 +1397,8 @@ fn blake2f_super_circuit() -> SuperCircuit } fn main() { - let mut super_circuit = blake2f_super_circuit::(); + let super_circuit = blake2f_super_circuit::(); + let compiled = chiquitoSuperCircuit2Halo2(&super_circuit); // h[0] = hex"48c9bdf267e6096a 3ba7ca8485ae67bb 2bf894fe72f36e3c f1361d5f3af54fa5"; // h[1] = hex"d182e6ad7f520e51 1f6c3e2b8c68059b 6bbd41fbabd9831f 79217e1319cde05b"; @@ -1476,24 +1480,17 @@ fn main() { f: true, // 8bits }; - let witness = super_circuit.get_mapping().generate(values); - - let params_path = "examples/ptau/hermez-raw-11"; - let halo2_prover = super_circuit.create_halo2_prover(params_path); - println!("k={}", halo2_prover.get_k()); + let circuit = + ChiquitoHalo2SuperCircuit::new(compiled, super_circuit.get_mapping().generate(values)); - let (proof, instance) = halo2_prover.generate_proof(witness); - - let result = halo2_verify( - proof, - halo2_prover.get_params(), - halo2_prover.get_vk(), - instance, - ); + let prover = MockProver::run(9, &circuit, Vec::new()).unwrap(); + let result = prover.verify(); println!("result = {:#?}", result); - if let Err(failure) = &result { - println!("{}", failure); + if let Err(failures) = &result { + for failure in failures.iter() { + println!("{}", failure); + } } } diff --git a/examples/factorial.rs b/examples/factorial.rs index c9d6beb2..9bef03aa 100644 --- a/examples/factorial.rs +++ b/examples/factorial.rs @@ -5,7 +5,7 @@ use chiquito::{ frontend::dsl::{circuit, trace::DSLTraceGenerator}, /* main function for constructing an AST * circuit */ plonkish::{ - backend::halo2::{halo2_verify, Halo2Provable}, + backend::halo2_legacy::{chiquito2Halo2, ChiquitoHalo2Circuit}, compiler::{ cell_manager::SingleRowCellManager, // input for constructing the compiler compile, // input for constructing the compiler @@ -22,7 +22,7 @@ use chiquito::{ * circuit */ poly::ToField, }; -use halo2_proofs::halo2curves::bn256::Fr; +use halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; const MAX_FACTORIAL: usize = 10; @@ -134,47 +134,24 @@ fn generate + Hash>() -> PlonkishCompilationResult(); - let params_path = "examples/ptau/hermez-raw-11"; - - let halo2_prover = plonkish.create_halo2_prover(params_path); - println!("k={}", halo2_prover.get_k()); - - let (proof, instance) = - halo2_prover.generate_proof(plonkish.assignment_generator.unwrap().generate(0)); - - let result = halo2_verify( - proof, - halo2_prover.get_params(), - halo2_prover.get_vk(), - instance, + let compilation_result = generate::(); + let compiled = chiquito2Halo2(compilation_result.circuit); + let circuit = ChiquitoHalo2Circuit::new( + compiled, + compilation_result + .assignment_generator + .map(|g| g.generate(0)), ); - println!("result = {:#?}", result); - - if let Err(error) = &result { - println!("{}", error); - } - - let mut plonkish = generate::(); - let params_path = "examples/ptau/hermez-raw-11"; - - let halo2_prover = plonkish.create_halo2_prover(params_path); - println!("k={}", halo2_prover.get_k()); + let prover = MockProver::::run(10, &circuit, circuit.instance()).unwrap(); - let (proof, instance) = - halo2_prover.generate_proof(plonkish.assignment_generator.unwrap().generate(7)); - - let result = halo2_verify( - proof, - halo2_prover.get_params(), - halo2_prover.get_vk(), - instance, - ); + let result = prover.verify(); println!("result = {:#?}", result); - if let Err(error) = &result { - println!("{}", error); + if let Err(failures) = &result { + for failure in failures.iter() { + println!("{}", failure); + } } } diff --git a/examples/fibo_with_padding.rs b/examples/fibo_with_padding.rs index f63b8cba..d93c5bbd 100644 --- a/examples/fibo_with_padding.rs +++ b/examples/fibo_with_padding.rs @@ -5,7 +5,7 @@ use chiquito::{ frontend::dsl::{circuit, trace::DSLTraceGenerator}, /* main function for constructing an AST * circuit */ plonkish::{ - backend::halo2::{halo2_verify, Halo2Provable}, + backend::halo2_legacy::{chiquito2Halo2, ChiquitoHalo2Circuit}, compiler::{ cell_manager::SingleRowCellManager, // input for constructing the compiler compile, // input for constructing the compiler @@ -22,7 +22,7 @@ use chiquito::{ * circuit */ poly::ToField, }; -use halo2_proofs::halo2curves::bn256::Fr; +use halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; // This example file extends the rust example file 'fibonacci.rs', // describing usage of multiple steptypes, padding, and exposing signals. @@ -204,25 +204,24 @@ fn fibo_circuit + Hash>( // standard main function for a Halo2 circuit fn main() { - let mut plonkish = fibo_circuit::(); - let params_path = "examples/ptau/hermez-raw-11"; - - let halo2_prover = plonkish.create_halo2_prover(params_path); - println!("k={}", halo2_prover.get_k()); + let compilation_result = fibo_circuit::(); + let compiled = chiquito2Halo2(compilation_result.circuit); + let circuit = ChiquitoHalo2Circuit::new( + compiled, + compilation_result + .assignment_generator + .map(|g| g.generate(7)), + ); - let (proof, instance) = - halo2_prover.generate_proof(plonkish.assignment_generator.unwrap().generate(7)); + let prover = MockProver::::run(7, &circuit, circuit.instance()).unwrap(); - let result = halo2_verify( - proof, - halo2_prover.get_params(), - halo2_prover.get_vk(), - instance, - ); + let result = prover.verify(); println!("{:#?}", result); - if let Err(failure) = &result { - println!("{}", failure); + if let Err(failures) = &result { + for failure in failures.iter() { + println!("{}", failure); + } } } diff --git a/examples/fibonacci.rs b/examples/fibonacci.rs index 67bb1a14..da25dab6 100644 --- a/examples/fibonacci.rs +++ b/examples/fibonacci.rs @@ -6,7 +6,7 @@ use chiquito::{ * circuit */ plonkish::{ backend::{ - halo2::{halo2_verify, Halo2Provable}, + halo2_legacy::{chiquito2Halo2, ChiquitoHalo2Circuit}, hyperplonk::ChiquitoHyperPlonkCircuit, }, compiler::{ @@ -14,8 +14,8 @@ use chiquito::{ compile, // input for constructing the compiler config, step_selector::SimpleStepSelectorBuilder, - PlonkishCompilationResult, }, + ir::{assignments::AssignmentGenerator, Circuit}, }, /* compiles to * Chiquito Halo2 * backend, @@ -26,7 +26,7 @@ use chiquito::{ poly::ToField, sbpir::SBPIR, }; -use halo2_proofs::halo2curves::bn256::Fr; +use halo2_proofs::dev::MockProver; // the main circuit function: returns the compiled IR of a Chiquito circuit // Generic types F, (), (u64, 64) stand for: @@ -35,7 +35,8 @@ use halo2_proofs::halo2curves::bn256::Fr; // 3. two witness generation arguments both of u64 type, i.e. (u64, u64) type FiboReturn = ( - PlonkishCompilationResult>, + Circuit, + Option>, SBPIR>, ); @@ -97,12 +98,12 @@ fn fibo_circuit + Hash>() -> FiboReturn { ctx.pragma_num_steps(16); - // Trace function is responsible for adding step instantiations defined in `step_type_def` - // function above. Trace function is Turing-complete and allows arbitrary user-defined - // logic for assigning witness values + // trace function is responsible for adding step instantiations defined in step_type_def + // function above trace function is Turing complete and allows arbitrary user + // defined logics for assigning witness values ctx.trace(move |ctx: _, _| { - // Add function adds a step instantiation to the main circuit and calls witness - // generation function defined in step_type_def. Input values for witness + // add function adds a step instantiation to the main circuit and calls witness + // generation function defined in step_type_def input values for witness // generation function are (1, 1) in this step instance ctx.add(&fibo_step, (1, 1)); let mut a = 1; @@ -123,7 +124,7 @@ fn fibo_circuit + Hash>() -> FiboReturn { &fibo, ); - (compiled, fibo) + (compiled.circuit, compiled.assignment_generator, fibo) } // After compiling Chiquito AST to an IR, it is further parsed by a Chiquito Halo2 backend and @@ -131,64 +132,48 @@ fn fibo_circuit + Hash>() -> FiboReturn { // standard main function for a Halo2 circuit fn main() { - let (mut chiquito, _) = fibo_circuit::(); + let (chiquito, wit_gen, _) = fibo_circuit::(); + let compiled = chiquito2Halo2(chiquito); + let circuit = ChiquitoHalo2Circuit::new(compiled, wit_gen.map(|g| g.generate(()))); - let params_path = "examples/ptau/hermez-raw-11"; + let prover = MockProver::::run(7, &circuit, circuit.instance()).unwrap(); - let halo2_prover = chiquito.create_halo2_prover(params_path); - println!("k={}", halo2_prover.get_k()); + let result = prover.verify(); - let (proof, instance) = - halo2_prover.generate_proof(chiquito.assignment_generator.unwrap().generate(())); + println!("{:#?}", result); - let result = halo2_verify( - proof, - halo2_prover.get_params(), - halo2_prover.get_vk(), - instance, - ); - - println!("result = {:#?}", result); - - if let Err(error) = &result { - println!("{}", error); + if let Err(failures) = &result { + for failure in failures.iter() { + println!("{}", failure); + } } // hyperplonk boilerplate use hyperplonk_benchmark::proof_system::{bench_plonkish_backend, System}; use plonkish_backend::{ backend, - halo2_curves::bn256::{Bn256, Fr as hpFr}, + halo2_curves::bn256::{Bn256, Fr}, pcs::{multilinear, univariate}, }; // get Chiquito ir - let (plonkish_compilation_result, _) = fibo_circuit::(); + let (circuit, assignment_generator, _) = fibo_circuit::(); // get assignments - let assignments = plonkish_compilation_result - .assignment_generator - .unwrap() - .generate(()); + let assignments = assignment_generator.unwrap().generate(()); // get hyperplonk circuit - let mut hyperplonk_circuit = - ChiquitoHyperPlonkCircuit::new(4, plonkish_compilation_result.circuit); + let mut hyperplonk_circuit = ChiquitoHyperPlonkCircuit::new(4, circuit); hyperplonk_circuit.set_assignment(assignments); type GeminiKzg = multilinear::Gemini>; type HyperPlonk = backend::hyperplonk::HyperPlonk; - bench_plonkish_backend::(System::HyperPlonk, 4, &hyperplonk_circuit); + bench_plonkish_backend::(System::HyperPlonk, 4, &hyperplonk_circuit); // pil boilerplate use chiquito::pil::backend::powdr_pil::chiquito2Pil; - let (plonkish_compilation_result, circuit) = fibo_circuit::(); + let (_, wit_gen, circuit) = fibo_circuit::(); let pil = chiquito2Pil( circuit, - Some( - plonkish_compilation_result - .assignment_generator - .unwrap() - .generate_trace_witness(()), - ), + Some(wit_gen.unwrap().generate_trace_witness(())), String::from("FiboCircuit"), ); print!("{}", pil); diff --git a/examples/keccak.rs b/examples/keccak.rs index cb491bcd..5a22f07e 100644 --- a/examples/keccak.rs +++ b/examples/keccak.rs @@ -3,7 +3,7 @@ use chiquito::{ lb::LookupTable, super_circuit, trace::DSLTraceGenerator, CircuitContext, StepTypeWGHandler, }, plonkish::{ - backend::halo2::{halo2_verify, Halo2Provable}, + backend::halo2_legacy::{chiquitoSuperCircuit2Halo2, ChiquitoHalo2SuperCircuit}, compiler::{ cell_manager::{MaxWidthCellManager, SingleRowCellManager}, config, @@ -16,7 +16,10 @@ use chiquito::{ }; use std::{hash::Hash, ops::Neg}; -use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField}; +use halo2_proofs::{ + dev::MockProver, + halo2curves::{bn256::Fr, group::ff::PrimeField}, +}; const BIT_COUNT: u64 = 3; const PART_SIZE: u64 = 5; @@ -2246,32 +2249,36 @@ fn keccak_super_circuit + Eq + Hash>( }) } -fn main() { - let circuit_param = KeccakCircuit { - bytes: vec![0, 1, 2, 3, 4, 5, 6, 7], - }; - - let mut super_circuit = keccak_super_circuit::(circuit_param.bytes.len()); - - let params_path = "examples/ptau/hermez-raw-11"; - - let witness = super_circuit.get_mapping().generate(circuit_param); - - let halo2_prover = super_circuit.create_halo2_prover(params_path); - println!("k={}", halo2_prover.get_k()); +fn keccak_run(circuit_param: KeccakCircuit, k: u32) -> bool { + let super_circuit = keccak_super_circuit::(circuit_param.bytes.len()); - let (proof, instance) = halo2_prover.generate_proof(witness); + let compiled = chiquitoSuperCircuit2Halo2(&super_circuit); - let result = halo2_verify( - proof, - halo2_prover.get_params(), - halo2_prover.get_vk(), - instance, + let circuit = ChiquitoHalo2SuperCircuit::new( + compiled, + super_circuit.get_mapping().generate(circuit_param), ); + let prover = MockProver::::run(k, &circuit, Vec::new()).unwrap(); + let result = prover.verify(); + println!("result = {:#?}", result); - if let Err(failure) = &result { - println!("{}", failure); + if let Err(failures) = &result { + for failure in failures.iter() { + println!("{}", failure); + } + false + } else { + true } } + +fn main() { + let circuit_param = KeccakCircuit { + bytes: vec![0, 1, 2, 3, 4, 5, 6, 7], + }; + + let res = keccak_run(circuit_param, 9); + assert!(res); +} diff --git a/examples/mimc7.rs b/examples/mimc7.rs index a5c5bd7d..468d0868 100644 --- a/examples/mimc7.rs +++ b/examples/mimc7.rs @@ -1,11 +1,14 @@ use std::hash::Hash; -use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField}; +use halo2_proofs::{ + dev::MockProver, + halo2curves::{bn256::Fr, group::ff::PrimeField}, +}; use chiquito::{ frontend::dsl::{lb::LookupTable, super_circuit, trace::DSLTraceGenerator, CircuitContext}, plonkish::{ - backend::halo2::{halo2_verify, Halo2Provable}, + backend::halo2_legacy::{chiquitoSuperCircuit2Halo2, ChiquitoHalo2SuperCircuit}, compiler::{ cell_manager::SingleRowCellManager, config, step_selector::SimpleStepSelectorBuilder, }, @@ -198,28 +201,23 @@ fn main() { let x_in_value = Fr::from_str_vartime("1").expect("expected a number"); let k_value = Fr::from_str_vartime("2").expect("expected a number"); - let mut super_circuit = mimc7_super_circuit::(); - - let params_path = "examples/ptau/hermez-raw-11"; - - let witness = super_circuit.get_mapping().generate((x_in_value, k_value)); - - let halo2_prover = super_circuit.create_halo2_prover(params_path); - println!("k={}", halo2_prover.get_k()); + let super_circuit = mimc7_super_circuit::(); + let compiled = chiquitoSuperCircuit2Halo2(&super_circuit); + let circuit = ChiquitoHalo2SuperCircuit::new( + compiled, + super_circuit.get_mapping().generate((x_in_value, k_value)), + ); - let (proof, instance) = halo2_prover.generate_proof(witness); + let prover = MockProver::::run(10, &circuit, circuit.instance()).unwrap(); - let result = halo2_verify( - proof, - halo2_prover.get_params(), - halo2_prover.get_vk(), - instance, - ); + let result = prover.verify(); println!("result = {:#?}", result); - if let Err(failure) = &result { - println!("{}", failure); + if let Err(failures) = &result { + for failure in failures.iter() { + println!("{}", failure); + } } // pil boilerplate diff --git a/examples/poseidon.rs b/examples/poseidon.rs index 598d8491..56b5f3e3 100644 --- a/examples/poseidon.rs +++ b/examples/poseidon.rs @@ -1,7 +1,7 @@ use chiquito::{ frontend::dsl::{lb::LookupTable, super_circuit, trace::DSLTraceGenerator, CircuitContext}, plonkish::{ - backend::halo2::{halo2_verify, Halo2Provable}, + backend::halo2_legacy::{chiquitoSuperCircuit2Halo2, ChiquitoHalo2SuperCircuit}, compiler::{ cell_manager::{MaxWidthCellManager, SingleRowCellManager}, config, @@ -14,7 +14,10 @@ use chiquito::{ use std::hash::Hash; -use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField}; +use halo2_proofs::{ + dev::MockProver, + halo2curves::{bn256::Fr, group::ff::PrimeField}, +}; #[derive(Clone)] struct RoundValues { @@ -700,27 +703,21 @@ fn main() { n_outputs: 1, }; - let mut super_circuit = poseidon_super_circuit(lens); - let witness = super_circuit.get_mapping().generate(values); - - let params_path = "examples/ptau/hermez-raw-11"; + let super_circuit = poseidon_super_circuit(lens); + let compiled = chiquitoSuperCircuit2Halo2(&super_circuit); + let circuit = + ChiquitoHalo2SuperCircuit::new(compiled, super_circuit.get_mapping().generate(values)); - let halo2_prover = super_circuit.create_halo2_prover(params_path); - println!("k={}", halo2_prover.get_k()); + let prover = MockProver::::run(12, &circuit, Vec::new()).unwrap(); - let (proof, instance) = halo2_prover.generate_proof(witness); - - let result = halo2_verify( - proof, - halo2_prover.get_params(), - halo2_prover.get_vk(), - instance, - ); + let result = prover.verify(); println!("result = {:#?}", result); - if let Err(failure) = &result { - println!("{}", failure); + if let Err(failures) = &result { + for failure in failures.iter() { + println!("{}", failure); + } } } diff --git a/src/plonkish/backend/halo2_legacy.rs b/src/plonkish/backend/halo2_legacy.rs new file mode 100644 index 00000000..b899bf3b --- /dev/null +++ b/src/plonkish/backend/halo2_legacy.rs @@ -0,0 +1,501 @@ +use std::{collections::HashMap, hash::Hash}; + +use halo2_proofs::{ + circuit::{Cell, Layouter, Region, RegionIndex, SimpleFloorPlanner, Value}, + halo2curves::ff::PrimeField, + plonk::{ + Advice, Any, Circuit as h2Circuit, Column, ConstraintSystem, ErrorFront, Expression, + FirstPhase, Fixed, Instance, SecondPhase, ThirdPhase, VirtualCells, + }, + poly::Rotation, +}; + +use crate::{ + plonkish::ir::{ + assignments::Assignments, + sc::{SuperAssignments, SuperCircuit}, + Circuit, Column as cColumn, + ColumnType::{Advice as cAdvice, Fixed as cFixed, Halo2Advice, Halo2Fixed}, + PolyExpr, + }, + poly::ToField, + util::UUID, +}; + +#[allow(non_snake_case)] +pub fn chiquito2Halo2 + Hash>(circuit: Circuit) -> ChiquitoHalo2 { + ChiquitoHalo2::new(circuit) +} + +#[allow(non_snake_case)] +pub fn chiquitoSuperCircuit2Halo2 + Hash, MappingArgs>( + super_circuit: &SuperCircuit, +) -> Vec> { + super_circuit + .get_sub_circuits() + .iter() + .map(|c| chiquito2Halo2((*c).clone())) + .collect() +} + +#[derive(Clone, Debug, Default)] +pub struct ChiquitoHalo2> { + pub debug: bool, + + circuit: Circuit, + + advice_columns: HashMap>, + fixed_columns: HashMap>, + instance_column: Option>, + + ir_id: UUID, +} + +impl + Hash> ChiquitoHalo2 { + pub fn new(circuit: Circuit) -> ChiquitoHalo2 { + let ir_id = circuit.id; + ChiquitoHalo2 { + debug: true, + circuit, + advice_columns: Default::default(), + fixed_columns: Default::default(), + instance_column: Default::default(), + ir_id, + } + } + + pub fn configure(&mut self, meta: &mut ConstraintSystem) { + self.configure_columns_sub_circuit(meta); + + self.configure_sub_circuit(meta); + } + + fn configure_columns_sub_circuit(&mut self, meta: &mut ConstraintSystem) { + let mut advice_columns = HashMap::>::new(); + let mut fixed_columns = HashMap::>::new(); + + for column in self.circuit.columns.iter() { + match column.ctype { + cAdvice => { + let halo2_column = to_halo2_advice(meta, column); + advice_columns.insert(column.uuid(), halo2_column); + meta.annotate_lookup_any_column(halo2_column, || column.annotation.clone()); + } + cFixed => { + let halo2_column = meta.fixed_column(); + fixed_columns.insert(column.uuid(), halo2_column); + meta.annotate_lookup_any_column(halo2_column, || column.annotation.clone()); + } + Halo2Advice => { + let halo2_column = column + .halo2_advice + .unwrap_or_else(|| { + panic!("halo2 advice column not found {}", column.annotation) + }) + .column; + advice_columns.insert(column.uuid(), halo2_column); + meta.annotate_lookup_any_column(halo2_column, || column.annotation.clone()); + } + Halo2Fixed => { + let halo2_column = column + .halo2_fixed + .unwrap_or_else(|| { + panic!("halo2 advice column not found {}", column.annotation) + }) + .column; + fixed_columns.insert(column.uuid(), halo2_column); + meta.annotate_lookup_any_column(halo2_column, || column.annotation.clone()); + } + } + } + + self.advice_columns = advice_columns; + self.fixed_columns = fixed_columns; + } + + pub fn configure_sub_circuit(&mut self, meta: &mut ConstraintSystem) { + if !self.circuit.exposed.is_empty() { + self.instance_column = Some(meta.instance_column()); + } + + if !self.circuit.polys.is_empty() { + meta.create_gate("main", |meta| { + let mut constraints: Vec<(&'static str, Expression)> = Vec::new(); + + for poly in self.circuit.polys.iter() { + let converted = self.convert_poly(meta, &poly.expr); + let annotation = Box::leak( + format!("{} => {:?}", poly.annotation, converted).into_boxed_str(), + ); + constraints.push((annotation, converted)); + } + + constraints + }); + } + + for lookup in self.circuit.lookups.iter() { + let annotation: &'static str = Box::leak(lookup.annotation.clone().into_boxed_str()); + meta.lookup_any(annotation, |meta| { + let mut exprs = Vec::new(); + for (src, dest) in lookup.exprs.iter() { + exprs.push((self.convert_poly(meta, src), self.convert_poly(meta, dest))) + } + + exprs + }); + } + } + + pub fn synthesize(&self, layouter: &mut impl Layouter, witness: Option<&Assignments>) { + let _ = layouter.assign_region( + || "circuit", + |mut region| { + self.annotate_circuit(&mut region); + + self.assign_fixed(&mut region, &self.circuit.fixed_assignments)?; + + if let Some(witness) = &witness { + self.assign_advice(&mut region, witness)?; + } + + Ok(()) + }, + ); + + for (index, (column, rotation)) in self.circuit.exposed.iter().enumerate() { + let halo2_column = + Column::::from(*self.advice_columns.get(&column.uuid()).unwrap()); + let cell = new_cell( + halo2_column, + // For single row cell manager, forward signal rotation is always zero. + // For max width cell manager, rotation can be non-zero. + // Offset is absolute row index calculated in `compile_exposed`. + *rotation as usize, + ); + let _ = layouter.constrain_instance(cell, self.instance_column.unwrap(), index); + } + } + + fn assign_advice( + &self, + region: &mut Region, + witness: &Assignments, + ) -> Result<(), ErrorFront> { + for (column, assignments) in witness.iter() { + let column = self.convert_advice_column(column); + + for (offset, value) in assignments.iter().enumerate() { + region.assign_advice(|| "", column, offset, || Value::known(*value))?; + } + } + + Ok(()) + } + + fn assign_fixed( + &self, + region: &mut Region, + fixed: &Assignments, + ) -> Result<(), ErrorFront> { + for (column, values) in fixed.iter() { + let column = self.convert_fixed_column(column); + + for (offset, value) in values.iter().enumerate() { + region.assign_fixed(|| "", column, offset, || Value::known(*value))?; + } + } + + Ok(()) + } + + fn annotate_circuit(&self, region: &mut Region) { + for column in self.circuit.columns.iter() { + match column.ctype { + cAdvice | Halo2Advice => { + let halo2_column = self + .advice_columns + .get(&column.uuid()) + .expect("advice column not found"); + + region.name_column(|| column.annotation.clone(), *halo2_column); + } + cFixed | Halo2Fixed => { + let halo2_column = self + .fixed_columns + .get(&column.uuid()) + .expect("fixed column not found"); + + region.name_column(|| column.annotation.clone(), *halo2_column); + } + } + } + } + + fn convert_poly(&self, meta: &mut VirtualCells<'_, F>, src: &PolyExpr) -> Expression { + match src { + PolyExpr::Const(c, _) => Expression::Constant(*c), + PolyExpr::Sum(es, _) => { + let mut iter = es.iter(); + let first = self.convert_poly(meta, iter.next().unwrap()); + iter.fold(first, |acc, e| acc + self.convert_poly(meta, e)) + } + PolyExpr::Mul(es, _) => { + let mut iter = es.iter(); + let first = self.convert_poly(meta, iter.next().unwrap()); + iter.fold(first, |acc, e| acc * self.convert_poly(meta, e)) + } + PolyExpr::Neg(e, _) => -self.convert_poly(meta, e), + PolyExpr::Pow(e, n, _) => { + if *n == 0 { + Expression::Constant(1.field()) + } else { + let e = self.convert_poly(meta, e); + (1..*n).fold(e.clone(), |acc, _| acc * e.clone()) + } + } + PolyExpr::Halo2Expr(e, _) => e.clone(), + PolyExpr::Query((column, rotation, _), _) => { + self.convert_query(meta, column, *rotation) + } + PolyExpr::MI(_, _) => panic!("mi elimination not done"), + } + } + + fn convert_query( + &self, + meta: &mut VirtualCells<'_, F>, + column: &cColumn, + rotation: i32, + ) -> Expression { + match column.ctype { + cAdvice | Halo2Advice => { + let c = self + .advice_columns + .get(&column.uuid()) + .unwrap_or_else(|| panic!("column not found {}", column.annotation)); + + meta.query_advice(*c, Rotation(rotation)) + } + cFixed | Halo2Fixed => { + let c = self + .fixed_columns + .get(&column.uuid()) + .unwrap_or_else(|| panic!("column not found {}", column.annotation)); + + meta.query_fixed(*c, Rotation(rotation)) + } + } + } + + fn convert_advice_column(&self, column: &cColumn) -> Column { + match column.ctype { + cAdvice | Halo2Advice => *self + .advice_columns + .get(&column.uuid()) + .unwrap_or_else(|| panic!("column not found {}", column.annotation)), + _ => panic!("wrong column type"), + } + } + + fn convert_fixed_column(&self, column: &cColumn) -> Column { + match column.ctype { + cFixed | Halo2Fixed => *self + .fixed_columns + .get(&column.uuid()) + .unwrap_or_else(|| panic!("column not found {}", column.annotation)), + _ => panic!("wrong column type"), + } + } +} + +#[allow(dead_code)] +// From Plaf Halo2 backend. +// _Cell is a helper struct used for constructing Halo2 Cell. +struct _Cell { + region_index: RegionIndex, + row_offset: usize, + column: Column, +} +// From Plaf Halo2 backend. +fn new_cell(column: Column, offset: usize) -> Cell { + let cell = _Cell { + region_index: RegionIndex::from(0), + row_offset: offset, + column, + }; + // NOTE: We use unsafe here to construct a Cell, which doesn't have a public constructor. This + // helps us set the copy constraints easily (without having to store all assigned cells + // previously) + unsafe { std::mem::transmute::<_Cell, Cell>(cell) } +} + +pub fn to_halo2_advice( + meta: &mut ConstraintSystem, + column: &cColumn, +) -> Column { + match column.phase { + 0 => meta.advice_column_in(FirstPhase), + 1 => meta.advice_column_in(SecondPhase), + 2 => meta.advice_column_in(ThirdPhase), + _ => panic!("jarll wrong phase"), + } +} + +#[derive(Clone, Default, Debug)] +pub struct ChiquitoHalo2Circuit> { + compiled: ChiquitoHalo2, + witness: Option>, +} + +impl + Hash> ChiquitoHalo2Circuit { + pub fn new(compiled: ChiquitoHalo2, witness: Option>) -> Self { + Self { compiled, witness } + } + + pub fn instance(&self) -> Vec> { + if !self.compiled.circuit.exposed.is_empty() { + if let Some(witness) = &self.witness { + return vec![self.compiled.circuit.instance(witness)]; + } + } + Vec::new() + } +} + +impl + Hash> h2Circuit for ChiquitoHalo2Circuit { + type Config = ChiquitoHalo2; + + type FloorPlanner = SimpleFloorPlanner; + + type Params = ChiquitoHalo2; + + fn without_witnesses(&self) -> Self { + Self { + compiled: self.compiled.clone(), + witness: self.witness.clone().map(|mut w| { + w.clear(); + w + }), + } + } + + fn params(&self) -> Self::Params { + self.compiled.clone() + } + + fn configure_with_params( + meta: &mut ConstraintSystem, + mut compiled: Self::Params, + ) -> Self::Config { + compiled.configure(meta); + + compiled + } + + fn synthesize( + &self, + compiled: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), ErrorFront> { + compiled.synthesize(&mut layouter, self.witness.as_ref()); + + Ok(()) + } + + fn configure(_: &mut ConstraintSystem) -> Self::Config { + unreachable!() + } +} + +#[derive(Debug, Default)] +pub struct ChiquitoHalo2SuperCircuit> { + sub_circuits: Vec>, + witness: SuperAssignments, +} + +impl + Hash> ChiquitoHalo2SuperCircuit { + pub fn new(sub_circuits: Vec>, witness: SuperAssignments) -> Self { + Self { + sub_circuits, + witness, + } + } + + pub fn instance(&self) -> Vec> { + let mut result = Vec::new(); + + for sub_circuit in &self.sub_circuits { + if !sub_circuit.circuit.exposed.is_empty() { + let instance_values = sub_circuit.circuit.instance( + self.witness + .get(&sub_circuit.ir_id) + .expect("No matching witness found for given UUID."), + ); + result.push(instance_values); + } + } + + result + } +} + +impl + Hash> h2Circuit for ChiquitoHalo2SuperCircuit { + type Config = Vec>; + + type FloorPlanner = SimpleFloorPlanner; + + type Params = Vec>; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn params(&self) -> Self::Params { + self.sub_circuits.clone() + } + + fn configure_with_params( + meta: &mut ConstraintSystem, + mut sub_circuits: Self::Params, + ) -> Self::Config { + sub_circuits + .iter_mut() + .for_each(|c| c.configure_columns_sub_circuit(meta)); + + let advice_columns: HashMap> = + sub_circuits.iter().fold(HashMap::default(), |mut acc, s| { + acc.extend(s.advice_columns.clone()); + acc + }); + let fixed_columns: HashMap> = + sub_circuits.iter().fold(HashMap::default(), |mut acc, s| { + acc.extend(s.fixed_columns.clone()); + acc + }); + + sub_circuits.iter_mut().for_each(|sub_circuit| { + sub_circuit.advice_columns = advice_columns.clone(); + sub_circuit.fixed_columns = fixed_columns.clone(); + sub_circuit.configure_sub_circuit(meta) + }); + + sub_circuits + } + + fn synthesize( + &self, + sub_circuits: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), ErrorFront> { + for sub_circuit in sub_circuits { + sub_circuit.synthesize(&mut layouter, self.witness.get(&sub_circuit.ir_id)) + } + + Ok(()) + } + + fn configure(_: &mut ConstraintSystem) -> Self::Config { + unreachable!() + } +} diff --git a/src/plonkish/backend/mod.rs b/src/plonkish/backend/mod.rs index 66cb822b..e9aab62b 100644 --- a/src/plonkish/backend/mod.rs +++ b/src/plonkish/backend/mod.rs @@ -1,2 +1,3 @@ pub mod halo2; +pub mod halo2_legacy; pub mod hyperplonk;