diff --git a/src/gadgets/arithmetic_u32.rs b/src/gadgets/arithmetic_u32.rs index ce35d4f0..0d88d52c 100644 --- a/src/gadgets/arithmetic_u32.rs +++ b/src/gadgets/arithmetic_u32.rs @@ -5,7 +5,7 @@ use crate::gates::subtraction_u32::U32SubtractionGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct U32Target(pub Target); impl, const D: usize> CircuitBuilder { @@ -28,6 +28,14 @@ impl, const D: usize> CircuitBuilder { U32Target(self.one()) } + pub fn connect_u32(&mut self, x: U32Target, y: U32Target) { + self.connect(x.0, y.0) + } + + pub fn assert_zero_u32(&self, x: U32Target) { + self.assert_zero(x.0) + } + // Returns x * y + z. pub fn mul_add_u32( &mut self, diff --git a/src/gadgets/biguint.rs b/src/gadgets/biguint.rs index 4adc2382..b30b4680 100644 --- a/src/gadgets/biguint.rs +++ b/src/gadgets/biguint.rs @@ -1,17 +1,81 @@ use std::marker::PhantomData; +use std::ops::Neg; use num::BigUint; use crate::field::field_types::RichField; use crate::field::{extension_field::Extendable, field_types::Field}; use crate::gadgets::arithmetic_u32::U32Target; +use crate::iop::generator::{GeneratedValues, SimpleGenerator}; +use crate::iop::target::{BoolTarget, Target}; +use crate::iop::witness::PartitionWitness; use crate::plonk::circuit_builder::CircuitBuilder; +#[derive(Clone, Debug)] pub struct BigUintTarget { - limbs: Vec, + pub limbs: Vec, +} + +impl BigUintTarget { + pub fn num_limbs(&self) -> usize { + self.limbs.len() + } + + pub fn get_limb(&self, i: usize) -> U32Target { + self.limbs[i] + } } impl, const D: usize> CircuitBuilder { + fn connect_biguint(&self, lhs: BigUintTarget, rhs: BigUintTarget) { + let min_limbs = lhs.num_limbs().min(rhs.num_limbs()); + for i in 0..min_limbs { + self.connect_u32(lhs.get_limb(i), rhs.get_limb(i)); + } + + for i in min_limbs..lhs.num_limbs() { + self.assert_zero_u32(lhs.get_limb(i)); + } + for i in min_limbs..rhs.num_limbs() { + self.assert_zero_u32(rhs.get_limb(i)); + } + } + + fn pad_biguints(&mut self, a: BigUintTarget, b: BigUintTarget) -> (BigUintTarget, BigUintTarget) { + if a.num_limbs() > b.num_limbs() { + let mut padded_b_limbs = b.limbs.clone(); + padded_b_limbs.extend(self.add_virtual_u32_targets(a.num_limbs() - b.num_limbs())); + let padded_b = BigUintTarget { + limbs: padded_b_limbs, + }; + (a, padded_b) + } else { + let mut padded_a_limbs = a.limbs.clone(); + padded_a_limbs.extend(self.add_virtual_u32_targets(b.num_limbs() - a.num_limbs())); + let padded_a = BigUintTarget { + limbs: padded_a_limbs, + }; + (padded_a, b) + } + } + + fn cmp_biguint(&mut self, a: BigUintTarget, b: BigUintTarget) -> BoolTarget { + let (padded_a, padded_b) = self.pad_biguints(a, b); + + let a_vec = a.limbs.iter().map(|&x| x.0).collect(); + let b_vec = b.limbs.iter().map(|&x| x.0).collect(); + + self.list_le(a_vec, b_vec, 32) + } + + fn add_virtual_biguint_target(&mut self, num_limbs: usize) -> BigUintTarget { + let limbs = (0..num_limbs).map(|_| self.add_virtual_u32_target()).collect(); + + BigUintTarget { + limbs, + } + } + // Add two `BigUintTarget`s. pub fn add_biguint(&mut self, a: BigUintTarget, b: BigUintTarget) -> BigUintTarget { let num_limbs = a.limbs.len(); @@ -79,4 +143,49 @@ impl, const D: usize> CircuitBuilder { limbs: combined_limbs, } } + + pub fn div_rem_biguint(&mut self, a: BigUintTarget, b: BigUintTarget) -> (BigUintTarget, BigUintTarget) { + let num_limbs = a.limbs.len(); + let div = self.add_virtual_biguint_target(num_limbs); + let rem = self.add_virtual_biguint_target(num_limbs); + + self.add_simple_generator(BigUintDivRemGenerator:: { + a: a.clone(), + b: b.clone(), + div: div.clone(), + rem: rem.clone(), + _phantom: PhantomData, + }); + + let div_b = self.mul_biguint(div, b); + let div_b_plus_rem = self.add_biguint(div_b, rem); + self.connect_biguint(x, div_b_plus_rem); + + let + + self.assert_one() + + (div, rem) + } } + +#[derive(Debug)] +struct BigUintDivRemGenerator, const D: usize> { + a: BigUintTarget, + b: BigUintTarget, + div: BigUintTarget, + rem: BigUintTarget, + _phantom: PhantomData, +} + +impl, const D: usize> SimpleGenerator + for BigUintDivRemGenerator +{ + fn dependencies(&self) -> Vec { + self.a.limbs.iter().map(|&l| l.0).chain(self.b.limbs.iter().map(|&l| l.0)).collect() + } + + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { + + } +} \ No newline at end of file diff --git a/src/gadgets/multiple_comparison.rs b/src/gadgets/multiple_comparison.rs index 11225ca5..3c2ac0f5 100644 --- a/src/gadgets/multiple_comparison.rs +++ b/src/gadgets/multiple_comparison.rs @@ -11,7 +11,7 @@ impl, const D: usize> CircuitBuilder { assert_eq!( a.len(), b.len(), - "Permutation must have same number of inputs and outputs" + "Comparison must be between same number of inputs and outputs" ); let n = a.len(); diff --git a/src/gadgets/nonnative.rs b/src/gadgets/nonnative.rs index 7faa6d4e..e41f8fb5 100644 --- a/src/gadgets/nonnative.rs +++ b/src/gadgets/nonnative.rs @@ -1,21 +1,12 @@ -use std::collections::BTreeMap; use std::marker::PhantomData; -use num::bigint::BigUint; use crate::field::field_types::RichField; use crate::field::{extension_field::Extendable, field_types::Field}; use crate::gadgets::arithmetic_u32::U32Target; -use crate::gates::arithmetic_u32::U32ArithmeticGate; -use crate::gates::switch::SwitchGate; -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::util::bimap::bimap_from_lists; pub struct ForeignFieldTarget { - /// These F elements are assumed to contain 32-bit values. limbs: Vec, _phantom: PhantomData, } @@ -30,6 +21,16 @@ impl, const D: usize> CircuitBuilder { .collect() } + fn power_of_2_mod_order(&mut self, i: usize) -> Vec { + + } + + pub fn powers_of_2_mod_order(&mut self, max: usize) -> Vec> { + for i in 0..max { + + } + } + // Add two `ForeignFieldTarget`s. pub fn add_nonnative( &mut self, @@ -63,7 +64,7 @@ impl, const D: usize> CircuitBuilder { let mut modulus_limbs = self.order_u32_limbs::(); modulus_limbs.append(self.zero_u32()); - let needs_reduce = self.list_le(modulus, limbs); + let needs_reduce = self.list_le(modulus_limbs, limbs); let mut to_subtract = vec![]; for i in 0..num_limbs { @@ -98,7 +99,7 @@ impl, const D: usize> CircuitBuilder { let mut borrow = self.zero_u32(); for i in 0..num_limbs { let (result, new_borrow) = self.sub_u32(a.limbs[i], b.limbs[i], borrow); - reduced_limbs[i] = result; + result_limbs[i] = result; borrow = new_borrow; } // Borrow should be zero here. @@ -147,6 +148,7 @@ impl, const D: usize> CircuitBuilder { } pub fn reduce_mul_result(&mut self, limbs: Vec) -> Vec { + todo!() } } diff --git a/src/iop/witness.rs b/src/iop/witness.rs index 858bacd9..12186fb1 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -1,9 +1,13 @@ use std::collections::HashMap; use std::convert::TryInto; +use num::BigUint; + use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::Field; +use crate::field::field_types::{Field, PrimeField}; +use crate::gadgets::arithmetic_u32::U32Target; +use crate::gadgets::biguint::BigUintTarget; use crate::hash::hash_types::HashOutTarget; use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; @@ -53,12 +57,24 @@ pub trait Witness { panic!("not a bool") } + fn get_u32_target(&self, target: U32Target) -> F { + let result = self.get_target(target.0); + debug_assert!(result.to_canonical_u64() < 1 << 32u64); + result + } + fn get_hash_target(&self, ht: HashOutTarget) -> HashOut { HashOut { elements: self.get_targets(&ht.elements).try_into().unwrap(), } } + fn get_biguint_target(&self, target: BigUintTarget) -> BigUint { + let mut result = BigUint::zero(); + for (i, &limb) in target + result + } + fn get_wire(&self, wire: Wire) -> F { self.get_target(Target::Wire(wire)) } diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index f21c68cb..804e7be2 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -246,6 +246,11 @@ impl, const D: usize> CircuitBuilder { self.connect(x, zero); } + pub fn assert_one(&mut self, x: Target) { + let one = self.one(); + self.connect(x, one); + } + pub fn add_generators(&mut self, generators: Vec>>) { self.generators.extend(generators); }