From 6e7cc4e930c2160c8e619bd0145dd655bbd1abba Mon Sep 17 00:00:00 2001 From: Igor Gulamov Date: Wed, 25 Jan 2023 00:07:40 +0400 Subject: [PATCH 1/8] Add snark for verifying delegated deposits --- Cargo.toml | 1 + src/circuit/delegated_deposit.rs | 97 ++++++++++++++++++++++++++++++++ src/circuit/mod.rs | 3 +- src/native/delegated_deposit.rs | 40 +++++++++++++ src/native/mod.rs | 1 + 5 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/circuit/delegated_deposit.rs create mode 100644 src/native/delegated_deposit.rs diff --git a/Cargo.toml b/Cargo.toml index 254a1e5..c50d698 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ lazy_static = "1.4.0" chacha20poly1305 = "0.8.0" clap={ package = "clap-v3", version = "3.0.0-beta.1", optional=true} convert_case = "0.4.0" +fawkes-crypto-keccak256="0.1.1" [features] in1out127=[] diff --git a/src/circuit/delegated_deposit.rs b/src/circuit/delegated_deposit.rs new file mode 100644 index 0000000..f4a717b --- /dev/null +++ b/src/circuit/delegated_deposit.rs @@ -0,0 +1,97 @@ +use crate::fawkes_crypto::circuit::{ + bool::CBool, + num::CNum, + bitify::{c_into_bits_le_strict, c_into_bits_le} +}; +use crate::fawkes_crypto::core::signal::Signal; +use crate::fawkes_crypto::circuit::cs::{RCS, CS}; +use crate::circuit::{boundednum::CBoundedNum, note::CNote}; +use crate::native::delegated_deposit::{DelegatedDeposit, DelegatedDepositBatchPub, DelegatedDepositBatchSec}; +use crate::fawkes_crypto::ff_uint::{PrimeFieldParams, Num}; +use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, OUT}; +use crate::fawkes_crypto::core::sizedvec::SizedVec; +use crate::native::params::PoolParams; +use crate::circuit::account::CAccount; +use crate::circuit::tx::c_out_commitment_hash; + + +use fawkes_crypto_keccak256::circuit::hash::c_keccak256_reduced; + +#[derive(Clone, Signal)] +#[Value = "DelegatedDeposit"] +pub struct CDelegatedDeposit { + pub d: CBoundedNum, + pub p_d: CNum, + pub b: CBoundedNum, +} + + + +fn num_to_iter_bits_be(n:&CNum) -> impl Iterator> { + assert!(C::Fr::MODULUS_BITS <= 256); + let bits = c_into_bits_le_strict(n); + let zero = n.derive_const(&false); + std::iter::repeat(zero).take(256 - bits.len()).chain(bits.into_iter().rev()) +} + + +fn boundednum_to_iter_bits_be(n:&CBoundedNum) -> impl Iterator> { + assert!(L < C::Fr::MODULUS_BITS as usize); + let bits = c_into_bits_le(n.as_num(), L); + bits.into_iter().rev() +} + +impl CDelegatedDeposit { + pub fn to_note(&self) -> CNote { + let cs = self.d.get_cs(); + CNote { + d: self.d.clone(), + p_d: self.p_d.clone(), + b: self.b.clone(), + t: CBoundedNum::new(&CNum::from_const(cs, &Num::ZERO)) + } + } + + // convert to iter over bits be + pub fn to_iter_bits_be(&self) -> impl Iterator> { + boundednum_to_iter_bits_be(&self.d) + .chain(num_to_iter_bits_be(&self.p_d)) + .chain(boundednum_to_iter_bits_be(&self.b)) + } + +} + +#[derive(Clone, Signal)] +#[Value = "DelegatedDepositBatchPub"] +pub struct CDelegatedDepositBatchPub { + pub keccak_sum: CNum +} + +#[derive(Clone, Signal)] +#[Value = "DelegatedDepositBatchSec"] +pub struct CDelegatedDepositBatchSec { + pub out_account: CAccount, + pub out_commitment_hash: CNum, + pub deposits: SizedVec, { OUT}>, +} + +pub fn check_delegated_deposit_batch>( + p: &CDelegatedDepositBatchPub, + s: &CDelegatedDepositBatchSec, + params: &P +) { + let cs = p.get_cs(); + let bits:Vec<_> = num_to_iter_bits_be(&s.out_commitment_hash).chain( + s.deposits.iter().flat_map( + |d| d.to_iter_bits_be() + )).collect(); + + c_keccak256_reduced(cs, &bits).assert_eq(&p.keccak_sum); + + let out_account_hash = s.out_account.hash(params); + let out_note_hash:Vec<_> = s.deposits.iter().map(|d| d.to_note()) + .map(|n| n.hash(params)).collect(); + + let out_hash = [[out_account_hash].as_ref(), out_note_hash.as_slice()].concat(); + c_out_commitment_hash(&out_hash, params).assert_eq(&s.out_commitment_hash); +} \ No newline at end of file diff --git a/src/circuit/mod.rs b/src/circuit/mod.rs index 9830ec3..4a477ec 100644 --- a/src/circuit/mod.rs +++ b/src/circuit/mod.rs @@ -3,4 +3,5 @@ pub mod boundednum; pub mod account; pub mod note; pub mod key; -pub mod tree; \ No newline at end of file +pub mod tree; +pub mod delegated_deposit; \ No newline at end of file diff --git a/src/native/delegated_deposit.rs b/src/native/delegated_deposit.rs new file mode 100644 index 0000000..38da287 --- /dev/null +++ b/src/native/delegated_deposit.rs @@ -0,0 +1,40 @@ +use fawkes_crypto::ff_uint::{Num, PrimeField}; +use crate::native::{boundednum::BoundedNum, note::Note}; +use std::fmt::Debug; +use crate::fawkes_crypto::core::sizedvec::SizedVec; +use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, OUT}; +use crate::native::account::Account; + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound(serialize = "", deserialize = ""))] +pub struct DelegatedDeposit { + pub d: BoundedNum, + pub p_d: Num, + pub b: BoundedNum +} + +impl DelegatedDeposit { + //convert to a note with zero salt + pub fn to_note(&self) -> Note { + Note { + d: self.d, + p_d: self.p_d, + b: self.b, + t: BoundedNum::new(Num::ZERO) + } + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound(serialize = "", deserialize = ""))] +pub struct DelegatedDepositBatchPub { + pub keccak_sum: Num +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(bound(serialize = "", deserialize = ""))] +pub struct DelegatedDepositBatchSec { + pub out_account:Account, + pub out_commitment_hash: Num, + pub deposits: SizedVec, OUT> +} \ No newline at end of file diff --git a/src/native/mod.rs b/src/native/mod.rs index bf28d76..eedb029 100644 --- a/src/native/mod.rs +++ b/src/native/mod.rs @@ -6,6 +6,7 @@ pub mod account; pub mod cipher; pub mod key; pub mod tree; +pub mod delegated_deposit; mod borsh; mod sample; From fd9b822e262965375103660982d5190f3c3b4d24 Mon Sep 17 00:00:00 2001 From: Igor Gulamov Date: Fri, 3 Feb 2023 13:40:37 +0400 Subject: [PATCH 2/8] delegated deposits fix & tests covered --- .gitignore | 10 +- Cargo.toml | 2 + src/circuit/delegated_deposit.rs | 17 ++- src/helpers/sample_data.rs | 166 +++++++++++++++++++++++++- src/native/borsh/delegated_deposit.rs | 23 ++++ src/native/borsh/mod.rs | 3 +- src/setup/main.rs | 49 +++++--- tests/circuit.rs | 29 ----- tests/delegated_deposit.rs | 81 +++++++++++++ tests/transaction.rs | 17 +++ 10 files changed, 344 insertions(+), 53 deletions(-) create mode 100644 src/native/borsh/delegated_deposit.rs delete mode 100644 tests/circuit.rs create mode 100644 tests/delegated_deposit.rs diff --git a/.gitignore b/.gitignore index af994a2..1fd83f2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,12 @@ Cargo.lock /target -.vscode \ No newline at end of file +.vscode + +#Generated data +**_inputs.json +**_object.json +**_params.bin +**_proof.json +**_key.json +**_verifier.sol \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index c50d698..12dd802 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,8 @@ clap={ package = "clap-v3", version = "3.0.0-beta.1", optional=true} convert_case = "0.4.0" fawkes-crypto-keccak256="0.1.1" + + [features] in1out127=[] in3out127=[] diff --git a/src/circuit/delegated_deposit.rs b/src/circuit/delegated_deposit.rs index f4a717b..8b3bced 100644 --- a/src/circuit/delegated_deposit.rs +++ b/src/circuit/delegated_deposit.rs @@ -27,18 +27,22 @@ pub struct CDelegatedDeposit { -fn num_to_iter_bits_be(n:&CNum) -> impl Iterator> { +pub fn num_to_iter_bits_be(n:&CNum) -> impl Iterator> { assert!(C::Fr::MODULUS_BITS <= 256); let bits = c_into_bits_le_strict(n); let zero = n.derive_const(&false); - std::iter::repeat(zero).take(256 - bits.len()).chain(bits.into_iter().rev()) + let bits_le = bits.into_iter().chain(std::iter::repeat(zero)).take(256).collect::>(); + let bits_be = bits_le.chunks(8).rev().flatten().cloned().collect::>(); + bits_be.into_iter() } -fn boundednum_to_iter_bits_be(n:&CBoundedNum) -> impl Iterator> { +pub fn boundednum_to_iter_bits_be(n:&CBoundedNum) -> impl Iterator> { assert!(L < C::Fr::MODULUS_BITS as usize); - let bits = c_into_bits_le(n.as_num(), L); - bits.into_iter().rev() + assert!(L%8 == 0); + let bits_le = c_into_bits_le(n.as_num(), L); + let bits_be = bits_le.chunks(8).rev().flatten().cloned().collect::>(); + bits_be.into_iter() } impl CDelegatedDeposit { @@ -94,4 +98,5 @@ pub fn check_delegated_deposit_batch>( let out_hash = [[out_account_hash].as_ref(), out_note_hash.as_slice()].concat(); c_out_commitment_hash(&out_hash, params).assert_eq(&s.out_commitment_hash); -} \ No newline at end of file +} + diff --git a/src/helpers/sample_data.rs b/src/helpers/sample_data.rs index d745b30..5b35373 100644 --- a/src/helpers/sample_data.rs +++ b/src/helpers/sample_data.rs @@ -1,9 +1,12 @@ +use fawkes_crypto::{BorshSerialize, ff_uint::PrimeField}; + use crate::{constants, fawkes_crypto::{ ff_uint::Num, native::poseidon::{poseidon, MerkleProof}, rand::{self, Rng}, + core::sizedvec::SizedVec }, native::{ account::Account, @@ -11,10 +14,14 @@ use crate::{constants, note::Note, params::{PoolParams}, tx::{make_delta, Tx, TransferPub, TransferSec, nullifier, tx_hash, tx_sign, out_commitment_hash}, - key::{derive_key_a, derive_key_eta, derive_key_p_d} + key::{derive_key_a, derive_key_eta, derive_key_p_d}, + tree::{TreePub, TreeSec}, + delegated_deposit::{DelegatedDepositBatchPub, DelegatedDepositBatchSec, DelegatedDeposit} } }; +use fawkes_crypto_keccak256::native::hash::keccak256; + pub const N_ITEMS:usize = 1000; @@ -141,7 +148,6 @@ impl State

