diff --git a/src/gadgets/arithmetic_u32.rs b/src/gadgets/arithmetic_u32.rs new file mode 100644 index 00000000..4a8cff42 --- /dev/null +++ b/src/gadgets/arithmetic_u32.rs @@ -0,0 +1,67 @@ +use std::collections::BTreeMap; +use std::marker::PhantomData; + +use crate::field::field_types::RichField; +use crate::field::{extension_field::Extendable, field_types::Field}; +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 U32Target(Target); + +impl, const D: usize> CircuitBuilder { + pub fn add_virtual_u32_target(&self) -> U32Target { + U32Target(self.add_virtual_target()) + } + + pub fn zero_u32(&self) -> U32Target { + U32Target(self.zero()) + } + + pub fn one_u32(&self) -> U32Target { + U32Target(self.one()) + } + + pub fn add_mul_u32( + &mut self, + x: U32Target, + y: U32Target, + z: U32Target, + ) -> (U32Target, U32Target) { + let (gate_index, copy) = match self.current_u32_arithmetic_gate { + None => { + let gate = U32ArithmeticGate { + _phantom: PhantomData, + }; + let gate_index = self.add_gate(gate.clone(), vec![]); + (gate_index, 0) + }, + Some((gate_index, copy) => (gate_index, copy), + }; + + let output_low = self.add_virtual_u32_target(); + let output_high = self.add_virtual_u32_target(); + + self.connect(Target::wire(gate_index, gate.wire_ith_multiplicand_0(copy)), x); + self.connect(Target::wire(gate_index, gate.wire_ith_multiplicand_1(copy)), y); + self.connect(Target::wire(gate_index, gate.wire_ith_addend(copy)), z); + self.connect(Target::wire(gate_index, gate.wire_ith_output_low_half(copy)), output_low); + self.connect(Target::wire(gate_index, gate.wire_ith_output_high_half(copy)), output_high); + + self.current_u32_arithmetic_gate = Some((gate_index, 0)); + + (output_low, output_high) + } + + pub fn add_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target) { + self.add_mul_u32(a, self.one_u32(), b) + } + + pub fn mul_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target) { + self.add_mul_u32(a, b, self.zero_u32()) + } +} diff --git a/src/gadgets/mod.rs b/src/gadgets/mod.rs index 5ec494c7..e38646e3 100644 --- a/src/gadgets/mod.rs +++ b/src/gadgets/mod.rs @@ -1,5 +1,6 @@ pub mod arithmetic; pub mod arithmetic_extension; +pub mod arithmetic_u32; pub mod hash; pub mod insert; pub mod interpolation; diff --git a/src/gadgets/nonnative.rs b/src/gadgets/nonnative.rs index 6763a1a5..1407360e 100644 --- a/src/gadgets/nonnative.rs +++ b/src/gadgets/nonnative.rs @@ -3,6 +3,8 @@ use std::marker::PhantomData; 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; @@ -10,8 +12,6 @@ use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bimap::bimap_from_lists; -pub struct U32Target(Target); - pub struct NonNativeTarget { /// The modulus of the field F' being represented. modulus: BigUInt, @@ -20,18 +20,6 @@ pub struct NonNativeTarget { } impl, const D: usize> CircuitBuilder { - pub fn add_mul_u32(&mut self, x: U32Target, y: U32Target, z:U32Target) -> (U32Target, U32Target) { - - } - - pub fn add_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target) { - - } - - pub fn mul_u32(&mut self, a: U32Target, b: U32Target) -> (U32Target, U32Target) { - - } - pub fn add_nonnative(&mut self, a: NonNativeTarget, b: NonNativeTarget) -> NonNativeTarget { let modulus = a.modulus; let num_limbs = a.limbs.len(); @@ -41,11 +29,7 @@ impl, const D: usize> CircuitBuilder { let mut combined_limbs = self.add_virtual_targets(num_limbs + 1); let mut carry = self.zero(); for i in 0..num_limbs { - let gate = ComparisonGate::new(bits, num_chunks); - let gate_index = self.add_gate(gate.clone(), vec![]); - - self.connect(Target::wire(gate_index, gate.wire_first_input()), lhs); - self.connect(Target::wire(gate_index, gate.wire_second_input()), rhs); + } } @@ -68,7 +52,7 @@ impl, const D: usize> CircuitBuilder { } let reduced_limbs = self.reduce(combined_limbs, modulus); - + NonNativeTarget { modulus, limbs: reduced_limbs, diff --git a/src/gates/arithmetic_u32.rs b/src/gates/arithmetic_u32.rs index 6564a876..c05cf72f 100644 --- a/src/gates/arithmetic_u32.rs +++ b/src/gates/arithmetic_u32.rs @@ -17,7 +17,7 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; pub const NUM_U32_ARITHMETIC_OPS: usize = 3; /// A gate to perform a basic mul-add on 32-bit values (we assume they are range-checked beforehand). -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct U32ArithmeticGate, const D: usize> { _phantom: PhantomData, } diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 5dcde1e0..e6020ad8 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -87,6 +87,9 @@ pub struct CircuitBuilder, const D: usize> { // of switches pub(crate) current_switch_gates: Vec, usize, usize)>>, + // The `U32ArithmeticGate` currently being filled (so new u32 arithmetic operations will be added to this gate before creating a new one) + pub(crate) current_u32_arithmetic_gate: Option<(usize, usize)>, + /// An available `ConstantGate` instance, if any. free_constant: Option<(usize, usize)>, } @@ -109,6 +112,7 @@ impl, const D: usize> CircuitBuilder { free_arithmetic: HashMap::new(), free_random_access: HashMap::new(), current_switch_gates: Vec::new(), + current_u32_arithmetic_gate: None, free_constant: None, }; builder.check_config();