Skip to content

Commit

Permalink
feat: use configure_with_params
Browse files Browse the repository at this point in the history
remove `thread_local!` usage
  • Loading branch information
jonathanpwang committed Aug 14, 2023
1 parent beaceb6 commit 87be060
Show file tree
Hide file tree
Showing 29 changed files with 415 additions and 533 deletions.
2 changes: 1 addition & 1 deletion halo2-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ mimalloc = { version = "0.1", default-features = false, optional = true }
default = ["halo2-axiom", "display"]
asm = ["halo2_proofs_axiom?/asm"]
dev-graph = ["halo2_proofs?/dev-graph", "halo2_proofs_axiom?/dev-graph", "plotters"]
halo2-pse = ["halo2_proofs"]
halo2-pse = ["halo2_proofs/circuit-params"]
halo2-axiom = ["halo2_proofs_axiom"]
display = []
profile = ["halo2_proofs_axiom?/profile"]
Expand Down
24 changes: 10 additions & 14 deletions halo2-base/benches/inner_product.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
#![allow(unused_imports)]
#![allow(unused_variables)]
use halo2_base::gates::builder::{GateCircuitBuilder, GateThreadBuilder, RangeCircuitBuilder};
use halo2_base::gates::flex_gate::{FlexGateConfig, GateChip, GateInstructions, GateStrategy};
use halo2_base::gates::builder::{GateThreadBuilder, RangeCircuitBuilder};
use halo2_base::gates::flex_gate::{GateChip, GateInstructions};
use halo2_base::halo2_proofs::{
arithmetic::Field,
circuit::*,
dev::MockProver,
halo2curves::bn256::{Bn256, Fr, G1Affine},
plonk::*,
Expand All @@ -15,14 +12,9 @@ use halo2_base::halo2_proofs::{
transcript::{Blake2bWrite, Challenge255, TranscriptWriterBuffer},
};
use halo2_base::utils::ScalarField;
use halo2_base::{
Context,
QuantumCell::{Existing, Witness},
SKIP_FIRST_PASS,
};
use halo2_base::{Context, QuantumCell::Existing};
use itertools::Itertools;
use rand::rngs::OsRng;
use std::marker::PhantomData;

use criterion::{criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion};
Expand All @@ -49,8 +41,8 @@ fn bench(c: &mut Criterion) {
// create circuit for keygen
let mut builder = GateThreadBuilder::new(false);
inner_prod_bench(builder.main(0), vec![Fr::zero(); 5], vec![Fr::zero(); 5]);
builder.config(k as usize, Some(20));
let circuit = RangeCircuitBuilder::mock(builder);
let config_params = builder.config(k as usize, Some(20), None);
let circuit = RangeCircuitBuilder::mock(builder, config_params.clone());

// check the circuit is correct just in case
MockProver::run(k, &circuit, vec![]).unwrap().assert_satisfied();
Expand All @@ -73,7 +65,11 @@ fn bench(c: &mut Criterion) {
let a = (0..5).map(|_| Fr::random(OsRng)).collect_vec();
let b = (0..5).map(|_| Fr::random(OsRng)).collect_vec();
inner_prod_bench(builder.main(0), a, b);
let circuit = RangeCircuitBuilder::prover(builder, break_points.clone());
let circuit = RangeCircuitBuilder::prover(
builder,
config_params.clone(),
break_points.clone(),
);

let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
create_proof::<
Expand Down
10 changes: 7 additions & 3 deletions halo2-base/benches/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ fn bench(c: &mut Criterion) {
// create circuit for keygen
let mut builder = GateThreadBuilder::new(false);
mul_bench(builder.main(0), [Fr::zero(); 2]);
builder.config(K as usize, Some(9));
let circuit = RangeCircuitBuilder::keygen(builder);
let config_params = builder.config(K as usize, Some(9), None);
let circuit = RangeCircuitBuilder::keygen(builder, config_params.clone());

let params = ParamsKZG::<Bn256>::setup(K, OsRng);
let vk = keygen_vk(&params, &circuit).expect("vk should not fail");
Expand All @@ -56,7 +56,11 @@ fn bench(c: &mut Criterion) {
let mut builder = GateThreadBuilder::new(true);
// do the computation
mul_bench(builder.main(0), inputs);
let circuit = RangeCircuitBuilder::prover(builder, break_points.clone());
let circuit = RangeCircuitBuilder::prover(
builder,
config_params.clone(),
break_points.clone(),
);

let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
create_proof::<
Expand Down
25 changes: 5 additions & 20 deletions halo2-base/examples/inner_product.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
#![allow(unused_imports)]
#![allow(unused_variables)]
use halo2_base::gates::builder::{GateThreadBuilder, RangeCircuitBuilder};
use halo2_base::gates::flex_gate::{FlexGateConfig, GateChip, GateInstructions, GateStrategy};
use halo2_base::gates::flex_gate::{GateChip, GateInstructions};
use halo2_base::halo2_proofs::{
arithmetic::Field,
circuit::*,
dev::MockProver,
halo2curves::bn256::{Bn256, Fr, G1Affine},
plonk::*,
Expand All @@ -18,21 +15,9 @@ use halo2_base::halo2_proofs::{
transcript::{Blake2bWrite, Challenge255, TranscriptWriterBuffer},
};
use halo2_base::utils::ScalarField;
use halo2_base::{
Context,
QuantumCell::{Existing, Witness},
SKIP_FIRST_PASS,
};
use halo2_base::{Context, QuantumCell::Existing};
use itertools::Itertools;
use rand::rngs::OsRng;
use std::marker::PhantomData;

use criterion::{criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion};

use pprof::criterion::{Output, PProfProfiler};
// Thanks to the example provided by @jebbow in his article
// https://www.jibbow.com/posts/criterion-flamegraphs/

const K: u32 = 19;

Expand All @@ -52,8 +37,8 @@ fn main() {
// create circuit for keygen
let mut builder = GateThreadBuilder::new(false);
inner_prod_bench(builder.main(0), vec![Fr::zero(); 5], vec![Fr::zero(); 5]);
builder.config(k as usize, Some(20));
let circuit = RangeCircuitBuilder::mock(builder);
let config_params = builder.config(k as usize, Some(20), None);
let circuit = RangeCircuitBuilder::mock(builder, config_params.clone());

// check the circuit is correct just in case
MockProver::run(k, &circuit, vec![]).unwrap().assert_satisfied();
Expand All @@ -68,7 +53,7 @@ fn main() {
let a = (0..5).map(|_| Fr::random(OsRng)).collect_vec();
let b = (0..5).map(|_| Fr::random(OsRng)).collect_vec();
inner_prod_bench(builder.main(0), a, b);
let circuit = RangeCircuitBuilder::prover(builder, break_points);
let circuit = RangeCircuitBuilder::prover(builder, config_params, break_points);

let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
create_proof::<
Expand Down
115 changes: 71 additions & 44 deletions halo2-base/src/gates/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@ pub type ThreadBreakPoints = Vec<usize>;
/// Vector of vectors tracking the thread break points across different halo2 phases
pub type MultiPhaseThreadBreakPoints = Vec<ThreadBreakPoints>;

thread_local! {
/// This is used as a thread-safe way to auto-configure a circuit's shape and then pass the configuration to `Circuit::configure`.
pub static BASE_CONFIG_PARAMS: RefCell<BaseConfigParams> = RefCell::new(Default::default());
}

/// Sets the thread-local number of bits to be range checkable via a lookup table with entries [0, 2<sup>lookup_bits</sup>)
pub fn set_lookup_bits(lookup_bits: usize) {
BASE_CONFIG_PARAMS.with(|conf| conf.borrow_mut().lookup_bits = Some(lookup_bits));
}

/// Stores the cell values loaded during the Keygen phase of a halo2 proof and breakpoints for multi-threading
#[derive(Clone, Debug, Default)]
pub struct KeygenAssignments<F: ScalarField> {
Expand Down Expand Up @@ -143,7 +133,13 @@ impl<F: ScalarField> GateThreadBuilder<F> {
///
/// * `k`: The number of in the circuit (i.e. numeber of rows = 2<sup>k</sup>)
/// * `minimum_rows`: The minimum number of rows in the circuit that cannot be used for witness assignments and contain random `blinding factors` to ensure zk property, defaults to 0.
pub fn config(&self, k: usize, minimum_rows: Option<usize>) -> BaseConfigParams {
/// * `lookup_bits`: (Optional) Create a lookup table with values [0, 2<sup>lookup_bits</sup>) for range checks.
pub fn config(
&self,
k: usize,
minimum_rows: Option<usize>,
lookup_bits: Option<usize>,
) -> BaseConfigParams {
let max_rows = (1 << k) - minimum_rows.unwrap_or(0);
let total_advice_per_phase = self
.threads
Expand Down Expand Up @@ -173,18 +169,14 @@ impl<F: ScalarField> GateThreadBuilder<F> {
.len();
let num_fixed = (total_fixed + (1 << k) - 1) >> k;

let mut params = BaseConfigParams {
let params = BaseConfigParams {
strategy: GateStrategy::Vertical,
num_advice_per_phase,
num_lookup_advice_per_phase,
num_fixed,
k,
lookup_bits: None,
lookup_bits,
};
BASE_CONFIG_PARAMS.with(|conf| {
params.lookup_bits = conf.borrow().lookup_bits;
*conf.borrow_mut() = params.clone();
});
#[cfg(feature = "display")]
{
for phase in 0..MAX_PHASE {
Expand Down Expand Up @@ -492,25 +484,40 @@ pub struct GateCircuitBuilder<F: ScalarField> {
pub builder: RefCell<GateThreadBuilder<F>>, // `RefCell` is just to trick circuit `synthesize` to take ownership of the inner builder
/// Break points for threads within the circuit
pub break_points: RefCell<MultiPhaseThreadBreakPoints>, // `RefCell` allows the circuit to record break points in a keygen call of `synthesize` for use in later witness gen
/// Configuration parameters for the circuit shape
pub config_params: BaseConfigParams,
}

impl<F: ScalarField> GateCircuitBuilder<F> {
/// Creates a new [GateCircuitBuilder] with `use_unknown` of [GateThreadBuilder] set to true.
pub fn keygen(builder: GateThreadBuilder<F>) -> Self {
Self { builder: RefCell::new(builder.unknown(true)), break_points: RefCell::new(vec![]) }
pub fn keygen(builder: GateThreadBuilder<F>, config_params: BaseConfigParams) -> Self {
Self {
builder: RefCell::new(builder.unknown(true)),
config_params,
break_points: Default::default(),
}
}

/// Creates a new [GateCircuitBuilder] with `use_unknown` of [GateThreadBuilder] set to false.
pub fn mock(builder: GateThreadBuilder<F>) -> Self {
Self { builder: RefCell::new(builder.unknown(false)), break_points: RefCell::new(vec![]) }
pub fn mock(builder: GateThreadBuilder<F>, config_params: BaseConfigParams) -> Self {
Self {
builder: RefCell::new(builder.unknown(false)),
config_params,
break_points: Default::default(),
}
}

/// Creates a new [GateCircuitBuilder].
/// Creates a new [GateCircuitBuilder] with a pinned circuit configuration given by `config_params` and `break_points`.
pub fn prover(
builder: GateThreadBuilder<F>,
config_params: BaseConfigParams,
break_points: MultiPhaseThreadBreakPoints,
) -> Self {
Self { builder: RefCell::new(builder), break_points: RefCell::new(break_points) }
Self {
builder: RefCell::new(builder),
config_params,
break_points: RefCell::new(break_points),
}
}

/// Synthesizes from the [GateCircuitBuilder] by populating the advice column and assigning new threads if witness generation is performed.
Expand Down Expand Up @@ -582,41 +589,48 @@ pub struct RangeCircuitBuilder<F: ScalarField>(pub GateCircuitBuilder<F>);

impl<F: ScalarField> RangeCircuitBuilder<F> {
/// Creates an instance of the [RangeCircuitBuilder] and executes in keygen mode.
pub fn keygen(builder: GateThreadBuilder<F>) -> Self {
Self(GateCircuitBuilder::keygen(builder))
pub fn keygen(builder: GateThreadBuilder<F>, config_params: BaseConfigParams) -> Self {
Self(GateCircuitBuilder::keygen(builder, config_params))
}

/// Creates a mock instance of the [RangeCircuitBuilder].
pub fn mock(builder: GateThreadBuilder<F>) -> Self {
Self(GateCircuitBuilder::mock(builder))
pub fn mock(builder: GateThreadBuilder<F>, config_params: BaseConfigParams) -> Self {
Self(GateCircuitBuilder::mock(builder, config_params))
}

/// Creates an instance of the [RangeCircuitBuilder] and executes in prover mode.
pub fn prover(
builder: GateThreadBuilder<F>,
config_params: BaseConfigParams,
break_points: MultiPhaseThreadBreakPoints,
) -> Self {
Self(GateCircuitBuilder::prover(builder, break_points))
Self(GateCircuitBuilder::prover(builder, config_params, break_points))
}
}

impl<F: ScalarField> Circuit<F> for RangeCircuitBuilder<F> {
type Config = BaseConfig<F>;
type FloorPlanner = SimpleFloorPlanner;
type Params = BaseConfigParams;

fn params(&self) -> Self::Params {
self.0.config_params.clone()
}

/// Creates a new instance of the [RangeCircuitBuilder] without witnesses by setting the witness_gen_only flag to false
fn without_witnesses(&self) -> Self {
unimplemented!()
}

/// Configures a new circuit using [`BaseConfigParams`]
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
let params = BASE_CONFIG_PARAMS
.try_with(|config| config.borrow().clone())
.expect("You need to call config() to configure the halo2-base circuit shape first");
fn configure_with_params(meta: &mut ConstraintSystem<F>, params: Self::Params) -> Self::Config {
BaseConfig::configure(meta, params)
}

fn configure(_: &mut ConstraintSystem<F>) -> Self::Config {
unimplemented!("You must use configure_with_params");
}

/// Performs the actual computation on the circuit (e.g., witness generation), populating the lookup table and filling in all the advice values for a particular proof.
fn synthesize(
&self,
Expand Down Expand Up @@ -662,35 +676,39 @@ impl<F: ScalarField> RangeWithInstanceCircuitBuilder<F> {
/// See [`RangeCircuitBuilder::keygen`]
pub fn keygen(
builder: GateThreadBuilder<F>,
config_params: BaseConfigParams,
assigned_instances: Vec<AssignedValue<F>>,
) -> Self {
Self { circuit: RangeCircuitBuilder::keygen(builder), assigned_instances }
Self { circuit: RangeCircuitBuilder::keygen(builder, config_params), assigned_instances }
}

/// See [`RangeCircuitBuilder::mock`]
pub fn mock(builder: GateThreadBuilder<F>, assigned_instances: Vec<AssignedValue<F>>) -> Self {
Self { circuit: RangeCircuitBuilder::mock(builder), assigned_instances }
pub fn mock(
builder: GateThreadBuilder<F>,
config_params: BaseConfigParams,
assigned_instances: Vec<AssignedValue<F>>,
) -> Self {
Self { circuit: RangeCircuitBuilder::mock(builder, config_params), assigned_instances }
}

/// See [`RangeCircuitBuilder::prover`]
pub fn prover(
builder: GateThreadBuilder<F>,
assigned_instances: Vec<AssignedValue<F>>,
config_params: BaseConfigParams,
break_points: MultiPhaseThreadBreakPoints,
assigned_instances: Vec<AssignedValue<F>>,
) -> Self {
Self { circuit: RangeCircuitBuilder::prover(builder, break_points), assigned_instances }
Self {
circuit: RangeCircuitBuilder::prover(builder, config_params, break_points),
assigned_instances,
}
}

/// Creates a new instance of the [RangeWithInstanceCircuitBuilder].
pub fn new(circuit: RangeCircuitBuilder<F>, assigned_instances: Vec<AssignedValue<F>>) -> Self {
Self { circuit, assigned_instances }
}

/// Calls [`GateThreadBuilder::config`]
pub fn config(&self, k: u32, minimum_rows: Option<usize>) -> BaseConfigParams {
self.circuit.0.builder.borrow().config(k as usize, minimum_rows)
}

/// Gets the break points of the circuit.
pub fn break_points(&self) -> MultiPhaseThreadBreakPoints {
self.circuit.0.break_points.borrow().clone()
Expand All @@ -710,18 +728,27 @@ impl<F: ScalarField> RangeWithInstanceCircuitBuilder<F> {
impl<F: ScalarField> Circuit<F> for RangeWithInstanceCircuitBuilder<F> {
type Config = PublicBaseConfig<F>;
type FloorPlanner = SimpleFloorPlanner;
type Params = BaseConfigParams;

fn params(&self) -> Self::Params {
self.circuit.0.config_params.clone()
}

fn without_witnesses(&self) -> Self {
unimplemented!()
}

fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
let base = RangeCircuitBuilder::configure(meta);
fn configure_with_params(meta: &mut ConstraintSystem<F>, params: Self::Params) -> Self::Config {
let base = BaseConfig::configure(meta, params);
let instance = meta.instance_column();
meta.enable_equality(instance);
PublicBaseConfig { base, instance }
}

fn configure(_: &mut ConstraintSystem<F>) -> Self::Config {
unimplemented!("You must use configure_with_params")
}

fn synthesize(
&self,
config: Self::Config,
Expand Down
4 changes: 2 additions & 2 deletions halo2-base/src/gates/tests/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ fn test_multithread_gates() {
builder.threads[0].extend(new_threads);

// auto-tune circuit
builder.config(k, Some(9));
let config_params = builder.config(k, Some(9), None);
// create circuit
let circuit = RangeCircuitBuilder::mock(builder);
let circuit = RangeCircuitBuilder::mock(builder, config_params);

MockProver::run(k as u32, &circuit, vec![]).unwrap().assert_satisfied();
}
Expand Down
Loading

0 comments on commit 87be060

Please sign in to comment.