Move u32 stuff to plonky2_u32 crate

This commit is contained in:
wborgeaud 2022-04-06 08:50:45 +02:00
parent 3c6ec8755b
commit b58d5d6747
32 changed files with 448 additions and 363 deletions

View File

@ -1,5 +1,5 @@
[workspace]
members = ["field", "insertion", "plonky2", "starky", "system_zero", "util", "waksman", "ecdsa"]
members = ["field", "insertion", "plonky2", "starky", "system_zero", "util", "waksman", "ecdsa", "plonky2_u32"]
[profile.release]
opt-level = 3

View File

@ -9,6 +9,7 @@ edition = "2021"
plonky2 = { path = "../plonky2" }
plonky2_util = { path = "../util" }
plonky2_field = { path = "../field" }
plonky2_u32 = { path = "../plonky2_u32" }
num = "0.4.0"
itertools = "0.10.0"
rayon = "1.5.1"

View File

@ -1,7 +1,6 @@
use std::marker::PhantomData;
use num::{BigUint, Integer, Zero};
use plonky2::gadgets::arithmetic_u32::U32Target;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
use plonky2::iop::target::{BoolTarget, Target};
@ -9,6 +8,9 @@ use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::PrimeField;
use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target};
use plonky2_u32::gadgets::multiple_comparison::list_le_u32_circuit;
use plonky2_u32::witness::{generated_values_set_u32_target, witness_set_u32_target};
#[derive(Clone, Debug)]
pub struct BigUintTarget {
@ -124,7 +126,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderBiguint<F, D>
fn cmp_biguint(&mut self, a: &BigUintTarget, b: &BigUintTarget) -> BoolTarget {
let (a, b) = self.pad_biguints(a, b);
self.list_le_u32(a.limbs, b.limbs)
list_le_u32_circuit(self, a.limbs, b.limbs)
}
fn add_virtual_biguint_target(&mut self, num_limbs: usize) -> BigUintTarget {
@ -289,7 +291,7 @@ pub fn witness_set_biguint_target<W: Witness<F>, F: PrimeField>(
assert!(target.num_limbs() >= limbs.len());
limbs.resize(target.num_limbs(), 0);
for i in 0..target.num_limbs() {
witness.set_u32_target(target.limbs[i], limbs[i]);
witness_set_u32_target(witness, target.limbs[i], limbs[i]);
}
}
@ -302,7 +304,7 @@ pub fn buffer_set_biguint_target<F: PrimeField>(
assert!(target.num_limbs() >= limbs.len());
limbs.resize(target.num_limbs(), 0);
for i in 0..target.num_limbs() {
buffer.set_u32_target(target.get_limb(i), limbs[i]);
generated_values_set_u32_target(buffer, target.get_limb(i), limbs[i]);
}
}

View File

@ -1,7 +1,6 @@
use std::marker::PhantomData;
use num::BigUint;
use plonky2::gadgets::arithmetic_u32::U32Target;
use plonky2::hash::hash_types::RichField;
use plonky2::hash::keccak::KeccakHash;
use plonky2::iop::target::{BoolTarget, Target};
@ -9,6 +8,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::config::{GenericHashOut, Hasher};
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target};
use crate::curve::curve_types::{Curve, CurveScalar};
use crate::gadgets::biguint::BigUintTarget;

View File

@ -1,7 +1,6 @@
use std::marker::PhantomData;
use num::{BigUint, Integer, One, Zero};
use plonky2::gadgets::arithmetic_u32::U32Target;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
use plonky2::iop::target::{BoolTarget, Target};
@ -9,6 +8,9 @@ use plonky2::iop::witness::PartitionWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2_field::field_types::PrimeField;
use plonky2_field::{extension_field::Extendable, field_types::Field};
use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target};
use plonky2_u32::gadgets::range_check::range_check_u32_circuit;
use plonky2_u32::witness::generated_values_set_u32_target;
use plonky2_util::ceil_div_usize;
use crate::gadgets::biguint::{
@ -249,8 +251,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderNonNative<F, D>
_phantom: PhantomData,
});
self.range_check_u32(sum.value.limbs.clone());
self.range_check_u32(vec![overflow]);
range_check_u32_circuit(self, sum.value.limbs.clone());
range_check_u32_circuit(self, vec![overflow]);
let sum_expected = summands
.iter()
@ -290,7 +292,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderNonNative<F, D>
_phantom: PhantomData,
});
self.range_check_u32(diff.value.limbs.clone());
range_check_u32_circuit(self, diff.value.limbs.clone());
self.assert_bool(overflow);
let diff_plus_b = self.add_biguint(&diff.value, &b.value);
@ -321,8 +323,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderNonNative<F, D>
_phantom: PhantomData,
});
self.range_check_u32(prod.value.limbs.clone());
self.range_check_u32(overflow.limbs.clone());
range_check_u32_circuit(self, prod.value.limbs.clone());
range_check_u32_circuit(self, overflow.limbs.clone());
let prod_expected = self.mul_biguint(&a.value, &b.value);
@ -523,7 +525,7 @@ impl<F: RichField + Extendable<D>, const D: usize, FF: PrimeField> SimpleGenerat
let overflow = overflow_biguint.to_u64_digits()[0] as u32;
buffer_set_biguint_target(out_buffer, &self.sum.value, &sum_reduced);
out_buffer.set_u32_target(self.overflow, overflow);
generated_values_set_u32_target(out_buffer, self.overflow, overflow);
}
}

