Skip to content

Commit

Permalink
Feat: extend halo2 base test coverage (#35)
Browse files Browse the repository at this point in the history
* feat: add flex_gate_test.rs and pos add() test

* feat: add pos sub() test

* feat: add pos neg() test

* feat: add pos mul() test

* feat: add pos mul_add() test

* feat: add pos mul_not() test

* feat: add pos assert_bit

* feat: add pos div_unsafe() test

* feat: add pos assert_is_const test

* feat: add pos inner_product() test

* feat: add pos inner_product_left_last() test

* feat: add pos inner_product_with_sums test

* feat: add pos sum_products_with_coeff_and_var test

* feat: add pos and() test

* feat: add pos not() test

* feat: add pos select() test

* feat: add pos or_and() test

* feat: add pos bits_to_indicator() test

* feat: add pos idx_to_indicator() test

* feat: add pos select_by_indicator() test

* feat: add pos select_from_idx() test

* feat: add pos is_zero() test

* feat: add pos is_equal() test

* feat: add pos num_to_bits() test

* feat: add pos lagrange_eval() test

* feat: add pos get_field_element() test

* feat: add pos range_check() tests

* feat: add pos check_less_than() test

* feat: add pos check_less_than_safe() test

* feat: add pos check_big_less_than_safe() test

* feat: add pos is_less_than() test

* feat: add pos is_less_than_safe() test

* feat: add pos is_big_less_than_safe() test

* feat: add pos div_mod() test

* feat: add pos get_last_bit() test

* feat: add pos div_mod_var() test

* fix: pass slices into test functions not arrays

* feat: Add pos property tests for flex_gate

* feat: Add positive property tests for flex_gate

* feat: add pos property tests for range_check.rs

* feat: add neg pranking test for idx_to_indicator

* fix: change div_mod_var test values

* feat(refactor): refactor property tests

* fix: fix neg test, assert_const, assert_bit

* fix: failing prop tests

* feat: expand negative testing is_less_than_failing

* fix: Circuit overflow errors on neg tests

* fix: prop_test_mul_not

* fix: everything but get_last_bit & lagrange

* fix: clippy

* fix: set LOOKUP_BITS in range tests, make range check neg test more

robust

* fix: neg_prop_tests cannot prank inputs

Inputs have many copy constraints; pranking initial input will cause all
copy constraints to fail

* fix: test_is_big_less_than_safe, 240 bits max

* Didn't want to change current `is_less_than` implementation, which in
  order to optimize lookups for smaller bits, only works when inputs
have at most `(F::CAPACITY // lookup_bits - 1) * lookup_bits` bits

* fix: inline doc for lagrange_and_eval

* Remove proptest for lagrange_and_eval and leave as todo

* tests: add readme about serial execution

---------

Co-authored-by: Jonathan Wang <jonathanpwang@users.noreply.github.com>
  • Loading branch information
PatStiles and jonathanpwang authored May 18, 2023
1 parent f566451 commit a79db0e
Show file tree
Hide file tree
Showing 12 changed files with 1,362 additions and 3 deletions.
2 changes: 2 additions & 0 deletions halo2-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pprof = { version = "0.11", features = ["criterion", "flamegraph"] }
criterion = "0.4"
criterion-macro = "0.4"
rayon = "1.6.1"
test-case = "3.1.0"
proptest = "1.1.0"

# memory allocation
[target.'cfg(not(target_env = "msvc"))'.dependencies]
Expand Down
11 changes: 11 additions & 0 deletions halo2-base/proptest-regressions/gates/tests/prop_test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 8489bbcc3439950355c90ecbc92546a66e4b57eae0a3856e7a4ccb59bf74b4ce # shrinks to k = 1, len = 1, idx = 0, witness_vals = [0x0000000000000000000000000000000000000000000000000000000000000000]
cc b18c4f5e502fe36dbc2471f89a6ffb389beaf473b280e844936298ab1cf9b74e # shrinks to (k, len, idx, witness_vals) = (8, 2, 1, [0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000001])
cc 4528fb02e7227f85116c2a16aef251b9c3b6d9c340ddb50b936c2140d7856cc4 # shrinks to inputs = ([], [])
cc 79bfe42c93b5962a38b2f831f1dd438d8381a24a6ce15bfb89a8562ce9af0a2d # shrinks to (k, len, idx, witness_vals) = (8, 62, 0, [0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000])
cc d0e10a06108cb58995a8ae77a91b299fb6230e9e6220121c48f2488e5d199e82 # shrinks to input = (0x000000000000000000000000000000000000000000000000070a95cb0607bef9, 4096)
2 changes: 1 addition & 1 deletion halo2-base/src/gates/flex_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ pub trait GateInstructions<F: ScalarField> {

/// Performs and constrains Lagrange interpolation on `coords` and evaluates the resulting polynomial at `x`.
///
/// Given pairs `coords[i] = (x_i, y_i)`, let `f` be the unique degree `len(coords)` polynomial such that `f(x_i) = y_i` for all `i`.
/// Given pairs `coords[i] = (x_i, y_i)`, let `f` be the unique degree `len(coords) - 1` polynomial such that `f(x_i) = y_i` for all `i`.
///
/// Returns:
/// (f(x), Prod_i(x - x_i))
Expand Down
10 changes: 8 additions & 2 deletions halo2-base/src/gates/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ pub trait RangeInstructions<F: ScalarField> {
num_bits: usize,
) -> AssignedValue<F>;

/// Performs a range check that `a` has at most `bit_length(b)` and then constrains that `a` is in `[0,b)`.
/// Performs a range check that `a` has at most `ceil(bit_length(b) / lookup_bits) * lookup_bits` and then constrains that `a` is in `[0,b)`.
///
/// Returns 1 if `a` < `b`, otherwise 0.
///
Expand All @@ -278,12 +278,14 @@ pub trait RangeInstructions<F: ScalarField> {
self.is_less_than(ctx, a, Constant(self.gate().get_field_element(b)), range_bits)
}

/// Performs a range check that `a` has at most `bit_length(b)` and then constrains that `a` is in `[0,b)`.
/// Performs a range check that `a` has at most `ceil(b.bits() / lookup_bits) * lookup_bits` bits and then constrains that `a` is in `[0,b)`.
///
/// Returns 1 if `a` < `b`, otherwise 0.
///
/// * a: [AssignedValue] value to check
/// * b: upper bound as [BigUint] value
///
/// For the current implementation using [`is_less_than`], we require `ceil(b.bits() / lookup_bits) + 1 < F::NUM_BITS / lookup_bits`
fn is_big_less_than_safe(
&self,
ctx: &mut Context<F>,
Expand Down Expand Up @@ -601,6 +603,10 @@ impl<F: ScalarField> RangeInstructions<F> for RangeChip<F> {

let k = (num_bits + self.lookup_bits - 1) / self.lookup_bits;
let padded_bits = k * self.lookup_bits;
debug_assert!(
padded_bits + self.lookup_bits <= F::CAPACITY as usize,
"num_bits is too large for this is_less_than implementation"
);
let pow_padded = self.gate.pow_of_two[padded_bits];

let shift_a_val = pow_padded + a.value();
Expand Down
9 changes: 9 additions & 0 deletions halo2-base/src/gates/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Tests

For tests that use `GateCircuitBuilder` or `RangeCircuitBuilder`, we currently must use environmental variables `FLEX_GATE_CONFIG` and `LOOKUP_BITS` to pass circuit configuration parameters to the `Circuit::configure` function. This is troublesome when Rust executes tests in parallel, so we to make sure all tests pass, run

```
cargo test -- --test-threads=1
```

to force serial execution.
266 changes: 266 additions & 0 deletions halo2-base/src/gates/tests/flex_gate_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
use super::*;
use crate::halo2_proofs::dev::MockProver;
use crate::halo2_proofs::dev::VerifyFailure;
use crate::utils::ScalarField;
use crate::QuantumCell::Witness;
use crate::{
gates::{
builder::{GateCircuitBuilder, GateThreadBuilder},
flex_gate::{GateChip, GateInstructions},
},
QuantumCell,
};
use test_case::test_case;

#[test_case(&[1, 1].map(Fr::from).map(Witness) => Fr::from(2) ; "add(): 1 + 1 == 2")]
pub fn test_add<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.add(ctx, inputs[0], inputs[1]);
*a.value()
}

#[test_case(&[1, 1].map(Fr::from).map(Witness) => Fr::from(0) ; "sub(): 1 - 1 == 0")]
pub fn test_sub<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.sub(ctx, inputs[0], inputs[1]);
*a.value()
}

#[test_case(Witness(Fr::from(1)) => -Fr::from(1) ; "neg(): 1 -> -1")]
pub fn test_neg<F: ScalarField>(a: QuantumCell<F>) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.neg(ctx, a);
*a.value()
}

#[test_case(&[1, 1].map(Fr::from).map(Witness) => Fr::from(1) ; "mul(): 1 * 1 == 1")]
pub fn test_mul<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.mul(ctx, inputs[0], inputs[1]);
*a.value()
}

