mirror of
https://github.com/privacy-scaling-explorations/chiquito.git
synced 2026-01-10 06:28:06 -05:00
Compile to Halo2 middleware (#263)
Switching to a more recent Halo2 version revealed a problem with our lookups - they don't pass a `lookup-any-sanity-checks` because they are using only the fixed query. This is why I had to disable the default features of all halo2 crates (that include `lookup-any-sanity-checks`) and only enable the rest. I suppose we can refactor our lookups to use `lookup` instead of `lookup_any`.
This commit is contained in:
17
Cargo.toml
17
Cargo.toml
@@ -8,23 +8,22 @@ authors = ["Leo Lara <leo@leolara.me>"]
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[patch.crates-io]
|
||||
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v0.3.0" }
|
||||
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", default-features = false, rev = "da4983e" }
|
||||
|
||||
[patch."https://github.com/scroll-tech/halo2.git"]
|
||||
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v0.3.0" }
|
||||
|
||||
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", default-features = false, rev = "da4983e" }
|
||||
|
||||
[dependencies]
|
||||
pyo3 = { version = "0.19.1", features = ["extension-module"] }
|
||||
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", features = [
|
||||
"circuit-params",
|
||||
"derive_serde",
|
||||
], tag = "v0.3.0" }
|
||||
|
||||
polyexen = { git = "https://github.com/Dhole/polyexen.git", rev = "16a85c5411f804dc49bbf373d24ff9eedadedfbe" }
|
||||
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", default-features = false, features = [ "circuit-params", "derive_serde"], rev = "da4983e"}
|
||||
|
||||
halo2_middleware = { git = "https://github.com/privacy-scaling-explorations/halo2.git", rev = "da4983e" }
|
||||
halo2_backend = { git = "https://github.com/privacy-scaling-explorations/halo2.git", features = ["derive_serde"], rev = "da4983e" }
|
||||
|
||||
num-bigint = { version = "0.4", features = ["rand"] }
|
||||
uuid = { version = "1.4.0", features = ["v1", "rng"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde = { version = "=1.0.203", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
hyperplonk_benchmark = { git = "https://github.com/qwang98/plonkish.git", branch = "main", package = "benchmark" }
|
||||
plonkish_backend = { git = "https://github.com/qwang98/plonkish.git", branch = "main", package = "plonkish_backend" }
|
||||
|
||||
@@ -7,7 +7,10 @@ use chiquito::{
|
||||
CircuitContext, StepTypeSetupContext, StepTypeWGHandler,
|
||||
},
|
||||
plonkish::{
|
||||
backend::halo2::{chiquitoSuperCircuit2Halo2, ChiquitoHalo2SuperCircuit},
|
||||
backend::halo2::{
|
||||
chiquitoSuperCircuit2Halo2, halo2_verify, ChiquitoHalo2SuperCircuit, DummyRng,
|
||||
Halo2Prover, PlonkishHalo2,
|
||||
},
|
||||
compiler::{
|
||||
cell_manager::{MaxWidthCellManager, SingleRowCellManager},
|
||||
config,
|
||||
@@ -18,10 +21,8 @@ use chiquito::{
|
||||
poly::ToExpr,
|
||||
sbpir::query::Queriable,
|
||||
};
|
||||
use halo2_proofs::{
|
||||
dev::MockProver,
|
||||
halo2curves::{bn256::Fr, group::ff::PrimeField},
|
||||
};
|
||||
use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField};
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
use std::{fmt::Write, hash::Hash};
|
||||
|
||||
pub const IV_LEN: usize = 8;
|
||||
@@ -1480,17 +1481,25 @@ fn main() {
|
||||
f: true, // 8bits
|
||||
};
|
||||
|
||||
let circuit =
|
||||
ChiquitoHalo2SuperCircuit::new(compiled, super_circuit.get_mapping().generate(values));
|
||||
let witness = super_circuit.get_mapping().generate(values);
|
||||
let mut circuit = ChiquitoHalo2SuperCircuit::new(compiled);
|
||||
|
||||
let prover = MockProver::run(9, &circuit, Vec::new()).unwrap();
|
||||
let result = prover.verify();
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let halo2_prover = circuit.create_halo2_prover(9, rng);
|
||||
|
||||
let (proof, instance) = halo2_prover.generate_proof(witness);
|
||||
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
if let Err(failures) = &result {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(failure) = &result {
|
||||
println!("{}", failure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ use chiquito::{
|
||||
frontend::dsl::{circuit, trace::DSLTraceGenerator}, /* main function for constructing an AST
|
||||
* circuit */
|
||||
plonkish::{
|
||||
backend::halo2::{chiquito2Halo2, ChiquitoHalo2Circuit},
|
||||
backend::halo2::{halo2_verify, DummyRng, Halo2Prover, PlonkishHalo2},
|
||||
compiler::{
|
||||
cell_manager::SingleRowCellManager, // input for constructing the compiler
|
||||
compile, // input for constructing the compiler
|
||||
config,
|
||||
step_selector::SimpleStepSelectorBuilder,
|
||||
PlonkishCompilationResult,
|
||||
},
|
||||
ir::{assignments::AssignmentGenerator, Circuit},
|
||||
}, /* compiles to
|
||||
* Chiquito Halo2
|
||||
* backend,
|
||||
@@ -22,12 +22,13 @@ use chiquito::{
|
||||
* circuit */
|
||||
poly::ToField,
|
||||
};
|
||||
use halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr};
|
||||
use halo2_proofs::halo2curves::bn256::Fr;
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
|
||||
const MAX_FACTORIAL: usize = 10;
|
||||
|
||||
type AssignGen<F> = AssignmentGenerator<F, DSLTraceGenerator<F, u32>>;
|
||||
fn generate<F: Field + From<u64> + Hash>() -> (Circuit<F>, Option<AssignGen<F>>) {
|
||||
fn generate<F: Field + From<u64> + Hash>() -> PlonkishCompilationResult<F, DSLTraceGenerator<F, u32>>
|
||||
{
|
||||
// table for the circuit:
|
||||
// | step_type | i | x |
|
||||
// ----------------------------------
|
||||
@@ -134,50 +135,45 @@ fn generate<F: Field + From<u64> + Hash>() -> (Circuit<F>, Option<AssignGen<F>>)
|
||||
|
||||
// standard main function for a Halo2 circuit
|
||||
fn main() {
|
||||
let (chiquito, wit_gen) = generate::<Fr>();
|
||||
let compiled = chiquito2Halo2(chiquito);
|
||||
let circuit = ChiquitoHalo2Circuit::new(compiled, wit_gen.map(|g| g.generate(0)));
|
||||
let mut plonkish = generate::<Fr>();
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let prover = MockProver::<Fr>::run(10, &circuit, circuit.instance()).unwrap();
|
||||
let halo2_prover = plonkish.create_halo2_prover(10, rng);
|
||||
|
||||
let result = prover.verify();
|
||||
let (proof, instance) =
|
||||
halo2_prover.generate_proof(plonkish.assignment_generator.unwrap().generate(0));
|
||||
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
if let Err(failures) = &result {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(error) = &result {
|
||||
println!("{}", error);
|
||||
}
|
||||
|
||||
// plaf boilerplate
|
||||
use chiquito::plonkish::backend::plaf::chiquito2Plaf;
|
||||
use polyexen::plaf::backends::halo2::PlafH2Circuit;
|
||||
let mut plonkish = generate::<Fr>();
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
// get Chiquito ir
|
||||
let (circuit, wit_gen) = generate::<Fr>();
|
||||
// get Plaf
|
||||
let (plaf, plaf_wit_gen) = chiquito2Plaf(circuit, 8, false);
|
||||
let wit = plaf_wit_gen.generate(wit_gen.map(|v| v.generate(7)));
|
||||
let halo2_prover = plonkish.create_halo2_prover(8, rng);
|
||||
|
||||
// debug only: print witness
|
||||
// println!("{}", polyexen::plaf::WitnessDisplayCSV(&wit));
|
||||
let (proof, instance) =
|
||||
halo2_prover.generate_proof(plonkish.assignment_generator.unwrap().generate(7));
|
||||
|
||||
// get Plaf halo2 circuit from Plaf's halo2 backend
|
||||
// this is just a proof of concept, because Plaf only has backend for halo2
|
||||
// this is unnecessary because Chiquito has a halo2 backend already
|
||||
let plaf_circuit = PlafH2Circuit { plaf, wit };
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
// same as halo2 boilerplate above
|
||||
let prover_plaf = MockProver::<Fr>::run(8, &plaf_circuit, Vec::new()).unwrap();
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
let result_plaf = prover_plaf.verify();
|
||||
|
||||
println!("result = {:#?}", result_plaf);
|
||||
|
||||
if let Err(failures) = &result_plaf {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(error) = &result {
|
||||
println!("{}", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ use chiquito::{
|
||||
frontend::dsl::{circuit, trace::DSLTraceGenerator}, /* main function for constructing an AST
|
||||
* circuit */
|
||||
plonkish::{
|
||||
backend::halo2::{chiquito2Halo2, ChiquitoHalo2Circuit},
|
||||
backend::halo2::{halo2_verify, DummyRng, Halo2Prover, PlonkishHalo2},
|
||||
compiler::{
|
||||
cell_manager::SingleRowCellManager, // input for constructing the compiler
|
||||
compile, // input for constructing the compiler
|
||||
config,
|
||||
step_selector::SimpleStepSelectorBuilder,
|
||||
PlonkishCompilationResult,
|
||||
},
|
||||
ir::{assignments::AssignmentGenerator, Circuit},
|
||||
}, /* compiles to
|
||||
* Chiquito Halo2
|
||||
* backend,
|
||||
@@ -22,15 +22,15 @@ use chiquito::{
|
||||
* circuit */
|
||||
poly::ToField,
|
||||
};
|
||||
use halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr};
|
||||
use halo2_proofs::halo2curves::bn256::Fr;
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
|
||||
// This example file extends the rust example file 'fibonacci.rs',
|
||||
// describing usage of multiple steptypes, padding, and exposing signals.
|
||||
|
||||
type AssignGen<F> = AssignmentGenerator<F, DSLTraceGenerator<F, u32>>;
|
||||
|
||||
// the main circuit function
|
||||
fn fibo_circuit<F: Field + From<u64> + Hash>() -> (Circuit<F>, Option<AssignGen<F>>)
|
||||
fn fibo_circuit<F: Field + From<u64> + Hash>(
|
||||
) -> PlonkishCompilationResult<F, DSLTraceGenerator<F, u32>>
|
||||
// u32 is for external input that indicates the number of fibnoacci iterations
|
||||
{
|
||||
use chiquito::{
|
||||
@@ -205,50 +205,24 @@ fn fibo_circuit<F: Field + From<u64> + Hash>() -> (Circuit<F>, Option<AssignGen<
|
||||
|
||||
// standard main function for a Halo2 circuit
|
||||
fn main() {
|
||||
let (chiquito, wit_gen) = fibo_circuit::<Fr>();
|
||||
let compiled = chiquito2Halo2(chiquito);
|
||||
let circuit = ChiquitoHalo2Circuit::new(compiled, wit_gen.map(|g| g.generate(7)));
|
||||
let mut plonkish = fibo_circuit::<Fr>();
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let prover = MockProver::<Fr>::run(7, &circuit, circuit.instance()).unwrap();
|
||||
let halo2_prover = plonkish.create_halo2_prover(7, rng);
|
||||
|
||||
let result = prover.verify();
|
||||
let (proof, instance) =
|
||||
halo2_prover.generate_proof(plonkish.assignment_generator.unwrap().generate(7));
|
||||
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
println!("{:#?}", result);
|
||||
|
||||
if let Err(failures) = &result {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
}
|
||||
|
||||
// plaf boilerplate
|
||||
use chiquito::plonkish::backend::plaf::chiquito2Plaf;
|
||||
use polyexen::plaf::{backends::halo2::PlafH2Circuit, WitnessDisplayCSV};
|
||||
|
||||
// get Chiquito ir
|
||||
let (circuit, wit_gen) = fibo_circuit::<Fr>();
|
||||
// get Plaf
|
||||
let (plaf, plaf_wit_gen) = chiquito2Plaf(circuit, 8, false);
|
||||
let wit = plaf_wit_gen.generate(wit_gen.map(|v| v.generate(7)));
|
||||
|
||||
// debug only: print witness
|
||||
println!("{}", WitnessDisplayCSV(&wit));
|
||||
|
||||
// get Plaf halo2 circuit from Plaf's halo2 backend
|
||||
// this is just a proof of concept, because Plaf only has backend for halo2
|
||||
// this is unnecessary because Chiquito has a halo2 backend already
|
||||
let plaf_circuit = PlafH2Circuit { plaf, wit };
|
||||
|
||||
// same as halo2 boilerplate above
|
||||
let prover_plaf = MockProver::<Fr>::run(8, &plaf_circuit, plaf_circuit.instance()).unwrap();
|
||||
|
||||
let result_plaf = prover_plaf.verify();
|
||||
|
||||
println!("result = {:#?}", result_plaf);
|
||||
|
||||
if let Err(failures) = &result_plaf {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(failure) = &result {
|
||||
println!("{}", failure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use chiquito::{
|
||||
* circuit */
|
||||
plonkish::{
|
||||
backend::{
|
||||
halo2::{chiquito2Halo2, ChiquitoHalo2Circuit},
|
||||
halo2::{halo2_verify, DummyRng, Halo2Prover, PlonkishHalo2},
|
||||
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,8 @@ use chiquito::{
|
||||
poly::ToField,
|
||||
sbpir::SBPIR,
|
||||
};
|
||||
use halo2_proofs::dev::MockProver;
|
||||
use halo2_proofs::halo2curves::bn256::Fr;
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
|
||||
// the main circuit function: returns the compiled IR of a Chiquito circuit
|
||||
// Generic types F, (), (u64, 64) stand for:
|
||||
@@ -35,8 +36,7 @@ use halo2_proofs::dev::MockProver;
|
||||
// 3. two witness generation arguments both of u64 type, i.e. (u64, u64)
|
||||
|
||||
type FiboReturn<F> = (
|
||||
Circuit<F>,
|
||||
Option<AssignmentGenerator<F>>,
|
||||
PlonkishCompilationResult<F, DSLTraceGenerator<F>>,
|
||||
SBPIR<F, DSLTraceGenerator<F>>,
|
||||
);
|
||||
|
||||
@@ -98,12 +98,12 @@ fn fibo_circuit<F: Field + From<u64> + Hash>() -> FiboReturn<F> {
|
||||
|
||||
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 logics 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
|
||||
// logic 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;
|
||||
@@ -124,7 +124,7 @@ fn fibo_circuit<F: Field + From<u64> + Hash>() -> FiboReturn<F> {
|
||||
&fibo,
|
||||
);
|
||||
|
||||
(compiled.0, compiled.1, fibo)
|
||||
(compiled, fibo)
|
||||
}
|
||||
|
||||
// After compiling Chiquito AST to an IR, it is further parsed by a Chiquito Halo2 backend and
|
||||
@@ -132,79 +132,63 @@ fn fibo_circuit<F: Field + From<u64> + Hash>() -> FiboReturn<F> {
|
||||
|
||||
// standard main function for a Halo2 circuit
|
||||
fn main() {
|
||||
let (chiquito, wit_gen, _) = fibo_circuit::<Fr>();
|
||||
let compiled = chiquito2Halo2(chiquito);
|
||||
let circuit = ChiquitoHalo2Circuit::new(compiled, wit_gen.map(|g| g.generate(())));
|
||||
let (mut chiquito, _) = fibo_circuit::<Fr>();
|
||||
|
||||
let prover = MockProver::<Fr>::run(7, &circuit, circuit.instance()).unwrap();
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let result = prover.verify();
|
||||
let halo2_prover = chiquito.create_halo2_prover(7, rng);
|
||||
|
||||
println!("{:#?}", result);
|
||||
let (proof, instance) =
|
||||
halo2_prover.generate_proof(chiquito.assignment_generator.unwrap().generate(()));
|
||||
|
||||
if let Err(failures) = &result {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
}
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
// plaf boilerplate
|
||||
use chiquito::plonkish::backend::plaf::chiquito2Plaf;
|
||||
use polyexen::plaf::{backends::halo2::PlafH2Circuit, WitnessDisplayCSV};
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
// get Chiquito ir
|
||||
let (circuit, wit_gen, _) = fibo_circuit::<Fr>();
|
||||
// get Plaf
|
||||
let (plaf, plaf_wit_gen) = chiquito2Plaf(circuit, 8, false);
|
||||
let wit = plaf_wit_gen.generate(wit_gen.map(|v| v.generate(())));
|
||||
|
||||
// debug only: print witness
|
||||
println!("{}", WitnessDisplayCSV(&wit));
|
||||
|
||||
// get Plaf halo2 circuit from Plaf's halo2 backend
|
||||
// this is just a proof of concept, because Plaf only has backend for halo2
|
||||
// this is unnecessary because Chiquito has a halo2 backend already
|
||||
let plaf_circuit = PlafH2Circuit { plaf, wit };
|
||||
|
||||
// same as halo2 boilerplate above
|
||||
let prover_plaf = MockProver::<Fr>::run(8, &plaf_circuit, plaf_circuit.instance()).unwrap();
|
||||
|
||||
let result_plaf = prover_plaf.verify();
|
||||
|
||||
println!("result = {:#?}", result_plaf);
|
||||
|
||||
if let Err(failures) = &result_plaf {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(error) = &result {
|
||||
println!("{}", error);
|
||||
}
|
||||
|
||||
// hyperplonk boilerplate
|
||||
use hyperplonk_benchmark::proof_system::{bench_plonkish_backend, System};
|
||||
use plonkish_backend::{
|
||||
backend,
|
||||
halo2_curves::bn256::{Bn256, Fr},
|
||||
halo2_curves::bn256::{Bn256, Fr as hpFr},
|
||||
pcs::{multilinear, univariate},
|
||||
};
|
||||
// get Chiquito ir
|
||||
let (circuit, assignment_generator, _) = fibo_circuit::<Fr>();
|
||||
let (plonkish_compilation_result, _) = fibo_circuit::<hpFr>();
|
||||
// get assignments
|
||||
let assignments = assignment_generator.unwrap().generate(());
|
||||
let assignments = plonkish_compilation_result
|
||||
.assignment_generator
|
||||
.unwrap()
|
||||
.generate(());
|
||||
// get hyperplonk circuit
|
||||
let mut hyperplonk_circuit = ChiquitoHyperPlonkCircuit::new(4, circuit);
|
||||
let mut hyperplonk_circuit =
|
||||
ChiquitoHyperPlonkCircuit::new(4, plonkish_compilation_result.circuit);
|
||||
hyperplonk_circuit.set_assignment(assignments);
|
||||
|
||||
type GeminiKzg = multilinear::Gemini<univariate::UnivariateKzg<Bn256>>;
|
||||
type HyperPlonk = backend::hyperplonk::HyperPlonk<GeminiKzg>;
|
||||
bench_plonkish_backend::<HyperPlonk, Fr>(System::HyperPlonk, 4, &hyperplonk_circuit);
|
||||
bench_plonkish_backend::<HyperPlonk, hpFr>(System::HyperPlonk, 4, &hyperplonk_circuit);
|
||||
|
||||
// pil boilerplate
|
||||
use chiquito::pil::backend::powdr_pil::chiquito2Pil;
|
||||
|
||||
let (_, wit_gen, circuit) = fibo_circuit::<Fr>();
|
||||
let (plonkish_compilation_result, circuit) = fibo_circuit::<hpFr>();
|
||||
let pil = chiquito2Pil(
|
||||
circuit,
|
||||
Some(wit_gen.unwrap().generate_trace_witness(())),
|
||||
Some(
|
||||
plonkish_compilation_result
|
||||
.assignment_generator
|
||||
.unwrap()
|
||||
.generate_trace_witness(()),
|
||||
),
|
||||
String::from("FiboCircuit"),
|
||||
);
|
||||
print!("{}", pil);
|
||||
|
||||
@@ -3,7 +3,10 @@ use chiquito::{
|
||||
lb::LookupTable, super_circuit, trace::DSLTraceGenerator, CircuitContext, StepTypeWGHandler,
|
||||
},
|
||||
plonkish::{
|
||||
backend::halo2::{chiquitoSuperCircuit2Halo2, ChiquitoHalo2SuperCircuit},
|
||||
backend::halo2::{
|
||||
chiquitoSuperCircuit2Halo2, halo2_verify, ChiquitoHalo2SuperCircuit, DummyRng,
|
||||
Halo2Prover, PlonkishHalo2,
|
||||
},
|
||||
compiler::{
|
||||
cell_manager::{MaxWidthCellManager, SingleRowCellManager},
|
||||
config,
|
||||
@@ -14,17 +17,10 @@ use chiquito::{
|
||||
poly::ToExpr,
|
||||
sbpir::query::Queriable,
|
||||
};
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
use std::{hash::Hash, ops::Neg};
|
||||
|
||||
use halo2_proofs::{
|
||||
dev::MockProver,
|
||||
halo2curves::{bn256::Fr, group::ff::PrimeField},
|
||||
};
|
||||
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{self, Write},
|
||||
};
|
||||
use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField};
|
||||
|
||||
const BIT_COUNT: u64 = 3;
|
||||
const PART_SIZE: u64 = 5;
|
||||
@@ -2254,114 +2250,35 @@ fn keccak_super_circuit<F: PrimeField<Repr = [u8; 32]> + Eq + Hash>(
|
||||
})
|
||||
}
|
||||
|
||||
use chiquito::plonkish::backend::plaf::chiquito2Plaf;
|
||||
use polyexen::plaf::{Plaf, PlafDisplayBaseTOML, PlafDisplayFixedCSV, Witness, WitnessDisplayCSV};
|
||||
|
||||
fn write_files(name: &str, plaf: &Plaf, wit: &Witness) -> Result<(), io::Error> {
|
||||
let mut base_file = File::create(format!("{}.toml", name))?;
|
||||
let mut fixed_file = File::create(format!("{}_fixed.csv", name))?;
|
||||
let mut witness_file = File::create(format!("{}_witness.csv", name))?;
|
||||
|
||||
write!(base_file, "{}", PlafDisplayBaseTOML(plaf))?;
|
||||
write!(fixed_file, "{}", PlafDisplayFixedCSV(plaf))?;
|
||||
write!(witness_file, "{}", WitnessDisplayCSV(wit))?;
|
||||
println!("write file success...{}", name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keccak_plaf(circuit_param: KeccakCircuit, k: u32) {
|
||||
let super_circuit = keccak_super_circuit::<Fr>(circuit_param.bytes.len());
|
||||
let witness = super_circuit.get_mapping().generate(circuit_param);
|
||||
|
||||
for wit_gen in witness.values() {
|
||||
let wit_gen = wit_gen.clone();
|
||||
|
||||
let mut circuit = super_circuit.get_sub_circuits()[0].clone();
|
||||
circuit
|
||||
.columns
|
||||
.append(&mut super_circuit.get_sub_circuits()[1].columns);
|
||||
circuit
|
||||
.columns
|
||||
.append(&mut super_circuit.get_sub_circuits()[2].columns);
|
||||
circuit
|
||||
.columns
|
||||
.append(&mut super_circuit.get_sub_circuits()[3].columns);
|
||||
circuit
|
||||
.columns
|
||||
.append(&mut super_circuit.get_sub_circuits()[4].columns);
|
||||
circuit
|
||||
.columns
|
||||
.append(&mut super_circuit.get_sub_circuits()[5].columns);
|
||||
circuit
|
||||
.columns
|
||||
.append(&mut super_circuit.get_sub_circuits()[6].columns);
|
||||
|
||||
for (key, value) in super_circuit.get_sub_circuits()[0].fixed_assignments.iter() {
|
||||
circuit.fixed_assignments.insert(key.clone(), value.clone());
|
||||
}
|
||||
for (key, value) in super_circuit.get_sub_circuits()[1].fixed_assignments.iter() {
|
||||
circuit.fixed_assignments.insert(key.clone(), value.clone());
|
||||
}
|
||||
for (key, value) in super_circuit.get_sub_circuits()[2].fixed_assignments.iter() {
|
||||
circuit.fixed_assignments.insert(key.clone(), value.clone());
|
||||
}
|
||||
for (key, value) in super_circuit.get_sub_circuits()[3].fixed_assignments.iter() {
|
||||
circuit.fixed_assignments.insert(key.clone(), value.clone());
|
||||
}
|
||||
for (key, value) in super_circuit.get_sub_circuits()[4].fixed_assignments.iter() {
|
||||
circuit.fixed_assignments.insert(key.clone(), value.clone());
|
||||
}
|
||||
for (key, value) in super_circuit.get_sub_circuits()[5].fixed_assignments.iter() {
|
||||
circuit.fixed_assignments.insert(key.clone(), value.clone());
|
||||
}
|
||||
|
||||
let (plaf, plaf_wit_gen) = chiquito2Plaf(circuit, k, false);
|
||||
|
||||
let mut plaf = plaf;
|
||||
plaf.set_challenge_alias(0, "r_keccak".to_string());
|
||||
let wit = plaf_wit_gen.generate(Some(wit_gen));
|
||||
write_files("keccak_output", &plaf, &wit).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn keccak_run(circuit_param: KeccakCircuit, k: u32) -> bool {
|
||||
let super_circuit = keccak_super_circuit::<Fr>(circuit_param.bytes.len());
|
||||
|
||||
let compiled = chiquitoSuperCircuit2Halo2(&super_circuit);
|
||||
|
||||
let circuit = ChiquitoHalo2SuperCircuit::new(
|
||||
compiled,
|
||||
super_circuit.get_mapping().generate(circuit_param),
|
||||
);
|
||||
|
||||
let prover = MockProver::<Fr>::run(k, &circuit, Vec::new()).unwrap();
|
||||
let result = prover.verify();
|
||||
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
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);
|
||||
let super_circuit = keccak_super_circuit::<Fr>(circuit_param.bytes.len());
|
||||
|
||||
if res {
|
||||
keccak_plaf(
|
||||
KeccakCircuit {
|
||||
bytes: vec![0, 1, 2, 3, 4, 5, 6, 7],
|
||||
},
|
||||
11,
|
||||
);
|
||||
let compiled = chiquitoSuperCircuit2Halo2(&super_circuit);
|
||||
|
||||
let mut circuit = ChiquitoHalo2SuperCircuit::new(compiled);
|
||||
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let witness = super_circuit.get_mapping().generate(circuit_param);
|
||||
|
||||
let halo2_prover = circuit.create_halo2_prover(9, rng);
|
||||
|
||||
let (proof, instance) = halo2_prover.generate_proof(witness);
|
||||
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
if let Err(failure) = &result {
|
||||
println!("{}", failure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::hash::Hash;
|
||||
|
||||
use halo2_proofs::{
|
||||
dev::MockProver,
|
||||
halo2curves::{bn256::Fr, group::ff::PrimeField},
|
||||
};
|
||||
use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField};
|
||||
|
||||
use chiquito::{
|
||||
frontend::dsl::{lb::LookupTable, super_circuit, trace::DSLTraceGenerator, CircuitContext},
|
||||
plonkish::{
|
||||
backend::halo2::{chiquitoSuperCircuit2Halo2, ChiquitoHalo2SuperCircuit},
|
||||
backend::halo2::{
|
||||
chiquitoSuperCircuit2Halo2, halo2_verify, ChiquitoHalo2SuperCircuit, DummyRng,
|
||||
Halo2Prover, PlonkishHalo2,
|
||||
},
|
||||
compiler::{
|
||||
cell_manager::SingleRowCellManager, config, step_selector::SimpleStepSelectorBuilder,
|
||||
},
|
||||
@@ -18,6 +18,7 @@ use chiquito::{
|
||||
};
|
||||
|
||||
use mimc7_constants::ROUND_CONSTANTS;
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
|
||||
// MiMC7 always has 91 rounds
|
||||
pub const ROUNDS: usize = 91;
|
||||
@@ -203,21 +204,28 @@ fn main() {
|
||||
|
||||
let super_circuit = mimc7_super_circuit::<Fr>();
|
||||
let compiled = chiquitoSuperCircuit2Halo2(&super_circuit);
|
||||
let circuit = ChiquitoHalo2SuperCircuit::new(
|
||||
compiled,
|
||||
super_circuit.get_mapping().generate((x_in_value, k_value)),
|
||||
|
||||
let mut circuit = ChiquitoHalo2SuperCircuit::new(compiled);
|
||||
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let witness = super_circuit.get_mapping().generate((x_in_value, k_value));
|
||||
|
||||
let halo2_prover = circuit.create_halo2_prover(10, rng);
|
||||
|
||||
let (proof, instance) = halo2_prover.generate_proof(witness);
|
||||
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
let prover = MockProver::<Fr>::run(10, &circuit, circuit.instance()).unwrap();
|
||||
|
||||
let result = prover.verify();
|
||||
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
if let Err(failures) = &result {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(failure) = &result {
|
||||
println!("{}", failure);
|
||||
}
|
||||
|
||||
// pil boilerplate
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use chiquito::{
|
||||
frontend::dsl::{lb::LookupTable, super_circuit, trace::DSLTraceGenerator, CircuitContext},
|
||||
plonkish::{
|
||||
backend::halo2::{chiquitoSuperCircuit2Halo2, ChiquitoHalo2SuperCircuit},
|
||||
backend::halo2::{
|
||||
chiquitoSuperCircuit2Halo2, halo2_verify, ChiquitoHalo2SuperCircuit, DummyRng,
|
||||
Halo2Prover, PlonkishHalo2,
|
||||
},
|
||||
compiler::{
|
||||
cell_manager::{MaxWidthCellManager, SingleRowCellManager},
|
||||
config,
|
||||
@@ -11,13 +14,11 @@ use chiquito::{
|
||||
},
|
||||
sbpir::query::Queriable,
|
||||
};
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
use halo2_proofs::{
|
||||
dev::MockProver,
|
||||
halo2curves::{bn256::Fr, group::ff::PrimeField},
|
||||
};
|
||||
use halo2_proofs::halo2curves::{bn256::Fr, group::ff::PrimeField};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct RoundValues<F: PrimeField> {
|
||||
@@ -705,19 +706,26 @@ fn main() {
|
||||
|
||||
let super_circuit = poseidon_super_circuit(lens);
|
||||
let compiled = chiquitoSuperCircuit2Halo2(&super_circuit);
|
||||
let circuit =
|
||||
ChiquitoHalo2SuperCircuit::new(compiled, super_circuit.get_mapping().generate(values));
|
||||
let witness = super_circuit.get_mapping().generate(values);
|
||||
let mut circuit = ChiquitoHalo2SuperCircuit::new(compiled);
|
||||
|
||||
let prover = MockProver::<Fr>::run(12, &circuit, Vec::new()).unwrap();
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let result = prover.verify();
|
||||
let halo2_prover = circuit.create_halo2_prover(12, rng);
|
||||
|
||||
let (proof, instance) = halo2_prover.generate_proof(witness);
|
||||
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
if let Err(failures) = &result {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(failure) = &result {
|
||||
println!("{}", failure);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::{
|
||||
ast::{debug_sym_factory::DebugSymRefFactory, tl::TLDecl, Identifiable, Identifier},
|
||||
lang::TLDeclsParser,
|
||||
},
|
||||
plonkish,
|
||||
plonkish::{self, compiler::PlonkishCompilationResult},
|
||||
poly::{self, mielim::mi_elimination, reduce::reduce_degree, Expr},
|
||||
sbpir::{query::Queriable, InternalSignal, SBPIR},
|
||||
wit_gen::{NullTraceGenerator, SymbolSignalMapping, TraceGenerator},
|
||||
@@ -41,10 +41,7 @@ impl<F: Field + Hash> CompilerResult<F> {
|
||||
>(
|
||||
&self,
|
||||
config: plonkish::compiler::CompilerConfig<CM, SSB>,
|
||||
) -> (
|
||||
crate::plonkish::ir::Circuit<F>,
|
||||
Option<plonkish::ir::assignments::AssignmentGenerator<F, InterpreterTraceGenerator>>,
|
||||
) {
|
||||
) -> PlonkishCompilationResult<F, InterpreterTraceGenerator> {
|
||||
plonkish::compiler::compile(config, &self.circuit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,19 @@ use pyo3::{
|
||||
prelude::*,
|
||||
types::{PyDict, PyList, PyLong, PyString},
|
||||
};
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
|
||||
use crate::{
|
||||
frontend::dsl::{StepTypeHandler, SuperCircuitContext},
|
||||
pil::backend::powdr_pil::chiquito2Pil,
|
||||
plonkish::{
|
||||
backend::halo2::{
|
||||
chiquito2Halo2, chiquitoSuperCircuit2Halo2, ChiquitoHalo2, ChiquitoHalo2Circuit,
|
||||
ChiquitoHalo2SuperCircuit,
|
||||
chiquito2Halo2, chiquitoSuperCircuit2Halo2, halo2_verify, ChiquitoHalo2,
|
||||
ChiquitoHalo2SuperCircuit, DummyRng, Halo2Prover, PlonkishHalo2,
|
||||
},
|
||||
compiler::{
|
||||
cell_manager::SingleRowCellManager, compile, config,
|
||||
step_selector::SimpleStepSelectorBuilder,
|
||||
step_selector::SimpleStepSelectorBuilder, PlonkishCompilationResult,
|
||||
},
|
||||
ir::{assignments::AssignmentGenerator, sc::MappingContext},
|
||||
},
|
||||
@@ -27,7 +28,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use core::result::Result;
|
||||
use halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr};
|
||||
use halo2_proofs::halo2curves::bn256::Fr;
|
||||
use serde::de::{self, Deserialize, Deserializer, IgnoredAny, MapAccess, Visitor};
|
||||
use std::{cell::RefCell, collections::HashMap, fmt};
|
||||
|
||||
@@ -62,14 +63,15 @@ pub fn chiquito_ast_to_halo2(ast_json: &str) -> UUID {
|
||||
serde_json::from_str(ast_json).expect("Json deserialization to Circuit failed.");
|
||||
|
||||
let config = config(SingleRowCellManager {}, SimpleStepSelectorBuilder {});
|
||||
let (chiquito, assignment_generator) = compile(config, &circuit);
|
||||
let chiquito_halo2 = chiquito2Halo2(chiquito);
|
||||
let plonkish = compile(config, &circuit);
|
||||
let chiquito_halo2 = chiquito2Halo2(plonkish.circuit);
|
||||
let uuid = uuid();
|
||||
|
||||
CIRCUIT_MAP.with(|circuit_map| {
|
||||
circuit_map
|
||||
.borrow_mut()
|
||||
.insert(uuid, (circuit, chiquito_halo2, assignment_generator));
|
||||
circuit_map.borrow_mut().insert(
|
||||
uuid,
|
||||
(circuit, chiquito_halo2, plonkish.assignment_generator),
|
||||
);
|
||||
});
|
||||
|
||||
uuid
|
||||
@@ -149,18 +151,25 @@ pub fn chiquito_super_circuit_halo2_mock_prover(
|
||||
|
||||
let super_assignments = mapping_ctx.get_super_assignments();
|
||||
|
||||
let circuit = ChiquitoHalo2SuperCircuit::new(compiled, super_assignments);
|
||||
let mut circuit = ChiquitoHalo2SuperCircuit::new(compiled);
|
||||
|
||||
let prover = MockProver::<Fr>::run(k as u32, &circuit, circuit.instance()).unwrap();
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let result = prover.verify();
|
||||
let halo2_prover = circuit.create_halo2_prover(k as u32, rng);
|
||||
|
||||
let (proof, instance) = halo2_prover.generate_proof(super_assignments);
|
||||
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
if let Err(failures) = &result {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(failure) = &result {
|
||||
println!("{}", failure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,21 +188,34 @@ pub fn chiquito_halo2_mock_prover(witness_json: &str, rust_id: UUID, k: usize) {
|
||||
let trace_witness: TraceWitness<Fr> =
|
||||
serde_json::from_str(witness_json).expect("Json deserialization to TraceWitness failed.");
|
||||
let (_, compiled, assignment_generator) = rust_id_to_halo2(rust_id);
|
||||
let circuit: ChiquitoHalo2Circuit<_> = ChiquitoHalo2Circuit::new(
|
||||
compiled,
|
||||
assignment_generator.map(|g| g.generate(trace_witness)),
|
||||
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let mut plonkish = PlonkishCompilationResult {
|
||||
circuit: compiled.circuit,
|
||||
assignment_generator,
|
||||
};
|
||||
|
||||
let halo2_prover = plonkish.create_halo2_prover(k as u32, rng);
|
||||
|
||||
let (proof, instance) = halo2_prover.generate_proof(
|
||||
plonkish
|
||||
.assignment_generator
|
||||
.unwrap()
|
||||
.generate(trace_witness),
|
||||
);
|
||||
|
||||
let prover = MockProver::<Fr>::run(k as u32, &circuit, circuit.instance()).unwrap();
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
let result = prover.verify();
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
println!("{:#?}", result);
|
||||
|
||||
if let Err(failures) = &result {
|
||||
for failure in failures.iter() {
|
||||
println!("{}", failure);
|
||||
}
|
||||
if let Err(error) = &result {
|
||||
println!("{}", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -321,15 +321,16 @@ fn get_block_stmts(stmt: &Statement<BigInt, Identifier>) -> Vec<Statement<BigInt
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::plonkish::backend::halo2::{Halo2Prover, PlonkishHalo2};
|
||||
use halo2_proofs::halo2curves::bn256::Fr;
|
||||
use rand_chacha::rand_core::block::BlockRng;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr};
|
||||
|
||||
use crate::{
|
||||
compiler::{compile, Config},
|
||||
parser::ast::debug_sym_factory::DebugSymRefFactory,
|
||||
plonkish::{
|
||||
backend::halo2::{chiquito2Halo2, ChiquitoHalo2Circuit},
|
||||
backend::halo2::{halo2_verify, DummyRng},
|
||||
compiler::{
|
||||
cell_manager::SingleRowCellManager, config,
|
||||
step_selector::SimpleStepSelectorBuilder,
|
||||
@@ -395,7 +396,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_run_halo2_mock_prover() {
|
||||
fn test_run_halo2_prover() {
|
||||
let code = "
|
||||
machine fibo(signal n) (signal b: field) {
|
||||
// n and be are created automatically as shared
|
||||
@@ -443,24 +444,28 @@ mod test {
|
||||
|
||||
chiquito.circuit.num_steps = 12;
|
||||
|
||||
let plonkish = chiquito.plonkish(config(
|
||||
let mut plonkish = chiquito.plonkish(config(
|
||||
SingleRowCellManager {},
|
||||
SimpleStepSelectorBuilder {},
|
||||
));
|
||||
|
||||
let compiled = chiquito2Halo2(plonkish.0);
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let circuit = ChiquitoHalo2Circuit::new(
|
||||
compiled,
|
||||
let halo2_prover = plonkish.create_halo2_prover(7, rng);
|
||||
|
||||
let (proof, instance) = halo2_prover.generate_proof(
|
||||
plonkish
|
||||
.1
|
||||
.map(|g| g.generate(HashMap::from([("n".to_string(), Fr::from(12))]))),
|
||||
.assignment_generator
|
||||
.unwrap()
|
||||
.generate(HashMap::from([("n".to_string(), Fr::from(12))])),
|
||||
);
|
||||
|
||||
let prover = MockProver::<Fr>::run(7, &circuit, circuit.instance()).unwrap();
|
||||
|
||||
let result = prover.verify();
|
||||
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
@@ -474,7 +479,7 @@ mod test {
|
||||
signal a: field, i;
|
||||
|
||||
// there is always a state called initial
|
||||
// input signals get binded to the signal
|
||||
// input signals get bound to the signal
|
||||
// in the initial state (first instance)
|
||||
state initial {
|
||||
signal c;
|
||||
@@ -519,28 +524,33 @@ mod test {
|
||||
// .wit_gen
|
||||
// .evil_assign(&mut witness, 1, ("//fibo", "i"), Fr::zero());
|
||||
|
||||
let plonkish = chiquito.plonkish(config(
|
||||
let mut plonkish = chiquito.plonkish(config(
|
||||
SingleRowCellManager {},
|
||||
SimpleStepSelectorBuilder {},
|
||||
));
|
||||
|
||||
let compiled = chiquito2Halo2(plonkish.0);
|
||||
let rng = BlockRng::new(DummyRng {});
|
||||
|
||||
let circuit = ChiquitoHalo2Circuit::new(
|
||||
compiled,
|
||||
let halo2_prover = plonkish.create_halo2_prover(7, rng);
|
||||
|
||||
let (proof, instance) = halo2_prover.generate_proof(
|
||||
plonkish
|
||||
.1
|
||||
.map(|g| g.generate(HashMap::from([("n".to_string(), Fr::from(12))]))),
|
||||
.assignment_generator
|
||||
.unwrap()
|
||||
.generate(HashMap::from([("n".to_string(), Fr::from(12))])),
|
||||
);
|
||||
|
||||
let prover = MockProver::<Fr>::run(7, &circuit, circuit.instance()).unwrap();
|
||||
let result = halo2_verify(
|
||||
proof,
|
||||
&halo2_prover.setup.params,
|
||||
&halo2_prover.setup.vk,
|
||||
instance,
|
||||
);
|
||||
|
||||
let result = prover.verify();
|
||||
println!("result = {:#?}", result);
|
||||
|
||||
assert!(result.is_err());
|
||||
|
||||
if let Err(result) = result {
|
||||
println!("{}", result.len());
|
||||
if let Err(error) = &result {
|
||||
println!("{}", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,56 @@
|
||||
use std::{collections::HashMap, hash::Hash};
|
||||
use std::{collections::HashMap, hash::Hash, vec};
|
||||
|
||||
use halo2_backend::plonk::{
|
||||
keygen::{keygen_pk, keygen_vk},
|
||||
prover::ProverSingle,
|
||||
verifier::verify_proof_single,
|
||||
Error as ErrorBack,
|
||||
};
|
||||
use halo2_middleware::{
|
||||
circuit::{Any as Columns, Cell as CellMid, ColumnMid, CompiledCircuit, Preprocessing},
|
||||
permutation::AssemblyMid,
|
||||
zal::impls::{H2cEngine, PlonkEngineConfig},
|
||||
};
|
||||
use halo2_proofs::{
|
||||
arithmetic::Field,
|
||||
circuit::{Cell, Layouter, Region, RegionIndex, SimpleFloorPlanner, Value},
|
||||
halo2curves::ff::PrimeField,
|
||||
plonk::{
|
||||
Advice, Any, Circuit as h2Circuit, Column, ConstraintSystem, Error, Expression, FirstPhase,
|
||||
Fixed, Instance, SecondPhase, ThirdPhase, VirtualCells,
|
||||
halo2curves::{
|
||||
bn256::{Bn256, Fr, G1Affine},
|
||||
ff::PrimeField,
|
||||
},
|
||||
plonk::{
|
||||
Advice, Any, Column, ConstraintSystem, ConstraintSystemMid, Error, Expression, FirstPhase,
|
||||
Fixed, Instance, ProvingKey, SecondPhase, ThirdPhase, VerifyingKey, VirtualCells,
|
||||
},
|
||||
poly::{
|
||||
commitment::Params,
|
||||
kzg::{
|
||||
commitment::{KZGCommitmentScheme, ParamsKZG},
|
||||
multiopen::{ProverSHPLONK, VerifierSHPLONK},
|
||||
strategy::SingleStrategy,
|
||||
},
|
||||
Rotation,
|
||||
},
|
||||
transcript::{
|
||||
Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer,
|
||||
},
|
||||
poly::Rotation,
|
||||
};
|
||||
use rand_chacha::rand_core::block::{BlockRng, BlockRngCore};
|
||||
|
||||
use crate::{
|
||||
field::Field as ChiquitoField,
|
||||
plonkish::ir::{
|
||||
assignments::Assignments,
|
||||
sc::{SuperAssignments, SuperCircuit},
|
||||
Circuit, Column as cColumn,
|
||||
ColumnType::{Advice as cAdvice, Fixed as cFixed, Halo2Advice, Halo2Fixed},
|
||||
PolyExpr,
|
||||
plonkish::{
|
||||
compiler::PlonkishCompilationResult,
|
||||
ir::{
|
||||
assignments::Assignments,
|
||||
sc::{SuperAssignments, SuperCircuit},
|
||||
Circuit, Column as cColumn,
|
||||
ColumnType::{Advice as cAdvice, Fixed as cFixed, Halo2Advice, Halo2Fixed},
|
||||
PolyExpr,
|
||||
},
|
||||
},
|
||||
poly::ToField,
|
||||
util::UUID,
|
||||
wit_gen::TraceGenerator,
|
||||
};
|
||||
|
||||
impl<T: PrimeField + From<u64>> ChiquitoField for T {
|
||||
@@ -50,6 +79,18 @@ pub fn chiquito2Halo2<F: PrimeField + From<u64> + Hash>(circuit: Circuit<F>) ->
|
||||
ChiquitoHalo2::new(circuit)
|
||||
}
|
||||
|
||||
fn compile_middleware<F: PrimeField + From<u64> + Hash, C: Halo2Configurable<F>>(
|
||||
k: u32,
|
||||
circuit: &mut C,
|
||||
) -> Result<CompiledCircuit<F>, Error> {
|
||||
let (cs, preprocessing) = circuit.configure(k)?;
|
||||
|
||||
Ok(CompiledCircuit {
|
||||
cs: cs.clone().into(),
|
||||
preprocessing,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn chiquitoSuperCircuit2Halo2<F: PrimeField + From<u64> + Hash, MappingArgs>(
|
||||
super_circuit: &SuperCircuit<F, MappingArgs>,
|
||||
@@ -65,7 +106,7 @@ pub fn chiquitoSuperCircuit2Halo2<F: PrimeField + From<u64> + Hash, MappingArgs>
|
||||
pub struct ChiquitoHalo2<F: PrimeField + From<u64>> {
|
||||
pub debug: bool,
|
||||
|
||||
circuit: Circuit<F>,
|
||||
pub circuit: Circuit<F>,
|
||||
|
||||
advice_columns: HashMap<UUID, Column<Advice>>,
|
||||
fixed_columns: HashMap<UUID, Column<Fixed>>,
|
||||
@@ -74,6 +115,59 @@ pub struct ChiquitoHalo2<F: PrimeField + From<u64>> {
|
||||
ir_id: UUID,
|
||||
}
|
||||
|
||||
trait Halo2Configurable<F: Field> {
|
||||
fn configure(&mut self, k: u32) -> Result<(ConstraintSystem<F>, Preprocessing<F>), Error> {
|
||||
let mut cs = self.configure_cs();
|
||||
let n = 2usize.pow(k);
|
||||
|
||||
if n < cs.minimum_rows() {
|
||||
return Err(Error::Backend(ErrorBack::NotEnoughRowsAvailable {
|
||||
current_k: k,
|
||||
}));
|
||||
}
|
||||
|
||||
let preprocessing = self.preprocessing(&mut cs, n);
|
||||
|
||||
Ok((cs.clone(), preprocessing))
|
||||
}
|
||||
|
||||
fn configure_cs(&mut self) -> ConstraintSystem<F>;
|
||||
fn preprocessing(&self, cs: &mut ConstraintSystem<F>, n: usize) -> Preprocessing<F>;
|
||||
}
|
||||
|
||||
impl<F: PrimeField + Hash> Halo2Configurable<F> for ChiquitoHalo2<F> {
|
||||
fn preprocessing(&self, cs: &mut ConstraintSystem<F>, n: usize) -> Preprocessing<F> {
|
||||
let fixed_count = self.circuit.fixed_assignments.0.len();
|
||||
let mut fixed = vec![vec![F::default(); n]; fixed_count];
|
||||
|
||||
for (column, values) in self.circuit.fixed_assignments.iter() {
|
||||
let column = self.convert_fixed_column(column);
|
||||
|
||||
for (offset, value) in values.iter().enumerate() {
|
||||
fixed[column.index][offset] = *value;
|
||||
}
|
||||
}
|
||||
|
||||
let mut copies = vec![];
|
||||
self.collect_permutations(cs, &mut copies);
|
||||
|
||||
Preprocessing {
|
||||
permutation: AssemblyMid { copies },
|
||||
fixed,
|
||||
}
|
||||
}
|
||||
|
||||
fn configure_cs(&mut self) -> ConstraintSystem<F> {
|
||||
let mut cs: ConstraintSystem<F> = ConstraintSystem::default();
|
||||
|
||||
self.configure_columns_sub_circuit(&mut cs);
|
||||
|
||||
self.configure_sub_circuit(&mut cs);
|
||||
|
||||
cs
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: PrimeField + From<u64> + Hash> ChiquitoHalo2<F> {
|
||||
pub fn new(circuit: Circuit<F>) -> ChiquitoHalo2<F> {
|
||||
let ir_id = circuit.id;
|
||||
@@ -87,12 +181,6 @@ impl<F: PrimeField + From<u64> + Hash> ChiquitoHalo2<F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn configure(&mut self, meta: &mut ConstraintSystem<F>) {
|
||||
self.configure_columns_sub_circuit(meta);
|
||||
|
||||
self.configure_sub_circuit(meta);
|
||||
}
|
||||
|
||||
fn configure_columns_sub_circuit(&mut self, meta: &mut ConstraintSystem<F>) {
|
||||
let mut advice_columns = HashMap::<UUID, Column<Advice>>::new();
|
||||
let mut fixed_columns = HashMap::<UUID, Column<Fixed>>::new();
|
||||
@@ -136,7 +224,7 @@ impl<F: PrimeField + From<u64> + Hash> ChiquitoHalo2<F> {
|
||||
self.fixed_columns = fixed_columns;
|
||||
}
|
||||
|
||||
pub fn configure_sub_circuit(&mut self, meta: &mut ConstraintSystem<F>) {
|
||||
fn configure_sub_circuit(&mut self, meta: &mut ConstraintSystem<F>) {
|
||||
if !self.circuit.exposed.is_empty() {
|
||||
self.instance_column = Some(meta.instance_column());
|
||||
}
|
||||
@@ -170,83 +258,6 @@ impl<F: PrimeField + From<u64> + Hash> ChiquitoHalo2<F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn synthesize(&self, layouter: &mut impl Layouter<F>, witness: Option<&Assignments<F>>) {
|
||||
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::<Any>::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<F>, witness: &Assignments<F>) -> Result<(), Error> {
|
||||
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<F>, fixed: &Assignments<F>) -> Result<(), Error> {
|
||||
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<F>) {
|
||||
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<F>) -> Expression<F> {
|
||||
match src {
|
||||
PolyExpr::Const(c, _) => Expression::Constant(*c),
|
||||
@@ -322,30 +333,51 @@ impl<F: PrimeField + From<u64> + Hash> ChiquitoHalo2<F> {
|
||||
_ => panic!("wrong column type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_permutations(
|
||||
&self,
|
||||
cs: &mut ConstraintSystem<F>,
|
||||
copies: &mut Vec<(CellMid, CellMid)>,
|
||||
) {
|
||||
self.circuit
|
||||
.exposed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(row, (column, offset))| {
|
||||
let col_type: Columns = match column.ctype {
|
||||
cAdvice | Halo2Advice => Columns::Advice,
|
||||
cFixed | Halo2Fixed => Columns::Fixed,
|
||||
};
|
||||
|
||||
let index = if col_type == Columns::Advice {
|
||||
let column = self.convert_advice_column(column);
|
||||
cs.enable_equality(column);
|
||||
column.index
|
||||
} else {
|
||||
let column = self.convert_fixed_column(column);
|
||||
cs.enable_equality(column);
|
||||
column.index
|
||||
};
|
||||
|
||||
let column_mid = ColumnMid::new(col_type, index);
|
||||
|
||||
let instance_column = ColumnMid::new(Columns::Instance, 0);
|
||||
cs.enable_equality(instance_column);
|
||||
copies.push((
|
||||
CellMid {
|
||||
column: column_mid,
|
||||
row: *offset as usize,
|
||||
},
|
||||
CellMid {
|
||||
column: instance_column,
|
||||
row,
|
||||
},
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[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<Any>,
|
||||
}
|
||||
// From Plaf Halo2 backend.
|
||||
fn new_cell(column: Column<Any>, 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<F: PrimeField>(
|
||||
fn to_halo2_advice<F: PrimeField>(
|
||||
meta: &mut ConstraintSystem<F>,
|
||||
column: &cColumn,
|
||||
) -> Column<Advice> {
|
||||
@@ -357,160 +389,333 @@ pub fn to_halo2_advice<F: PrimeField>(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct ChiquitoHalo2Circuit<F: PrimeField + From<u64>> {
|
||||
compiled: ChiquitoHalo2<F>,
|
||||
witness: Option<Assignments<F>>,
|
||||
}
|
||||
|
||||
impl<F: PrimeField + From<u64> + Hash> ChiquitoHalo2Circuit<F> {
|
||||
pub fn new(compiled: ChiquitoHalo2<F>, witness: Option<Assignments<F>>) -> Self {
|
||||
Self { compiled, witness }
|
||||
}
|
||||
|
||||
pub fn instance(&self) -> Vec<Vec<F>> {
|
||||
if !self.compiled.circuit.exposed.is_empty() {
|
||||
if let Some(witness) = &self.witness {
|
||||
return vec![self.compiled.circuit.instance(witness)];
|
||||
}
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: PrimeField + From<u64> + Hash> h2Circuit<F> for ChiquitoHalo2Circuit<F> {
|
||||
type Config = ChiquitoHalo2<F>;
|
||||
|
||||
type FloorPlanner = SimpleFloorPlanner;
|
||||
|
||||
type Params = ChiquitoHalo2<F>;
|
||||
|
||||
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<F>,
|
||||
mut compiled: Self::Params,
|
||||
) -> Self::Config {
|
||||
compiled.configure(meta);
|
||||
|
||||
compiled
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
compiled: Self::Config,
|
||||
mut layouter: impl Layouter<F>,
|
||||
) -> Result<(), Error> {
|
||||
compiled.synthesize(&mut layouter, self.witness.as_ref());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn configure(_: &mut ConstraintSystem<F>) -> Self::Config {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ChiquitoHalo2SuperCircuit<F: PrimeField + From<u64>> {
|
||||
sub_circuits: Vec<ChiquitoHalo2<F>>,
|
||||
witness: SuperAssignments<F>,
|
||||
}
|
||||
|
||||
impl<F: PrimeField + From<u64> + Hash> ChiquitoHalo2SuperCircuit<F> {
|
||||
pub fn new(sub_circuits: Vec<ChiquitoHalo2<F>>, witness: SuperAssignments<F>) -> Self {
|
||||
Self {
|
||||
sub_circuits,
|
||||
witness,
|
||||
}
|
||||
pub fn new(sub_circuits: Vec<ChiquitoHalo2<F>>) -> Self {
|
||||
Self { sub_circuits }
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: PrimeField + Hash> Halo2Configurable<F> for ChiquitoHalo2SuperCircuit<F> {
|
||||
fn configure_cs(&mut self) -> ConstraintSystem<F> {
|
||||
let mut cs = ConstraintSystem::default();
|
||||
|
||||
self.sub_circuits
|
||||
.iter_mut()
|
||||
.for_each(|c| c.configure_columns_sub_circuit(&mut cs));
|
||||
|
||||
let advice_columns: HashMap<UUID, Column<Advice>> =
|
||||
self.sub_circuits
|
||||
.iter()
|
||||
.fold(HashMap::default(), |mut acc, s| {
|
||||
acc.extend(s.advice_columns.clone());
|
||||
acc
|
||||
});
|
||||
let fixed_columns: HashMap<UUID, Column<Fixed>> =
|
||||
self.sub_circuits
|
||||
.iter()
|
||||
.fold(HashMap::default(), |mut acc, s| {
|
||||
acc.extend(s.fixed_columns.clone());
|
||||
acc
|
||||
});
|
||||
|
||||
self.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(&mut cs)
|
||||
});
|
||||
|
||||
cs
|
||||
}
|
||||
|
||||
pub fn instance(&self) -> Vec<Vec<F>> {
|
||||
let mut result = Vec::new();
|
||||
fn preprocessing(&self, cs: &mut ConstraintSystem<F>, n: usize) -> Preprocessing<F> {
|
||||
let fixed_columns: HashMap<UUID, Column<Fixed>> =
|
||||
self.sub_circuits
|
||||
.iter()
|
||||
.fold(HashMap::default(), |mut acc, s| {
|
||||
acc.extend(s.fixed_columns.clone());
|
||||
acc
|
||||
});
|
||||
|
||||
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)
|
||||
let fixed_count = fixed_columns.len();
|
||||
let mut fixed = vec![vec![F::default(); n]; fixed_count];
|
||||
|
||||
let mut copies = vec![];
|
||||
for subcircuit in self.sub_circuits.iter() {
|
||||
for (column, values) in subcircuit.circuit.fixed_assignments.iter() {
|
||||
let column = fixed_columns.get(&column.uuid()).unwrap();
|
||||
|
||||
for (offset, value) in values.iter().enumerate() {
|
||||
fixed[column.index][offset] = *value;
|
||||
}
|
||||
}
|
||||
subcircuit.collect_permutations(cs, &mut copies);
|
||||
}
|
||||
|
||||
Preprocessing {
|
||||
permutation: AssemblyMid { copies },
|
||||
fixed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify Halo2 proof
|
||||
/// ### Arguments
|
||||
/// * `proof` - Halo2 proof
|
||||
/// * `params` - KZG parameters
|
||||
/// * `vk` - Verifying key
|
||||
/// * `instance` - circuit instance values
|
||||
/// ### Returns
|
||||
/// * `Ok(())` if the proof is valid
|
||||
/// * `Err(ErrorBack)` if the proof is invalid
|
||||
pub fn halo2_verify(
|
||||
proof: Vec<u8>,
|
||||
params: &ParamsKZG<Bn256>,
|
||||
vk: &VerifyingKey<G1Affine>,
|
||||
instance: Vec<Vec<Fr>>,
|
||||
) -> Result<(), ErrorBack> {
|
||||
// Verify
|
||||
let mut verifier_transcript =
|
||||
Blake2bRead::<_, G1Affine, Challenge255<_>>::init(proof.as_slice());
|
||||
let verifier_params = params.verifier_params();
|
||||
let strategy = SingleStrategy::new(&verifier_params);
|
||||
|
||||
let result = verify_proof_single::<KZGCommitmentScheme<Bn256>, VerifierSHPLONK<Bn256>, _, _, _>(
|
||||
&verifier_params,
|
||||
vk,
|
||||
strategy,
|
||||
instance,
|
||||
&mut verifier_transcript,
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
/// Halo2 setup
|
||||
pub struct Setup {
|
||||
pub cs: ConstraintSystemMid<Fr>,
|
||||
pub params: ParamsKZG<Bn256>,
|
||||
pub vk: VerifyingKey<G1Affine>,
|
||||
pub pk: ProvingKey<G1Affine>,
|
||||
rng: BlockRng<DummyRng>,
|
||||
}
|
||||
|
||||
/// Halo2 prover for a single circuit
|
||||
pub struct SingleCircuitProver<F: PrimeField> {
|
||||
pub setup: Setup,
|
||||
circuit: ChiquitoHalo2<F>,
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn create_prover<'a>(
|
||||
setup: &'a Setup,
|
||||
instance: &[Vec<Fr>],
|
||||
transcript: &'a mut Blake2bWrite<Vec<u8>, G1Affine, Challenge255<G1Affine>>,
|
||||
) -> ProverSingle<
|
||||
'a,
|
||||
'a,
|
||||
KZGCommitmentScheme<Bn256>,
|
||||
ProverSHPLONK<'a, Bn256>,
|
||||
Challenge255<G1Affine>,
|
||||
BlockRng<DummyRng>,
|
||||
Blake2bWrite<Vec<u8>, G1Affine, Challenge255<G1Affine>>,
|
||||
H2cEngine,
|
||||
> {
|
||||
ProverSingle::<
|
||||
KZGCommitmentScheme<Bn256>,
|
||||
ProverSHPLONK<'_, Bn256>,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
>::new_with_engine(
|
||||
PlonkEngineConfig::new()
|
||||
.set_curve::<G1Affine>()
|
||||
.set_msm(H2cEngine::new())
|
||||
.build(),
|
||||
&setup.params,
|
||||
&setup.pk,
|
||||
instance.to_vec(),
|
||||
setup.rng.clone(),
|
||||
transcript,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn assign_witness(
|
||||
circuit: &ChiquitoHalo2<Fr>,
|
||||
witness: &Assignments<Fr>,
|
||||
assigned_witness: &mut [Option<Vec<Fr>>],
|
||||
) {
|
||||
for (column, values) in witness.iter() {
|
||||
let circuit_column = circuit.advice_columns.get(&column.uuid()).unwrap();
|
||||
let halo2_column = Column::<Any>::from(*circuit_column);
|
||||
for (offset, value) in values.iter().enumerate() {
|
||||
assigned_witness[halo2_column.index].as_mut().unwrap()[offset] = *value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Halo2 prover for a super circuit
|
||||
pub struct SuperCircuitProver<F: PrimeField> {
|
||||
pub setup: Setup,
|
||||
circuit: ChiquitoHalo2SuperCircuit<F>,
|
||||
}
|
||||
|
||||
pub trait Halo2Prover {
|
||||
/// Witness type
|
||||
type W;
|
||||
/// Generate Halo2 proof
|
||||
/// #### Arguments
|
||||
/// * `witness` - circuit witness
|
||||
/// #### Returns
|
||||
/// * a tuple of proof and instance values
|
||||
fn generate_proof(&self, witness: Self::W) -> (Vec<u8>, Vec<Vec<Fr>>);
|
||||
}
|
||||
|
||||
impl Halo2Prover for SuperCircuitProver<Fr> {
|
||||
type W = SuperAssignments<Fr>;
|
||||
|
||||
fn generate_proof(&self, witnesses: Self::W) -> (Vec<u8>, Vec<Vec<Fr>>) {
|
||||
let mut instance = Vec::new();
|
||||
|
||||
for circuit in self.circuit.sub_circuits.iter() {
|
||||
if !circuit.circuit.exposed.is_empty() {
|
||||
let instance_values = circuit.circuit.instance(
|
||||
witnesses
|
||||
.get(&circuit.ir_id)
|
||||
.expect("No matching witness found for given UUID."),
|
||||
);
|
||||
result.push(instance_values);
|
||||
instance.push(instance_values);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
// Proving
|
||||
let mut transcript = Blake2bWrite::<_, G1Affine, Challenge255<_>>::init(vec![]);
|
||||
let mut prover = create_prover(&self.setup, &instance, &mut transcript);
|
||||
|
||||
for phase in 0..self.setup.cs.phases() {
|
||||
let mut assigned_witness =
|
||||
vec![
|
||||
Some(vec![Fr::default(); self.setup.params.n() as usize]);
|
||||
self.setup.cs.num_advice_columns
|
||||
];
|
||||
|
||||
for circuit in self.circuit.sub_circuits.iter() {
|
||||
if let Some(assignments) = witnesses.get(&circuit.ir_id) {
|
||||
assign_witness(circuit, assignments, &mut assigned_witness);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO ignoring the challenges produced by the phase, but can they be useful later?
|
||||
let _ = prover.commit_phase(phase as u8, assigned_witness).unwrap();
|
||||
}
|
||||
prover.create_proof().unwrap();
|
||||
let proof = transcript.finalize();
|
||||
|
||||
(proof, instance)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: PrimeField + From<u64> + Hash> h2Circuit<F> for ChiquitoHalo2SuperCircuit<F> {
|
||||
type Config = Vec<ChiquitoHalo2<F>>;
|
||||
impl Halo2Prover for SingleCircuitProver<Fr> {
|
||||
type W = Assignments<Fr>;
|
||||
|
||||
type FloorPlanner = SimpleFloorPlanner;
|
||||
fn generate_proof(&self, witness: Self::W) -> (Vec<u8>, Vec<Vec<Fr>>) {
|
||||
let mut instance = Vec::new();
|
||||
|
||||
type Params = Vec<ChiquitoHalo2<F>>;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn params(&self) -> Self::Params {
|
||||
self.sub_circuits.clone()
|
||||
}
|
||||
|
||||
fn configure_with_params(
|
||||
meta: &mut ConstraintSystem<F>,
|
||||
mut sub_circuits: Self::Params,
|
||||
) -> Self::Config {
|
||||
sub_circuits
|
||||
.iter_mut()
|
||||
.for_each(|c| c.configure_columns_sub_circuit(meta));
|
||||
|
||||
let advice_columns: HashMap<UUID, Column<Advice>> =
|
||||
sub_circuits.iter().fold(HashMap::default(), |mut acc, s| {
|
||||
acc.extend(s.advice_columns.clone());
|
||||
acc
|
||||
});
|
||||
let fixed_columns: HashMap<UUID, Column<Fixed>> =
|
||||
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<F>,
|
||||
) -> Result<(), Error> {
|
||||
for sub_circuit in sub_circuits {
|
||||
sub_circuit.synthesize(&mut layouter, self.witness.get(&sub_circuit.ir_id))
|
||||
if !self.circuit.circuit.exposed.is_empty() {
|
||||
let instance_values = self.circuit.circuit.instance(&witness);
|
||||
instance.push(instance_values);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// Proving
|
||||
let mut transcript = Blake2bWrite::<_, G1Affine, Challenge255<_>>::init(vec![]);
|
||||
|
||||
fn configure(_: &mut ConstraintSystem<F>) -> Self::Config {
|
||||
unreachable!()
|
||||
let mut prover = create_prover(&self.setup, &instance, &mut transcript);
|
||||
|
||||
for phase in 0..self.setup.cs.phases() {
|
||||
let mut assigned_witness =
|
||||
vec![
|
||||
Some(vec![Fr::default(); self.setup.params.n() as usize]);
|
||||
self.setup.cs.num_advice_columns
|
||||
];
|
||||
|
||||
assign_witness(&self.circuit, &witness, &mut assigned_witness);
|
||||
|
||||
// TODO ignoring the challenges produced by the phase, but can they be useful later?
|
||||
let _ = prover.commit_phase(phase as u8, assigned_witness).unwrap();
|
||||
}
|
||||
prover.create_proof().unwrap();
|
||||
let proof = transcript.finalize();
|
||||
|
||||
(proof, instance)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PlonkishHalo2<F: PrimeField, P: Halo2Prover> {
|
||||
/// Create a Halo2 prover
|
||||
///
|
||||
/// ### Arguments
|
||||
/// * `k` - logaritmic size of the circuit
|
||||
/// * `rng` - random number generator
|
||||
///
|
||||
/// ### Returns
|
||||
/// * a Halo2 prover
|
||||
fn create_halo2_prover(&mut self, k: u32, rng: BlockRng<DummyRng>) -> P;
|
||||
}
|
||||
|
||||
impl<TG: TraceGenerator<Fr> + Default> PlonkishHalo2<Fr, SingleCircuitProver<Fr>>
|
||||
for PlonkishCompilationResult<Fr, TG>
|
||||
{
|
||||
fn create_halo2_prover(&mut self, k: u32, rng: BlockRng<DummyRng>) -> SingleCircuitProver<Fr> {
|
||||
let mut circuit = ChiquitoHalo2::new(self.circuit.clone());
|
||||
let compiled = compile_middleware(k, &mut circuit).unwrap();
|
||||
let setup = create_setup(k, rng, compiled);
|
||||
SingleCircuitProver { setup, circuit }
|
||||
}
|
||||
}
|
||||
|
||||
impl PlonkishHalo2<Fr, SuperCircuitProver<Fr>> for ChiquitoHalo2SuperCircuit<Fr> {
|
||||
fn create_halo2_prover(&mut self, k: u32, rng: BlockRng<DummyRng>) -> SuperCircuitProver<Fr> {
|
||||
let compiled = compile_middleware(k, self).unwrap();
|
||||
let setup = create_setup(k, rng, compiled);
|
||||
SuperCircuitProver {
|
||||
circuit: self.clone(),
|
||||
setup,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_setup(k: u32, rng: BlockRng<DummyRng>, circuit: CompiledCircuit<Fr>) -> Setup {
|
||||
let params = ParamsKZG::<Bn256>::setup::<BlockRng<DummyRng>>(k, rng.clone());
|
||||
let vk = keygen_vk(¶ms, &circuit).expect("keygen_vk should not fail");
|
||||
let pk = keygen_pk(¶ms, vk.clone(), &circuit).expect("keygen_pk should not fail");
|
||||
|
||||
Setup {
|
||||
cs: circuit.cs,
|
||||
params,
|
||||
vk,
|
||||
pk,
|
||||
rng,
|
||||
}
|
||||
}
|
||||
|
||||
/// ⚠️ Not for production use! ⚠️
|
||||
///
|
||||
/// One-number generator that can be used as a deterministic Rng outputting fixed values.
|
||||
#[derive(Clone)]
|
||||
pub struct DummyRng {}
|
||||
|
||||
impl BlockRngCore for DummyRng {
|
||||
type Item = u32;
|
||||
type Results = [u32; 16];
|
||||
|
||||
fn generate(&mut self, results: &mut Self::Results) {
|
||||
for elem in results.iter_mut() {
|
||||
*elem = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
pub mod halo2;
|
||||
pub mod hyperplonk;
|
||||
pub mod plaf;
|
||||
|
||||
@@ -1,327 +0,0 @@
|
||||
use std::{collections::HashMap, hash::Hash};
|
||||
|
||||
use halo2_proofs::halo2curves::ff::PrimeField;
|
||||
|
||||
use crate::{
|
||||
plonkish::ir::{
|
||||
assignments::Assignments,
|
||||
Circuit as cCircuit, Column as cColumn,
|
||||
ColumnType::{Advice as cAdvice, Fixed as cFixed, Halo2Advice, Halo2Fixed},
|
||||
PolyExpr as cPolyExpr,
|
||||
},
|
||||
util::UUID,
|
||||
};
|
||||
|
||||
use num_bigint::BigUint;
|
||||
use polyexen::{
|
||||
expr::{get_field_p, Column as pColumn, ColumnKind, ColumnQuery, Expr as pExpr, PlonkVar},
|
||||
plaf::{
|
||||
ColumnFixed, ColumnPublic, ColumnWitness, CopyC as pCopyC, Lookup as pLookup, Plaf,
|
||||
Poly as pPoly, Witness as pWitness,
|
||||
},
|
||||
};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn chiquito2Plaf<F: PrimeField<Repr = [u8; 32]>>(
|
||||
circuit: cCircuit<F>,
|
||||
k: u32,
|
||||
debug: bool,
|
||||
) -> (Plaf, ChiquitoPlafWitGen) {
|
||||
let mut chiquito_plaf = ChiquitoPlaf::new(circuit, debug);
|
||||
let plaf = chiquito_plaf.get_plaf(k);
|
||||
let empty_witness = plaf.gen_empty_witness();
|
||||
let wit_gen =
|
||||
ChiquitoPlafWitGen::new(empty_witness, chiquito_plaf.c_column_id_to_p_column_index);
|
||||
|
||||
(plaf, wit_gen)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ChiquitoPlaf<F: PrimeField> {
|
||||
debug: bool,
|
||||
circuit: cCircuit<F>,
|
||||
// Chiquito column id doesn't start from zero.
|
||||
// Plaf column index starts from 0 for each column type (advice, fixed, and instance).
|
||||
// Therefore a mapping is needed to convert chiquito column id to plaf index.
|
||||
c_column_id_to_p_column_index: HashMap<UUID, usize>,
|
||||
}
|
||||
|
||||
impl<F: PrimeField<Repr = [u8; 32]>> ChiquitoPlaf<F> {
|
||||
pub fn new(circuit: cCircuit<F>, debug: bool) -> ChiquitoPlaf<F> {
|
||||
ChiquitoPlaf {
|
||||
debug,
|
||||
circuit,
|
||||
c_column_id_to_p_column_index: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_plaf(&mut self, k: u32) -> Plaf {
|
||||
let mut plaf = Plaf::default();
|
||||
let p = get_field_p::<F>();
|
||||
plaf.info.p = p;
|
||||
|
||||
plaf.info.num_rows = 2usize.pow(k);
|
||||
|
||||
let mut c_column_id_to_p_column_index = HashMap::<UUID, usize>::new();
|
||||
let mut advice_index = 0;
|
||||
let mut fixed_index = 0;
|
||||
|
||||
for column in self.circuit.columns.iter() {
|
||||
if self.debug {
|
||||
println!("annotation: {}, id: {}", column.annotation, column.id);
|
||||
}
|
||||
self.convert_and_push_plaf_column(
|
||||
column,
|
||||
&mut plaf,
|
||||
&mut c_column_id_to_p_column_index,
|
||||
&mut advice_index,
|
||||
&mut fixed_index,
|
||||
);
|
||||
if self.debug {
|
||||
println!("MAP {:#?}", c_column_id_to_p_column_index);
|
||||
}
|
||||
}
|
||||
|
||||
self.c_column_id_to_p_column_index = c_column_id_to_p_column_index;
|
||||
|
||||
for c_poly in &mut self.circuit.polys.iter() {
|
||||
let plaf_poly = pPoly {
|
||||
name: c_poly.annotation.clone(),
|
||||
exp: self.convert_plaf_poly(&c_poly.expr),
|
||||
};
|
||||
plaf.polys.push(plaf_poly);
|
||||
}
|
||||
|
||||
for lookup in self.circuit.lookups.iter() {
|
||||
let exps = lookup.exprs.clone().into_iter().fold(
|
||||
(Vec::default(), Vec::default()),
|
||||
|mut result, tuple| {
|
||||
result.0.push(self.convert_plaf_poly(&tuple.0));
|
||||
result.1.push(self.convert_plaf_poly(&tuple.1));
|
||||
result
|
||||
},
|
||||
);
|
||||
|
||||
let plaf_lookup = pLookup {
|
||||
name: lookup.annotation.clone(),
|
||||
exps,
|
||||
};
|
||||
|
||||
plaf.lookups.push(plaf_lookup);
|
||||
}
|
||||
|
||||
// Fixed
|
||||
let mut fixed: Vec<Vec<Option<BigUint>>> = Vec::with_capacity(plaf.columns.fixed.len());
|
||||
for _i in 0..plaf.columns.fixed.len() {
|
||||
fixed.push(vec![None; plaf.info.num_rows]);
|
||||
}
|
||||
|
||||
for (column, values) in self.circuit.fixed_assignments.clone().0.into_iter() {
|
||||
let column = self
|
||||
.c_column_id_to_p_column_index
|
||||
.get(&column.uuid())
|
||||
.expect("plaf column not found for fixed signal");
|
||||
|
||||
for (offset, value) in values.iter().enumerate() {
|
||||
// region.assign_fixed(|| "", *column, offset, || Value::known(value.clone()));
|
||||
fixed[*column][offset] = Some(BigUint::from_bytes_le(&value.to_repr()));
|
||||
}
|
||||
}
|
||||
plaf.fixed = fixed;
|
||||
|
||||
if !self.circuit.exposed.is_empty() {
|
||||
// Public column not pulled from Chiquito ir, because it's not stored anywhere.
|
||||
// Therefore, we create a Plaf public column from scratch.
|
||||
let plaf_public = ColumnPublic::new(String::from(
|
||||
"exposed forward signal values in first step instance",
|
||||
));
|
||||
plaf.columns.public.push(plaf_public);
|
||||
}
|
||||
|
||||
for (index, (c_column, rotation)) in self.circuit.exposed.iter().enumerate() {
|
||||
let public_column = pColumn {
|
||||
kind: ColumnKind::Public,
|
||||
index: 0, // Chiquito only has one public column, so the index is always 0.
|
||||
};
|
||||
|
||||
let witness_index = self
|
||||
.c_column_id_to_p_column_index
|
||||
.get(&c_column.uuid())
|
||||
.unwrap();
|
||||
|
||||
let witness_column = pColumn {
|
||||
kind: ColumnKind::Witness,
|
||||
index: *witness_index,
|
||||
};
|
||||
|
||||
let copy = pCopyC {
|
||||
columns: (public_column, witness_column),
|
||||
offsets: vec![(index, *rotation as usize)],
|
||||
};
|
||||
|
||||
plaf.copys.push(copy);
|
||||
}
|
||||
|
||||
plaf
|
||||
}
|
||||
|
||||
fn convert_and_push_plaf_column(
|
||||
&self,
|
||||
column: &cColumn,
|
||||
plaf: &mut Plaf,
|
||||
c_column_id_to_p_column_index: &mut HashMap<UUID, usize>,
|
||||
advice_index: &mut usize,
|
||||
fixed_index: &mut usize,
|
||||
) {
|
||||
match column.ctype {
|
||||
cAdvice => {
|
||||
let plaf_witness = ColumnWitness::new(column.annotation.clone(), column.phase);
|
||||
self.add_id_index_mapping(column, c_column_id_to_p_column_index, advice_index);
|
||||
plaf.columns.witness.push(plaf_witness);
|
||||
}
|
||||
cFixed => {
|
||||
let plaf_fixed = ColumnFixed::new(column.annotation.clone());
|
||||
self.add_id_index_mapping(column, c_column_id_to_p_column_index, fixed_index);
|
||||
plaf.columns.fixed.push(plaf_fixed);
|
||||
}
|
||||
Halo2Advice => {
|
||||
panic!("Imported Halo2Advice is not supported");
|
||||
}
|
||||
Halo2Fixed => {
|
||||
panic!("Imported Halo2Fixed is not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_plaf_poly(&self, chiquito_poly: &cPolyExpr<F>) -> pExpr<PlonkVar> {
|
||||
match chiquito_poly {
|
||||
cPolyExpr::Const(c, _) => pExpr::Const(BigUint::from_bytes_le(&c.to_repr())),
|
||||
cPolyExpr::Sum(es, _) => {
|
||||
let mut iter = es.iter();
|
||||
let first = self.convert_plaf_poly(iter.next().unwrap());
|
||||
iter.fold(first, |acc, e| acc + self.convert_plaf_poly(e))
|
||||
}
|
||||
cPolyExpr::Mul(es, _) => {
|
||||
let mut iter = es.iter();
|
||||
let first = self.convert_plaf_poly(iter.next().unwrap());
|
||||
iter.fold(first, |acc, e| acc * self.convert_plaf_poly(e))
|
||||
}
|
||||
cPolyExpr::Neg(e, _) => -self.convert_plaf_poly(e),
|
||||
cPolyExpr::Pow(e, n, _) => {
|
||||
if *n == 0 {
|
||||
pExpr::Const(BigUint::from(1u32))
|
||||
} else {
|
||||
let e = self.convert_plaf_poly(e);
|
||||
(1..*n).fold(e.clone(), |acc, _| acc * e.clone())
|
||||
}
|
||||
}
|
||||
cPolyExpr::Halo2Expr(e, _) => pExpr::from(e),
|
||||
cPolyExpr::Query((column, rotation, annotation), _) => {
|
||||
let index = self
|
||||
.c_column_id_to_p_column_index
|
||||
.get(&column.uuid())
|
||||
.unwrap();
|
||||
if self.debug {
|
||||
println!(
|
||||
"GET c column id {} match p column index {}",
|
||||
column.uuid(),
|
||||
index
|
||||
);
|
||||
println!("MAP {:#?}", self.c_column_id_to_p_column_index);
|
||||
}
|
||||
pExpr::Var(PlonkVar::Query(
|
||||
self.convert_plaf_query(column, rotation, annotation, *index),
|
||||
))
|
||||
}
|
||||
cPolyExpr::MI(_, _) => panic!("mi elimination not done"),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_id_index_mapping(
|
||||
&self,
|
||||
column: &cColumn,
|
||||
c_column_id_to_p_column_index: &mut HashMap<UUID, usize>,
|
||||
counter: &mut usize,
|
||||
) {
|
||||
c_column_id_to_p_column_index.insert(column.uuid(), *counter);
|
||||
if self.debug {
|
||||
println!(
|
||||
"c column id {} match p column index {}",
|
||||
column.uuid(),
|
||||
counter
|
||||
);
|
||||
}
|
||||
*counter += 1;
|
||||
}
|
||||
|
||||
fn convert_plaf_query(
|
||||
&self,
|
||||
column: &cColumn,
|
||||
rotation: &i32,
|
||||
_annotation: &str,
|
||||
index: usize, // Plaf index starts from 0 for each column type.
|
||||
) -> ColumnQuery {
|
||||
match column.ctype {
|
||||
cAdvice => ColumnQuery {
|
||||
column: pColumn {
|
||||
kind: ColumnKind::Witness,
|
||||
index,
|
||||
},
|
||||
rotation: *rotation,
|
||||
},
|
||||
cFixed => ColumnQuery {
|
||||
column: pColumn {
|
||||
kind: ColumnKind::Fixed,
|
||||
index,
|
||||
},
|
||||
rotation: *rotation,
|
||||
},
|
||||
Halo2Advice | Halo2Fixed => {
|
||||
panic!("Imported Halo2Advice and Halo2Fixed are not supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChiquitoPlafWitGen {
|
||||
empty_witness: pWitness,
|
||||
c_column_id_to_p_column_index: HashMap<UUID, usize>,
|
||||
}
|
||||
|
||||
impl ChiquitoPlafWitGen {
|
||||
fn new(empty_witness: pWitness, c_column_id_to_p_column_index: HashMap<UUID, usize>) -> Self {
|
||||
Self {
|
||||
empty_witness,
|
||||
c_column_id_to_p_column_index,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate<F: PrimeField<Repr = [u8; 32]> + Hash>(
|
||||
&self,
|
||||
witness: Option<Assignments<F>>,
|
||||
) -> pWitness {
|
||||
let mut plaf_witness = pWitness {
|
||||
num_rows: self.empty_witness.num_rows,
|
||||
columns: self.empty_witness.columns.clone(),
|
||||
witness: self.empty_witness.witness.clone(),
|
||||
};
|
||||
|
||||
if let Some(witness) = &witness {
|
||||
for (column, assignments) in witness.iter() {
|
||||
let p_column_index = self
|
||||
.c_column_id_to_p_column_index
|
||||
.get(&column.uuid())
|
||||
.unwrap_or_else(|| panic!("plaf column not found for column {:?}", column));
|
||||
|
||||
for (offset, value) in assignments.iter().enumerate() {
|
||||
plaf_witness.witness[*p_column_index][offset] =
|
||||
Some(BigUint::from_bytes_le(&value.to_repr()));
|
||||
}
|
||||
}
|
||||
|
||||
plaf_witness
|
||||
} else {
|
||||
plaf_witness
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,12 +43,20 @@ pub fn compile<
|
||||
>(
|
||||
config: CompilerConfig<CM, SSB>,
|
||||
ast: &astCircuit<F, TG>,
|
||||
) -> (Circuit<F>, Option<AssignmentGenerator<F, TG>>) {
|
||||
) -> PlonkishCompilationResult<F, TG> {
|
||||
let (mut unit, assignment) = compile_phase1(config, ast);
|
||||
|
||||
compile_phase2(&mut unit);
|
||||
|
||||
(unit.into(), assignment)
|
||||
PlonkishCompilationResult {
|
||||
circuit: unit.into(),
|
||||
assignment_generator: assignment,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PlonkishCompilationResult<F, TG> {
|
||||
pub circuit: Circuit<F>,
|
||||
pub assignment_generator: Option<AssignmentGenerator<F, TG>>,
|
||||
}
|
||||
|
||||
pub fn compile_phase1<
|
||||
@@ -615,11 +623,13 @@ mod test {
|
||||
|
||||
let mock_ast_circuit = astCircuit::<Fr, NullTraceGenerator>::default();
|
||||
|
||||
let (circuit, assignment_generator) =
|
||||
compile::<Fr, SingleRowCellManager, SimpleStepSelectorBuilder, NullTraceGenerator>(
|
||||
config,
|
||||
&mock_ast_circuit,
|
||||
);
|
||||
let PlonkishCompilationResult {
|
||||
circuit,
|
||||
assignment_generator,
|
||||
} = compile::<Fr, SingleRowCellManager, SimpleStepSelectorBuilder, NullTraceGenerator>(
|
||||
config,
|
||||
&mock_ast_circuit,
|
||||
);
|
||||
|
||||
assert_eq!(circuit.columns.len(), 1);
|
||||
assert_eq!(circuit.exposed.len(), 0);
|
||||
|
||||
@@ -15,6 +15,8 @@ pub mod sc;
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Circuit<F> {
|
||||
pub columns: Vec<Column>,
|
||||
/// Exposed cells of the Column at the given rotation. Used to generate the instance
|
||||
/// (equivalent to public inputs)
|
||||
pub exposed: Vec<(Column, i32)>,
|
||||
|
||||
pub polys: Vec<Poly<F>>,
|
||||
|
||||
Reference in New Issue
Block a user