View File

@ -1,12 +1,12 @@
use std::marker::PhantomData;
use itertools::Itertools;
use plonky2::gadgets::arithmetic_u32::U32Target;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::target::Target;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target};
use crate::gadgets::biguint::BigUintTarget;
use crate::gadgets::nonnative::NonNativeTarget;

View File

@ -13,7 +13,6 @@ default-run = "generate_constants"
[dependencies]
plonky2_field = { path = "../field" }
plonky2_util = { path = "../util" }
array_tool = "1.0.3"
env_logger = "0.9.0"
log = "0.4.14"
itertools = "0.10.0"

View File

@ -1,9 +1,7 @@
pub mod arithmetic;
pub mod arithmetic_extension;
pub mod arithmetic_u32;
pub mod hash;
pub mod interpolation;
pub mod multiple_comparison;
pub mod polynomial;
pub mod random_access;
pub mod range_check;

View File

@ -1,142 +0,0 @@
use plonky2_field::extension_field::Extendable;
use plonky2_util::ceil_div_usize;
use super::arithmetic_u32::U32Target;
use crate::gates::comparison::ComparisonGate;
use crate::hash::hash_types::RichField;
use crate::iop::target::{BoolTarget, Target};
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Returns true if a is less than or equal to b, considered as base-`2^num_bits` limbs of a large value.
/// This range-checks its inputs.
pub fn list_le(&mut self, a: Vec<Target>, b: Vec<Target>, num_bits: usize) -> BoolTarget {
assert_eq!(
a.len(),
b.len(),
"Comparison must be between same number of inputs and outputs"
);
let n = a.len();
let chunk_bits = 2;
let num_chunks = ceil_div_usize(num_bits, chunk_bits);
let one = self.one();
let mut result = one;
for i in 0..n {
let a_le_b_gate = ComparisonGate::new(num_bits, num_chunks);
let a_le_b_gate_index = self.add_gate(a_le_b_gate.clone(), vec![]);
self.connect(
Target::wire(a_le_b_gate_index, a_le_b_gate.wire_first_input()),
a[i],
);
self.connect(
Target::wire(a_le_b_gate_index, a_le_b_gate.wire_second_input()),
b[i],
);
let a_le_b_result = Target::wire(a_le_b_gate_index, a_le_b_gate.wire_result_bool());
let b_le_a_gate = ComparisonGate::new(num_bits, num_chunks);
let b_le_a_gate_index = self.add_gate(b_le_a_gate.clone(), vec![]);
self.connect(
Target::wire(b_le_a_gate_index, b_le_a_gate.wire_first_input()),
b[i],
);
self.connect(
Target::wire(b_le_a_gate_index, b_le_a_gate.wire_second_input()),
a[i],
);
let b_le_a_result = Target::wire(b_le_a_gate_index, b_le_a_gate.wire_result_bool());
let these_limbs_equal = self.mul(a_le_b_result, b_le_a_result);
let these_limbs_less_than = self.sub(one, b_le_a_result);
result = self.mul_add(these_limbs_equal, result, these_limbs_less_than);
}
// `result` being boolean is an invariant, maintained because its new value is always
// `x * result + y`, where `x` and `y` are booleans that are not simultaneously true.
BoolTarget::new_unsafe(result)
}
/// Helper function for comparing, specifically, lists of `U32Target`s.
pub fn list_le_u32(&mut self, a: Vec<U32Target>, b: Vec<U32Target>) -> BoolTarget {
let a_targets: Vec<Target> = a.iter().map(|&t| t.0).collect();
let b_targets: Vec<Target> = b.iter().map(|&t| t.0).collect();
self.list_le(a_targets, b_targets, 32)
}
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use num::BigUint;
use plonky2_field::field_types::Field;
use rand::Rng;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::verifier::verify;
fn test_list_le(size: usize, num_bits: usize) -> Result<()> {
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, D>::new(config);
let mut rng = rand::thread_rng();
let lst1: Vec<u64> = (0..size)
.map(|_| rng.gen_range(0..(1 << num_bits)))
.collect();
let lst2: Vec<u64> = (0..size)
.map(|_| rng.gen_range(0..(1 << num_bits)))
.collect();
let a_biguint = BigUint::from_slice(
&lst1
.iter()
.flat_map(|&x| [x as u32, (x >> 32) as u32])
.collect::<Vec<_>>(),
);
let b_biguint = BigUint::from_slice(
&lst2
.iter()
.flat_map(|&x| [x as u32, (x >> 32) as u32])
.collect::<Vec<_>>(),
);
let a = lst1
.iter()
.map(|&x| builder.constant(F::from_canonical_u64(x)))
.collect();
let b = lst2
.iter()
.map(|&x| builder.constant(F::from_canonical_u64(x)))
.collect();
let result = builder.list_le(a, b, num_bits);
let expected_result = builder.constant_bool(a_biguint <= b_biguint);
builder.connect(result.target, expected_result.target);
let data = builder.build::<C>();
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)
}
#[test]
fn test_multiple_comparison() -> Result<()> {
for size in [1, 3, 6] {
for num_bits in [20, 32, 40, 44] {
test_list_le(size, num_bits).unwrap();
}
}
Ok(())
}
}