#[test_case(&[1, 1, 1].map(Fr::from).map(Witness) => Fr::from(2) ; "mul_add(): 1 * 1 + 1 == 2")]
pub fn test_mul_add<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.mul_add(ctx, inputs[0], inputs[1], inputs[2]);
*a.value()
}

#[test_case(&[1, 1].map(Fr::from).map(Witness) => Fr::from(0) ; "mul_not(): 1 * 1 == 0")]
pub fn test_mul_not<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.mul_not(ctx, inputs[0], inputs[1]);
*a.value()
}

#[test_case(Fr::from(1) => Ok(()); "assert_bit(): 1 == bit")]
pub fn test_assert_bit<F: ScalarField>(input: F) -> Result<(), Vec<VerifyFailure>> {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = ctx.assign_witnesses([input])[0];
chip.assert_bit(ctx, a);
// auto-tune circuit
builder.config(6, Some(9));
// create circuit
let circuit = GateCircuitBuilder::mock(builder);
MockProver::run(6, &circuit, vec![]).unwrap().verify()
}

#[test_case(&[1, 1].map(Fr::from).map(Witness) => Fr::from(1) ; "div_unsafe(): 1 / 1 == 1")]
pub fn test_div_unsafe<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.div_unsafe(ctx, inputs[0], inputs[1]);
*a.value()
}

