Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions halo2-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.gi
plotters = { version = "0.3.0", optional = true }
tabbycat = { version = "0.1", features = ["attributes"], optional = true }

# test-utils
rand = { version = "0.8", optional = true }

[dev-dependencies]
ark-std = { version = "0.3.0", features = ["print-trace"] }
rand = "0.8"
Expand All @@ -44,6 +47,7 @@ halo2-pse = ["halo2_proofs"]
halo2-axiom = ["halo2_proofs_axiom"]
display = []
profile = ["halo2_proofs_axiom?/profile"]
test-utils = ["dep:rand"]

[[bench]]
name = "mul"
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/gates/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod builder;
pub mod flex_gate;
pub mod range;

#[cfg(test)]
#[cfg(any(test, feature = "test-utils"))]
pub mod tests;

pub use flex_gate::{GateChip, GateInstructions};
Expand Down
170 changes: 170 additions & 0 deletions halo2-base/src/gates/tests/general.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
use super::*;
use crate::gates::{
builder::{GateCircuitBuilder, GateThreadBuilder, RangeCircuitBuilder},
flex_gate::{GateChip, GateInstructions},
range::{RangeChip, RangeInstructions},
};
use crate::halo2_proofs::dev::MockProver;
use crate::utils::{BigPrimeField, ScalarField};
use crate::{Context, QuantumCell::Constant};
use ff::Field;
use rayon::prelude::*;

fn gate_tests<F: ScalarField>(ctx: &mut Context<F>, inputs: [F; 3]) {
let [a, b, c]: [_; 3] = ctx.assign_witnesses(inputs).try_into().unwrap();
let chip = GateChip::default();

// test add
chip.add(ctx, a, b);

// test sub
chip.sub(ctx, a, b);

// test multiply
chip.mul(ctx, c, b);

// test idx_to_indicator
chip.idx_to_indicator(ctx, Constant(F::from(3u64)), 4);

let bits = ctx.assign_witnesses([F::zero(), F::one()]);
chip.bits_to_indicator(ctx, &bits);

chip.is_equal(ctx, b, a);

chip.is_zero(ctx, a);
}

#[test]
fn test_gates() {
let k = 6;
let inputs = [10u64, 12u64, 120u64].map(Fr::from);
let mut builder = GateThreadBuilder::mock();
gate_tests(builder.main(0), inputs);

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

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

#[test]
fn test_multithread_gates() {
let k = 6;
let inputs = [10u64, 12u64, 120u64].map(Fr::from);
let mut builder = GateThreadBuilder::mock();
gate_tests(builder.main(0), inputs);

let thread_ids = (0..4usize).map(|_| builder.get_new_thread_id()).collect::<Vec<_>>();
let new_threads = thread_ids
.into_par_iter()
.map(|id| {
let mut ctx = Context::new(builder.witness_gen_only(), id);
gate_tests(&mut ctx, [(); 3].map(|_| Fr::random(OsRng)));
ctx
})
.collect::<Vec<_>>();
builder.threads[0].extend(new_threads);

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

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

#[cfg(feature = "dev-graph")]
#[test]
fn plot_gates() {
let k = 5;
use plotters::prelude::*;

let root = BitMapBackend::new("layout.png", (1024, 1024)).into_drawing_area();
root.fill(&WHITE).unwrap();
let root = root.titled("Gates Layout", ("sans-serif", 60)).unwrap();

let inputs = [Fr::zero(); 3];
let builder = GateThreadBuilder::new(false);
gate_tests(builder.main(0), inputs);

// auto-tune circuit
builder.config(k, Some(9));
// create circuit
let circuit = GateCircuitBuilder::keygen(builder);
halo2_proofs::dev::CircuitLayout::default().render(k, &circuit, &root).unwrap();
}

fn range_tests<F: BigPrimeField>(
ctx: &mut Context<F>,
lookup_bits: usize,
inputs: [F; 2],
range_bits: usize,
lt_bits: usize,
) {
let [a, b]: [_; 2] = ctx.assign_witnesses(inputs).try_into().unwrap();
let chip = RangeChip::default(lookup_bits);
std::env::set_var("LOOKUP_BITS", lookup_bits.to_string());

chip.range_check(ctx, a, range_bits);

chip.check_less_than(ctx, a, b, lt_bits);

chip.is_less_than(ctx, a, b, lt_bits);

chip.is_less_than(ctx, b, a, lt_bits);

chip.div_mod(ctx, a, 7u64, lt_bits);
}

#[test]
fn test_range_single() {
let k = 11;
let inputs = [100, 101].map(Fr::from);
let mut builder = GateThreadBuilder::mock();
range_tests(builder.main(0), 3, inputs, 8, 8);

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

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

#[test]
fn test_range_multicolumn() {
let k = 5;
let inputs = [100, 101].map(Fr::from);
let mut builder = GateThreadBuilder::mock();
range_tests(builder.main(0), 3, inputs, 8, 8);

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

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

#[cfg(feature = "dev-graph")]
#[test]
fn plot_range() {
use plotters::prelude::*;

let root = BitMapBackend::new("layout.png", (1024, 1024)).into_drawing_area();
root.fill(&WHITE).unwrap();
let root = root.titled("Range Layout", ("sans-serif", 60)).unwrap();

let k = 11;
let inputs = [0, 0].map(Fr::from);
let mut builder = GateThreadBuilder::new(false);
range_tests(builder.main(0), 3, inputs, 8, 8);

// auto-tune circuit
builder.config(k, Some(9));
// create circuit
let circuit = RangeCircuitBuilder::keygen(builder);
halo2_proofs::dev::CircuitLayout::default().render(7, &circuit, &root).unwrap();
}
15 changes: 11 additions & 4 deletions halo2-base/src/gates/tests/idx_to_indicator.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
use crate::halo2_proofs::{
plonk::keygen_pk,
plonk::{keygen_vk, Assigned},
poly::kzg::commitment::ParamsKZG,
use crate::{
gates::{
builder::{GateCircuitBuilder, GateThreadBuilder},
GateChip, GateInstructions,
},
halo2_proofs::{
plonk::keygen_pk,
plonk::{keygen_vk, Assigned},
poly::kzg::commitment::ParamsKZG,
},
};

use ff::Field;
use itertools::Itertools;
use rand::{thread_rng, Rng};

Expand Down
Loading