Skip to content

Commit

Permalink
Merge pull request #25 from zkBob/develop
Browse files Browse the repository at this point in the history
Merge the develop branch into main branch
  • Loading branch information
EvgenKor authored Oct 27, 2022
2 parents 48bd6db + 1afc42c commit 5500186
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 40 deletions.
2 changes: 1 addition & 1 deletion libzkbob-rs-wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "libzkbob-rs-wasm"
description = "A higher level zkBob API for Wasm"
version = "0.6.1"
version = "0.7.0"
authors = ["Dmitry Vdovin <[email protected]>"]
repository = "https://github.com/zkBob/libzkbob-rs/"
license = "MIT OR Apache-2.0"
Expand Down
3 changes: 3 additions & 0 deletions libzkbob-rs-wasm/scripts/build
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ function build () {
# Remove invalid typings
sed -i.bak -E '/BroccoliDestroyInstance/d' $PARENT_DIR/$1/libzkbob_rs_wasm.d.ts
sed -i.bak -E '/BroccoliDestroyInstance/d' $PARENT_DIR/$1/libzkbob_rs_wasm_bg.wasm.d.ts

rm $PARENT_DIR/$1/libzkbob_rs_wasm_bg.wasm.d.ts

# Patch package.json, since wasm-pack doesn't allow renaming packages
sed -i.bak -E "s/\"name\": \"libzkbob-rs-wasm\"/\"name\": \"libzkbob-rs-wasm-$1\"/g" $PARENT_DIR/$1/package.json
# Add workerHelpers.js in package.json
Expand Down
6 changes: 3 additions & 3 deletions libzkbob-rs-wasm/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ use crate::client::tx_parser::StateUpdate;
use crate::database::Database;
use crate::ts_types::Hash as JsHash;
use crate::{
keys::reduce_sk, Account, Fr, Fs, Hashes, IDepositData, IDepositPermittableData,
ITransferData, IWithdrawData, IMultiTransferData, IMultiWithdrawData,
keys::reduce_sk, Account, Fr, Fs, Hashes,
IDepositData, IDepositPermittableData, ITransferData, IWithdrawData,
IndexedNote, IndexedNotes, MerkleProof, Pair, PoolParams, Transaction, UserState, POOL_PARAMS,
};

mod tx_types;
use tx_types::{JsTxType, JsMultiTxType};
use tx_types::JsTxType;

mod tx_parser;

Expand Down
2 changes: 1 addition & 1 deletion libzkbob-rs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "libzkbob-rs"
description = "A higher level zkBob API"
version = "0.6.1"
version = "0.7.0"
authors = ["Dmitry Vdovin <[email protected]>"]
repository = "https://github.com/zkBob/libzkbob-rs/"
license = "MIT OR Apache-2.0"
Expand Down
6 changes: 3 additions & 3 deletions libzkbob-rs/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ where
let next_by_optimistic_leaf = extra_state.new_leafs
.last()
.map(|leafs| {
(((leafs.0 + (leafs.1.len() as u64)) >> constants::OUTPLUSONELOG) + 1) << constants::OUTPLUSONELOG
(((leafs.0 + (leafs.1.len() as u64) - 1) >> constants::OUTPLUSONELOG) + 1) << constants::OUTPLUSONELOG
});
let next_by_optimistic_commitment = extra_state.new_commitments
.last()
Expand All @@ -250,7 +250,7 @@ where
.into_iter()
.chain(next_by_optimistic_commitment)
.max()
.unwrap_or(self.state.tree.next_index())
.unwrap_or_else(|| self.state.tree.next_index())
}));