#[test_case(&[1, 1].map(Fr::from); "assert_is_const()")]
pub fn test_assert_is_const<F: ScalarField>(inputs: &[F]) {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = ctx.assign_witnesses([inputs[0]])[0];
chip.assert_is_const(ctx, &a, &inputs[1]);
// auto-tune circuit
builder.config(6, Some(9));
// create circuit
let circuit = GateCircuitBuilder::mock(builder);
MockProver::run(6, &circuit, vec![]).unwrap().assert_satisfied()
}

#[test_case((vec![Witness(Fr::one()); 5], vec![Witness(Fr::one()); 5]) => Fr::from(5) ; "inner_product(): 1 * 1 + ... + 1 * 1 == 5")]
pub fn test_inner_product<F: ScalarField>(input: (Vec<QuantumCell<F>>, Vec<QuantumCell<F>>)) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.inner_product(ctx, input.0, input.1);
*a.value()
}

#[test_case((vec![Witness(Fr::one()); 5], vec![Witness(Fr::one()); 5]) => (Fr::from(5), Fr::from(1)); "inner_product_left_last(): 1 * 1 + ... + 1 * 1 == (5, 1)")]
pub fn test_inner_product_left_last<F: ScalarField>(
input: (Vec<QuantumCell<F>>, Vec<QuantumCell<F>>),
) -> (F, F) {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.inner_product_left_last(ctx, input.0, input.1);
(*a.0.value(), *a.1.value())
}

#[test_case((vec![Witness(Fr::one()); 5], vec![Witness(Fr::one()); 5]) => vec![Fr::one(), Fr::from(2), Fr::from(3), Fr::from(4), Fr::from(5)]; "inner_product_with_sums(): 1 * 1 + ... + 1 * 1 == [1, 2, 3, 4, 5]")]
pub fn test_inner_product_with_sums<F: ScalarField>(
input: (Vec<QuantumCell<F>>, Vec<QuantumCell<F>>),
) -> Vec<F> {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.inner_product_with_sums(ctx, input.0, input.1);
a.into_iter().map(|x| *x.value()).collect()
}

#[test_case((vec![(Fr::from(1), Witness(Fr::from(1)), Witness(Fr::from(1)))], Witness(Fr::from(1))) => Fr::from(2) ; "sum_product_with_coeff_and_var(): 1 * 1 + 1 == 2")]
pub fn test_sum_products_with_coeff_and_var<F: ScalarField>(
input: (Vec<(F, QuantumCell<F>, QuantumCell<F>)>, QuantumCell<F>),
) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.sum_products_with_coeff_and_var(ctx, input.0, input.1);
*a.value()
}

#[test_case(&[1, 1].map(Fr::from).map(Witness) => Fr::from(1) ; "and(): 1 && 1 == 1")]
pub fn test_and<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.and(ctx, inputs[0], inputs[1]);
*a.value()
}

#[test_case(Witness(Fr::from(1)) => Fr::zero() ; "not(): !1 == 0")]
pub fn test_not<F: ScalarField>(a: QuantumCell<F>) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.not(ctx, a);
*a.value()
}

#[test_case(&[2, 3, 1].map(Fr::from).map(Witness) => Fr::from(2) ; "select(): 2 ? 3 : 1 == 2")]
pub fn test_select<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.select(ctx, inputs[0], inputs[1], inputs[2]);
*a.value()
}

#[test_case(&[1, 1, 1].map(Fr::from).map(Witness) => Fr::from(1) ; "or_and(): 1 || 1 && 1 == 1")]
pub fn test_or_and<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.or_and(ctx, inputs[0], inputs[1], inputs[2]);
*a.value()
}

#[test_case(Fr::zero() => vec![Fr::one(), Fr::zero()]; "bits_to_indicator(): 0 -> [1, 0]")]
pub fn test_bits_to_indicator<F: ScalarField>(bits: F) -> Vec<F> {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = ctx.assign_witnesses([bits])[0];
let a = chip.bits_to_indicator(ctx, &[a]);
a.iter().map(|x| *x.value()).collect()
}