{ } } - pub fn random_sample_transfer(&self, rng:&mut R, params:&P) -> (TransferPub, TransferSec) { @@ -249,3 +255,159 @@ impl State

{ } } + + +pub fn random_sample_tree_update(rng:&mut R, params:&P) -> (TreePub, TreeSec) { + use std::collections::HashMap; + + let index_filled:usize = rng.gen_range(0, N_ITEMS); + let index_free = index_filled + 1; + + const PATH_LENGTH:usize = constants::HEIGHT-constants::OUTPLUSONELOG; + + let mut cell = HashMap::new(); + + let zero_leaf_value = { + let mut c = Num::ZERO; + for _ in 0..constants::OUTPLUSONELOG { + c = poseidon(&[c, c], params.compress()); + } + c + }; + + let cell_defaults = { + let mut c = zero_leaf_value; + let mut res = vec![c;PATH_LENGTH+1]; + for i in 1..PATH_LENGTH { + c = poseidon(&[c,c], params.compress()); + res[i] = c; + } + res + }; + + macro_rules! cell_get { + ($h:expr, $i:expr) => { cell.get(&(($h),($i))).unwrap_or_else(||&cell_defaults[($h)]).clone() } + } + + macro_rules! cell_set { + ($h:expr, $i:expr, $v:expr) => { cell.insert((($h),($i)), ($v)); } + } + + + + let prev_leaf:Num = rng.gen(); + cell_set!(0, index_filled, prev_leaf); + for h in 0..PATH_LENGTH { + let index_level = index_filled>>h; + if index_level & 1 == 1 { + cell_set!(h, index_level^1, rng.gen()); + } + } + + for h in 1..PATH_LENGTH+1 { + let index = index_filled>>h; + let left = cell_get!(h-1, index*2); + let right = cell_get!(h-1, index*2+1); + let hash = poseidon(&[left,right], params.compress()); + cell_set!(h, index, hash); + } + + + + + let path_filled = (0..PATH_LENGTH).map(|i| (index_filled>>i)&1==1).collect(); + let sibling_filled:SizedVec, PATH_LENGTH> = (0..PATH_LENGTH).map(|h| cell_get!(h, (index_filled>>h)^1 )).collect(); + + + let proof_filled = MerkleProof { + sibling: sibling_filled, + path: path_filled + }; + + let root_before = cell_get!(PATH_LENGTH, 0); + + let path_free = (0..PATH_LENGTH).map(|i| (index_free>>i)&1==1).collect(); + let sibling_free:SizedVec, PATH_LENGTH> = (0..PATH_LENGTH).map(|h| cell_get!(h, (index_free>>h)^1 )).collect(); + + let leaf = rng.gen(); + cell_set!(0, index_free, leaf); + + for h in 1..PATH_LENGTH+1 { + let index = index_free>>h; + let left = cell_get!(h-1, index*2); + let right = cell_get!(h-1, index*2+1); + let hash = poseidon(&[left,right], params.compress()); + cell_set!(h, index, hash); + } + + let root_after = cell_get!(PATH_LENGTH, 0); + + let proof_free = MerkleProof { + sibling: sibling_free, + path: path_free + }; + + let p = TreePub { + root_before, + root_after, + leaf + }; + + let s = TreeSec { + proof_filled, + proof_free, + prev_leaf + }; + + (p,s) + +} + +pub fn serialize_scalar_and_delegated_deposits_be(och:Num, deposits:&[DelegatedDeposit]) -> Vec { + deposits.iter().rev().flat_map(|d| { + let mut res = d.b.try_to_vec().unwrap(); + res.extend(d.p_d.try_to_vec().unwrap()); + res.extend(d.d.try_to_vec().unwrap()); + res + + }).chain(och.try_to_vec().unwrap()).rev().collect::>() +} + +pub fn random_sample_delegated_deposit(rng:&mut R, params:&P) -> (DelegatedDepositBatchPub, DelegatedDepositBatchSec) { + let out_account = Account::sample(rng, params); + + let deposits:SizedVec<_,{constants::OUT}> = (0..constants::OUT).map(|_| { + let n = Note::sample(rng, params); + DelegatedDeposit { + d:n.d, + p_d:n.p_d, + b:n.b, + } + }).collect(); + + let out_account_hash = out_account.hash(params); + let out_note_hash:Vec<_> = deposits.iter().map(|d| d.to_note()) + .map(|n| n.hash(params)).collect(); + + let out_hash = [[out_account_hash].as_ref(), out_note_hash.as_slice()].concat(); + let och = out_commitment_hash(&out_hash, params); + + + let data = serialize_scalar_and_delegated_deposits_be(och, deposits.as_slice()); + + + let keccak_sum = { + let t = keccak256(&data); + let mut res = Num::ZERO; + let mut mpl = Num::ONE; + for limb in t.iter() { + res = res + mpl * Num::from(*limb); + mpl = mpl * Num::from(256); + } + res + }; + let p = DelegatedDepositBatchPub {keccak_sum}; + let s = DelegatedDepositBatchSec {out_account, out_commitment_hash:och, deposits}; + (p,s) + +} \ No newline at end of file diff --git a/src/native/borsh/delegated_deposit.rs b/src/native/borsh/delegated_deposit.rs new file mode 100644 index 0000000..4b901ff --- /dev/null +++ b/src/native/borsh/delegated_deposit.rs @@ -0,0 +1,23 @@ +use crate::native::delegated_deposit::*; +use fawkes_crypto::ff_uint::PrimeField; +use crate::fawkes_crypto::borsh::{BorshSerialize, BorshDeserialize}; +use std::io::{self, Write}; + + +impl BorshSerialize for DelegatedDeposit { + fn serialize(&self, writer: &mut W) -> io::Result<()> { + self.d.serialize(writer)?; + self.p_d.serialize(writer)?; + self.b.serialize(writer) + } +} + +impl BorshDeserialize for DelegatedDeposit { + fn deserialize(buf: &mut &[u8]) -> io::Result { + Ok(Self{ + d: BorshDeserialize::deserialize(buf)?, + p_d: BorshDeserialize::deserialize(buf)?, + b: BorshDeserialize::deserialize(buf)? + }) + } +} \ No newline at end of file diff --git a/src/native/borsh/mod.rs b/src/native/borsh/mod.rs index ac07c42..378270f 100644 --- a/src/native/borsh/mod.rs +++ b/src/native/borsh/mod.rs @@ -1,3 +1,4 @@ pub mod account; pub mod note; -pub mod boundednum; \ No newline at end of file +pub mod boundednum; +pub mod delegated_deposit; \ No newline at end of file diff --git a/src/setup/main.rs b/src/setup/main.rs index b0e194d..a26f214 100644 --- a/src/setup/main.rs +++ b/src/setup/main.rs @@ -4,6 +4,7 @@ use libzeropool::{ POOL_PARAMS, circuit::tree::{tree_update, CTreePub, CTreeSec}, circuit::tx::{c_transfer, CTransferPub, CTransferSec}, + circuit::delegated_deposit::{check_delegated_deposit_batch, CDelegatedDepositBatchPub, CDelegatedDepositBatchSec}, clap::Clap, }; use core::panic; @@ -16,7 +17,7 @@ use fawkes_crypto::backend::bellman_groth16::{verifier::{VK, verify}, prover::{P use evm_verifier::generate_sol_data; use fawkes_crypto::circuit::cs::CS; use fawkes_crypto::rand::rngs::OsRng; -use libzeropool::helpers::sample_data::State; +use libzeropool::helpers::sample_data::{State, random_sample_tree_update, random_sample_delegated_deposit}; use convert_case::{Case, Casing}; #[derive(Clap)] @@ -125,6 +126,10 @@ fn tx_circuit>(public: CTransferPub, secret: CTransferSec) { c_transfer(&public, &secret, &*POOL_PARAMS); } +fn delegated_deposit_circuit>(public: CDelegatedDepositBatchPub, secret: CDelegatedDepositBatchSec) { + check_delegated_deposit_batch(&public, &secret, &*POOL_PARAMS); +} + fn cli_setup(o:SetupOpts) { let params_path = o.params.unwrap_or(format!("{}_params.bin", o.circuit)); let vk_path = o.vk.unwrap_or(format!("{}_verification_key.json", o.circuit)); @@ -133,6 +138,7 @@ fn cli_setup(o:SetupOpts) { let params = match o.circuit.as_str() { "tree_update" => setup::(tree_circuit), "transfer" => setup::(tx_circuit), + "delegated_deposit" => setup::(delegated_deposit_circuit), _ => panic!("Wrong cicruit parameter") }; @@ -177,18 +183,25 @@ fn cli_verify(o:VerifyOpts) { fn cli_generate_test_data(o:GenerateTestDataOpts) { let object_path = o.object.unwrap_or(format!("{}_object.json", o.circuit)); - - match o.circuit.as_str() { + let mut rng = OsRng::default(); + let data_str = match o.circuit.as_str() { "transfer" => { - let mut rng = OsRng::default(); let state = State::random_sample_state(&mut rng, &*POOL_PARAMS); let data = state.random_sample_transfer(&mut rng, &*POOL_PARAMS); - let data_str = serde_json::to_string_pretty(&data).unwrap(); - std::fs::write(object_path, &data_str.into_bytes()).unwrap(); + serde_json::to_string_pretty(&data).unwrap() + + }, + "tree_update" => { + let data = random_sample_tree_update(&mut rng, &*POOL_PARAMS); + serde_json::to_string_pretty(&data).unwrap() + }, + "delegated_deposit" => { + let data = random_sample_delegated_deposit(&mut rng, &*POOL_PARAMS); + serde_json::to_string_pretty(&data).unwrap() }, - "tree_update" => std::unimplemented!(), _ => panic!("Wrong cicruit parameter") - } + }; + std::fs::write(object_path, &data_str.into_bytes()).unwrap(); println!("Test data generated") @@ -206,12 +219,20 @@ fn cli_prove(o:ProveOpts) { let params = Parameters::::read(&mut params_data_cur, false, false).unwrap(); let object_str = std::fs::read_to_string(object_path).unwrap(); - let (inputs, snark_proof) = if o.circuit.eq("tree_update") { - let (public, secret) = serde_json::from_str(&object_str).unwrap(); - prove(¶ms, &public, &secret, tree_circuit) - } else { - let (public, secret) = serde_json::from_str(&object_str).unwrap(); - prove(¶ms, &public, &secret, tx_circuit) + let (inputs, snark_proof) = match o.circuit.as_str() { + "transfer" => { + let (public, secret) = serde_json::from_str(&object_str).unwrap(); + prove(¶ms, &public, &secret, tx_circuit) + }, + "tree_update" => { + let (public, secret) = serde_json::from_str(&object_str).unwrap(); + prove(¶ms, &public, &secret, tree_circuit) + }, + "delegated_deposit" => { + let (public, secret) = serde_json::from_str(&object_str).unwrap(); + prove(¶ms, &public, &secret, delegated_deposit_circuit) + }, + _ => panic!("Wrong cicruit parameter") }; diff --git a/tests/circuit.rs b/tests/circuit.rs deleted file mode 100644 index fa87e84..0000000 --- a/tests/circuit.rs +++ /dev/null @@ -1,29 +0,0 @@ -use fawkes_crypto::circuit::cs::CS; -use libzeropool::{ - fawkes_crypto::{ - circuit::cs::DebugCS, - core::signal::Signal, - } -}; - -use libzeropool::POOL_PARAMS; -use libzeropool::circuit::tx::{CTransferPub, CTransferSec, c_transfer}; -use std::time::Instant; - -#[test] -fn test_circuit_tx() { - let ref cs = DebugCS::rc_new(); - let ref p = CTransferPub::alloc(cs, None); - let ref s = CTransferSec::alloc(cs, None); - - - let mut n_gates = cs.borrow().num_gates(); - let start = Instant::now(); - c_transfer(p, s, &*POOL_PARAMS); - let duration = start.elapsed(); - n_gates=cs.borrow().num_gates()-n_gates; - - println!("tx constraints = {}", n_gates); - println!("Time elapsed in c_transfer() is: {:?}", duration); - -} diff --git a/tests/delegated_deposit.rs b/tests/delegated_deposit.rs new file mode 100644 index 0000000..6c4a686 --- /dev/null +++ b/tests/delegated_deposit.rs @@ -0,0 +1,81 @@ +use libzeropool::{POOL_PARAMS, + circuit::delegated_deposit::{CDelegatedDepositBatchPub, CDelegatedDepositBatchSec, check_delegated_deposit_batch, CDelegatedDeposit, num_to_iter_bits_be}, + native::note::Note, + native::delegated_deposit::{DelegatedDeposit}, + helpers::sample_data::serialize_scalar_and_delegated_deposits_be, + fawkes_crypto::{ + circuit::{ + cs::{CS, DebugCS}, + num::CNum, + }, + core::{signal::Signal, sizedvec::SizedVec}, + rand::{thread_rng, Rng}, + }, +}; + +use std::time::Instant; +use libzeropool::fawkes_crypto::engines::bn256::Fr; + + + +#[test] +fn test_check_delegated_deposit_batch() { + let ref cs = DebugCS::rc_new(); + let ref p = CDelegatedDepositBatchPub::alloc(cs, None); + let ref s = CDelegatedDepositBatchSec::alloc(cs, None); + + + let mut n_gates = cs.borrow().num_gates(); + let start = Instant::now(); + check_delegated_deposit_batch(p, s, &*POOL_PARAMS); + let duration = start.elapsed(); + n_gates=cs.borrow().num_gates()-n_gates; + + println!("tx constraints = {}", n_gates); + println!("Time elapsed in check_delegated_deposit_batch() is: {:?}", duration); + +} + +#[test] +fn test_bitify_delegated_deposits_be() { + const N_ITEMS:usize = 10; + let mut rng = thread_rng(); + + let deposits:SizedVec<_,{N_ITEMS}> = (0..N_ITEMS).map(|_| { + let n = Note::sample(&mut rng, &*POOL_PARAMS); + DelegatedDeposit { + d:n.d, + p_d:n.p_d, + b:n.b, + } + }).collect(); + + let och = rng.gen(); + + let data = serialize_scalar_and_delegated_deposits_be(och, deposits.as_slice()); + + let bitlen = data.len()*8; + + let bits = (0..bitlen).map(|i| { + let byte = data[i/8]; + let bit = byte & (1 << (i%8)); + bit != 0 + }).collect::>(); + + let ref cs = DebugCS::rc_new(); + + let c_deposits:SizedVec>,{N_ITEMS}> = Signal::alloc(cs, Some(deposits).as_ref()); + let c_och = CNum::alloc(cs, Some(och).as_ref()); + + let c_bits = num_to_iter_bits_be(&c_och).chain(c_deposits.iter().flat_map( + |d| d.to_iter_bits_be() + )).collect::>(); + + assert_eq!(bits.len(), c_bits.len()); + + for (i, (b, c_b)) in bits.iter().zip(c_bits.iter()).enumerate() { + assert_eq!(*b, c_b.get_value().unwrap(), "bit {} is not equal", i); + } + +} + \ No newline at end of file diff --git a/tests/transaction.rs b/tests/transaction.rs index 8a695d5..148f8a2 100644 --- a/tests/transaction.rs +++ b/tests/transaction.rs @@ -20,6 +20,23 @@ use std::time::Instant; use libzeropool::helpers::sample_data::State; +#[test] +fn test_circuit_tx() { + let ref cs = DebugCS::rc_new(); + let ref p = CTransferPub::alloc(cs, None); + let ref s = CTransferSec::alloc(cs, None); + + + let mut n_gates = cs.borrow().num_gates(); + let start = Instant::now(); + c_transfer(p, s, &*POOL_PARAMS); + let duration = start.elapsed(); + n_gates=cs.borrow().num_gates()-n_gates; + + println!("tx constraints = {}", n_gates); + println!("Time elapsed in c_transfer() is: {:?}", duration); + +} #[test] fn test_circuit_tx_fullfill() { From d81cbea0e35edb2ff8ce38a6e4f4b6a569bfd7eb Mon Sep 17 00:00:00 2001 From: Igor Gulamov Date: Fri, 3 Feb 2023 18:11:29 +0400 Subject: [PATCH 3/8] change number of delegated deposits to 16 --- src/circuit/delegated_deposit.rs | 37 +++++++++++++++++++++++--------- src/constants/mod.rs | 2 ++ src/helpers/sample_data.rs | 25 ++++++++++++++------- src/native/delegated_deposit.rs | 4 ++-- tests/delegated_deposit.rs | 10 ++++++--- 5 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/circuit/delegated_deposit.rs b/src/circuit/delegated_deposit.rs index 8b3bced..c19cac1 100644 --- a/src/circuit/delegated_deposit.rs +++ b/src/circuit/delegated_deposit.rs @@ -1,21 +1,23 @@ use crate::fawkes_crypto::circuit::{ bool::CBool, num::CNum, - bitify::{c_into_bits_le_strict, c_into_bits_le} + bitify::{c_into_bits_le_strict, c_into_bits_le, c_from_bits_le} }; use crate::fawkes_crypto::core::signal::Signal; use crate::fawkes_crypto::circuit::cs::{RCS, CS}; use crate::circuit::{boundednum::CBoundedNum, note::CNote}; use crate::native::delegated_deposit::{DelegatedDeposit, DelegatedDepositBatchPub, DelegatedDepositBatchSec}; use crate::fawkes_crypto::ff_uint::{PrimeFieldParams, Num}; -use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, OUT}; +use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM, OUT}; use crate::fawkes_crypto::core::sizedvec::SizedVec; use crate::native::params::PoolParams; +use crate::native::note::Note; +use crate::native::boundednum::BoundedNum; use crate::circuit::account::CAccount; use crate::circuit::tx::c_out_commitment_hash; -use fawkes_crypto_keccak256::circuit::hash::c_keccak256_reduced; +use fawkes_crypto_keccak256::circuit::hash::c_keccak256; #[derive(Clone, Signal)] #[Value = "DelegatedDeposit"] @@ -76,7 +78,7 @@ pub struct CDelegatedDepositBatchPub { pub struct CDelegatedDepositBatchSec { pub out_account: CAccount, pub out_commitment_hash: CNum, - pub deposits: SizedVec, { OUT}>, + pub deposits: SizedVec, { DELEGATED_DEPOSITS_NUM}>, } pub fn check_delegated_deposit_batch>( @@ -84,17 +86,32 @@ pub fn check_delegated_deposit_batch>( s: &CDelegatedDepositBatchSec, params: &P ) { + assert!(DELEGATED_DEPOSITS_NUM <= OUT); let cs = p.get_cs(); - let bits:Vec<_> = num_to_iter_bits_be(&s.out_commitment_hash).chain( - s.deposits.iter().flat_map( - |d| d.to_iter_bits_be() + let out_account_hash = s.out_account.hash(params); + + let bits:Vec<_> = num_to_iter_bits_be(&s.out_commitment_hash) + .chain(num_to_iter_bits_be(&out_account_hash)).chain( + s.deposits.iter().flat_map( + |d| d.to_iter_bits_be() )).collect(); - c_keccak256_reduced(cs, &bits).assert_eq(&p.keccak_sum); + let keccak_bits_be = c_keccak256(cs, &bits); + let keccak_bits_le = keccak_bits_be.as_slice().chunks(8).rev().flatten().cloned().collect::>(); + c_from_bits_le(&keccak_bits_le).assert_eq(&p.keccak_sum); + + let zero_note_hash = (Note { + d:BoundedNum::new(Num::ZERO), + p_d:Num::ZERO, + b:BoundedNum::new(Num::ZERO), + t:BoundedNum::new(Num::ZERO) + }).hash(params); - let out_account_hash = s.out_account.hash(params); + let c_zero_note_hash = CNum::from_const(cs, &zero_note_hash); + + let out_note_hash:Vec<_> = s.deposits.iter().map(|d| d.to_note()) - .map(|n| n.hash(params)).collect(); + .map(|n| n.hash(params)).chain(std::iter::repeat(c_zero_note_hash)).take(OUT).collect(); let out_hash = [[out_account_hash].as_ref(), out_note_hash.as_slice()].concat(); c_out_commitment_hash(&out_hash, params).assert_eq(&s.out_commitment_hash); diff --git a/src/constants/mod.rs b/src/constants/mod.rs index 25270c7..45cba7f 100644 --- a/src/constants/mod.rs +++ b/src/constants/mod.rs @@ -15,6 +15,8 @@ pub const ENERGY_SIZE_BITS: usize = BALANCE_SIZE_BITS+HEIGHT; pub const SALT_SIZE_BITS: usize = 80; pub const POOLID_SIZE_BITS: usize = 24; +pub const DELEGATED_DEPOSITS_NUM:usize = 16; + pub const POLY_1305_TAG_SIZE: usize = 16; pub const U256_SIZE:usize = 32; diff --git a/src/helpers/sample_data.rs b/src/helpers/sample_data.rs index 5b35373..e889733 100644 --- a/src/helpers/sample_data.rs +++ b/src/helpers/sample_data.rs @@ -363,20 +363,23 @@ pub fn random_sample_tree_update(rng:&mut R, params:&P) -> ( } -pub fn serialize_scalar_and_delegated_deposits_be(och:Num, deposits:&[DelegatedDeposit]) -> Vec { +pub fn serialize_scalars_and_delegated_deposits_be(och:Num, out_account_hash:Num, deposits:&[DelegatedDeposit]) -> Vec { deposits.iter().rev().flat_map(|d| { let mut res = d.b.try_to_vec().unwrap(); res.extend(d.p_d.try_to_vec().unwrap()); res.extend(d.d.try_to_vec().unwrap()); res - }).chain(och.try_to_vec().unwrap()).rev().collect::>() + }) + .chain(out_account_hash.try_to_vec().unwrap()) + .chain(och.try_to_vec().unwrap()) + .rev().collect::>() } pub fn random_sample_delegated_deposit(rng:&mut R, params:&P) -> (DelegatedDepositBatchPub, DelegatedDepositBatchSec) { let out_account = Account::sample(rng, params); - let deposits:SizedVec<_,{constants::OUT}> = (0..constants::OUT).map(|_| { + let deposits:SizedVec<_,{constants::DELEGATED_DEPOSITS_NUM}> = (0..constants::DELEGATED_DEPOSITS_NUM).map(|_| { let n = Note::sample(rng, params); DelegatedDeposit { d:n.d, @@ -385,24 +388,30 @@ pub fn random_sample_delegated_deposit(rng:&mut R, params:&P } }).collect(); + let zero_note_hash = (Note { + d:BoundedNum::new(Num::ZERO), + p_d:Num::ZERO, + b:BoundedNum::new(Num::ZERO), + t:BoundedNum::new(Num::ZERO) + }).hash(params); + let out_account_hash = out_account.hash(params); + let out_note_hash:Vec<_> = deposits.iter().map(|d| d.to_note()) - .map(|n| n.hash(params)).collect(); + .map(|n| n.hash(params)).chain(std::iter::repeat(zero_note_hash)).take(constants::OUT).collect(); let out_hash = [[out_account_hash].as_ref(), out_note_hash.as_slice()].concat(); let och = out_commitment_hash(&out_hash, params); - let data = serialize_scalar_and_delegated_deposits_be(och, deposits.as_slice()); + let data = serialize_scalars_and_delegated_deposits_be(och, out_account_hash, deposits.as_slice()); let keccak_sum = { let t = keccak256(&data); let mut res = Num::ZERO; - let mut mpl = Num::ONE; for limb in t.iter() { - res = res + mpl * Num::from(*limb); - mpl = mpl * Num::from(256); + res = res * Num::from(256) + Num::from(*limb); } res }; diff --git a/src/native/delegated_deposit.rs b/src/native/delegated_deposit.rs index 38da287..a54ff9c 100644 --- a/src/native/delegated_deposit.rs +++ b/src/native/delegated_deposit.rs @@ -2,7 +2,7 @@ use fawkes_crypto::ff_uint::{Num, PrimeField}; use crate::native::{boundednum::BoundedNum, note::Note}; use std::fmt::Debug; use crate::fawkes_crypto::core::sizedvec::SizedVec; -use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, OUT}; +use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM}; use crate::native::account::Account; #[derive(Clone, Debug, Serialize, Deserialize)] @@ -36,5 +36,5 @@ pub struct DelegatedDepositBatchPub { pub struct DelegatedDepositBatchSec { pub out_account:Account, pub out_commitment_hash: Num, - pub deposits: SizedVec, OUT> + pub deposits: SizedVec, DELEGATED_DEPOSITS_NUM> } \ No newline at end of file diff --git a/tests/delegated_deposit.rs b/tests/delegated_deposit.rs index 6c4a686..a309b61 100644 --- a/tests/delegated_deposit.rs +++ b/tests/delegated_deposit.rs @@ -2,7 +2,7 @@ use libzeropool::{POOL_PARAMS, circuit::delegated_deposit::{CDelegatedDepositBatchPub, CDelegatedDepositBatchSec, check_delegated_deposit_batch, CDelegatedDeposit, num_to_iter_bits_be}, native::note::Note, native::delegated_deposit::{DelegatedDeposit}, - helpers::sample_data::serialize_scalar_and_delegated_deposits_be, + helpers::sample_data::serialize_scalars_and_delegated_deposits_be, fawkes_crypto::{ circuit::{ cs::{CS, DebugCS}, @@ -51,8 +51,9 @@ fn test_bitify_delegated_deposits_be() { }).collect(); let och = rng.gen(); + let out_account_hash = rng.gen(); - let data = serialize_scalar_and_delegated_deposits_be(och, deposits.as_slice()); + let data = serialize_scalars_and_delegated_deposits_be(och, out_account_hash, deposits.as_slice()); let bitlen = data.len()*8; @@ -66,8 +67,11 @@ fn test_bitify_delegated_deposits_be() { let c_deposits:SizedVec>,{N_ITEMS}> = Signal::alloc(cs, Some(deposits).as_ref()); let c_och = CNum::alloc(cs, Some(och).as_ref()); + let c_out_account_hash = CNum::alloc(cs, Some(out_account_hash).as_ref()); - let c_bits = num_to_iter_bits_be(&c_och).chain(c_deposits.iter().flat_map( + let c_bits = num_to_iter_bits_be(&c_och) + .chain(num_to_iter_bits_be(&c_out_account_hash)) + .chain(c_deposits.iter().flat_map( |d| d.to_iter_bits_be() )).collect::>(); From 651e396eee3f0e08bbe753fbdd8c5a911da31692 Mon Sep 17 00:00:00 2001 From: Igor Gulamov Date: Sun, 5 Feb 2023 21:10:50 +0400 Subject: [PATCH 4/8] add 0xffffffff prefix for message --- src/circuit/delegated_deposit.rs | 5 ++++- src/helpers/sample_data.rs | 1 + tests/delegated_deposit.rs | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/circuit/delegated_deposit.rs b/src/circuit/delegated_deposit.rs index c19cac1..c200171 100644 --- a/src/circuit/delegated_deposit.rs +++ b/src/circuit/delegated_deposit.rs @@ -88,10 +88,13 @@ pub fn check_delegated_deposit_batch>( ) { assert!(DELEGATED_DEPOSITS_NUM <= OUT); let cs = p.get_cs(); + let c_true = CBool::from_const(cs, &true); let out_account_hash = s.out_account.hash(params); let bits:Vec<_> = num_to_iter_bits_be(&s.out_commitment_hash) - .chain(num_to_iter_bits_be(&out_account_hash)).chain( + .chain(std::iter::repeat(c_true).take(32)) + .chain(num_to_iter_bits_be(&out_account_hash)) + .chain( s.deposits.iter().flat_map( |d| d.to_iter_bits_be() )).collect(); diff --git a/src/helpers/sample_data.rs b/src/helpers/sample_data.rs index e889733..0196dcf 100644 --- a/src/helpers/sample_data.rs +++ b/src/helpers/sample_data.rs @@ -372,6 +372,7 @@ pub fn serialize_scalars_and_delegated_deposits_be(och:Num, o }) .chain(out_account_hash.try_to_vec().unwrap()) + .chain(vec![0xff;4]) .chain(och.try_to_vec().unwrap()) .rev().collect::>() } diff --git a/tests/delegated_deposit.rs b/tests/delegated_deposit.rs index a309b61..2e21b5f 100644 --- a/tests/delegated_deposit.rs +++ b/tests/delegated_deposit.rs @@ -7,6 +7,7 @@ use libzeropool::{POOL_PARAMS, circuit::{ cs::{CS, DebugCS}, num::CNum, + bool::CBool }, core::{signal::Signal, sizedvec::SizedVec}, rand::{thread_rng, Rng}, @@ -66,10 +67,12 @@ fn test_bitify_delegated_deposits_be() { let ref cs = DebugCS::rc_new(); let c_deposits:SizedVec>,{N_ITEMS}> = Signal::alloc(cs, Some(deposits).as_ref()); + let c_true = CBool::from_const(cs, &true); let c_och = CNum::alloc(cs, Some(och).as_ref()); let c_out_account_hash = CNum::alloc(cs, Some(out_account_hash).as_ref()); let c_bits = num_to_iter_bits_be(&c_och) + .chain(std::iter::repeat(c_true).take(32)) .chain(num_to_iter_bits_be(&c_out_account_hash)) .chain(c_deposits.iter().flat_map( |d| d.to_iter_bits_be() From 10ce724991a783dbd577c94b3233e078b40576c2 Mon Sep 17 00:00:00 2001 From: Igor Gulamov Date: Wed, 8 Feb 2023 05:08:20 +0400 Subject: [PATCH 5/8] join all snarks into one for delegated deposits --- src/circuit/delegated_deposit.rs | 106 ++++++++++++++++++++----------- src/helpers/sample_data.rs | 64 ++++++++++++------- src/native/boundednum.rs | 3 + src/native/delegated_deposit.rs | 15 +++-- tests/delegated_deposit.rs | 17 ++--- 5 files changed, 130 insertions(+), 75 deletions(-) diff --git a/src/circuit/delegated_deposit.rs b/src/circuit/delegated_deposit.rs index c200171..b4c00d9 100644 --- a/src/circuit/delegated_deposit.rs +++ b/src/circuit/delegated_deposit.rs @@ -1,22 +1,29 @@ use crate::fawkes_crypto::circuit::{ bool::CBool, num::CNum, - bitify::{c_into_bits_le_strict, c_into_bits_le, c_from_bits_le} + bitify::{c_into_bits_le_strict, c_into_bits_le, c_from_bits_le}, + cs::{RCS, CS}, + poseidon::CMerkleProof }; -use crate::fawkes_crypto::core::signal::Signal; -use crate::fawkes_crypto::circuit::cs::{RCS, CS}; -use crate::circuit::{boundednum::CBoundedNum, note::CNote}; -use crate::native::delegated_deposit::{DelegatedDeposit, DelegatedDepositBatchPub, DelegatedDepositBatchSec}; use crate::fawkes_crypto::ff_uint::{PrimeFieldParams, Num}; -use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM, OUT}; -use crate::fawkes_crypto::core::sizedvec::SizedVec; -use crate::native::params::PoolParams; -use crate::native::note::Note; -use crate::native::boundednum::BoundedNum; -use crate::circuit::account::CAccount; -use crate::circuit::tx::c_out_commitment_hash; - - +use crate::fawkes_crypto::core::{ + signal::Signal, + sizedvec::SizedVec +}; +use crate::circuit::{ + boundednum::CBoundedNum, + note::CNote, + tx::c_out_commitment_hash, + tree::{CTreePub, CTreeSec, tree_update} +}; +use crate::native::{ + params::PoolParams, + note::Note, + boundednum::BoundedNum, + account::Account, + delegated_deposit::{DelegatedDeposit, DelegatedDepositBatchPub, DelegatedDepositBatchSec} +}; +use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM, OUT, HEIGHT, OUTPLUSONELOG}; use fawkes_crypto_keccak256::circuit::hash::c_keccak256; #[derive(Clone, Signal)] @@ -76,9 +83,18 @@ pub struct CDelegatedDepositBatchPub { #[derive(Clone, Signal)] #[Value = "DelegatedDepositBatchSec"] pub struct CDelegatedDepositBatchSec { - pub out_account: CAccount, - pub out_commitment_hash: CNum, - pub deposits: SizedVec, { DELEGATED_DEPOSITS_NUM}>, + pub root_before: CNum, + pub root_after: CNum, + pub deposits: SizedVec, DELEGATED_DEPOSITS_NUM>, + pub proof_filled:CMerkleProof, + pub proof_free:CMerkleProof, + pub prev_leaf:CNum, +} + +fn c_keccak256_be_reduced(cs:&RCS, bits:&[CBool]) -> CNum { + let keccak_bits_be = c_keccak256(cs, &bits); + let keccak_bits_le = keccak_bits_be.as_slice().chunks(8).rev().flatten().cloned().collect::>(); + c_from_bits_le(&keccak_bits_le) } pub fn check_delegated_deposit_batch>( @@ -88,35 +104,51 @@ pub fn check_delegated_deposit_batch>( ) { assert!(DELEGATED_DEPOSITS_NUM <= OUT); let cs = p.get_cs(); - let c_true = CBool::from_const(cs, &true); - let out_account_hash = s.out_account.hash(params); - - let bits:Vec<_> = num_to_iter_bits_be(&s.out_commitment_hash) - .chain(std::iter::repeat(c_true).take(32)) - .chain(num_to_iter_bits_be(&out_account_hash)) + let bits:Vec<_> = num_to_iter_bits_be(&s.root_before) + .chain(num_to_iter_bits_be(&s.root_after)) .chain( s.deposits.iter().flat_map( |d| d.to_iter_bits_be() )).collect(); - let keccak_bits_be = c_keccak256(cs, &bits); - let keccak_bits_le = keccak_bits_be.as_slice().chunks(8).rev().flatten().cloned().collect::>(); - c_from_bits_le(&keccak_bits_le).assert_eq(&p.keccak_sum); + c_keccak256_be_reduced(cs, &bits).assert_eq(&p.keccak_sum); - let zero_note_hash = (Note { - d:BoundedNum::new(Num::ZERO), + let c_zero_account_hash = CNum::from_const(cs, &Account { + d:BoundedNum::ZERO, p_d:Num::ZERO, - b:BoundedNum::new(Num::ZERO), - t:BoundedNum::new(Num::ZERO) - }).hash(params); + i:BoundedNum::ZERO, + b:BoundedNum::ZERO, + e:BoundedNum::ZERO, + }.hash(params)); - let c_zero_note_hash = CNum::from_const(cs, &zero_note_hash); + let c_zero_note_hash = CNum::from_const(cs, &Note { + d:BoundedNum::ZERO, + p_d:Num::ZERO, + b:BoundedNum::ZERO, + t:BoundedNum::ZERO + }.hash(params)); - - let out_note_hash:Vec<_> = s.deposits.iter().map(|d| d.to_note()) - .map(|n| n.hash(params)).chain(std::iter::repeat(c_zero_note_hash)).take(OUT).collect(); - let out_hash = [[out_account_hash].as_ref(), out_note_hash.as_slice()].concat(); - c_out_commitment_hash(&out_hash, params).assert_eq(&s.out_commitment_hash); + let out_hash = std::iter::once(c_zero_account_hash) + .chain(s.deposits.iter().map(|d| d.to_note().hash(params))) + .chain(std::iter::repeat(c_zero_note_hash)).take(OUT+1).collect::>(); + + let out_commitment_hash = c_out_commitment_hash(&out_hash, params); + + // this variable is not public in this circuit + let tree_pub = CTreePub { + root_before: s.root_before.clone(), + root_after: s.root_after.clone(), + leaf: out_commitment_hash.clone(), + }; + + let tree_sec = CTreeSec { + proof_filled: s.proof_filled.clone(), + proof_free: s.proof_free.clone(), + prev_leaf: s.prev_leaf.clone(), + }; + + tree_update(&tree_pub, &tree_sec, params); + } diff --git a/src/helpers/sample_data.rs b/src/helpers/sample_data.rs index 0196dcf..97290d2 100644 --- a/src/helpers/sample_data.rs +++ b/src/helpers/sample_data.rs @@ -1,5 +1,6 @@ use fawkes_crypto::{BorshSerialize, ff_uint::PrimeField}; +use fawkes_crypto::native::poseidon::{poseidon_merkle_proof_root}; use crate::{constants, fawkes_crypto::{ @@ -104,7 +105,7 @@ impl State

{ } items[account_id].0.p_d = derive_key_p_d(items[account_id].0.d.to_num(), eta, params).x; - items[account_id].0.i = BoundedNum::new(Num::ZERO); + items[account_id].0.i = BoundedNum::ZERO; let mut default_hashes = vec![Num::ZERO;constants::HEIGHT+1]; let mut hashes = vec![]; @@ -152,10 +153,10 @@ impl State

{ pub fn random_sample_transfer(&self, rng:&mut R, params:&P) -> (TransferPub, TransferSec) { let zero_note = Note { - d: BoundedNum::new(Num::ZERO), + d: BoundedNum::ZERO, p_d: Num::ZERO, - b: BoundedNum::new(Num::ZERO), - t: BoundedNum::new(Num::ZERO), + b: BoundedNum::ZERO, + t: BoundedNum::ZERO, }; let root = self.root(); @@ -187,7 +188,7 @@ impl State

{ let mut out_note: Note = Note::sample(rng, params); - out_note.b = BoundedNum::new(Num::ZERO); + out_note.b = BoundedNum::ZERO; let mut input_hashes = vec![self.items[self.account_id].0.hash(params)]; for &i in self.note_id.iter() { @@ -363,7 +364,7 @@ pub fn random_sample_tree_update(rng:&mut R, params:&P) -> ( } -pub fn serialize_scalars_and_delegated_deposits_be(och:Num, out_account_hash:Num, deposits:&[DelegatedDeposit]) -> Vec { +pub fn serialize_scalars_and_delegated_deposits_be(scalars:&[Num], deposits:&[DelegatedDeposit]) -> Vec { deposits.iter().rev().flat_map(|d| { let mut res = d.b.try_to_vec().unwrap(); res.extend(d.p_d.try_to_vec().unwrap()); @@ -371,14 +372,12 @@ pub fn serialize_scalars_and_delegated_deposits_be(och:Num, o res }) - .chain(out_account_hash.try_to_vec().unwrap()) - .chain(vec![0xff;4]) - .chain(och.try_to_vec().unwrap()) + .chain(scalars.iter().rev().flat_map(|s| s.try_to_vec().unwrap())) .rev().collect::>() } + pub fn random_sample_delegated_deposit(rng:&mut R, params:&P) -> (DelegatedDepositBatchPub, DelegatedDepositBatchSec) { - let out_account = Account::sample(rng, params); let deposits:SizedVec<_,{constants::DELEGATED_DEPOSITS_NUM}> = (0..constants::DELEGATED_DEPOSITS_NUM).map(|_| { let n = Note::sample(rng, params); @@ -389,23 +388,36 @@ pub fn random_sample_delegated_deposit(rng:&mut R, params:&P } }).collect(); - let zero_note_hash = (Note { - d:BoundedNum::new(Num::ZERO), + let zero_note_hash = Note { + d:BoundedNum::ZERO, p_d:Num::ZERO, - b:BoundedNum::new(Num::ZERO), - t:BoundedNum::new(Num::ZERO) - }).hash(params); + b:BoundedNum::ZERO, + t:BoundedNum::ZERO + }.hash(params); + + let zero_account_hash = Account { + d: BoundedNum::ZERO, + p_d: Num::ZERO, + i: BoundedNum::ZERO, + b: BoundedNum::ZERO, + e: BoundedNum::ZERO, + }.hash(params); + + let out_hash = std::iter::once(zero_account_hash) + .chain(deposits.iter().map(|d| d.to_note().hash(params))) + .chain(std::iter::repeat(zero_note_hash)).take(constants::OUT+1).collect::>(); - let out_account_hash = out_account.hash(params); + let _out_commitment_hash = out_commitment_hash(&out_hash, params); - let out_note_hash:Vec<_> = deposits.iter().map(|d| d.to_note()) - .map(|n| n.hash(params)).chain(std::iter::repeat(zero_note_hash)).take(constants::OUT).collect(); + let (mut tree_pub, tree_sec) = random_sample_tree_update(rng, params); - let out_hash = [[out_account_hash].as_ref(), out_note_hash.as_slice()].concat(); - let och = out_commitment_hash(&out_hash, params); + tree_pub.leaf = _out_commitment_hash; + tree_pub.root_after = poseidon_merkle_proof_root(tree_pub.leaf, &tree_sec.proof_free, params.compress()); - let data = serialize_scalars_and_delegated_deposits_be(och, out_account_hash, deposits.as_slice()); + let data = serialize_scalars_and_delegated_deposits_be( + &[tree_pub.root_before, tree_pub.root_after], deposits.as_slice()); + let keccak_sum = { @@ -416,8 +428,16 @@ pub fn random_sample_delegated_deposit(rng:&mut R, params:&P } res }; + let p = DelegatedDepositBatchPub {keccak_sum}; - let s = DelegatedDepositBatchSec {out_account, out_commitment_hash:och, deposits}; + + let s = DelegatedDepositBatchSec { + root_before:tree_pub.root_before, + root_after:tree_pub.root_after, + proof_filled:tree_sec.proof_filled, + proof_free:tree_sec.proof_free, + prev_leaf: tree_sec.prev_leaf, + deposits}; (p,s) } \ No newline at end of file diff --git a/src/native/boundednum.rs b/src/native/boundednum.rs index 41a24f5..308e949 100644 --- a/src/native/boundednum.rs +++ b/src/native/boundednum.rs @@ -18,6 +18,9 @@ impl PartialEq for BoundedNum { impl BoundedNum { + pub const ONE: Self = BoundedNum(Num::::ONE); + pub const ZERO: Self = BoundedNum(Num::::ZERO); + pub fn new(n:Num) -> Self { assert!(L < Fr::MODULUS_BITS as usize && n.to_uint() < (NumRepr::::ONE << L as u32)); Self::new_unchecked(n) diff --git a/src/native/delegated_deposit.rs b/src/native/delegated_deposit.rs index a54ff9c..571b538 100644 --- a/src/native/delegated_deposit.rs +++ b/src/native/delegated_deposit.rs @@ -2,8 +2,8 @@ use fawkes_crypto::ff_uint::{Num, PrimeField}; use crate::native::{boundednum::BoundedNum, note::Note}; use std::fmt::Debug; use crate::fawkes_crypto::core::sizedvec::SizedVec; -use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM}; -use crate::native::account::Account; +use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM, HEIGHT, OUTPLUSONELOG}; +use fawkes_crypto::native::poseidon::MerkleProof; #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(bound(serialize = "", deserialize = ""))] @@ -20,7 +20,7 @@ impl DelegatedDeposit { d: self.d, p_d: self.p_d, b: self.b, - t: BoundedNum::new(Num::ZERO) + t: BoundedNum::ZERO } } } @@ -34,7 +34,10 @@ pub struct DelegatedDepositBatchPub { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(bound(serialize = "", deserialize = ""))] pub struct DelegatedDepositBatchSec { - pub out_account:Account, - pub out_commitment_hash: Num, + pub root_before: Num, + pub root_after: Num, + pub proof_filled:MerkleProof, + pub proof_free:MerkleProof, + pub prev_leaf:Num, pub deposits: SizedVec, DELEGATED_DEPOSITS_NUM> -} \ No newline at end of file +} diff --git a/tests/delegated_deposit.rs b/tests/delegated_deposit.rs index 2e21b5f..e8a7670 100644 --- a/tests/delegated_deposit.rs +++ b/tests/delegated_deposit.rs @@ -7,10 +7,10 @@ use libzeropool::{POOL_PARAMS, circuit::{ cs::{CS, DebugCS}, num::CNum, - bool::CBool }, core::{signal::Signal, sizedvec::SizedVec}, rand::{thread_rng, Rng}, + ff_uint::Num }, }; @@ -51,10 +51,10 @@ fn test_bitify_delegated_deposits_be() { } }).collect(); - let och = rng.gen(); - let out_account_hash = rng.gen(); + let roots:SizedVec,2> = (0..2).map(|_|rng.gen()).collect(); - let data = serialize_scalars_and_delegated_deposits_be(och, out_account_hash, deposits.as_slice()); + + let data = serialize_scalars_and_delegated_deposits_be(roots.as_slice(), deposits.as_slice()); let bitlen = data.len()*8; @@ -67,13 +67,10 @@ fn test_bitify_delegated_deposits_be() { let ref cs = DebugCS::rc_new(); let c_deposits:SizedVec>,{N_ITEMS}> = Signal::alloc(cs, Some(deposits).as_ref()); - let c_true = CBool::from_const(cs, &true); - let c_och = CNum::alloc(cs, Some(och).as_ref()); - let c_out_account_hash = CNum::alloc(cs, Some(out_account_hash).as_ref()); + + let c_roots:SizedVec>,2> = Signal::alloc(cs, Some(roots).as_ref()); - let c_bits = num_to_iter_bits_be(&c_och) - .chain(std::iter::repeat(c_true).take(32)) - .chain(num_to_iter_bits_be(&c_out_account_hash)) + let c_bits = c_roots.iter().flat_map(num_to_iter_bits_be) .chain(c_deposits.iter().flat_map( |d| d.to_iter_bits_be() )).collect::>(); From 64ba628e7ba96d084c2a9c5533daa5e0af0eeef5 Mon Sep 17 00:00:00 2001 From: Igor Gulamov Date: Wed, 8 Feb 2023 13:55:50 +0400 Subject: [PATCH 6/8] remove tree update from delegated deposit snark --- src/circuit/delegated_deposit.rs | 34 ++++++-------------------------- src/helpers/sample_data.rs | 18 +++++------------ src/native/delegated_deposit.rs | 9 ++------- tests/delegated_deposit.rs | 4 ++-- 4 files changed, 15 insertions(+), 50 deletions(-) diff --git a/src/circuit/delegated_deposit.rs b/src/circuit/delegated_deposit.rs index b4c00d9..2d63a21 100644 --- a/src/circuit/delegated_deposit.rs +++ b/src/circuit/delegated_deposit.rs @@ -2,8 +2,7 @@ use crate::fawkes_crypto::circuit::{ bool::CBool, num::CNum, bitify::{c_into_bits_le_strict, c_into_bits_le, c_from_bits_le}, - cs::{RCS, CS}, - poseidon::CMerkleProof + cs::{RCS, CS} }; use crate::fawkes_crypto::ff_uint::{PrimeFieldParams, Num}; use crate::fawkes_crypto::core::{ @@ -14,7 +13,6 @@ use crate::circuit::{ boundednum::CBoundedNum, note::CNote, tx::c_out_commitment_hash, - tree::{CTreePub, CTreeSec, tree_update} }; use crate::native::{ params::PoolParams, @@ -23,7 +21,7 @@ use crate::native::{ account::Account, delegated_deposit::{DelegatedDeposit, DelegatedDepositBatchPub, DelegatedDepositBatchSec} }; -use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM, OUT, HEIGHT, OUTPLUSONELOG}; +use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM, OUT}; use fawkes_crypto_keccak256::circuit::hash::c_keccak256; #[derive(Clone, Signal)] @@ -83,12 +81,8 @@ pub struct CDelegatedDepositBatchPub { #[derive(Clone, Signal)] #[Value = "DelegatedDepositBatchSec"] pub struct CDelegatedDepositBatchSec { - pub root_before: CNum, - pub root_after: CNum, - pub deposits: SizedVec, DELEGATED_DEPOSITS_NUM>, - pub proof_filled:CMerkleProof, - pub proof_free:CMerkleProof, - pub prev_leaf:CNum, + pub out_commitment_hash: CNum, + pub deposits: SizedVec, DELEGATED_DEPOSITS_NUM> } fn c_keccak256_be_reduced(cs:&RCS, bits:&[CBool]) -> CNum { @@ -104,8 +98,7 @@ pub fn check_delegated_deposit_batch>( ) { assert!(DELEGATED_DEPOSITS_NUM <= OUT); let cs = p.get_cs(); - let bits:Vec<_> = num_to_iter_bits_be(&s.root_before) - .chain(num_to_iter_bits_be(&s.root_after)) + let bits:Vec<_> = num_to_iter_bits_be(&s.out_commitment_hash) .chain( s.deposits.iter().flat_map( |d| d.to_iter_bits_be() @@ -133,22 +126,7 @@ pub fn check_delegated_deposit_batch>( .chain(s.deposits.iter().map(|d| d.to_note().hash(params))) .chain(std::iter::repeat(c_zero_note_hash)).take(OUT+1).collect::>(); - let out_commitment_hash = c_out_commitment_hash(&out_hash, params); - - // this variable is not public in this circuit - let tree_pub = CTreePub { - root_before: s.root_before.clone(), - root_after: s.root_after.clone(), - leaf: out_commitment_hash.clone(), - }; - - let tree_sec = CTreeSec { - proof_filled: s.proof_filled.clone(), - proof_free: s.proof_free.clone(), - prev_leaf: s.prev_leaf.clone(), - }; - - tree_update(&tree_pub, &tree_sec, params); + c_out_commitment_hash(&out_hash, params).assert_eq(&s.out_commitment_hash); } diff --git a/src/helpers/sample_data.rs b/src/helpers/sample_data.rs index 97290d2..5a71fad 100644 --- a/src/helpers/sample_data.rs +++ b/src/helpers/sample_data.rs @@ -1,6 +1,5 @@ use fawkes_crypto::{BorshSerialize, ff_uint::PrimeField}; -use fawkes_crypto::native::poseidon::{poseidon_merkle_proof_root}; use crate::{constants, fawkes_crypto::{ @@ -409,14 +408,10 @@ pub fn random_sample_delegated_deposit(rng:&mut R, params:&P let _out_commitment_hash = out_commitment_hash(&out_hash, params); - let (mut tree_pub, tree_sec) = random_sample_tree_update(rng, params); - - tree_pub.leaf = _out_commitment_hash; - tree_pub.root_after = poseidon_merkle_proof_root(tree_pub.leaf, &tree_sec.proof_free, params.compress()); - + let data = serialize_scalars_and_delegated_deposits_be( - &[tree_pub.root_before, tree_pub.root_after], deposits.as_slice()); + &[_out_commitment_hash], deposits.as_slice()); @@ -432,12 +427,9 @@ pub fn random_sample_delegated_deposit(rng:&mut R, params:&P let p = DelegatedDepositBatchPub {keccak_sum}; let s = DelegatedDepositBatchSec { - root_before:tree_pub.root_before, - root_after:tree_pub.root_after, - proof_filled:tree_sec.proof_filled, - proof_free:tree_sec.proof_free, - prev_leaf: tree_sec.prev_leaf, - deposits}; + out_commitment_hash:_out_commitment_hash, + deposits + }; (p,s) } \ No newline at end of file diff --git a/src/native/delegated_deposit.rs b/src/native/delegated_deposit.rs index 571b538..d7a9fb7 100644 --- a/src/native/delegated_deposit.rs +++ b/src/native/delegated_deposit.rs @@ -2,8 +2,7 @@ use fawkes_crypto::ff_uint::{Num, PrimeField}; use crate::native::{boundednum::BoundedNum, note::Note}; use std::fmt::Debug; use crate::fawkes_crypto::core::sizedvec::SizedVec; -use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM, HEIGHT, OUTPLUSONELOG}; -use fawkes_crypto::native::poseidon::MerkleProof; +use crate::constants::{DIVERSIFIER_SIZE_BITS, BALANCE_SIZE_BITS, DELEGATED_DEPOSITS_NUM}; #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(bound(serialize = "", deserialize = ""))] @@ -34,10 +33,6 @@ pub struct DelegatedDepositBatchPub { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(bound(serialize = "", deserialize = ""))] pub struct DelegatedDepositBatchSec { - pub root_before: Num, - pub root_after: Num, - pub proof_filled:MerkleProof, - pub proof_free:MerkleProof, - pub prev_leaf:Num, + pub out_commitment_hash: Num, pub deposits: SizedVec, DELEGATED_DEPOSITS_NUM> } diff --git a/tests/delegated_deposit.rs b/tests/delegated_deposit.rs index e8a7670..ff1d278 100644 --- a/tests/delegated_deposit.rs +++ b/tests/delegated_deposit.rs @@ -51,7 +51,7 @@ fn test_bitify_delegated_deposits_be() { } }).collect(); - let roots:SizedVec,2> = (0..2).map(|_|rng.gen()).collect(); + let roots:SizedVec,1> = (0..1).map(|_|rng.gen()).collect(); let data = serialize_scalars_and_delegated_deposits_be(roots.as_slice(), deposits.as_slice()); @@ -68,7 +68,7 @@ fn test_bitify_delegated_deposits_be() { let c_deposits:SizedVec>,{N_ITEMS}> = Signal::alloc(cs, Some(deposits).as_ref()); - let c_roots:SizedVec>,2> = Signal::alloc(cs, Some(roots).as_ref()); + let c_roots:SizedVec>,1> = Signal::alloc(cs, Some(roots).as_ref()); let c_bits = c_roots.iter().flat_map(num_to_iter_bits_be) .chain(c_deposits.iter().flat_map( From 4058cad45127ebdeb87bb6b095685667dd01d9de Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Thu, 9 Feb 2023 19:45:22 +0300 Subject: [PATCH 7/8] Fix dependencies --- Cargo.toml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8fbea3c..912330f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ name = "libzeropool-setup" required-features = ["cli_libzeropool_setup"] [dependencies] -fawkes-crypto = { git = "ssh://git@github.com/zkBob/fawkes-crypto.git", branch = "multicore-wasm", version = "4.3.3", features = ["rand_support"] } +fawkes-crypto = { git = "https://github.com/zkBob/fawkes-crypto", branch = "feature/delegated-deposits", features = ["rand_support"] } sha3 = "0.9.1" serde = { version = "1.0", features = ["derive"] } @@ -26,9 +26,7 @@ lazy_static = "1.4.0" chacha20poly1305 = "0.8.0" clap={ package = "clap-v3", version = "3.0.0-beta.1", optional=true} convert_case = "0.4.0" -fawkes-crypto-keccak256="0.1.1" - - +fawkes-crypto-keccak256 = { git = "https://github.com/zkbob/keccak", branch = "zkbob" } [features] in1out127=[] @@ -39,4 +37,4 @@ cli_libzeropool_setup = ["clap", "fawkes-crypto/rand_support", "fawkes-crypto/ba default=["cli_libzeropool_setup", "in3out127"] [dev-dependencies] -fawkes-crypto = { git = "ssh://git@github.com/zkBob/fawkes-crypto.git", branch = "multicore-wasm", version = "4.3.3", features = ["rand_support", "backend_bellman_groth16"] } +fawkes-crypto = { git = "https://github.com/zkBob/fawkes-crypto", branch = "feature/delegated-deposits", features = ["rand_support", "backend_bellman_groth16"] } From a1964378e323dd22607fde37e3eb5416ebe66ae9 Mon Sep 17 00:00:00 2001 From: Vladimir Popov Date: Sun, 12 Feb 2023 21:04:14 +0300 Subject: [PATCH 8/8] remove out_commitment from dd secret inputs --- src/circuit/delegated_deposit.rs | 18 +++++++++--------- src/helpers/sample_data.rs | 1 - src/native/delegated_deposit.rs | 1 - 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/circuit/delegated_deposit.rs b/src/circuit/delegated_deposit.rs index 2d63a21..1c037ff 100644 --- a/src/circuit/delegated_deposit.rs +++ b/src/circuit/delegated_deposit.rs @@ -81,7 +81,6 @@ pub struct CDelegatedDepositBatchPub { #[derive(Clone, Signal)] #[Value = "DelegatedDepositBatchSec"] pub struct CDelegatedDepositBatchSec { - pub out_commitment_hash: CNum, pub deposits: SizedVec, DELEGATED_DEPOSITS_NUM> } @@ -98,13 +97,6 @@ pub fn check_delegated_deposit_batch>( ) { assert!(DELEGATED_DEPOSITS_NUM <= OUT); let cs = p.get_cs(); - let bits:Vec<_> = num_to_iter_bits_be(&s.out_commitment_hash) - .chain( - s.deposits.iter().flat_map( - |d| d.to_iter_bits_be() - )).collect(); - - c_keccak256_be_reduced(cs, &bits).assert_eq(&p.keccak_sum); let c_zero_account_hash = CNum::from_const(cs, &Account { d:BoundedNum::ZERO, @@ -126,7 +118,15 @@ pub fn check_delegated_deposit_batch>( .chain(s.deposits.iter().map(|d| d.to_note().hash(params))) .chain(std::iter::repeat(c_zero_note_hash)).take(OUT+1).collect::>(); - c_out_commitment_hash(&out_hash, params).assert_eq(&s.out_commitment_hash); + let out_commitment_hash = c_out_commitment_hash(&out_hash, params); + let bits:Vec<_> = num_to_iter_bits_be(&out_commitment_hash) + .chain( + s.deposits.iter().flat_map( + |d| d.to_iter_bits_be() + )).collect(); + + c_keccak256_be_reduced(cs, &bits).assert_eq(&p.keccak_sum); + } diff --git a/src/helpers/sample_data.rs b/src/helpers/sample_data.rs index 5a71fad..74cdb71 100644 --- a/src/helpers/sample_data.rs +++ b/src/helpers/sample_data.rs @@ -427,7 +427,6 @@ pub fn random_sample_delegated_deposit(rng:&mut R, params:&P let p = DelegatedDepositBatchPub {keccak_sum}; let s = DelegatedDepositBatchSec { - out_commitment_hash:_out_commitment_hash, deposits }; (p,s) diff --git a/src/native/delegated_deposit.rs b/src/native/delegated_deposit.rs index d7a9fb7..9ac8645 100644 --- a/src/native/delegated_deposit.rs +++ b/src/native/delegated_deposit.rs @@ -33,6 +33,5 @@ pub struct DelegatedDepositBatchPub { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(bound(serialize = "", deserialize = ""))] pub struct DelegatedDepositBatchSec { - pub out_commitment_hash: Num, pub deposits: SizedVec, DELEGATED_DEPOSITS_NUM> }