View File

@ -1,7 +1,5 @@
use plonky2_field::extension_field::Extendable;
use crate::gadgets::arithmetic_u32::U32Target;
use crate::gates::range_check_u32::U32RangeCheckGate;
use crate::hash::hash_types::RichField;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::{BoolTarget, Target};
@ -44,19 +42,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
(low, high)
}
pub fn range_check_u32(&mut self, vals: Vec<U32Target>) {
let num_input_limbs = vals.len();
let gate = U32RangeCheckGate::<F, D>::new(num_input_limbs);
let gate_index = self.add_gate(gate, vec![]);
for i in 0..num_input_limbs {
self.connect(
Target::wire(gate_index, gate.wire_ith_input_limb(i)),
vals[i].0,
);
}
}
pub fn assert_bool(&mut self, b: BoolTarget) {
let z = self.mul_sub(b.target, b.target, b.target);
let zero = self.zero();

View File

@ -1,13 +1,10 @@
// Gates have `new` methods that return `GateRef`s.
#![allow(clippy::new_ret_no_self)]
pub mod add_many_u32;
pub mod arithmetic_base;
pub mod arithmetic_extension;
pub mod arithmetic_u32;
pub mod assert_le;
pub mod base_sum;
pub mod comparison;
pub mod constant;
pub mod exponentiation;
pub mod gate;
@ -15,17 +12,14 @@ pub mod interpolation;
pub mod low_degree_interpolation;
pub mod multiplication_extension;
pub mod noop;
mod packed_util;
pub mod packed_util;
pub mod poseidon;
pub(crate) mod poseidon_mds;
pub(crate) mod public_input;
pub mod random_access;
pub mod range_check_u32;
pub mod reducing;
pub mod reducing_extension;
pub(crate) mod selectors;
pub mod subtraction_u32;
pub mod switch;
pub mod util;
// Can't use #[cfg(test)] here because it needs to be visible to other crates.

View File

@ -4,7 +4,6 @@ use std::marker::PhantomData;
use plonky2_field::extension_field::{Extendable, FieldExtension};
use plonky2_field::field_types::Field;
use crate::gadgets::arithmetic_u32::U32Target;
use crate::hash::hash_types::{HashOut, HashOutTarget, RichField};
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::target::{BoolTarget, Target};
@ -162,10 +161,6 @@ impl<F: Field> GeneratedValues<F> {
self.set_target(target.target, F::from_bool(value))
}
pub fn set_u32_target(&mut self, target: U32Target, value: u32) {
self.set_target(target.0, F::from_canonical_u32(value))
}
pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut<F>) {
ht.elements
.iter()

View File

@ -6,7 +6,6 @@ use plonky2_field::field_types::Field;
use crate::fri::structure::{FriOpenings, FriOpeningsTarget};
use crate::fri::witness_util::set_fri_proof_target;
use crate::gadgets::arithmetic_u32::U32Target;
use crate::hash::hash_types::HashOutTarget;
use crate::hash::hash_types::RichField;
use crate::hash::hash_types::{HashOut, MerkleCapTarget};
@ -128,10 +127,6 @@ pub trait Witness<F: Field> {
self.set_target(target.target, F::from_bool(value))
}
fn set_u32_target(&mut self, target: U32Target, value: u32) {
self.set_target(target.0, F::from_canonical_u32(value))
}
/// Set the targets in a `ProofWithPublicInputsTarget` to their corresponding values in a
/// `ProofWithPublicInputs`.
fn set_proof_with_pis_target<C: GenericConfig<D, F = F>, const D: usize>(

View File

@ -14,7 +14,6 @@ use crate::fri::oracle::PolynomialBatch;
use crate::fri::{FriConfig, FriParams};
use crate::gadgets::arithmetic::BaseArithmeticOperation;
use crate::gadgets::arithmetic_extension::ExtensionArithmeticOperation;
use crate::gadgets::arithmetic_u32::U32Target;
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
use crate::gates::arithmetic_base::ArithmeticGate;
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
@ -362,11 +361,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
/// Returns a U32Target for the value `c`, which is assumed to be at most 32 bits.
pub fn constant_u32(&mut self, c: u32) -> U32Target {
U32Target(self.constant(F::from_canonical_u32(c)))
}
/// If the given target is a constant (i.e. it was created by the `constant(F)` method), returns
/// its constant value. Otherwise, returns `None`.
pub fn target_as_constant(&self, target: Target) -> Option<F> {

15
plonky2_u32/Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "plonky2_u32"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.40"
rand = "0.8.4"
num = { version = "0.4", features = [ "rand" ] }
itertools = "0.10.0"
plonky2 = { path = "../plonky2" }
plonky2_util = { path = "../util" }
plonky2_field = { path = "../field" }

View File

@ -1,51 +1,104 @@
use std::marker::PhantomData;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
use plonky2::iop::target::Target;
use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2_field::extension_field::Extendable;
use crate::gates::add_many_u32::U32AddManyGate;
use crate::gates::arithmetic_u32::U32ArithmeticGate;
use crate::gates::subtraction_u32::U32SubtractionGate;
use crate::hash::hash_types::RichField;
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::witness::generated_values_set_u32_target;
#[derive(Clone, Copy, Debug)]
pub struct U32Target(pub Target);
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn add_virtual_u32_target(&mut self) -> U32Target {
pub trait CircuitBuilderU32<F: RichField + Extendable<D>, const D: usize> {
fn add_virtual_u32_target(&mut self) -> U32Target;
fn add_virtual_u32_targets(&mut self, n: usize) -> Vec<U32Target>;
/// Returns a U32Target for the value `c`, which is assumed to be at most 32 bits.
fn constant_u32(&mut self, c: u32) -> U32Target;
fn zero_u32(&mut self) -> U32Target;
fn one_u32(&mut self) -> U32Target;
fn connect_u32(&mut self, x: U32Target, y: U32Target);
fn assert_zero_u32(&mut self, x: U32Target);
/// Checks for special cases where the value of
/// `x * y + z`
/// can be determined without adding a `U32ArithmeticGate`.
fn arithmetic_u32_special_cases(
&mut self,
x: U32Target,
y: U32Target,
z: U32Target,
) -> Option<(U32Target, U32Target)>;
// Returns x * y + z.
fn mul_add_u32(&mut self, x: U32Target, y: U32Target, z: U32Target) -> (U32Target, U32Target);
fn add_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target);
fn add_many_u32(&mut self, to_add: &[U32Target]) -> (U32Target, U32Target);
fn add_u32s_with_carry(
&mut self,
to_add: &[U32Target],
carry: U32Target,
) -> (U32Target, U32Target);
fn mul_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target);
// Returns x - y - borrow, as a pair (result, borrow), where borrow is 0 or 1 depending on whether borrowing from the next digit is required (iff y + borrow > x).
fn sub_u32(&mut self, x: U32Target, y: U32Target, borrow: U32Target) -> (U32Target, U32Target);
}
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderU32<F, D>
for CircuitBuilder<F, D>
{
fn add_virtual_u32_target(&mut self) -> U32Target {
U32Target(self.add_virtual_target())
}
pub fn add_virtual_u32_targets(&mut self, n: usize) -> Vec<U32Target> {
fn add_virtual_u32_targets(&mut self, n: usize) -> Vec<U32Target> {
self.add_virtual_targets(n)
.into_iter()
.map(U32Target)
.collect()
}
pub fn zero_u32(&mut self) -> U32Target {
/// Returns a U32Target for the value `c`, which is assumed to be at most 32 bits.
fn constant_u32(&mut self, c: u32) -> U32Target {
U32Target(self.constant(F::from_canonical_u32(c)))
}
fn zero_u32(&mut self) -> U32Target {
U32Target(self.zero())
}
pub fn one_u32(&mut self) -> U32Target {
fn one_u32(&mut self) -> U32Target {
U32Target(self.one())
}
pub fn connect_u32(&mut self, x: U32Target, y: U32Target) {
fn connect_u32(&mut self, x: U32Target, y: U32Target) {
self.connect(x.0, y.0)
}
pub fn assert_zero_u32(&mut self, x: U32Target) {
fn assert_zero_u32(&mut self, x: U32Target) {
self.assert_zero(x.0)
}
/// Checks for special cases where the value of
/// `x * y + z`
/// can be determined without adding a `U32ArithmeticGate`.
pub fn arithmetic_u32_special_cases(
fn arithmetic_u32_special_cases(
&mut self,
x: U32Target,
y: U32Target,
@ -72,12 +125,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
// Returns x * y + z.
pub fn mul_add_u32(
&mut self,
x: U32Target,
y: U32Target,
z: U32Target,
) -> (U32Target, U32Target) {
fn mul_add_u32(&mut self, x: U32Target, y: U32Target, z: U32Target) -> (U32Target, U32Target) {
if let Some(result) = self.arithmetic_u32_special_cases(x, y, z) {
return result;
}
@ -107,12 +155,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
(output_low, output_high)
}
pub fn add_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target) {
fn add_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target) {
let one = self.one_u32();
self.mul_add_u32(a, one, b)
}
pub fn add_many_u32(&mut self, to_add: &[U32Target]) -> (U32Target, U32Target) {
fn add_many_u32(&mut self, to_add: &[U32Target]) -> (U32Target, U32Target) {
match to_add.len() {
0 => (self.zero_u32(), self.zero_u32()),
1 => (to_add[0], self.zero_u32()),
@ -142,7 +190,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
pub fn add_u32s_with_carry(
fn add_u32s_with_carry(
&mut self,
to_add: &[U32Target],
carry: U32Target,
@ -170,18 +218,13 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
(output, output_carry)
}
pub fn mul_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target) {
fn mul_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target) {
let zero = self.zero_u32();
self.mul_add_u32(a, b, zero)
}
// Returns x - y - borrow, as a pair (result, borrow), where borrow is 0 or 1 depending on whether borrowing from the next digit is required (iff y + borrow > x).
pub fn sub_u32(
&mut self,
x: U32Target,
y: U32Target,
borrow: U32Target,
) -> (U32Target, U32Target) {
fn sub_u32(&mut self, x: U32Target, y: U32Target, borrow: U32Target) -> (U32Target, U32Target) {
let gate = U32SubtractionGate::<F, D>::new_from_config(&self.config);
let (gate_index, copy) = self.find_slot(gate, &[], &[]);
@ -220,21 +263,21 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
let low = x_u64 as u32;
let high = (x_u64 >> 32) as u32;
out_buffer.set_u32_target(self.low, low);
out_buffer.set_u32_target(self.high, high);
generated_values_set_u32_target(out_buffer, self.low, low);
generated_values_set_u32_target(out_buffer, self.high, high);
}
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use rand::{thread_rng, Rng};
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::verifier::verify;
use crate::gadgets::arithmetic_u32::CircuitBuilderU32;
#[test]
pub fn test_add_many_u32s() -> Result<()> {
@ -267,6 +310,6 @@ mod tests {
let data = builder.build::<C>();
let proof = data.prove(pw).unwrap();
verify(proof, &data.verifier_only, &data.common)
data.verify(proof)
}
}

View File

@ -0,0 +1,3 @@
pub mod arithmetic_u32;
pub mod multiple_comparison;
pub mod range_check;

View File

@ -0,0 +1,149 @@
use plonky2::hash::hash_types::RichField;
use plonky2::iop::target::{BoolTarget, Target};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2_field::extension_field::Extendable;
use plonky2_util::ceil_div_usize;
use super::arithmetic_u32::U32Target;
use crate::gates::comparison::ComparisonGate;
/// Returns true if a is less than or equal to b, considered as base-`2^num_bits` limbs of a large value.
/// This range-checks its inputs.
pub fn list_le_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
a: Vec<Target>,
b: Vec<Target>,
num_bits: usize,
) -> BoolTarget {
assert_eq!(
a.len(),
b.len(),
"Comparison must be between same number of inputs and outputs"
);
let n = a.len();
let chunk_bits = 2;
let num_chunks = ceil_div_usize(num_bits, chunk_bits);
let one = builder.one();
let mut result = one;
for i in 0..n {
let a_le_b_gate = ComparisonGate::new(num_bits, num_chunks);
let a_le_b_gate_index = builder.add_gate(a_le_b_gate.clone(), vec![]);
builder.connect(
Target::wire(a_le_b_gate_index, a_le_b_gate.wire_first_input()),
a[i],
);
builder.connect(
Target::wire(a_le_b_gate_index, a_le_b_gate.wire_second_input()),
b[i],
);
let a_le_b_result = Target::wire(a_le_b_gate_index, a_le_b_gate.wire_result_bool());
let b_le_a_gate = ComparisonGate::new(num_bits, num_chunks);
let b_le_a_gate_index = builder.add_gate(b_le_a_gate.clone(), vec![]);
builder.connect(
Target::wire(b_le_a_gate_index, b_le_a_gate.wire_first_input()),
b[i],
);
builder.connect(
Target::wire(b_le_a_gate_index, b_le_a_gate.wire_second_input()),
a[i],
);
let b_le_a_result = Target::wire(b_le_a_gate_index, b_le_a_gate.wire_result_bool());
let these_limbs_equal = builder.mul(a_le_b_result, b_le_a_result);
let these_limbs_less_than = builder.sub(one, b_le_a_result);
result = builder.mul_add(these_limbs_equal, result, these_limbs_less_than);
}
// `result` being boolean is an invariant, maintained because its new value is always
// `x * result + y`, where `x` and `y` are booleans that are not simultaneously true.
BoolTarget::new_unsafe(result)
}
/// Helper function for comparing, specifically, lists of `U32Target`s.
pub fn list_le_u32_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
a: Vec<U32Target>,
b: Vec<U32Target>,
) -> BoolTarget {
let a_targets: Vec<Target> = a.iter().map(|&t| t.0).collect();
let b_targets: Vec<Target> = b.iter().map(|&t| t.0).collect();
list_le_circuit(builder, a_targets, b_targets, 32)
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use num::BigUint;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use plonky2_field::field_types::Field;
use rand::Rng;
use crate::gadgets::multiple_comparison::list_le_circuit;
fn test_list_le(size: usize, num_bits: usize) -> Result<()> {
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
let config = CircuitConfig::standard_recursion_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, D>::new(config);
let mut rng = rand::thread_rng();
let lst1: Vec<u64> = (0..size)
.map(|_| rng.gen_range(0..(1 << num_bits)))
.collect();
let lst2: Vec<u64> = (0..size)
.map(|_| rng.gen_range(0..(1 << num_bits)))
.collect();
let a_biguint = BigUint::from_slice(
&lst1
.iter()
.flat_map(|&x| [x as u32, (x >> 32) as u32])
.collect::<Vec<_>>(),
);
let b_biguint = BigUint::from_slice(
&lst2
.iter()
.flat_map(|&x| [x as u32, (x >> 32) as u32])
.collect::<Vec<_>>(),
);
let a = lst1
.iter()
.map(|&x| builder.constant(F::from_canonical_u64(x)))
.collect();
let b = lst2
.iter()
.map(|&x| builder.constant(F::from_canonical_u64(x)))
.collect();
let result = list_le_circuit(&mut builder, a, b, num_bits);
let expected_result = builder.constant_bool(a_biguint <= b_biguint);
builder.connect(result.target, expected_result.target);
let data = builder.build::<C>();
let proof = data.prove(pw).unwrap();
data.verify(proof)
}
#[test]
fn test_multiple_comparison() -> Result<()> {
for size in [1, 3, 6] {
for num_bits in [20, 32, 40, 44] {
test_list_le(size, num_bits).unwrap();
}
}
Ok(())
}
}

View File

@ -0,0 +1,23 @@
use plonky2::hash::hash_types::RichField;
use plonky2::iop::target::Target;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2_field::extension_field::Extendable;
use crate::gadgets::arithmetic_u32::U32Target;
use crate::gates::range_check_u32::U32RangeCheckGate;
pub fn range_check_u32_circuit<F: RichField + Extendable<D>, const D: usize>(
builder: &mut CircuitBuilder<F, D>,
vals: Vec<U32Target>,
) {
let num_input_limbs = vals.len();
let gate = U32RangeCheckGate::<F, D>::new(num_input_limbs);
let gate_index = builder.add_gate(gate, vec![]);
for i in 0..num_input_limbs {
builder.connect(
Target::wire(gate_index, gate.wire_ith_input_limb(i)),
vals[i].0,
);
}
}

View File

@ -1,22 +1,21 @@
use std::marker::PhantomData;
use itertools::unfold;
use plonky2::gates::gate::Gate;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::target::Target;
use plonky2::iop::wire::Wire;
use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_util::ceil_div_usize;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
const LOG2_MAX_NUM_ADDENDS: usize = 4;
const MAX_NUM_ADDENDS: usize = 16;
@ -349,17 +348,17 @@ mod tests {
use anyhow::Result;
use itertools::unfold;
use plonky2::gates::gate::Gate;
use plonky2::gates::gate_testing::{test_eval_fns, test_low_degree};
use plonky2::hash::hash_types::HashOut;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use plonky2::plonk::vars::EvaluationVars;
use plonky2_field::extension_field::quartic::QuarticExtension;
use plonky2_field::field_types::Field;
use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::field::goldilocks_field::GoldilocksField;
use crate::gates::add_many_u32::U32AddManyGate;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::hash::hash_types::HashOut;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::vars::EvaluationVars;
#[test]
fn low_degree() {

View File

@ -1,25 +1,24 @@
use std::marker::PhantomData;
use itertools::unfold;
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_field::packed_field::PackedField;
use crate::gates::gate::Gate;
use crate::gates::packed_util::PackedEvaluableBase;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::vars::{
use plonky2::gates::gate::Gate;
use plonky2::gates::packed_util::PackedEvaluableBase;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::target::Target;
use plonky2::iop::wire::Wire;
use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked,
};
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_field::packed_field::PackedField;
/// A gate to perform a basic mul-add on 32-bit values (we assume they are range-checked beforehand).
#[derive(Copy, Clone, Debug)]
@ -349,16 +348,16 @@ mod tests {
use std::marker::PhantomData;
use anyhow::Result;
use plonky2::gates::gate::Gate;
use plonky2::gates::gate_testing::{test_eval_fns, test_low_degree};
use plonky2::hash::hash_types::HashOut;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use plonky2::plonk::vars::EvaluationVars;
use plonky2_field::field_types::Field;
use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;
use crate::gates::arithmetic_u32::U32ArithmeticGate;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::hash::hash_types::HashOut;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::vars::EvaluationVars;
#[test]
fn low_degree() {

View File

@ -1,26 +1,25 @@
use std::marker::PhantomData;
use plonky2::gates::gate::Gate;
use plonky2::gates::packed_util::PackedEvaluableBase;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::target::Target;
use plonky2::iop::wire::Wire;
use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_recursive};
use plonky2::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked,
};
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::{Field, Field64};
use plonky2_field::packed_field::PackedField;
use plonky2_util::{bits_u64, ceil_div_usize};
use crate::gates::gate::Gate;
use crate::gates::packed_util::PackedEvaluableBase;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_recursive};
use crate::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked,
};
/// A gate for checking that one value is less than or equal to another.
#[derive(Clone, Debug)]
pub struct ComparisonGate<F: Field64 + Extendable<D>, const D: usize> {
@ -520,17 +519,17 @@ mod tests {
use std::marker::PhantomData;
use anyhow::Result;
use plonky2::gates::gate::Gate;
use plonky2::gates::gate_testing::{test_eval_fns, test_low_degree};
use plonky2::hash::hash_types::HashOut;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use plonky2::plonk::vars::EvaluationVars;
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField64;
use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;
use crate::gates::comparison::ComparisonGate;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::hash::hash_types::HashOut;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::vars::EvaluationVars;
#[test]
fn wire_indices() {

View File

@ -0,0 +1,5 @@
pub mod add_many_u32;
pub mod arithmetic_u32;
pub mod comparison;
pub mod range_check_u32;
pub mod subtraction_u32;

View File

@ -1,20 +1,19 @@
use std::marker::PhantomData;
use plonky2::gates::gate::Gate;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::target::Target;
use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_recursive};
use plonky2::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_util::ceil_div_usize;
use crate::field::extension_field::Extendable;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_recursive};
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
/// A gate which can decompose a number into base B little-endian limbs.
#[derive(Copy, Clone, Debug)]
pub struct U32RangeCheckGate<F: RichField + Extendable<D>, const D: usize> {
@ -220,18 +219,18 @@ mod tests {
use anyhow::Result;
use itertools::unfold;
use plonky2::gates::gate::Gate;
use plonky2::gates::gate_testing::{test_eval_fns, test_low_degree};
use plonky2::hash::hash_types::HashOut;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use plonky2::plonk::vars::EvaluationVars;
use plonky2_field::extension_field::quartic::QuarticExtension;
use plonky2_field::field_types::Field;
use plonky2_field::goldilocks_field::GoldilocksField;
use plonky2_util::ceil_div_usize;
use rand::Rng;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::field::goldilocks_field::GoldilocksField;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::gates::range_check_u32::U32RangeCheckGate;
use crate::hash::hash_types::HashOut;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::vars::EvaluationVars;
#[test]
fn low_degree() {

View File

@ -1,24 +1,23 @@
use std::marker::PhantomData;
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_field::packed_field::PackedField;
use crate::gates::gate::Gate;
use crate::gates::packed_util::PackedEvaluableBase;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::vars::{
use plonky2::gates::gate::Gate;
use plonky2::gates::packed_util::PackedEvaluableBase;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
use plonky2::iop::target::Target;
use plonky2::iop::wire::Wire;
use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked,
};
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_field::packed_field::PackedField;
/// A gate to perform a subtraction on 32-bit limbs: given `x`, `y`, and `borrow`, it returns
/// the result `x - y - borrow` and, if this underflows, a new `borrow`. Inputs are not range-checked.
@ -337,18 +336,18 @@ mod tests {
use std::marker::PhantomData;
use anyhow::Result;
use plonky2::gates::gate::Gate;
use plonky2::gates::gate_testing::{test_eval_fns, test_low_degree};
use plonky2::hash::hash_types::HashOut;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use plonky2::plonk::vars::EvaluationVars;
use plonky2_field::extension_field::quartic::QuarticExtension;
use plonky2_field::field_types::Field;
use plonky2_field::field_types::PrimeField64;
use plonky2_field::goldilocks_field::GoldilocksField;
use rand::Rng;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::gates::subtraction_u32::U32SubtractionGate;
use crate::hash::hash_types::HashOut;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::vars::EvaluationVars;
#[test]
fn low_degree() {

5
plonky2_u32/src/lib.rs Normal file
View File

@ -0,0 +1,5 @@
#![allow(clippy::needless_range_loop)]
pub mod gadgets;
pub mod gates;
pub mod witness;

View File

@ -0,0 +1,21 @@
use plonky2::iop::generator::GeneratedValues;
use plonky2::iop::witness::Witness;
use plonky2_field::field_types::Field;
use crate::gadgets::arithmetic_u32::U32Target;
pub fn generated_values_set_u32_target<F: Field>(
buffer: &mut GeneratedValues<F>,
target: U32Target,
value: u32,
) {
buffer.set_target(target.0, F::from_canonical_u32(value))
}
pub fn witness_set_u32_target<W: Witness<F>, F: Field>(
witness: &mut W,
target: U32Target,
value: u32,
) {
witness.set_target(target.0, F::from_canonical_u32(value))
}

View File

@ -6,8 +6,10 @@ edition = "2021"
[dependencies]
"plonky2" = { path = "../plonky2" }
"plonky2_field" = { path = "../field" }
"plonky2_util" = { path = "../util" }
anyhow = "1.0.40"
bimap = "0.6.1"
itertools = "0.10.0"
rand = "0.8.4"
array_tool = "1.0.3"

1
waksman/src/gates/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod switch;

View File

@ -1,25 +1,24 @@
use std::marker::PhantomData;
use array_tool::vec::Union;
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_field::packed_field::PackedField;
use crate::gates::gate::Gate;
use crate::gates::packed_util::PackedEvaluableBase;
use crate::gates::util::StridedConstraintConsumer;
use crate::hash::hash_types::RichField;
use crate::iop::ext_target::ExtensionTarget;
use crate::iop::generator::{GeneratedValues, WitnessGenerator};
use crate::iop::target::Target;
use crate::iop::wire::Wire;
use crate::iop::witness::{PartitionWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::vars::{
use plonky2::gates::gate::Gate;
use plonky2::gates::packed_util::PackedEvaluableBase;
use plonky2::gates::util::StridedConstraintConsumer;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::iop::generator::{GeneratedValues, WitnessGenerator};
use plonky2::iop::target::Target;
use plonky2::iop::wire::Wire;
use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::vars::{
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
EvaluationVarsBasePacked,
};
use plonky2_field::extension_field::Extendable;
use plonky2_field::field_types::Field;
use plonky2_field::packed_field::PackedField;
/// A gate for conditionally swapping input values based on a boolean.
#[derive(Copy, Clone, Debug)]
@ -332,16 +331,16 @@ mod tests {
use std::marker::PhantomData;
use anyhow::Result;
use plonky2::gates::gate::Gate;
use plonky2::gates::gate_testing::{test_eval_fns, test_low_degree};
use plonky2::hash::hash_types::HashOut;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use plonky2::plonk::vars::EvaluationVars;
use plonky2_field::field_types::Field;
use plonky2_field::goldilocks_field::GoldilocksField;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
use crate::gates::switch::SwitchGate;
use crate::hash::hash_types::HashOut;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
use crate::plonk::vars::EvaluationVars;
#[test]
fn wire_indices() {

View File

@ -6,5 +6,6 @@
#![allow(clippy::return_self_not_must_use)]
pub mod bimap;
pub mod gates;
pub mod permutation;
pub mod sorting;

View File

@ -2,7 +2,6 @@ use std::collections::BTreeMap;
use std::marker::PhantomData;
use plonky2::field::{extension_field::Extendable, field_types::Field};
use plonky2::gates::switch::SwitchGate;
use plonky2::hash::hash_types::RichField;
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
use plonky2::iop::target::Target;
@ -10,6 +9,7 @@ use plonky2::iop::witness::{PartitionWitness, Witness};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use crate::bimap::bimap_from_lists;
use crate::gates::switch::SwitchGate;
/// Assert that two lists of expressions evaluate to permutations of one another.
pub fn assert_permutation<F: RichField + Extendable<D>, const D: usize>(