#[test_case((Witness(Fr::zero()), 3) => vec![Fr::one(), Fr::zero(), Fr::zero()] ; "idx_to_indicator(): 0 -> [1, 0, 0]")]
pub fn test_idx_to_indicator<F: ScalarField>(input: (QuantumCell<F>, usize)) -> Vec<F> {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.idx_to_indicator(ctx, input.0, input.1);
a.iter().map(|x| *x.value()).collect()
}

#[test_case((vec![Witness(Fr::zero()), Witness(Fr::one()), Witness(Fr::from(2))], Witness(Fr::one())) => Fr::from(1) ; "select_by_indicator(): [0, 1, 2] -> 1")]
pub fn test_select_by_indicator<F: ScalarField>(input: (Vec<QuantumCell<F>>, QuantumCell<F>)) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.idx_to_indicator(ctx, input.1, input.0.len());
let a = chip.select_by_indicator(ctx, input.0, a);
*a.value()
}

#[test_case((vec![Witness(Fr::zero()), Witness(Fr::one()), Witness(Fr::from(2))], Witness(Fr::one())) => Fr::from(1) ; "select_from_idx(): [0, 1, 2] -> 1")]
pub fn test_select_from_idx<F: ScalarField>(input: (Vec<QuantumCell<F>>, QuantumCell<F>)) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.idx_to_indicator(ctx, input.1, input.0.len());
let a = chip.select_by_indicator(ctx, input.0, a);
*a.value()
}

#[test_case(Fr::zero() => Fr::from(1) ; "is_zero(): 0 -> 1")]
pub fn test_is_zero<F: ScalarField>(x: F) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = ctx.assign_witnesses([x])[0];
let a = chip.is_zero(ctx, a);
*a.value()
}

#[test_case(&[1, 1].map(Fr::from).map(Witness) => Fr::one() ; "is_equal(): 1 == 1")]
pub fn test_is_equal<F: ScalarField>(inputs: &[QuantumCell<F>]) -> F {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = chip.is_equal(ctx, inputs[0], inputs[1]);
*a.value()
}

#[test_case((Fr::one(), 2) => vec![Fr::one(), Fr::zero()] ; "num_to_bits(): 1 -> [1, 0]")]
pub fn test_num_to_bits<F: ScalarField>(input: (F, usize)) -> Vec<F> {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let a = ctx.assign_witnesses([input.0])[0];
let a = chip.num_to_bits(ctx, a, input.1);
a.iter().map(|x| *x.value()).collect()
}

#[test_case(&[0, 1, 2].map(Fr::from) => (Fr::one(), Fr::from(2)) ; "lagrange_eval(): constant fn")]
pub fn test_lagrange_eval<F: ScalarField>(input: &[F]) -> (F, F) {
let mut builder = GateThreadBuilder::mock();
let ctx = builder.main(0);
let chip = GateChip::default();
let input = ctx.assign_witnesses(input.iter().copied());
let a = chip.lagrange_and_eval(ctx, &[(input[0], input[1])], input[2]);
(*a.0.value(), *a.1.value())
}

#[test_case(1 => Fr::one(); "inner_product_simple(): 1 -> 1")]
pub fn test_get_field_element<F: ScalarField>(n: u64) -> F {
let chip = GateChip::default();
chip.get_field_element(n)
}
5 changes: 5 additions & 0 deletions halo2-base/src/gates/tests/idx_to_indicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,10 @@ fn test_idx_to_indicator() {
test_idx_to_indicator_gen(8, 4);
test_idx_to_indicator_gen(8, 10);
test_idx_to_indicator_gen(8, 20);
}

#[test]
#[ignore = "takes too long"]
fn test_idx_to_indicator_large() {
test_idx_to_indicator_gen(11, 100);
}
11 changes: 11 additions & 0 deletions halo2-base/src/gates/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(clippy::type_complexity)]
use crate::halo2_proofs::{
halo2curves::bn256::{Bn256, Fr, G1Affine},
plonk::{create_proof, verify_proof, Circuit, ProvingKey, VerifyingKey},
Expand All @@ -12,10 +13,20 @@ use crate::halo2_proofs::{
};
use rand::rngs::OsRng;

#[cfg(test)]
mod flex_gate_tests;
#[cfg(test)]
mod general;
#[cfg(test)]
mod idx_to_indicator;
#[cfg(test)]
mod neg_prop_tests;
#[cfg(test)]
mod pos_prop_tests;
#[cfg(test)]
mod range_gate_tests;
#[cfg(test)]
mod test_ground_truths;

/// helper function to generate a proof with real prover
pub fn gen_proof(
Expand Down
Loading

0 comments on commit a79db0e

Please sign in to comment.