let (fee, tx_data, user_data) = {
Expand Down Expand Up @@ -320,7 +320,7 @@ where

let (num_real_out_notes, out_notes): (_, SizedVec<_, { constants::OUT }>) =
if let TxType::Transfer(_, _, outputs) = &tx {
if outputs.len() >= constants::OUT {
if outputs.len() > constants::OUT {
return Err(CreateTxError::TooManyOutputs {
max: constants::OUT,
got: outputs.len(),
Expand Down
6 changes: 3 additions & 3 deletions libzkbob-rs/src/client/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{merkle::MerkleTree, sparse_array::SparseArray};

pub type TxStorage<D, Fr> = SparseArray<D, Transaction<Fr>>;

#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug)]
pub enum Transaction<Fr: PrimeField> {
Account(NativeAccount<Fr>),
Note(NativeNote<Fr>),
Expand Down Expand Up @@ -197,8 +197,8 @@ where
/// Return an index of a earliest usable note including optimistic state
pub fn earliest_usable_index_optimistic(
&self,
optimistic_accounts: &Vec<(u64, Account<P::Fr>)>,
optimistic_notes: &Vec<(u64, Note<P::Fr>)>
optimistic_accounts: &[(u64, Account<P::Fr>)],
optimistic_notes: &[(u64, Note<P::Fr>)]
) -> u64 {
let latest_account_index = optimistic_accounts
.last()
Expand Down
119 changes: 90 additions & 29 deletions libzkbob-rs/src/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,39 +150,44 @@ impl<D: KeyValueDB, P: PoolParams> MerkleTree<D, P> {
return;
}

let mut next_index: u64 = 0;
let mut start_index: u64 = u64::MAX;
let mut last_bound_index: u64 = 0;
let mut first_bound_index: u64 = u64::MAX;
let mut virtual_nodes: HashMap<(u32, u64), Hash<P::Fr>> = commitments
.into_iter()
.map(|(index, hash)| {
assert_eq!(index & ((1 << constants::OUTPLUSONELOG) - 1), 0);
start_index = start_index.min(index);
next_index = next_index.max(index + 1);
first_bound_index = first_bound_index.min(index);
last_bound_index = last_bound_index.max(index);
((constants::OUTPLUSONELOG as u32, index >> constants::OUTPLUSONELOG), hash)
})
.collect();

leafs.into_iter().for_each(|(index, leafs)| {
assert_eq!(index & ((1 << constants::OUTPLUSONELOG) - 1), 0);
start_index = start_index.min(index);
next_index = next_index.max(index + leafs.len() as u64);
(0..constants::OUTPLUSONELOG)
.for_each(|height| {
virtual_nodes.insert((height as u32, ((index + leafs.len() as u64 - 1) >> height) + 1), self.zero_note_hashes[height]);
leafs.into_iter()
.filter(|(_, leafs)| !leafs.is_empty())
.for_each(|(index, leafs)| {
assert_eq!(index & ((1 << constants::OUTPLUSONELOG) - 1), 0);
first_bound_index = first_bound_index.min(index);
last_bound_index = last_bound_index.max(index + leafs.len() as u64 - 1);
(0..constants::OUTPLUSONELOG)
.for_each(|height| {
let level_index = ((index + leafs.len() as u64 - 1) >> height) + 1;
if level_index < ((index + (constants::OUT as u64 + 1)) >> height) && level_index % 2 == 1 {
virtual_nodes.insert((height as u32, level_index), self.zero_note_hashes[height]);
}
});
leafs.into_iter().enumerate().for_each(|(i, leaf)| {
virtual_nodes.insert((0_u32, index + i as u64), leaf);
});
leafs.into_iter().enumerate().for_each(|(i, leaf)| {
virtual_nodes.insert((0_u32, index + i as u64), leaf);
});
});

let original_next_index = self.next_index;
self.update_next_index_from_node(0, next_index);
self.update_next_index_from_node(0, last_bound_index);

let update_boundaries = UpdateBoundaries {
updated_range_left_index: original_next_index,
updated_range_right_index: self.next_index,
new_hashes_left_index: start_index,
new_hashes_right_index: next_index,
new_hashes_left_index: first_bound_index,
new_hashes_right_index: last_bound_index + 1,
};

// calculate new hashes
Expand Down Expand Up @@ -326,7 +331,7 @@ impl<D: KeyValueDB, P: PoolParams> MerkleTree<D, P> {
update_boundaries: &UpdateBoundaries,
) -> Hash<P::Fr>
{
self.get_virtual_node_full(constants::HEIGHT as u32, 0, virtual_nodes, &update_boundaries)
self.get_virtual_node_full(constants::HEIGHT as u32, 0, virtual_nodes, update_boundaries)
}

pub fn get_opt(&self, height: u32, index: u64) -> Option<Hash<P::Fr>> {
Expand Down Expand Up @@ -468,38 +473,41 @@ impl<D: KeyValueDB, P: PoolParams> MerkleTree<D, P> {
I1: IntoIterator<Item = (u64, Vec<Hash<P::Fr>>)>,
I2: IntoIterator<Item = (u64, Hash<P::Fr>)>,
{
let mut next_index: Option<u64> = None;
let mut start_index: Option<u64> = None;
let mut last_bound_index: Option<u64> = None;
let mut first_bound_index: Option<u64> = None;
let mut virtual_nodes: HashMap<(u32, u64), Hash<P::Fr>> = new_commitments
.into_iter()
.map(|(index, hash)| {
assert_eq!(index & ((1 << constants::OUTPLUSONELOG) - 1), 0);
start_index = Some(start_index.unwrap_or(u64::MAX).min(index));
next_index = Some(next_index.unwrap_or(0).max(index + 1));
first_bound_index = Some(first_bound_index.unwrap_or(u64::MAX).min(index));
last_bound_index = Some(last_bound_index.unwrap_or(0).max(index));
((constants::OUTPLUSONELOG as u32, index >> constants::OUTPLUSONELOG), hash)
})
.collect();

new_hashes.into_iter().for_each(|(index, leafs)| {
assert_eq!(index & ((1 << constants::OUTPLUSONELOG) - 1), 0);
start_index = Some(start_index.unwrap_or(u64::MAX).min(index));
next_index = Some(next_index.unwrap_or(0).max(index + leafs.len() as u64));
first_bound_index = Some(first_bound_index.unwrap_or(u64::MAX).min(index));
last_bound_index = Some(last_bound_index.unwrap_or(0).max(index + leafs.len() as u64 - 1));
(0..constants::OUTPLUSONELOG)
.for_each(|height| {
virtual_nodes.insert((height as u32, ((index + leafs.len() as u64 - 1) >> height) + 1), self.zero_note_hashes[height]);
let level_index = ((index + leafs.len() as u64 - 1) >> height) + 1;
if level_index < ((index + (constants::OUT as u64 + 1)) >> height) && level_index % 2 == 1 {
virtual_nodes.insert((height as u32, level_index), self.zero_note_hashes[height]);
}
});
leafs.into_iter().enumerate().for_each(|(i, leaf)| {
virtual_nodes.insert((0_u32, index + i as u64), leaf);
});
});

let update_boundaries = {
if let (Some(start_index), Some(next_index)) = (start_index, next_index) {
if let (Some(first_bound_index), Some(last_bound_index)) = (first_bound_index, last_bound_index) {
UpdateBoundaries {
updated_range_left_index: self.next_index,
updated_range_right_index: Self::calc_next_index(next_index),
new_hashes_left_index: start_index,
new_hashes_right_index: next_index,
updated_range_right_index: Self::calc_next_index(last_bound_index),
new_hashes_left_index: first_bound_index,
new_hashes_right_index: last_bound_index + 1,
}
} else {
UpdateBoundaries {
Expand Down Expand Up @@ -1476,6 +1484,8 @@ mod tests {
#[test_case(15, 7, 0.0)]
#[test_case(15, 7, 0.5)]
#[test_case(15, 7, 1.0)]
#[test_case(15, 100, 0.0)]
#[test_case(15, 128, 0.0)]
fn test_add_leafs_and_commitments(tx_count: u64, max_leafs_count: u32, commitments_probability: f64) {
let mut rng = CustomRng;
let mut first_tree = MerkleTree::new(create(3), POOL_PARAMS.clone());
Expand Down Expand Up @@ -1523,6 +1533,56 @@ mod tests {
assert_eq!(first_tree.next_index(), second_tree.next_index());
}

#[test_case(2, 1)]
#[test_case(2, 2)]
#[test_case(2, 64)]
#[test_case(2, 65)]
#[test_case(2, 100)]
#[test_case(2, 127)]
#[test_case(2, 128)]
fn test_add_leafs_and_commitments_multinotes(tx_count: u64, leafs_count: u32) {
let mut rng = CustomRng;
let mut first_tree = MerkleTree::new(create(3), POOL_PARAMS.clone());
let mut second_tree = MerkleTree::new(create(3), POOL_PARAMS.clone());

let leafs: Vec<(u64, Vec<_>)> = (0..tx_count)
.map(|i| {
(i * (constants::OUT + 1) as u64, (0..leafs_count).map(|_| rng.gen()).collect())
})
.collect();

for (index, leafs) in leafs.clone().into_iter() {
first_tree.add_hashes(index, leafs)
}

let commitments: Vec<(u64, _)> = leafs.clone().into_iter().map(|(index, leafs)| {
let mut out_hashes = leafs.clone();
out_hashes.resize(constants::OUT+1, first_tree.zero_note_hashes[0]);
let commitment = tx::out_commitment_hash(out_hashes.as_slice(), &POOL_PARAMS.clone());
(index, commitment)
}).collect();

commitments.iter().for_each(|(index, commitment)| {
assert_eq!(first_tree.get(constants::OUTPLUSONELOG as u32, *index >> constants::OUTPLUSONELOG), *commitment);
});

let mut sub_leafs: Vec<(u64, Vec<_>)> = Vec::new();
let sub_commitments: Vec<(u64, _)> = Vec::new();
(0..leafs.len()).for_each(|i| {
/*if rng.gen_bool(commitments_probability) {
sub_commitments.push(commitments[i as usize]);
} else {
sub_leafs.push((leafs[i as usize].0, leafs[i as usize].1.clone()));
}*/
sub_leafs.push((leafs[i as usize].0, leafs[i as usize].1.clone()));
});

second_tree.add_leafs_and_commitments(sub_leafs, sub_commitments);

assert_eq!(first_tree.get_root().to_string(), second_tree.get_root().to_string());
assert_eq!(first_tree.next_index(), second_tree.next_index());
}


#[test_case(0, 0, 0.0)]
#[test_case(1, 1, 0.0)]
Expand All @@ -1533,6 +1593,7 @@ mod tests {
#[test_case(15, 7, 0.0)]
#[test_case(15, 7, 0.5)]
#[test_case(15, 7, 1.0)]
#[test_case(15, 128, 0.0)]
fn test_get_root_optimistic(tx_count: u64, max_leafs_count: u32, commitments_probability: f64) {
let mut rng = CustomRng;
let mut tree = MerkleTree::new(create(3), POOL_PARAMS.clone());
Expand Down

0 comments on commit 5500186

Please sign in to comment.