Skip to content

Commit

Permalink
feat: add zero element to the tree
Browse files Browse the repository at this point in the history
  • Loading branch information
enricobottazzi committed Dec 7, 2023
1 parent 8be1acc commit ad0c388
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 24 deletions.
14 changes: 14 additions & 0 deletions csv/entry_13.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
username,balance_ETH_ETH,balance_USDT_ETH
dxGaEAii,11888,41163
MBlfbBGI,67823,18651
lAhWlEWZ,18651,2087
nuZweYtO,22073,55683
gbdSwiuY,34897,83296
RZNneNuP,83296,16881
YsscHXkp,31699,35479
RkLzkDun,2087,79731
HlQlnEYI,30605,11888
RqkZOFYe,16881,14874
NjCSRAfD,41163,67823
pHniJMQY,14874,22073
dOGIMzKR,10032,10032
19 changes: 19 additions & 0 deletions csv/entry_17.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
username,balance_ETH_ETH,balance_USDT_ETH
dxGaEAii,11888,41163
MBlfbBGI,67823,18651
lAhWlEWZ,18651,2087
nuZweYtO,22073,55683
gbdSwiuY,34897,83296
RZNneNuP,83296,16881
YsscHXkp,31699,35479
RkLzkDun,2087,79731
HlQlnEYI,30605,11888
RqkZOFYe,16881,14874
NjCSRAfD,41163,67823
pHniJMQY,14874,22073
dOGIMzKR,10032,10032
HfMDmNLp,55683,34897
xPLKzCBl,79731,30605
AtwIxZHo,35479,31699
HuIIxzHo,1,1

56 changes: 33 additions & 23 deletions zk_prover/src/merkle_sum_tree/mst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,6 @@ pub struct Cryptocurrency {
}

impl<const N_CURRENCIES: usize, const N_BYTES: usize> MerkleSumTree<N_CURRENCIES, N_BYTES> {
pub fn from_params(
root: Node<N_CURRENCIES>,
nodes: Vec<Vec<Node<N_CURRENCIES>>>,
depth: usize,
entries: Vec<Entry<N_CURRENCIES>>,
cryptocurrencies: Vec<Cryptocurrency>,
is_sorted: bool,
) -> Result<Self, Box<dyn std::error::Error>>
where
[usize; N_CURRENCIES + 1]: Sized,
[usize; N_CURRENCIES + 2]: Sized,
{
Ok(MerkleSumTree::<N_CURRENCIES, N_BYTES> {
root,
nodes,
depth,
entries,
cryptocurrencies,
is_sorted,
})
}

/// Builds a Merkle Sum Tree from a CSV file stored at `path`. The CSV file must be formatted as follows:
///
/// `username,balance_<cryptocurrency>_<chain>,balance_<cryptocurrency>_<chain>,...`
Expand Down Expand Up @@ -120,8 +98,9 @@ impl<const N_CURRENCIES: usize, const N_BYTES: usize> MerkleSumTree<N_CURRENCIES
Self::from_entries(entries, cryptocurrencies, true)
}

/// Builds a Merkle Sum Tree from a vector of entries
pub fn from_entries(
entries: Vec<Entry<N_CURRENCIES>>,
mut entries: Vec<Entry<N_CURRENCIES>>,
cryptocurrencies: Vec<Cryptocurrency>,
is_sorted: bool,
) -> Result<MerkleSumTree<N_CURRENCIES, N_BYTES>, Box<dyn std::error::Error>>
Expand All @@ -133,6 +112,14 @@ impl<const N_CURRENCIES: usize, const N_BYTES: usize> MerkleSumTree<N_CURRENCIES

let mut nodes = vec![];

// Pad the entries with empty entries to make the number of entries equal to 2^depth
if entries.len() < 2usize.pow(depth as u32) {
entries.extend(vec![
Entry::init_empty();
2usize.pow(depth as u32) - entries.len()
]);
}

let leaves = build_leaves_from_entries(&entries);

let root = build_merkle_tree_from_leaves(&leaves, depth, &mut nodes)?;
Expand All @@ -147,6 +134,29 @@ impl<const N_CURRENCIES: usize, const N_BYTES: usize> MerkleSumTree<N_CURRENCIES
})
}

/// Builds a Merkle Sum Tree from a root node, a vector of nodes, a depth, a vector of entries, a vector of cryptocurrencies and a boolean indicating whether the leaves are sorted by the username byte values.
pub fn from_params(
root: Node<N_CURRENCIES>,
nodes: Vec<Vec<Node<N_CURRENCIES>>>,
depth: usize,
entries: Vec<Entry<N_CURRENCIES>>,
cryptocurrencies: Vec<Cryptocurrency>,
is_sorted: bool,
) -> Result<Self, Box<dyn std::error::Error>>
where
[usize; N_CURRENCIES + 1]: Sized,
[usize; N_CURRENCIES + 2]: Sized,
{
Ok(MerkleSumTree::<N_CURRENCIES, N_BYTES> {
root,
nodes,
depth,
entries,
cryptocurrencies,
is_sorted,
})
}

/// Updates the balances of the entry with the given username and returns the new root of the tree.
///
/// # Arguments
Expand Down
54 changes: 53 additions & 1 deletion zk_prover/src/merkle_sum_tree/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ mod test {
assert_eq!(root.balances, merkle_tree_2.root().balances);

// should create valid proof for each entry in the tree and verify it
for i in 0..15 {
for i in 0..=15 {
let proof = merkle_tree.generate_proof(i).unwrap();
assert!(merkle_tree.verify_proof(&proof));
}
Expand Down Expand Up @@ -198,4 +198,56 @@ mod test {
// The hash of the leaf should match the hash computed from the hash preimage
assert_eq!(leaf.hash, computed_leaf.hash);
}

#[test]
fn test_tree_with_zero_element_1() {
// create new merkle tree
let merkle_tree =
MerkleSumTree::<N_CURRENCIES, N_BYTES>::from_csv("../csv/entry_13.csv").unwrap();

// get root
let root = merkle_tree.root();

// expect root hash to be different than 0
assert!(root.hash != 0.into());
// expect balance to match the sum of all entries
assert!(root.balances == [385969.into(), 459661.into()]);
// expect depth to be 4
assert!(*merkle_tree.depth() == 4_usize);

// should create valid proof for each entry in the tree and verify it
for i in 0..=15 {
let proof = merkle_tree.generate_proof(i).unwrap();
assert!(merkle_tree.verify_proof(&proof));
}

// shouldn't create a proof for an entry that doesn't exist in the tree
assert!(merkle_tree.generate_proof(16).is_err());
}

#[test]
fn test_tree_with_zero_element_2() {
// create new merkle tree
let merkle_tree =
MerkleSumTree::<N_CURRENCIES, N_BYTES>::from_csv("../csv/entry_17.csv").unwrap();

// get root
let root = merkle_tree.root();

// expect root hash to be different than 0
assert!(root.hash != 0.into());
// expect balance to match the sum of all entries
assert!(root.balances == [556863.into(), 556863.into()]);
// expect depth to be 5
assert!(*merkle_tree.depth() == 5_usize);

// should create valid proof for each entry in the tree and verify it
for i in 0..=31 {
let proof = merkle_tree.generate_proof(i).unwrap();
assert!(merkle_tree.verify_proof(&proof));
}

// shouldn't create a proof for an entry that doesn't exist in the tree
assert!(merkle_tree.generate_proof(32).is_err());
}
}

0 comments on commit ad0c388

Please sign in to comment.