From daead4aebf26f83e8c6d98cec02549682c630fb5 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Wed, 29 Mar 2023 12:53:33 +0300 Subject: [PATCH 1/6] Parse gates before proving --- .../src/backend/bellman_groth16/mod.rs | 20 +++-- .../src/backend/bellman_groth16/precompute.rs | 79 +++++++++++++++++++ .../src/backend/bellman_groth16/prover.rs | 25 +++++- fawkes-crypto/src/circuit/r1cs/cs.rs | 69 +++------------- fawkes-crypto/tests/circuit_ecc.rs | 2 +- fawkes-crypto/tests/circuit_poseidon.rs | 2 +- 6 files changed, 133 insertions(+), 64 deletions(-) create mode 100644 fawkes-crypto/src/backend/bellman_groth16/precompute.rs diff --git a/fawkes-crypto/src/backend/bellman_groth16/mod.rs b/fawkes-crypto/src/backend/bellman_groth16/mod.rs index cf40a68..9bff862 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/mod.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/mod.rs @@ -1,7 +1,7 @@ use crate::{ circuit::{ cs::{RCS, WitnessCS, CS}, - lc::{Index} + lc::Index, }, core::signal::Signal, ff_uint::{Num, PrimeField}, @@ -20,6 +20,8 @@ use bellman::pairing::CurveAffine; use std::marker::PhantomData; use engines::Engine; +use self::precompute::PrecomputedData; + pub mod engines; #[cfg(feature = "rand_support")] pub mod osrng; @@ -28,7 +30,7 @@ pub mod prover; pub mod setup; pub mod verifier; pub mod group; - +pub mod precompute; #[repr(transparent)] @@ -143,8 +145,13 @@ impl Parameters { verifier::VK::from_bellman(&self.0.vk) } - pub fn get_witness_rcs(&self)->RCS> { - WitnessCS::rc_new(self.1 as usize, &self.2, &self.3) + pub fn get_witness_rcs(&self) -> RCS> { + let gates = PrecomputedData::parse_gates(&self); + WitnessCS::rc_new(self.1 as usize, gates, &self.3) + } + + pub fn get_witness_rcs_precomputed(&self, precomputed: &PrecomputedData) -> RCS> { + WitnessCS::rc_new(self.1 as usize, precomputed.gates.clone(), &self.3) } pub fn write(&self, writer: &mut W) -> std::io::Result<()> { @@ -174,4 +181,7 @@ impl Parameters { Ok(Self(e0, e1, e2, e3)) } -} + pub fn precompute(&self) -> PrecomputedData { + PrecomputedData::prepare(&self) + } +} \ No newline at end of file diff --git a/fawkes-crypto/src/backend/bellman_groth16/precompute.rs b/fawkes-crypto/src/backend/bellman_groth16/precompute.rs new file mode 100644 index 0000000..c8e2331 --- /dev/null +++ b/fawkes-crypto/src/backend/bellman_groth16/precompute.rs @@ -0,0 +1,79 @@ +use std::{marker::PhantomData, rc::Rc}; + +use borsh::BorshDeserialize; +use byteorder::{ByteOrder, LittleEndian}; +use ff_uint::{Num, PrimeField}; + +use crate::circuit::{cs::Gate, lc::Index}; + +use super::{engines::Engine, Parameters}; + +pub struct PrecomputedData { + pub(crate) gates: Rc>>, +} + +impl PrecomputedData { + pub(crate) fn prepare(params: &Parameters) -> Self { + PrecomputedData { + gates: PrecomputedData::parse_gates(params) + } + } + + pub(crate) fn parse_gates(params: &Parameters) -> Rc>> { + Rc::new( + GateStreamedIterator( + brotli::Decompressor::new(¶ms.2 as &[u8], 4096), + PhantomData::, + ) + .collect::>(), + ) + } +} + +struct GateStreamedIterator(pub R, pub PhantomData); + +fn read_u32(r: &mut R) -> std::io::Result { + let mut b = [0; 4]; + r.read_exact(&mut b)?; + Ok(LittleEndian::read_u32(&b)) +} + +fn read_gate_part( + r: &mut R, +) -> std::io::Result, Index)>> { + let sz = read_u32(r)? as usize; + + let item_size = + std::mem::size_of::() + std::mem::size_of::() + std::mem::size_of::(); + let mut buf = vec![0; sz * item_size]; + r.read_exact(&mut buf)?; + let mut buf_ref = &buf[..]; + let mut gate_part = Vec::with_capacity(sz); + for _ in 0..sz { + let a = Num::::deserialize(&mut buf_ref)?; + let b1 = u8::deserialize(&mut buf_ref)?; + let b2 = u32::deserialize(&mut buf_ref)?; + let b = match b1 { + 0 => Index::Input(b2), + 1 => Index::Aux(b2), + _ => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "enum elements overflow", + )) + } + }; + gate_part.push((a, b)); + } + Ok(gate_part) +} + +impl Iterator for GateStreamedIterator { + type Item = Gate; + fn next(&mut self) -> Option { + let a = read_gate_part(&mut self.0).ok()?; + let b = read_gate_part(&mut self.0).ok()?; + let c = read_gate_part(&mut self.0).ok()?; + Some(Gate(a, b, c)) + } +} diff --git a/fawkes-crypto/src/backend/bellman_groth16/prover.rs b/fawkes-crypto/src/backend/bellman_groth16/prover.rs index 2dc1bce..e38263f 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/prover.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/prover.rs @@ -66,7 +66,30 @@ pub fn prove<'a, E: Engine, Pub: Signal>, Sec: Signal (Vec>, Proof) { - let ref rcs = params.get_witness_rcs(); + let rcs = params.get_witness_rcs(); + prove_internal(params, input_pub, input_sec, circuit, &rcs) +} + +#[cfg(feature = "rand_support")] +pub fn prove_precomputed<'a, E: Engine, Pub: Signal>, Sec: Signal>, C: Fn(Pub, Sec)>( + params: &'a Parameters, + input_pub: &Pub::Value, + input_sec: &Sec::Value, + circuit: C, + precomputed: &PrecomputedData +) -> (Vec>, Proof) { + let rcs = params.get_witness_rcs_precomputed(precomputed); + prove_internal(params, input_pub, input_sec, circuit, &rcs) +} + +#[cfg(feature = "rand_support")] +fn prove_internal<'a, E: Engine, Pub: Signal>, Sec: Signal>, C: Fn(Pub, Sec)>( + params: &'a Parameters, + input_pub: &Pub::Value, + input_sec: &Sec::Value, + circuit: C, + rcs: &RCS> +) -> (Vec>, Proof) { let signal_pub = Pub::alloc(rcs, Some(input_pub)); signal_pub.inputize(); let signal_sec = Sec::alloc(rcs, Some(input_sec)); diff --git a/fawkes-crypto/src/circuit/r1cs/cs.rs b/fawkes-crypto/src/circuit/r1cs/cs.rs index 2b8a74a..0ee28a5 100644 --- a/fawkes-crypto/src/circuit/r1cs/cs.rs +++ b/fawkes-crypto/src/circuit/r1cs/cs.rs @@ -9,7 +9,6 @@ use crate::{ use std::{cell::RefCell, marker::PhantomData, rc::Rc}; use bit_vec::BitVec; -use byteorder::{ByteOrder, LittleEndian}; pub type RCS = Rc>; @@ -28,13 +27,13 @@ pub struct Gate( pub trait CS: Clone { type Fr: PrimeField; type LC: AbstractLC; - type GateIterator: Iterator>; + type GateIterator<'g>: Iterator> where Self: 'g; fn num_gates(&self) -> usize; fn num_input(&self) -> usize; fn num_aux(&self) -> usize; fn get_value(&self, index:Index) -> Option>; - fn get_gate_iterator(&self) -> Self::GateIterator; + fn get_gate_iterator<'g>(&'g self) -> Self::GateIterator<'g>; // a*b === c fn enforce(a: &CNum, b: &CNum, c: &CNum); @@ -100,13 +99,13 @@ pub struct WitnessCS<'a, Fr: PrimeField> { pub values_input: Vec>, pub values_aux: Vec>, pub num_gates: usize, - pub gates_data: &'a[u8], + pub gates_data: Rc>>, pub const_tracker: &'a BitVec, pub const_tracker_index: usize } impl<'a, Fr: PrimeField> WitnessCS<'a, Fr> { - pub fn new(num_gates:usize, gates_data: &'a[u8], const_tracker: &'a BitVec) -> Self { + pub fn new(num_gates:usize, gates_data: Rc>>, const_tracker: &'a BitVec) -> Self { Self { values_input: vec![Num::ONE], values_aux: vec![], @@ -117,7 +116,7 @@ impl<'a, Fr: PrimeField> WitnessCS<'a, Fr> { } } - pub fn rc_new(num_gates:usize, gates_data: &'a[u8], const_tracker: &'a BitVec) -> RCS { + pub fn rc_new(num_gates:usize, gates_data: Rc>>, const_tracker: &'a BitVec) -> RCS { Rc::new(RefCell::new(Self::new(num_gates, gates_data, const_tracker))) } } @@ -126,7 +125,7 @@ impl<'a, Fr: PrimeField> WitnessCS<'a, Fr> { impl CS for DebugCS { type Fr = Fr; type LC = LC; - type GateIterator = core::iter::Empty>; + type GateIterator<'g> = core::iter::Empty<&'g Gate> where Self: 'g; fn num_gates(&self) -> usize { self.num_gates @@ -143,7 +142,7 @@ impl CS for DebugCS { None } - fn get_gate_iterator(&self) -> Self::GateIterator { + fn get_gate_iterator<'g>(&'g self) -> Self::GateIterator<'g> { std::unimplemented!(); } @@ -180,52 +179,10 @@ impl CS for DebugCS { } - -pub struct GateStreamedIterator(R,PhantomData); - -fn read_u32(r: &mut R) -> std::io::Result { - let mut b = [0; 4]; - r.read_exact(&mut b)?; - Ok(LittleEndian::read_u32(&b)) -} - - -fn read_gate_part(r: &mut R) -> std::io::Result, Index)>> { - let sz = read_u32(r)? as usize; - - let item_size = std::mem::size_of::() + std::mem::size_of::() + std::mem::size_of::(); - let mut buf = vec![0; sz*item_size]; - r.read_exact(&mut buf)?; - let mut buf_ref = &buf[..]; - let mut gate_part = Vec::with_capacity(sz); - for _ in 0..sz { - let a = Num::::deserialize(&mut buf_ref)?; - let b1 = u8::deserialize(&mut buf_ref)?; - let b2 = u32::deserialize(&mut buf_ref)?; - let b = match b1 { - 0 => Index::Input(b2), - 1 => Index::Aux(b2), - _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "enum elements overflow")) - }; - gate_part.push((a,b)); - } - Ok(gate_part) -} - -impl Iterator for GateStreamedIterator { - type Item = Gate; - fn next(&mut self) -> Option { - let a = read_gate_part(&mut self.0).ok()?; - let b = read_gate_part(&mut self.0).ok()?; - let c = read_gate_part(&mut self.0).ok()?; - Some(Gate(a,b,c)) - } -} - impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { type Fr = Fr; type LC = ZeroLC; - type GateIterator = GateStreamedIterator>; + type GateIterator<'g> = core::slice::Iter<'g, Gate> where Self: 'g; fn num_gates(&self) -> usize { self.num_gates @@ -245,8 +202,8 @@ impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { } } - fn get_gate_iterator(&self) -> Self::GateIterator { - GateStreamedIterator(brotli::Decompressor::new(self.gates_data, 4096), PhantomData) + fn get_gate_iterator<'g>(&'g self) -> Self::GateIterator<'g> { + self.gates_data.iter() } fn enforce(_: &CNum, _: &CNum, _: &CNum) { @@ -279,7 +236,7 @@ impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { impl CS for BuildCS { type Fr = Fr; type LC = LC; - type GateIterator = std::vec::IntoIter>; + type GateIterator<'g> = core::slice::Iter<'g, Gate> where Self: 'g; fn num_gates(&self) -> usize { self.gates.len() @@ -296,8 +253,8 @@ impl CS for BuildCS { None } - fn get_gate_iterator(&self) -> Self::GateIterator { - self.gates.clone().into_iter() + fn get_gate_iterator<'g>(&'g self) -> Self::GateIterator<'g> { + self.gates.iter() } // a*b === c diff --git a/fawkes-crypto/tests/circuit_ecc.rs b/fawkes-crypto/tests/circuit_ecc.rs index 45848bd..016d09e 100644 --- a/fawkes-crypto/tests/circuit_ecc.rs +++ b/fawkes-crypto/tests/circuit_ecc.rs @@ -1,5 +1,5 @@ -use fawkes_crypto::{ +use fawkes_crypto_zkbob::{ circuit::{bitify::c_into_bits_le_strict, cs::DebugCS, ecc::*, num::CNum, cs::CS}, native::ecc::*, ff_uint::Num, diff --git a/fawkes-crypto/tests/circuit_poseidon.rs b/fawkes-crypto/tests/circuit_poseidon.rs index 0b56df2..b92cc04 100644 --- a/fawkes-crypto/tests/circuit_poseidon.rs +++ b/fawkes-crypto/tests/circuit_poseidon.rs @@ -1,5 +1,5 @@ -use fawkes_crypto::{ +use fawkes_crypto_zkbob::{ circuit::{cs::{DebugCS, CS}, poseidon::*, num::CNum}, core::{signal::Signal, sizedvec::SizedVec}, engines::bn256::Fr, From 8aeb818dcbe977b04b460a748bddb59a7af862c3 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Wed, 5 Apr 2023 12:26:18 +0300 Subject: [PATCH 2/6] Revert "Parse gates before proving" This reverts commit daead4aebf26f83e8c6d98cec02549682c630fb5. --- .../src/backend/bellman_groth16/mod.rs | 20 ++--- .../src/backend/bellman_groth16/precompute.rs | 79 ------------------- .../src/backend/bellman_groth16/prover.rs | 25 +----- fawkes-crypto/src/circuit/r1cs/cs.rs | 69 +++++++++++++--- fawkes-crypto/tests/circuit_ecc.rs | 2 +- fawkes-crypto/tests/circuit_poseidon.rs | 2 +- 6 files changed, 64 insertions(+), 133 deletions(-) delete mode 100644 fawkes-crypto/src/backend/bellman_groth16/precompute.rs diff --git a/fawkes-crypto/src/backend/bellman_groth16/mod.rs b/fawkes-crypto/src/backend/bellman_groth16/mod.rs index 9bff862..cf40a68 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/mod.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/mod.rs @@ -1,7 +1,7 @@ use crate::{ circuit::{ cs::{RCS, WitnessCS, CS}, - lc::Index, + lc::{Index} }, core::signal::Signal, ff_uint::{Num, PrimeField}, @@ -20,8 +20,6 @@ use bellman::pairing::CurveAffine; use std::marker::PhantomData; use engines::Engine; -use self::precompute::PrecomputedData; - pub mod engines; #[cfg(feature = "rand_support")] pub mod osrng; @@ -30,7 +28,7 @@ pub mod prover; pub mod setup; pub mod verifier; pub mod group; -pub mod precompute; + #[repr(transparent)] @@ -145,13 +143,8 @@ impl Parameters { verifier::VK::from_bellman(&self.0.vk) } - pub fn get_witness_rcs(&self) -> RCS> { - let gates = PrecomputedData::parse_gates(&self); - WitnessCS::rc_new(self.1 as usize, gates, &self.3) - } - - pub fn get_witness_rcs_precomputed(&self, precomputed: &PrecomputedData) -> RCS> { - WitnessCS::rc_new(self.1 as usize, precomputed.gates.clone(), &self.3) + pub fn get_witness_rcs(&self)->RCS> { + WitnessCS::rc_new(self.1 as usize, &self.2, &self.3) } pub fn write(&self, writer: &mut W) -> std::io::Result<()> { @@ -181,7 +174,4 @@ impl Parameters { Ok(Self(e0, e1, e2, e3)) } - pub fn precompute(&self) -> PrecomputedData { - PrecomputedData::prepare(&self) - } -} \ No newline at end of file +} diff --git a/fawkes-crypto/src/backend/bellman_groth16/precompute.rs b/fawkes-crypto/src/backend/bellman_groth16/precompute.rs deleted file mode 100644 index c8e2331..0000000 --- a/fawkes-crypto/src/backend/bellman_groth16/precompute.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::{marker::PhantomData, rc::Rc}; - -use borsh::BorshDeserialize; -use byteorder::{ByteOrder, LittleEndian}; -use ff_uint::{Num, PrimeField}; - -use crate::circuit::{cs::Gate, lc::Index}; - -use super::{engines::Engine, Parameters}; - -pub struct PrecomputedData { - pub(crate) gates: Rc>>, -} - -impl PrecomputedData { - pub(crate) fn prepare(params: &Parameters) -> Self { - PrecomputedData { - gates: PrecomputedData::parse_gates(params) - } - } - - pub(crate) fn parse_gates(params: &Parameters) -> Rc>> { - Rc::new( - GateStreamedIterator( - brotli::Decompressor::new(¶ms.2 as &[u8], 4096), - PhantomData::, - ) - .collect::>(), - ) - } -} - -struct GateStreamedIterator(pub R, pub PhantomData); - -fn read_u32(r: &mut R) -> std::io::Result { - let mut b = [0; 4]; - r.read_exact(&mut b)?; - Ok(LittleEndian::read_u32(&b)) -} - -fn read_gate_part( - r: &mut R, -) -> std::io::Result, Index)>> { - let sz = read_u32(r)? as usize; - - let item_size = - std::mem::size_of::() + std::mem::size_of::() + std::mem::size_of::(); - let mut buf = vec![0; sz * item_size]; - r.read_exact(&mut buf)?; - let mut buf_ref = &buf[..]; - let mut gate_part = Vec::with_capacity(sz); - for _ in 0..sz { - let a = Num::::deserialize(&mut buf_ref)?; - let b1 = u8::deserialize(&mut buf_ref)?; - let b2 = u32::deserialize(&mut buf_ref)?; - let b = match b1 { - 0 => Index::Input(b2), - 1 => Index::Aux(b2), - _ => { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "enum elements overflow", - )) - } - }; - gate_part.push((a, b)); - } - Ok(gate_part) -} - -impl Iterator for GateStreamedIterator { - type Item = Gate; - fn next(&mut self) -> Option { - let a = read_gate_part(&mut self.0).ok()?; - let b = read_gate_part(&mut self.0).ok()?; - let c = read_gate_part(&mut self.0).ok()?; - Some(Gate(a, b, c)) - } -} diff --git a/fawkes-crypto/src/backend/bellman_groth16/prover.rs b/fawkes-crypto/src/backend/bellman_groth16/prover.rs index e38263f..2dc1bce 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/prover.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/prover.rs @@ -66,30 +66,7 @@ pub fn prove<'a, E: Engine, Pub: Signal>, Sec: Signal (Vec>, Proof) { - let rcs = params.get_witness_rcs(); - prove_internal(params, input_pub, input_sec, circuit, &rcs) -} - -#[cfg(feature = "rand_support")] -pub fn prove_precomputed<'a, E: Engine, Pub: Signal>, Sec: Signal>, C: Fn(Pub, Sec)>( - params: &'a Parameters, - input_pub: &Pub::Value, - input_sec: &Sec::Value, - circuit: C, - precomputed: &PrecomputedData -) -> (Vec>, Proof) { - let rcs = params.get_witness_rcs_precomputed(precomputed); - prove_internal(params, input_pub, input_sec, circuit, &rcs) -} - -#[cfg(feature = "rand_support")] -fn prove_internal<'a, E: Engine, Pub: Signal>, Sec: Signal>, C: Fn(Pub, Sec)>( - params: &'a Parameters, - input_pub: &Pub::Value, - input_sec: &Sec::Value, - circuit: C, - rcs: &RCS> -) -> (Vec>, Proof) { + let ref rcs = params.get_witness_rcs(); let signal_pub = Pub::alloc(rcs, Some(input_pub)); signal_pub.inputize(); let signal_sec = Sec::alloc(rcs, Some(input_sec)); diff --git a/fawkes-crypto/src/circuit/r1cs/cs.rs b/fawkes-crypto/src/circuit/r1cs/cs.rs index 0ee28a5..2b8a74a 100644 --- a/fawkes-crypto/src/circuit/r1cs/cs.rs +++ b/fawkes-crypto/src/circuit/r1cs/cs.rs @@ -9,6 +9,7 @@ use crate::{ use std::{cell::RefCell, marker::PhantomData, rc::Rc}; use bit_vec::BitVec; +use byteorder::{ByteOrder, LittleEndian}; pub type RCS = Rc>; @@ -27,13 +28,13 @@ pub struct Gate( pub trait CS: Clone { type Fr: PrimeField; type LC: AbstractLC; - type GateIterator<'g>: Iterator> where Self: 'g; + type GateIterator: Iterator>; fn num_gates(&self) -> usize; fn num_input(&self) -> usize; fn num_aux(&self) -> usize; fn get_value(&self, index:Index) -> Option>; - fn get_gate_iterator<'g>(&'g self) -> Self::GateIterator<'g>; + fn get_gate_iterator(&self) -> Self::GateIterator; // a*b === c fn enforce(a: &CNum, b: &CNum, c: &CNum); @@ -99,13 +100,13 @@ pub struct WitnessCS<'a, Fr: PrimeField> { pub values_input: Vec>, pub values_aux: Vec>, pub num_gates: usize, - pub gates_data: Rc>>, + pub gates_data: &'a[u8], pub const_tracker: &'a BitVec, pub const_tracker_index: usize } impl<'a, Fr: PrimeField> WitnessCS<'a, Fr> { - pub fn new(num_gates:usize, gates_data: Rc>>, const_tracker: &'a BitVec) -> Self { + pub fn new(num_gates:usize, gates_data: &'a[u8], const_tracker: &'a BitVec) -> Self { Self { values_input: vec![Num::ONE], values_aux: vec![], @@ -116,7 +117,7 @@ impl<'a, Fr: PrimeField> WitnessCS<'a, Fr> { } } - pub fn rc_new(num_gates:usize, gates_data: Rc>>, const_tracker: &'a BitVec) -> RCS { + pub fn rc_new(num_gates:usize, gates_data: &'a[u8], const_tracker: &'a BitVec) -> RCS { Rc::new(RefCell::new(Self::new(num_gates, gates_data, const_tracker))) } } @@ -125,7 +126,7 @@ impl<'a, Fr: PrimeField> WitnessCS<'a, Fr> { impl CS for DebugCS { type Fr = Fr; type LC = LC; - type GateIterator<'g> = core::iter::Empty<&'g Gate> where Self: 'g; + type GateIterator = core::iter::Empty>; fn num_gates(&self) -> usize { self.num_gates @@ -142,7 +143,7 @@ impl CS for DebugCS { None } - fn get_gate_iterator<'g>(&'g self) -> Self::GateIterator<'g> { + fn get_gate_iterator(&self) -> Self::GateIterator { std::unimplemented!(); } @@ -179,10 +180,52 @@ impl CS for DebugCS { } + +pub struct GateStreamedIterator(R,PhantomData); + +fn read_u32(r: &mut R) -> std::io::Result { + let mut b = [0; 4]; + r.read_exact(&mut b)?; + Ok(LittleEndian::read_u32(&b)) +} + + +fn read_gate_part(r: &mut R) -> std::io::Result, Index)>> { + let sz = read_u32(r)? as usize; + + let item_size = std::mem::size_of::() + std::mem::size_of::() + std::mem::size_of::(); + let mut buf = vec![0; sz*item_size]; + r.read_exact(&mut buf)?; + let mut buf_ref = &buf[..]; + let mut gate_part = Vec::with_capacity(sz); + for _ in 0..sz { + let a = Num::::deserialize(&mut buf_ref)?; + let b1 = u8::deserialize(&mut buf_ref)?; + let b2 = u32::deserialize(&mut buf_ref)?; + let b = match b1 { + 0 => Index::Input(b2), + 1 => Index::Aux(b2), + _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "enum elements overflow")) + }; + gate_part.push((a,b)); + } + Ok(gate_part) +} + +impl Iterator for GateStreamedIterator { + type Item = Gate; + fn next(&mut self) -> Option { + let a = read_gate_part(&mut self.0).ok()?; + let b = read_gate_part(&mut self.0).ok()?; + let c = read_gate_part(&mut self.0).ok()?; + Some(Gate(a,b,c)) + } +} + impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { type Fr = Fr; type LC = ZeroLC; - type GateIterator<'g> = core::slice::Iter<'g, Gate> where Self: 'g; + type GateIterator = GateStreamedIterator>; fn num_gates(&self) -> usize { self.num_gates @@ -202,8 +245,8 @@ impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { } } - fn get_gate_iterator<'g>(&'g self) -> Self::GateIterator<'g> { - self.gates_data.iter() + fn get_gate_iterator(&self) -> Self::GateIterator { + GateStreamedIterator(brotli::Decompressor::new(self.gates_data, 4096), PhantomData) } fn enforce(_: &CNum, _: &CNum, _: &CNum) { @@ -236,7 +279,7 @@ impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { impl CS for BuildCS { type Fr = Fr; type LC = LC; - type GateIterator<'g> = core::slice::Iter<'g, Gate> where Self: 'g; + type GateIterator = std::vec::IntoIter>; fn num_gates(&self) -> usize { self.gates.len() @@ -253,8 +296,8 @@ impl CS for BuildCS { None } - fn get_gate_iterator<'g>(&'g self) -> Self::GateIterator<'g> { - self.gates.iter() + fn get_gate_iterator(&self) -> Self::GateIterator { + self.gates.clone().into_iter() } // a*b === c diff --git a/fawkes-crypto/tests/circuit_ecc.rs b/fawkes-crypto/tests/circuit_ecc.rs index 016d09e..45848bd 100644 --- a/fawkes-crypto/tests/circuit_ecc.rs +++ b/fawkes-crypto/tests/circuit_ecc.rs @@ -1,5 +1,5 @@ -use fawkes_crypto_zkbob::{ +use fawkes_crypto::{ circuit::{bitify::c_into_bits_le_strict, cs::DebugCS, ecc::*, num::CNum, cs::CS}, native::ecc::*, ff_uint::Num, diff --git a/fawkes-crypto/tests/circuit_poseidon.rs b/fawkes-crypto/tests/circuit_poseidon.rs index b92cc04..0b56df2 100644 --- a/fawkes-crypto/tests/circuit_poseidon.rs +++ b/fawkes-crypto/tests/circuit_poseidon.rs @@ -1,5 +1,5 @@ -use fawkes_crypto_zkbob::{ +use fawkes_crypto::{ circuit::{cs::{DebugCS, CS}, poseidon::*, num::CNum}, core::{signal::Signal, sizedvec::SizedVec}, engines::bn256::Fr, From 5e9d549b51c9bf86df02cfec780f7131d0da3424 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Wed, 5 Apr 2023 17:13:20 +0300 Subject: [PATCH 3/6] [WIP] Refactor gates iterator --- .../src/backend/bellman_groth16/mod.rs | 25 +++- .../src/backend/bellman_groth16/prover.rs | 23 ++++ fawkes-crypto/src/circuit/r1cs/cs.rs | 86 +++--------- fawkes-crypto/src/circuit/r1cs/gates.rs | 128 ++++++++++++++++++ fawkes-crypto/src/circuit/r1cs/mod.rs | 3 +- 5 files changed, 189 insertions(+), 76 deletions(-) create mode 100644 fawkes-crypto/src/circuit/r1cs/gates.rs diff --git a/fawkes-crypto/src/backend/bellman_groth16/mod.rs b/fawkes-crypto/src/backend/bellman_groth16/mod.rs index cf40a68..7424d91 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/mod.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/mod.rs @@ -1,7 +1,7 @@ use crate::{ circuit::{ cs::{RCS, WitnessCS, CS}, - lc::{Index} + lc::{Index}, gates::{GateSource, Gate, GateIterator} }, core::signal::Signal, ff_uint::{Num, PrimeField}, @@ -92,9 +92,9 @@ impl> bellman::Circuit for BellmanCS { for (i,g) in cs.get_gate_iterator().enumerate() { bellman_cs.enforce( || format!("constraint {}", i), - |_| convert_lc::(&g.0, &variables_input, &variables_aux), - |_| convert_lc::(&g.1, &variables_input, &variables_aux), - |_| convert_lc::(&g.2, &variables_input, &variables_aux), + |_| convert_lc::(&g.as_ref().0, &variables_input, &variables_aux), + |_| convert_lc::(&g.as_ref().1, &variables_input, &variables_aux), + |_| convert_lc::(&g.as_ref().2, &variables_input, &variables_aux), ); } Ok(()) @@ -143,8 +143,12 @@ impl Parameters { verifier::VK::from_bellman(&self.0.vk) } - pub fn get_witness_rcs(&self)->RCS> { - WitnessCS::rc_new(self.1 as usize, &self.2, &self.3) + pub fn get_witness_rcs(&self) -> RCS> { + WitnessCS::rc_new(self.1 as usize, GateSource::Compressed(&self.2), &self.3) + } + + pub fn get_witness_rcs_precomputed<'a>(&'a self, data: &'a PrecomputedData) -> RCS> { + WitnessCS::rc_new(self.1 as usize, GateSource::Parsed(&data.gates), &self.3) } pub fn write(&self, writer: &mut W) -> std::io::Result<()> { @@ -174,4 +178,13 @@ impl Parameters { Ok(Self(e0, e1, e2, e3)) } + pub fn precompute(&self) -> PrecomputedData { + PrecomputedData { + gates: GateIterator::new(&GateSource::Compressed(&self.2)).map(|g| g.gate()).collect() + } + } +} + +pub struct PrecomputedData { + gates: Vec> } diff --git a/fawkes-crypto/src/backend/bellman_groth16/prover.rs b/fawkes-crypto/src/backend/bellman_groth16/prover.rs index 2dc1bce..b753ad1 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/prover.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/prover.rs @@ -67,6 +67,29 @@ pub fn prove<'a, E: Engine, Pub: Signal>, Sec: Signal (Vec>, Proof) { let ref rcs = params.get_witness_rcs(); + prove_internal(params, input_pub, input_sec, circuit, rcs) +} + +#[cfg(feature = "rand_support")] +pub fn prove_precomputed<'a, E: Engine, Pub: Signal>, Sec: Signal>, C: Fn(Pub, Sec)>( + params: &'a Parameters, + input_pub: &Pub::Value, + input_sec: &Sec::Value, + circuit: C, + precomputed: &'a PrecomputedData, +) -> (Vec>, Proof) { + let ref rcs = params.get_witness_rcs_precomputed(precomputed); + prove_internal(params, input_pub, input_sec, circuit, rcs) +} + +#[cfg(feature = "rand_support")] +fn prove_internal<'a, E: Engine, Pub: Signal>, Sec: Signal>, C: Fn(Pub, Sec)>( + params: &'a Parameters, + input_pub: &Pub::Value, + input_sec: &Sec::Value, + circuit: C, + rcs: &RCS> +) -> (Vec>, Proof) { let signal_pub = Pub::alloc(rcs, Some(input_pub)); signal_pub.inputize(); let signal_sec = Sec::alloc(rcs, Some(input_sec)); diff --git a/fawkes-crypto/src/circuit/r1cs/cs.rs b/fawkes-crypto/src/circuit/r1cs/cs.rs index 2b8a74a..968641d 100644 --- a/fawkes-crypto/src/circuit/r1cs/cs.rs +++ b/fawkes-crypto/src/circuit/r1cs/cs.rs @@ -9,32 +9,22 @@ use crate::{ use std::{cell::RefCell, marker::PhantomData, rc::Rc}; use bit_vec::BitVec; -use byteorder::{ByteOrder, LittleEndian}; pub type RCS = Rc>; -#[cfg(feature="borsh_support")] -use crate::borsh::{BorshSerialize, BorshDeserialize}; +use super::gates::{Gate, self, GateSource, GateWrapper}; -#[derive(Clone, Debug)] -#[cfg_attr(feature = "borsh_support", derive(BorshSerialize, BorshDeserialize))] -pub struct Gate( - pub Vec<(Num, Index)>, - pub Vec<(Num, Index)>, - pub Vec<(Num, Index)>, -); - pub trait CS: Clone { type Fr: PrimeField; type LC: AbstractLC; - type GateIterator: Iterator>; + type GateIterator<'a>: Iterator> where Self: 'a; fn num_gates(&self) -> usize; fn num_input(&self) -> usize; fn num_aux(&self) -> usize; fn get_value(&self, index:Index) -> Option>; - fn get_gate_iterator(&self) -> Self::GateIterator; + fn get_gate_iterator<'a>(&'a self) -> Self::GateIterator<'a>; // a*b === c fn enforce(a: &CNum, b: &CNum, c: &CNum); @@ -100,25 +90,25 @@ pub struct WitnessCS<'a, Fr: PrimeField> { pub values_input: Vec>, pub values_aux: Vec>, pub num_gates: usize, - pub gates_data: &'a[u8], + pub gates: GateSource<'a, Fr>, pub const_tracker: &'a BitVec, pub const_tracker_index: usize } impl<'a, Fr: PrimeField> WitnessCS<'a, Fr> { - pub fn new(num_gates:usize, gates_data: &'a[u8], const_tracker: &'a BitVec) -> Self { + pub fn new(num_gates:usize, gates: GateSource<'a, Fr>, const_tracker: &'a BitVec) -> Self { Self { values_input: vec![Num::ONE], values_aux: vec![], num_gates, - gates_data, + gates, const_tracker, const_tracker_index: 0 } } - pub fn rc_new(num_gates:usize, gates_data: &'a[u8], const_tracker: &'a BitVec) -> RCS { - Rc::new(RefCell::new(Self::new(num_gates, gates_data, const_tracker))) + pub fn rc_new(num_gates:usize, gates: GateSource<'a, Fr>, const_tracker: &'a BitVec) -> RCS { + Rc::new(RefCell::new(Self::new(num_gates, gates, const_tracker))) } } @@ -126,7 +116,7 @@ impl<'a, Fr: PrimeField> WitnessCS<'a, Fr> { impl CS for DebugCS { type Fr = Fr; type LC = LC; - type GateIterator = core::iter::Empty>; + type GateIterator<'a> = core::iter::Empty> where Self: 'a; fn num_gates(&self) -> usize { self.num_gates @@ -143,7 +133,7 @@ impl CS for DebugCS { None } - fn get_gate_iterator(&self) -> Self::GateIterator { + fn get_gate_iterator<'a>(&'a self) -> Self::GateIterator<'a> { std::unimplemented!(); } @@ -180,52 +170,10 @@ impl CS for DebugCS { } - -pub struct GateStreamedIterator(R,PhantomData); - -fn read_u32(r: &mut R) -> std::io::Result { - let mut b = [0; 4]; - r.read_exact(&mut b)?; - Ok(LittleEndian::read_u32(&b)) -} - - -fn read_gate_part(r: &mut R) -> std::io::Result, Index)>> { - let sz = read_u32(r)? as usize; - - let item_size = std::mem::size_of::() + std::mem::size_of::() + std::mem::size_of::(); - let mut buf = vec![0; sz*item_size]; - r.read_exact(&mut buf)?; - let mut buf_ref = &buf[..]; - let mut gate_part = Vec::with_capacity(sz); - for _ in 0..sz { - let a = Num::::deserialize(&mut buf_ref)?; - let b1 = u8::deserialize(&mut buf_ref)?; - let b2 = u32::deserialize(&mut buf_ref)?; - let b = match b1 { - 0 => Index::Input(b2), - 1 => Index::Aux(b2), - _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "enum elements overflow")) - }; - gate_part.push((a,b)); - } - Ok(gate_part) -} - -impl Iterator for GateStreamedIterator { - type Item = Gate; - fn next(&mut self) -> Option { - let a = read_gate_part(&mut self.0).ok()?; - let b = read_gate_part(&mut self.0).ok()?; - let c = read_gate_part(&mut self.0).ok()?; - Some(Gate(a,b,c)) - } -} - -impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { +impl<'a, Fr: PrimeField + 'a> CS for WitnessCS<'a, Fr> { type Fr = Fr; type LC = ZeroLC; - type GateIterator = GateStreamedIterator>; + type GateIterator<'b> = gates::GateIterator<'b, Fr> where Self: 'b; fn num_gates(&self) -> usize { self.num_gates @@ -245,8 +193,8 @@ impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { } } - fn get_gate_iterator(&self) -> Self::GateIterator { - GateStreamedIterator(brotli::Decompressor::new(self.gates_data, 4096), PhantomData) + fn get_gate_iterator(&self) -> Self::GateIterator<'a> { + gates::GateIterator::new(&self.gates) } fn enforce(_: &CNum, _: &CNum, _: &CNum) { @@ -279,7 +227,7 @@ impl<'a, Fr: PrimeField> CS for WitnessCS<'a, Fr> { impl CS for BuildCS { type Fr = Fr; type LC = LC; - type GateIterator = std::vec::IntoIter>; + type GateIterator<'a> = std::vec::IntoIter> where Self: 'a; fn num_gates(&self) -> usize { self.gates.len() @@ -296,8 +244,8 @@ impl CS for BuildCS { None } - fn get_gate_iterator(&self) -> Self::GateIterator { - self.gates.clone().into_iter() + fn get_gate_iterator<'a>(&'a self) -> Self::GateIterator<'a> { + self.gates.iter().map(|g| g.wrap()).collect::>().into_iter() } // a*b === c diff --git a/fawkes-crypto/src/circuit/r1cs/gates.rs b/fawkes-crypto/src/circuit/r1cs/gates.rs new file mode 100644 index 0000000..2327884 --- /dev/null +++ b/fawkes-crypto/src/circuit/r1cs/gates.rs @@ -0,0 +1,128 @@ +use std::marker::PhantomData; + +#[cfg(feature="borsh_support")] +use borsh::{BorshSerialize, BorshDeserialize}; + +use byteorder::{LittleEndian, ByteOrder}; +use ff_uint::{PrimeField, Num}; + +use super::lc::Index; + + +#[derive(Clone, Debug)] +#[cfg_attr(feature = "borsh_support", derive(BorshSerialize, BorshDeserialize))] +pub struct Gate( + pub Vec<(Num, Index)>, + pub Vec<(Num, Index)>, + pub Vec<(Num, Index)>, +); + +impl Gate { + pub fn wrap<'a>(&'a self) -> GateWrapper<'a, Fr> { + GateWrapper::Ref(self) + } +} + +#[derive(Clone, Debug)] +pub enum GateSource<'a, Fr: PrimeField> { + Compressed(&'a [u8]), + Parsed(&'a Vec>) +} + +pub enum GateIterator<'a, Fr: PrimeField> { + Streamed(GateStreamedIterator>), + Precomputed(std::slice::Iter<'a, Gate>) +} + +impl<'a, Fr: PrimeField> GateIterator<'a, Fr> { + pub fn new(source: &GateSource<'a, Fr>) -> Self { + match source { + GateSource::Compressed(bytes) => { + Self::Streamed(GateStreamedIterator(brotli::Decompressor::new(bytes, 4096), PhantomData)) + }, + GateSource::Parsed(vec) => { + Self::Precomputed(vec.iter()) + } + } + } +} + + +impl<'a, Fr: PrimeField> Iterator for GateIterator<'a, Fr> { + type Item = GateWrapper<'a, Fr>; + fn next(&mut self) -> Option { + match self { + Self::Streamed(iter) => { + iter.next().map(|g| GateWrapper::Value(g)) + } + Self::Precomputed(iter) => { + iter.next().map(|g| GateWrapper::Ref(g)) + }, + } + } +} + + +pub struct GateStreamedIterator(R, PhantomData); + +fn read_u32(r: &mut R) -> std::io::Result { + let mut b = [0; 4]; + r.read_exact(&mut b)?; + Ok(LittleEndian::read_u32(&b)) +} + + +fn read_gate_part(r: &mut R) -> std::io::Result, Index)>> { + let sz = read_u32(r)? as usize; + + let item_size = std::mem::size_of::() + std::mem::size_of::() + std::mem::size_of::(); + let mut buf = vec![0; sz*item_size]; + r.read_exact(&mut buf)?; + let mut buf_ref = &buf[..]; + let mut gate_part = Vec::with_capacity(sz); + for _ in 0..sz { + let a = Num::::deserialize(&mut buf_ref)?; + let b1 = u8::deserialize(&mut buf_ref)?; + let b2 = u32::deserialize(&mut buf_ref)?; + let b = match b1 { + 0 => Index::Input(b2), + 1 => Index::Aux(b2), + _ => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "enum elements overflow")) + }; + gate_part.push((a,b)); + } + Ok(gate_part) +} + +impl Iterator for GateStreamedIterator { + type Item = Gate; + fn next(&mut self) -> Option { + let a = read_gate_part(&mut self.0).ok()?; + let b = read_gate_part(&mut self.0).ok()?; + let c = read_gate_part(&mut self.0).ok()?; + Some(Gate(a,b,c)) + } +} + +pub enum GateWrapper<'a, Fr: PrimeField> { + Value(Gate), + Ref(&'a Gate) +} + +impl<'a, Fr: PrimeField> GateWrapper<'a, Fr> { + pub fn gate(self) -> Gate { + match self { + Self::Value(v) => v, + Self::Ref(r) => r.clone() + } + } +} + +impl<'a, Fr: PrimeField> AsRef> for GateWrapper<'a, Fr> { + fn as_ref(&self) -> &Gate { + match self { + Self::Value(val) => &val, + Self::Ref(reference) => reference + } + } +} \ No newline at end of file diff --git a/fawkes-crypto/src/circuit/r1cs/mod.rs b/fawkes-crypto/src/circuit/r1cs/mod.rs index 26be863..726ef18 100644 --- a/fawkes-crypto/src/circuit/r1cs/mod.rs +++ b/fawkes-crypto/src/circuit/r1cs/mod.rs @@ -1,4 +1,5 @@ pub mod bool; pub mod cs; pub mod num; -pub mod lc; \ No newline at end of file +pub mod lc; +pub mod gates; \ No newline at end of file From 15530b3e6c040d48efe8a1b57462295a8a7a45ca Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Thu, 6 Apr 2023 11:16:17 +0300 Subject: [PATCH 4/6] Refactor code --- .../src/backend/bellman_groth16/mod.rs | 8 +++---- .../src/backend/bellman_groth16/prover.rs | 4 ++-- fawkes-crypto/src/circuit/r1cs/cs.rs | 12 +++++----- fawkes-crypto/src/circuit/r1cs/gates.rs | 24 ++++++++----------- fawkes-crypto/tests/circuit_ecc.rs | 2 +- fawkes-crypto/tests/circuit_poseidon.rs | 2 +- 6 files changed, 24 insertions(+), 28 deletions(-) diff --git a/fawkes-crypto/src/backend/bellman_groth16/mod.rs b/fawkes-crypto/src/backend/bellman_groth16/mod.rs index 7424d91..9ec2e5b 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/mod.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/mod.rs @@ -92,9 +92,9 @@ impl> bellman::Circuit for BellmanCS { for (i,g) in cs.get_gate_iterator().enumerate() { bellman_cs.enforce( || format!("constraint {}", i), - |_| convert_lc::(&g.as_ref().0, &variables_input, &variables_aux), - |_| convert_lc::(&g.as_ref().1, &variables_input, &variables_aux), - |_| convert_lc::(&g.as_ref().2, &variables_input, &variables_aux), + |_| convert_lc::(&g.0, &variables_input, &variables_aux), + |_| convert_lc::(&g.1, &variables_input, &variables_aux), + |_| convert_lc::(&g.2, &variables_input, &variables_aux), ); } Ok(()) @@ -148,7 +148,7 @@ impl Parameters { } pub fn get_witness_rcs_precomputed<'a>(&'a self, data: &'a PrecomputedData) -> RCS> { - WitnessCS::rc_new(self.1 as usize, GateSource::Parsed(&data.gates), &self.3) + WitnessCS::rc_new(self.1 as usize, GateSource::Precomputed(&data.gates), &self.3) } pub fn write(&self, writer: &mut W) -> std::io::Result<()> { diff --git a/fawkes-crypto/src/backend/bellman_groth16/prover.rs b/fawkes-crypto/src/backend/bellman_groth16/prover.rs index b753ad1..174b962 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/prover.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/prover.rs @@ -66,7 +66,7 @@ pub fn prove<'a, E: Engine, Pub: Signal>, Sec: Signal (Vec>, Proof) { - let ref rcs = params.get_witness_rcs(); + let rcs = ¶ms.get_witness_rcs(); prove_internal(params, input_pub, input_sec, circuit, rcs) } @@ -78,7 +78,7 @@ pub fn prove_precomputed<'a, E: Engine, Pub: Signal>, Sec: circuit: C, precomputed: &'a PrecomputedData, ) -> (Vec>, Proof) { - let ref rcs = params.get_witness_rcs_precomputed(precomputed); + let rcs = ¶ms.get_witness_rcs_precomputed(precomputed); prove_internal(params, input_pub, input_sec, circuit, rcs) } diff --git a/fawkes-crypto/src/circuit/r1cs/cs.rs b/fawkes-crypto/src/circuit/r1cs/cs.rs index 968641d..8fce0da 100644 --- a/fawkes-crypto/src/circuit/r1cs/cs.rs +++ b/fawkes-crypto/src/circuit/r1cs/cs.rs @@ -24,7 +24,7 @@ pub trait CS: Clone { fn num_input(&self) -> usize; fn num_aux(&self) -> usize; fn get_value(&self, index:Index) -> Option>; - fn get_gate_iterator<'a>(&'a self) -> Self::GateIterator<'a>; + fn get_gate_iterator(&self) -> Self::GateIterator<'_>; // a*b === c fn enforce(a: &CNum, b: &CNum, c: &CNum); @@ -133,7 +133,7 @@ impl CS for DebugCS { None } - fn get_gate_iterator<'a>(&'a self) -> Self::GateIterator<'a> { + fn get_gate_iterator(&self) -> Self::GateIterator<'_> { std::unimplemented!(); } @@ -193,7 +193,7 @@ impl<'a, Fr: PrimeField + 'a> CS for WitnessCS<'a, Fr> { } } - fn get_gate_iterator(&self) -> Self::GateIterator<'a> { + fn get_gate_iterator(&self) -> Self::GateIterator<'_> { gates::GateIterator::new(&self.gates) } @@ -227,7 +227,7 @@ impl<'a, Fr: PrimeField + 'a> CS for WitnessCS<'a, Fr> { impl CS for BuildCS { type Fr = Fr; type LC = LC; - type GateIterator<'a> = std::vec::IntoIter> where Self: 'a; + type GateIterator<'b> = gates::GateIterator<'b, Fr> where Self: 'b; fn num_gates(&self) -> usize { self.gates.len() @@ -244,8 +244,8 @@ impl CS for BuildCS { None } - fn get_gate_iterator<'a>(&'a self) -> Self::GateIterator<'a> { - self.gates.iter().map(|g| g.wrap()).collect::>().into_iter() + fn get_gate_iterator(&self) -> Self::GateIterator<'_> { + gates::GateIterator::new(&GateSource::Precomputed(&self.gates)) } // a*b === c diff --git a/fawkes-crypto/src/circuit/r1cs/gates.rs b/fawkes-crypto/src/circuit/r1cs/gates.rs index 2327884..efd4fd7 100644 --- a/fawkes-crypto/src/circuit/r1cs/gates.rs +++ b/fawkes-crypto/src/circuit/r1cs/gates.rs @@ -1,4 +1,4 @@ -use std::marker::PhantomData; +use std::{marker::PhantomData, ops::Deref}; #[cfg(feature="borsh_support")] use borsh::{BorshSerialize, BorshDeserialize}; @@ -17,20 +17,14 @@ pub struct Gate( pub Vec<(Num, Index)>, ); -impl Gate { - pub fn wrap<'a>(&'a self) -> GateWrapper<'a, Fr> { - GateWrapper::Ref(self) - } -} - #[derive(Clone, Debug)] pub enum GateSource<'a, Fr: PrimeField> { Compressed(&'a [u8]), - Parsed(&'a Vec>) + Precomputed(&'a Vec>) } pub enum GateIterator<'a, Fr: PrimeField> { - Streamed(GateStreamedIterator>), + Streamed(Box>>), Precomputed(std::slice::Iter<'a, Gate>) } @@ -38,9 +32,9 @@ impl<'a, Fr: PrimeField> GateIterator<'a, Fr> { pub fn new(source: &GateSource<'a, Fr>) -> Self { match source { GateSource::Compressed(bytes) => { - Self::Streamed(GateStreamedIterator(brotli::Decompressor::new(bytes, 4096), PhantomData)) + Self::Streamed(Box::new(GateStreamedIterator(brotli::Decompressor::new(bytes, 4096), PhantomData))) }, - GateSource::Parsed(vec) => { + GateSource::Precomputed(vec) => { Self::Precomputed(vec.iter()) } } @@ -118,10 +112,12 @@ impl<'a, Fr: PrimeField> GateWrapper<'a, Fr> { } } -impl<'a, Fr: PrimeField> AsRef> for GateWrapper<'a, Fr> { - fn as_ref(&self) -> &Gate { +impl<'a, Fr: PrimeField> Deref for GateWrapper<'a, Fr> { + type Target = Gate; + + fn deref(&self) -> &Self::Target { match self { - Self::Value(val) => &val, + Self::Value(val) => val, Self::Ref(reference) => reference } } diff --git a/fawkes-crypto/tests/circuit_ecc.rs b/fawkes-crypto/tests/circuit_ecc.rs index 45848bd..016d09e 100644 --- a/fawkes-crypto/tests/circuit_ecc.rs +++ b/fawkes-crypto/tests/circuit_ecc.rs @@ -1,5 +1,5 @@ -use fawkes_crypto::{ +use fawkes_crypto_zkbob::{ circuit::{bitify::c_into_bits_le_strict, cs::DebugCS, ecc::*, num::CNum, cs::CS}, native::ecc::*, ff_uint::Num, diff --git a/fawkes-crypto/tests/circuit_poseidon.rs b/fawkes-crypto/tests/circuit_poseidon.rs index 0b56df2..b92cc04 100644 --- a/fawkes-crypto/tests/circuit_poseidon.rs +++ b/fawkes-crypto/tests/circuit_poseidon.rs @@ -1,5 +1,5 @@ -use fawkes_crypto::{ +use fawkes_crypto_zkbob::{ circuit::{cs::{DebugCS, CS}, poseidon::*, num::CNum}, core::{signal::Signal, sizedvec::SizedVec}, engines::bn256::Fr, From 09028648d4d8d0f9ab3cd445c9492cf82810cfab Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Thu, 6 Apr 2023 16:01:20 +0300 Subject: [PATCH 5/6] Evaluate gates memory size --- .../src/backend/bellman_groth16/mod.rs | 6 +- fawkes-crypto/src/circuit/r1cs/gates.rs | 70 ++++++++++++------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/fawkes-crypto/src/backend/bellman_groth16/mod.rs b/fawkes-crypto/src/backend/bellman_groth16/mod.rs index 9ec2e5b..5b07852 100644 --- a/fawkes-crypto/src/backend/bellman_groth16/mod.rs +++ b/fawkes-crypto/src/backend/bellman_groth16/mod.rs @@ -1,7 +1,7 @@ use crate::{ circuit::{ cs::{RCS, WitnessCS, CS}, - lc::{Index}, gates::{GateSource, Gate, GateIterator} + lc::{Index}, gates::{GateSource, Gate, GateIterator, evaluate_gates_memory_size} }, core::signal::Signal, ff_uint::{Num, PrimeField}, @@ -183,6 +183,10 @@ impl Parameters { gates: GateIterator::new(&GateSource::Compressed(&self.2)).map(|g| g.gate()).collect() } } + + pub fn precompute_memory_size(&self) -> std::io::Result { + evaluate_gates_memory_size::(self.1 as usize, &self.2) + } } pub struct PrecomputedData { diff --git a/fawkes-crypto/src/circuit/r1cs/gates.rs b/fawkes-crypto/src/circuit/r1cs/gates.rs index efd4fd7..ea29795 100644 --- a/fawkes-crypto/src/circuit/r1cs/gates.rs +++ b/fawkes-crypto/src/circuit/r1cs/gates.rs @@ -1,4 +1,4 @@ -use std::{marker::PhantomData, ops::Deref}; +use std::{marker::PhantomData, ops::Deref, io::Read}; #[cfg(feature="borsh_support")] use borsh::{BorshSerialize, BorshDeserialize}; @@ -41,6 +41,30 @@ impl<'a, Fr: PrimeField> GateIterator<'a, Fr> { } } +pub enum GateWrapper<'a, Fr: PrimeField> { + Value(Gate), + Ref(&'a Gate) +} + +impl<'a, Fr: PrimeField> GateWrapper<'a, Fr> { + pub fn gate(self) -> Gate { + match self { + Self::Value(v) => v, + Self::Ref(r) => r.clone() + } + } +} + +impl<'a, Fr: PrimeField> Deref for GateWrapper<'a, Fr> { + type Target = Gate; + + fn deref(&self) -> &Self::Target { + match self { + Self::Value(val) => val, + Self::Ref(reference) => reference + } + } +} impl<'a, Fr: PrimeField> Iterator for GateIterator<'a, Fr> { type Item = GateWrapper<'a, Fr>; @@ -56,6 +80,25 @@ impl<'a, Fr: PrimeField> Iterator for GateIterator<'a, Fr> { } } +pub fn evaluate_gates_memory_size( + num_gates: usize, + bytes: &[u8], +) -> std::io::Result { + let r = &mut brotli::Decompressor::new(bytes, 4096); + let mut memory_size = 0; + let item_size = std::mem::size_of::() + std::mem::size_of::() + std::mem::size_of::(); + let gate_size = std::mem::size_of::() + std::mem::size_of::(); + for _ in 0..num_gates { + for _ in 0..3 { + let count = read_u32(r)? as usize; + memory_size += count * gate_size; + + let mut buf = vec![0; count * item_size]; + r.read_exact(&mut buf)?; + } + } + Ok(memory_size) +} pub struct GateStreamedIterator(R, PhantomData); @@ -96,29 +139,4 @@ impl Iterator for GateStreamedIterator { let c = read_gate_part(&mut self.0).ok()?; Some(Gate(a,b,c)) } -} - -pub enum GateWrapper<'a, Fr: PrimeField> { - Value(Gate), - Ref(&'a Gate) -} - -impl<'a, Fr: PrimeField> GateWrapper<'a, Fr> { - pub fn gate(self) -> Gate { - match self { - Self::Value(v) => v, - Self::Ref(r) => r.clone() - } - } -} - -impl<'a, Fr: PrimeField> Deref for GateWrapper<'a, Fr> { - type Target = Gate; - - fn deref(&self) -> &Self::Target { - match self { - Self::Value(val) => val, - Self::Ref(reference) => reference - } - } } \ No newline at end of file From 2bc3e766239e06c8f380675c6a80d36ad317ed02 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Thu, 6 Apr 2023 16:03:20 +0300 Subject: [PATCH 6/6] Minor fix --- fawkes-crypto/src/circuit/r1cs/cs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fawkes-crypto/src/circuit/r1cs/cs.rs b/fawkes-crypto/src/circuit/r1cs/cs.rs index 8fce0da..2382e3e 100644 --- a/fawkes-crypto/src/circuit/r1cs/cs.rs +++ b/fawkes-crypto/src/circuit/r1cs/cs.rs @@ -227,7 +227,7 @@ impl<'a, Fr: PrimeField + 'a> CS for WitnessCS<'a, Fr> { impl CS for BuildCS { type Fr = Fr; type LC = LC; - type GateIterator<'b> = gates::GateIterator<'b, Fr> where Self: 'b; + type GateIterator<'a> = gates::GateIterator<'a, Fr> where Self: 'a; fn num_gates(&self) -> usize { self.gates.len()