mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
Move u32 stuff to plonky2_u32 crate
This commit is contained in:
parent
3c6ec8755b
commit
b58d5d6747
@ -1,5 +1,5 @@
|
|||||||
[workspace]
|
[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]
|
[profile.release]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|||||||
@ -9,6 +9,7 @@ edition = "2021"
|
|||||||
plonky2 = { path = "../plonky2" }
|
plonky2 = { path = "../plonky2" }
|
||||||
plonky2_util = { path = "../util" }
|
plonky2_util = { path = "../util" }
|
||||||
plonky2_field = { path = "../field" }
|
plonky2_field = { path = "../field" }
|
||||||
|
plonky2_u32 = { path = "../plonky2_u32" }
|
||||||
num = "0.4.0"
|
num = "0.4.0"
|
||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use num::{BigUint, Integer, Zero};
|
use num::{BigUint, Integer, Zero};
|
||||||
use plonky2::gadgets::arithmetic_u32::U32Target;
|
|
||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::RichField;
|
||||||
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||||
use plonky2::iop::target::{BoolTarget, Target};
|
use plonky2::iop::target::{BoolTarget, Target};
|
||||||
@ -9,6 +8,9 @@ use plonky2::iop::witness::{PartitionWitness, Witness};
|
|||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use plonky2_field::extension_field::Extendable;
|
use plonky2_field::extension_field::Extendable;
|
||||||
use plonky2_field::field_types::PrimeField;
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BigUintTarget {
|
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 {
|
fn cmp_biguint(&mut self, a: &BigUintTarget, b: &BigUintTarget) -> BoolTarget {
|
||||||
let (a, b) = self.pad_biguints(a, b);
|
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 {
|
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());
|
assert!(target.num_limbs() >= limbs.len());
|
||||||
limbs.resize(target.num_limbs(), 0);
|
limbs.resize(target.num_limbs(), 0);
|
||||||
for i in 0..target.num_limbs() {
|
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());
|
assert!(target.num_limbs() >= limbs.len());
|
||||||
limbs.resize(target.num_limbs(), 0);
|
limbs.resize(target.num_limbs(), 0);
|
||||||
for i in 0..target.num_limbs() {
|
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use num::BigUint;
|
use num::BigUint;
|
||||||
use plonky2::gadgets::arithmetic_u32::U32Target;
|
|
||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::RichField;
|
||||||
use plonky2::hash::keccak::KeccakHash;
|
use plonky2::hash::keccak::KeccakHash;
|
||||||
use plonky2::iop::target::{BoolTarget, Target};
|
use plonky2::iop::target::{BoolTarget, Target};
|
||||||
@ -9,6 +8,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
|
|||||||
use plonky2::plonk::config::{GenericHashOut, Hasher};
|
use plonky2::plonk::config::{GenericHashOut, Hasher};
|
||||||
use plonky2_field::extension_field::Extendable;
|
use plonky2_field::extension_field::Extendable;
|
||||||
use plonky2_field::field_types::Field;
|
use plonky2_field::field_types::Field;
|
||||||
|
use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target};
|
||||||
|
|
||||||
use crate::curve::curve_types::{Curve, CurveScalar};
|
use crate::curve::curve_types::{Curve, CurveScalar};
|
||||||
use crate::gadgets::biguint::BigUintTarget;
|
use crate::gadgets::biguint::BigUintTarget;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use num::{BigUint, Integer, One, Zero};
|
use num::{BigUint, Integer, One, Zero};
|
||||||
use plonky2::gadgets::arithmetic_u32::U32Target;
|
|
||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::RichField;
|
||||||
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||||
use plonky2::iop::target::{BoolTarget, Target};
|
use plonky2::iop::target::{BoolTarget, Target};
|
||||||
@ -9,6 +8,9 @@ use plonky2::iop::witness::PartitionWitness;
|
|||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use plonky2_field::field_types::PrimeField;
|
use plonky2_field::field_types::PrimeField;
|
||||||
use plonky2_field::{extension_field::Extendable, field_types::Field};
|
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 plonky2_util::ceil_div_usize;
|
||||||
|
|
||||||
use crate::gadgets::biguint::{
|
use crate::gadgets::biguint::{
|
||||||
@ -249,8 +251,8 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderNonNative<F, D>
|
|||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.range_check_u32(sum.value.limbs.clone());
|
range_check_u32_circuit(self, sum.value.limbs.clone());
|
||||||
self.range_check_u32(vec![overflow]);
|
range_check_u32_circuit(self, vec![overflow]);
|
||||||
|
|
||||||
let sum_expected = summands
|
let sum_expected = summands
|
||||||
.iter()
|
.iter()
|
||||||
@ -290,7 +292,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderNonNative<F, D>
|
|||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.range_check_u32(diff.value.limbs.clone());
|
range_check_u32_circuit(self, diff.value.limbs.clone());
|
||||||
self.assert_bool(overflow);
|
self.assert_bool(overflow);
|
||||||
|
|
||||||
let diff_plus_b = self.add_biguint(&diff.value, &b.value);
|
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,
|
_phantom: PhantomData,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.range_check_u32(prod.value.limbs.clone());
|
range_check_u32_circuit(self, prod.value.limbs.clone());
|
||||||
self.range_check_u32(overflow.limbs.clone());
|
range_check_u32_circuit(self, overflow.limbs.clone());
|
||||||
|
|
||||||
let prod_expected = self.mul_biguint(&a.value, &b.value);
|
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;
|
let overflow = overflow_biguint.to_u64_digits()[0] as u32;
|
||||||
|
|
||||||
buffer_set_biguint_target(out_buffer, &self.sum.value, &sum_reduced);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use plonky2::gadgets::arithmetic_u32::U32Target;
|
|
||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::RichField;
|
||||||
use plonky2::iop::target::Target;
|
use plonky2::iop::target::Target;
|
||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use plonky2_field::extension_field::Extendable;
|
use plonky2_field::extension_field::Extendable;
|
||||||
use plonky2_field::field_types::Field;
|
use plonky2_field::field_types::Field;
|
||||||
|
use plonky2_u32::gadgets::arithmetic_u32::{CircuitBuilderU32, U32Target};
|
||||||
|
|
||||||
use crate::gadgets::biguint::BigUintTarget;
|
use crate::gadgets::biguint::BigUintTarget;
|
||||||
use crate::gadgets::nonnative::NonNativeTarget;
|
use crate::gadgets::nonnative::NonNativeTarget;
|
||||||
|
|||||||
@ -13,7 +13,6 @@ default-run = "generate_constants"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
plonky2_field = { path = "../field" }
|
plonky2_field = { path = "../field" }
|
||||||
plonky2_util = { path = "../util" }
|
plonky2_util = { path = "../util" }
|
||||||
array_tool = "1.0.3"
|
|
||||||
env_logger = "0.9.0"
|
env_logger = "0.9.0"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
pub mod arithmetic;
|
pub mod arithmetic;
|
||||||
pub mod arithmetic_extension;
|
pub mod arithmetic_extension;
|
||||||
pub mod arithmetic_u32;
|
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
pub mod interpolation;
|
pub mod interpolation;
|
||||||
pub mod multiple_comparison;
|
|
||||||
pub mod polynomial;
|
pub mod polynomial;
|
||||||
pub mod random_access;
|
pub mod random_access;
|
||||||
pub mod range_check;
|
pub mod range_check;
|
||||||
|
|||||||
@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,7 +1,5 @@
|
|||||||
use plonky2_field::extension_field::Extendable;
|
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::hash::hash_types::RichField;
|
||||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||||
use crate::iop::target::{BoolTarget, Target};
|
use crate::iop::target::{BoolTarget, Target};
|
||||||
@ -44,19 +42,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
(low, high)
|
(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) {
|
pub fn assert_bool(&mut self, b: BoolTarget) {
|
||||||
let z = self.mul_sub(b.target, b.target, b.target);
|
let z = self.mul_sub(b.target, b.target, b.target);
|
||||||
let zero = self.zero();
|
let zero = self.zero();
|
||||||
|
|||||||
@ -1,13 +1,10 @@
|
|||||||
// Gates have `new` methods that return `GateRef`s.
|
// Gates have `new` methods that return `GateRef`s.
|
||||||
#![allow(clippy::new_ret_no_self)]
|
#![allow(clippy::new_ret_no_self)]
|
||||||
|
|
||||||
pub mod add_many_u32;
|
|
||||||
pub mod arithmetic_base;
|
pub mod arithmetic_base;
|
||||||
pub mod arithmetic_extension;
|
pub mod arithmetic_extension;
|
||||||
pub mod arithmetic_u32;
|
|
||||||
pub mod assert_le;
|
pub mod assert_le;
|
||||||
pub mod base_sum;
|
pub mod base_sum;
|
||||||
pub mod comparison;
|
|
||||||
pub mod constant;
|
pub mod constant;
|
||||||
pub mod exponentiation;
|
pub mod exponentiation;
|
||||||
pub mod gate;
|
pub mod gate;
|
||||||
@ -15,17 +12,14 @@ pub mod interpolation;
|
|||||||
pub mod low_degree_interpolation;
|
pub mod low_degree_interpolation;
|
||||||
pub mod multiplication_extension;
|
pub mod multiplication_extension;
|
||||||
pub mod noop;
|
pub mod noop;
|
||||||
mod packed_util;
|
pub mod packed_util;
|
||||||
pub mod poseidon;
|
pub mod poseidon;
|
||||||
pub(crate) mod poseidon_mds;
|
pub(crate) mod poseidon_mds;
|
||||||
pub(crate) mod public_input;
|
pub(crate) mod public_input;
|
||||||
pub mod random_access;
|
pub mod random_access;
|
||||||
pub mod range_check_u32;
|
|
||||||
pub mod reducing;
|
pub mod reducing;
|
||||||
pub mod reducing_extension;
|
pub mod reducing_extension;
|
||||||
pub(crate) mod selectors;
|
pub(crate) mod selectors;
|
||||||
pub mod subtraction_u32;
|
|
||||||
pub mod switch;
|
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
// Can't use #[cfg(test)] here because it needs to be visible to other crates.
|
// Can't use #[cfg(test)] here because it needs to be visible to other crates.
|
||||||
|
|||||||
@ -4,7 +4,6 @@ use std::marker::PhantomData;
|
|||||||
use plonky2_field::extension_field::{Extendable, FieldExtension};
|
use plonky2_field::extension_field::{Extendable, FieldExtension};
|
||||||
use plonky2_field::field_types::Field;
|
use plonky2_field::field_types::Field;
|
||||||
|
|
||||||
use crate::gadgets::arithmetic_u32::U32Target;
|
|
||||||
use crate::hash::hash_types::{HashOut, HashOutTarget, RichField};
|
use crate::hash::hash_types::{HashOut, HashOutTarget, RichField};
|
||||||
use crate::iop::ext_target::ExtensionTarget;
|
use crate::iop::ext_target::ExtensionTarget;
|
||||||
use crate::iop::target::{BoolTarget, Target};
|
use crate::iop::target::{BoolTarget, Target};
|
||||||
@ -162,10 +161,6 @@ impl<F: Field> GeneratedValues<F> {
|
|||||||
self.set_target(target.target, F::from_bool(value))
|
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>) {
|
pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut<F>) {
|
||||||
ht.elements
|
ht.elements
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@ -6,7 +6,6 @@ use plonky2_field::field_types::Field;
|
|||||||
|
|
||||||
use crate::fri::structure::{FriOpenings, FriOpeningsTarget};
|
use crate::fri::structure::{FriOpenings, FriOpeningsTarget};
|
||||||
use crate::fri::witness_util::set_fri_proof_target;
|
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::HashOutTarget;
|
||||||
use crate::hash::hash_types::RichField;
|
use crate::hash::hash_types::RichField;
|
||||||
use crate::hash::hash_types::{HashOut, MerkleCapTarget};
|
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))
|
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
|
/// Set the targets in a `ProofWithPublicInputsTarget` to their corresponding values in a
|
||||||
/// `ProofWithPublicInputs`.
|
/// `ProofWithPublicInputs`.
|
||||||
fn set_proof_with_pis_target<C: GenericConfig<D, F = F>, const D: usize>(
|
fn set_proof_with_pis_target<C: GenericConfig<D, F = F>, const D: usize>(
|
||||||
|
|||||||
@ -14,7 +14,6 @@ use crate::fri::oracle::PolynomialBatch;
|
|||||||
use crate::fri::{FriConfig, FriParams};
|
use crate::fri::{FriConfig, FriParams};
|
||||||
use crate::gadgets::arithmetic::BaseArithmeticOperation;
|
use crate::gadgets::arithmetic::BaseArithmeticOperation;
|
||||||
use crate::gadgets::arithmetic_extension::ExtensionArithmeticOperation;
|
use crate::gadgets::arithmetic_extension::ExtensionArithmeticOperation;
|
||||||
use crate::gadgets::arithmetic_u32::U32Target;
|
|
||||||
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
|
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
|
||||||
use crate::gates::arithmetic_base::ArithmeticGate;
|
use crate::gates::arithmetic_base::ArithmeticGate;
|
||||||
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
|
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
|
/// If the given target is a constant (i.e. it was created by the `constant(F)` method), returns
|
||||||
/// its constant value. Otherwise, returns `None`.
|
/// its constant value. Otherwise, returns `None`.
|
||||||
pub fn target_as_constant(&self, target: Target) -> Option<F> {
|
pub fn target_as_constant(&self, target: Target) -> Option<F> {
|
||||||
|
|||||||
15
plonky2_u32/Cargo.toml
Normal file
15
plonky2_u32/Cargo.toml
Normal 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" }
|
||||||
@ -1,51 +1,104 @@
|
|||||||
use std::marker::PhantomData;
|
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 plonky2_field::extension_field::Extendable;
|
||||||
|
|
||||||
use crate::gates::add_many_u32::U32AddManyGate;
|
use crate::gates::add_many_u32::U32AddManyGate;
|
||||||
use crate::gates::arithmetic_u32::U32ArithmeticGate;
|
use crate::gates::arithmetic_u32::U32ArithmeticGate;
|
||||||
use crate::gates::subtraction_u32::U32SubtractionGate;
|
use crate::gates::subtraction_u32::U32SubtractionGate;
|
||||||
use crate::hash::hash_types::RichField;
|
use crate::witness::generated_values_set_u32_target;
|
||||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
|
||||||
use crate::iop::target::Target;
|
|
||||||
use crate::iop::witness::{PartitionWitness, Witness};
|
|
||||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct U32Target(pub Target);
|
pub struct U32Target(pub Target);
|
||||||
|
|
||||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
pub trait CircuitBuilderU32<F: RichField + Extendable<D>, const D: usize> {
|
||||||
pub fn add_virtual_u32_target(&mut self) -> U32Target {
|
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())
|
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)
|
self.add_virtual_targets(n)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(U32Target)
|
.map(U32Target)
|
||||||
.collect()
|
.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())
|
U32Target(self.zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn one_u32(&mut self) -> U32Target {
|
fn one_u32(&mut self) -> U32Target {
|
||||||
U32Target(self.one())
|
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)
|
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)
|
self.assert_zero(x.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks for special cases where the value of
|
/// Checks for special cases where the value of
|
||||||
/// `x * y + z`
|
/// `x * y + z`
|
||||||
/// can be determined without adding a `U32ArithmeticGate`.
|
/// can be determined without adding a `U32ArithmeticGate`.
|
||||||
pub fn arithmetic_u32_special_cases(
|
fn arithmetic_u32_special_cases(
|
||||||
&mut self,
|
&mut self,
|
||||||
x: U32Target,
|
x: U32Target,
|
||||||
y: U32Target,
|
y: U32Target,
|
||||||
@ -72,12 +125,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns x * y + z.
|
// Returns x * y + z.
|
||||||
pub fn mul_add_u32(
|
fn mul_add_u32(&mut self, x: U32Target, y: U32Target, z: U32Target) -> (U32Target, U32Target) {
|
||||||
&mut self,
|
|
||||||
x: U32Target,
|
|
||||||
y: U32Target,
|
|
||||||
z: U32Target,
|
|
||||||
) -> (U32Target, U32Target) {
|
|
||||||
if let Some(result) = self.arithmetic_u32_special_cases(x, y, z) {
|
if let Some(result) = self.arithmetic_u32_special_cases(x, y, z) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -107,12 +155,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
(output_low, output_high)
|
(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();
|
let one = self.one_u32();
|
||||||
self.mul_add_u32(a, one, b)
|
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() {
|
match to_add.len() {
|
||||||
0 => (self.zero_u32(), self.zero_u32()),
|
0 => (self.zero_u32(), self.zero_u32()),
|
||||||
1 => (to_add[0], 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,
|
&mut self,
|
||||||
to_add: &[U32Target],
|
to_add: &[U32Target],
|
||||||
carry: U32Target,
|
carry: U32Target,
|
||||||
@ -170,18 +218,13 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
(output, output_carry)
|
(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();
|
let zero = self.zero_u32();
|
||||||
self.mul_add_u32(a, b, zero)
|
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).
|
// 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(
|
fn sub_u32(&mut self, x: U32Target, y: U32Target, borrow: U32Target) -> (U32Target, U32Target) {
|
||||||
&mut self,
|
|
||||||
x: U32Target,
|
|
||||||
y: U32Target,
|
|
||||||
borrow: U32Target,
|
|
||||||
) -> (U32Target, U32Target) {
|
|
||||||
let gate = U32SubtractionGate::<F, D>::new_from_config(&self.config);
|
let gate = U32SubtractionGate::<F, D>::new_from_config(&self.config);
|
||||||
let (gate_index, copy) = self.find_slot(gate, &[], &[]);
|
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 low = x_u64 as u32;
|
||||||
let high = (x_u64 >> 32) as u32;
|
let high = (x_u64 >> 32) as u32;
|
||||||
|
|
||||||
out_buffer.set_u32_target(self.low, low);
|
generated_values_set_u32_target(out_buffer, self.low, low);
|
||||||
out_buffer.set_u32_target(self.high, high);
|
generated_values_set_u32_target(out_buffer, self.high, high);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use anyhow::Result;
|
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 rand::{thread_rng, Rng};
|
||||||
|
|
||||||
use crate::iop::witness::PartialWitness;
|
use crate::gadgets::arithmetic_u32::CircuitBuilderU32;
|
||||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
|
||||||
use crate::plonk::circuit_data::CircuitConfig;
|
|
||||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
|
||||||
use crate::plonk::verifier::verify;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_add_many_u32s() -> Result<()> {
|
pub fn test_add_many_u32s() -> Result<()> {
|
||||||
@ -267,6 +310,6 @@ mod tests {
|
|||||||
|
|
||||||
let data = builder.build::<C>();
|
let data = builder.build::<C>();
|
||||||
let proof = data.prove(pw).unwrap();
|
let proof = data.prove(pw).unwrap();
|
||||||
verify(proof, &data.verifier_only, &data.common)
|
data.verify(proof)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
3
plonky2_u32/src/gadgets/mod.rs
Normal file
3
plonky2_u32/src/gadgets/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod arithmetic_u32;
|
||||||
|
pub mod multiple_comparison;
|
||||||
|
pub mod range_check;
|
||||||
149
plonky2_u32/src/gadgets/multiple_comparison.rs
Normal file
149
plonky2_u32/src/gadgets/multiple_comparison.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
23
plonky2_u32/src/gadgets/range_check.rs
Normal file
23
plonky2_u32/src/gadgets/range_check.rs
Normal 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,22 +1,21 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use itertools::unfold;
|
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 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 LOG2_MAX_NUM_ADDENDS: usize = 4;
|
||||||
const MAX_NUM_ADDENDS: usize = 16;
|
const MAX_NUM_ADDENDS: usize = 16;
|
||||||
|
|
||||||
@ -349,17 +348,17 @@ mod tests {
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use itertools::unfold;
|
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 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::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]
|
#[test]
|
||||||
fn low_degree() {
|
fn low_degree() {
|
||||||
@ -1,25 +1,24 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use itertools::unfold;
|
use itertools::unfold;
|
||||||
use plonky2_field::extension_field::Extendable;
|
use plonky2::gates::gate::Gate;
|
||||||
use plonky2_field::field_types::Field;
|
use plonky2::gates::packed_util::PackedEvaluableBase;
|
||||||
use plonky2_field::packed_field::PackedField;
|
use plonky2::gates::util::StridedConstraintConsumer;
|
||||||
|
use plonky2::hash::hash_types::RichField;
|
||||||
use crate::gates::gate::Gate;
|
use plonky2::iop::ext_target::ExtensionTarget;
|
||||||
use crate::gates::packed_util::PackedEvaluableBase;
|
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||||
use crate::gates::util::StridedConstraintConsumer;
|
use plonky2::iop::target::Target;
|
||||||
use crate::hash::hash_types::RichField;
|
use plonky2::iop::wire::Wire;
|
||||||
use crate::iop::ext_target::ExtensionTarget;
|
use plonky2::iop::witness::{PartitionWitness, Witness};
|
||||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use crate::iop::target::Target;
|
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||||
use crate::iop::wire::Wire;
|
use plonky2::plonk::vars::{
|
||||||
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, EvaluationVarsBaseBatch,
|
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||||
EvaluationVarsBasePacked,
|
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).
|
/// A gate to perform a basic mul-add on 32-bit values (we assume they are range-checked beforehand).
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@ -349,16 +348,16 @@ mod tests {
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use anyhow::Result;
|
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::Field;
|
||||||
use plonky2_field::goldilocks_field::GoldilocksField;
|
use plonky2_field::goldilocks_field::GoldilocksField;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::gates::arithmetic_u32::U32ArithmeticGate;
|
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]
|
#[test]
|
||||||
fn low_degree() {
|
fn low_degree() {
|
||||||
@ -1,26 +1,25 @@
|
|||||||
use std::marker::PhantomData;
|
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::extension_field::Extendable;
|
||||||
use plonky2_field::field_types::{Field, Field64};
|
use plonky2_field::field_types::{Field, Field64};
|
||||||
use plonky2_field::packed_field::PackedField;
|
use plonky2_field::packed_field::PackedField;
|
||||||
use plonky2_util::{bits_u64, ceil_div_usize};
|
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.
|
/// A gate for checking that one value is less than or equal to another.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ComparisonGate<F: Field64 + Extendable<D>, const D: usize> {
|
pub struct ComparisonGate<F: Field64 + Extendable<D>, const D: usize> {
|
||||||
@ -520,17 +519,17 @@ mod tests {
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use anyhow::Result;
|
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::Field;
|
||||||
use plonky2_field::field_types::PrimeField64;
|
use plonky2_field::field_types::PrimeField64;
|
||||||
use plonky2_field::goldilocks_field::GoldilocksField;
|
use plonky2_field::goldilocks_field::GoldilocksField;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::gates::comparison::ComparisonGate;
|
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]
|
#[test]
|
||||||
fn wire_indices() {
|
fn wire_indices() {
|
||||||
5
plonky2_u32/src/gates/mod.rs
Normal file
5
plonky2_u32/src/gates/mod.rs
Normal 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;
|
||||||
@ -1,20 +1,19 @@
|
|||||||
use std::marker::PhantomData;
|
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 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.
|
/// A gate which can decompose a number into base B little-endian limbs.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct U32RangeCheckGate<F: RichField + Extendable<D>, const D: usize> {
|
pub struct U32RangeCheckGate<F: RichField + Extendable<D>, const D: usize> {
|
||||||
@ -220,18 +219,18 @@ mod tests {
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use itertools::unfold;
|
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 plonky2_util::ceil_div_usize;
|
||||||
use rand::Rng;
|
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::gates::range_check_u32::U32RangeCheckGate;
|
||||||
use crate::hash::hash_types::HashOut;
|
|
||||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
|
||||||
use crate::plonk::vars::EvaluationVars;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn low_degree() {
|
fn low_degree() {
|
||||||
@ -1,24 +1,23 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use plonky2_field::extension_field::Extendable;
|
use plonky2::gates::gate::Gate;
|
||||||
use plonky2_field::field_types::Field;
|
use plonky2::gates::packed_util::PackedEvaluableBase;
|
||||||
use plonky2_field::packed_field::PackedField;
|
use plonky2::gates::util::StridedConstraintConsumer;
|
||||||
|
use plonky2::hash::hash_types::RichField;
|
||||||
use crate::gates::gate::Gate;
|
use plonky2::iop::ext_target::ExtensionTarget;
|
||||||
use crate::gates::packed_util::PackedEvaluableBase;
|
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||||
use crate::gates::util::StridedConstraintConsumer;
|
use plonky2::iop::target::Target;
|
||||||
use crate::hash::hash_types::RichField;
|
use plonky2::iop::wire::Wire;
|
||||||
use crate::iop::ext_target::ExtensionTarget;
|
use plonky2::iop::witness::{PartitionWitness, Witness};
|
||||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use crate::iop::target::Target;
|
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||||
use crate::iop::wire::Wire;
|
use plonky2::plonk::vars::{
|
||||||
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, EvaluationVarsBaseBatch,
|
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||||
EvaluationVarsBasePacked,
|
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
|
/// 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.
|
/// 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 std::marker::PhantomData;
|
||||||
|
|
||||||
use anyhow::Result;
|
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::extension_field::quartic::QuarticExtension;
|
||||||
use plonky2_field::field_types::Field;
|
use plonky2_field::field_types::Field;
|
||||||
use plonky2_field::field_types::PrimeField64;
|
use plonky2_field::field_types::PrimeField64;
|
||||||
use plonky2_field::goldilocks_field::GoldilocksField;
|
use plonky2_field::goldilocks_field::GoldilocksField;
|
||||||
use rand::Rng;
|
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::gates::subtraction_u32::U32SubtractionGate;
|
||||||
use crate::hash::hash_types::HashOut;
|
|
||||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
|
||||||
use crate::plonk::vars::EvaluationVars;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn low_degree() {
|
fn low_degree() {
|
||||||
5
plonky2_u32/src/lib.rs
Normal file
5
plonky2_u32/src/lib.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#![allow(clippy::needless_range_loop)]
|
||||||
|
|
||||||
|
pub mod gadgets;
|
||||||
|
pub mod gates;
|
||||||
|
pub mod witness;
|
||||||
21
plonky2_u32/src/witness.rs
Normal file
21
plonky2_u32/src/witness.rs
Normal 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))
|
||||||
|
}
|
||||||
@ -6,8 +6,10 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
"plonky2" = { path = "../plonky2" }
|
"plonky2" = { path = "../plonky2" }
|
||||||
|
"plonky2_field" = { path = "../field" }
|
||||||
"plonky2_util" = { path = "../util" }
|
"plonky2_util" = { path = "../util" }
|
||||||
anyhow = "1.0.40"
|
anyhow = "1.0.40"
|
||||||
bimap = "0.6.1"
|
bimap = "0.6.1"
|
||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
rand = "0.8.4"
|
rand = "0.8.4"
|
||||||
|
array_tool = "1.0.3"
|
||||||
|
|||||||
1
waksman/src/gates/mod.rs
Normal file
1
waksman/src/gates/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod switch;
|
||||||
@ -1,25 +1,24 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use array_tool::vec::Union;
|
use array_tool::vec::Union;
|
||||||
use plonky2_field::extension_field::Extendable;
|
use plonky2::gates::gate::Gate;
|
||||||
use plonky2_field::field_types::Field;
|
use plonky2::gates::packed_util::PackedEvaluableBase;
|
||||||
use plonky2_field::packed_field::PackedField;
|
use plonky2::gates::util::StridedConstraintConsumer;
|
||||||
|
use plonky2::hash::hash_types::RichField;
|
||||||
use crate::gates::gate::Gate;
|
use plonky2::iop::ext_target::ExtensionTarget;
|
||||||
use crate::gates::packed_util::PackedEvaluableBase;
|
use plonky2::iop::generator::{GeneratedValues, WitnessGenerator};
|
||||||
use crate::gates::util::StridedConstraintConsumer;
|
use plonky2::iop::target::Target;
|
||||||
use crate::hash::hash_types::RichField;
|
use plonky2::iop::wire::Wire;
|
||||||
use crate::iop::ext_target::ExtensionTarget;
|
use plonky2::iop::witness::{PartitionWitness, Witness};
|
||||||
use crate::iop::generator::{GeneratedValues, WitnessGenerator};
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
use crate::iop::target::Target;
|
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||||
use crate::iop::wire::Wire;
|
use plonky2::plonk::vars::{
|
||||||
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, EvaluationVarsBaseBatch,
|
EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch,
|
||||||
EvaluationVarsBasePacked,
|
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.
|
/// A gate for conditionally swapping input values based on a boolean.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@ -332,16 +331,16 @@ mod tests {
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use anyhow::Result;
|
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::field_types::Field;
|
||||||
use plonky2_field::goldilocks_field::GoldilocksField;
|
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::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]
|
#[test]
|
||||||
fn wire_indices() {
|
fn wire_indices() {
|
||||||
@ -6,5 +6,6 @@
|
|||||||
#![allow(clippy::return_self_not_must_use)]
|
#![allow(clippy::return_self_not_must_use)]
|
||||||
|
|
||||||
pub mod bimap;
|
pub mod bimap;
|
||||||
|
pub mod gates;
|
||||||
pub mod permutation;
|
pub mod permutation;
|
||||||
pub mod sorting;
|
pub mod sorting;
|
||||||
|
|||||||
@ -2,7 +2,6 @@ use std::collections::BTreeMap;
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use plonky2::field::{extension_field::Extendable, field_types::Field};
|
use plonky2::field::{extension_field::Extendable, field_types::Field};
|
||||||
use plonky2::gates::switch::SwitchGate;
|
|
||||||
use plonky2::hash::hash_types::RichField;
|
use plonky2::hash::hash_types::RichField;
|
||||||
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||||
use plonky2::iop::target::Target;
|
use plonky2::iop::target::Target;
|
||||||
@ -10,6 +9,7 @@ use plonky2::iop::witness::{PartitionWitness, Witness};
|
|||||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||||
|
|
||||||
use crate::bimap::bimap_from_lists;
|
use crate::bimap::bimap_from_lists;
|
||||||
|
use crate::gates::switch::SwitchGate;
|
||||||
|
|
||||||
/// Assert that two lists of expressions evaluate to permutations of one another.
|
/// Assert that two lists of expressions evaluate to permutations of one another.
|
||||||
pub fn assert_permutation<F: RichField + Extendable<D>, const D: usize>(
|
pub fn assert_permutation<F: RichField + Extendable<D>, const D: usize>(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user