mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-02 13:53:07 +00:00
Move u32 stuff to plonky2_u32 crate
This commit is contained in:
parent
3c6ec8755b
commit
b58d5d6747
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 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();
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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>(
|
||||
|
||||
@ -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
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 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)
|
||||
}
|
||||
}
|
||||
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 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() {
|
||||
@ -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() {
|
||||
@ -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() {
|
||||
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 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() {
|
||||
@ -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
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]
|
||||
"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
1
waksman/src/gates/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod switch;
|
||||
@ -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() {
|
||||
@ -6,5 +6,6 @@
|
||||
#![allow(clippy::return_self_not_must_use)]
|
||||
|
||||
pub mod bimap;
|
||||
pub mod gates;
|
||||
pub mod permutation;
|
||||
pub mod sorting;
|
||||
|
||||
@ -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>(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user