Skip to content

Commit

Permalink
chore: add guide on MerkleProof
Browse files Browse the repository at this point in the history
  • Loading branch information
enricobottazzi committed Nov 27, 2023
1 parent fc44e01 commit 94404ed
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 28 deletions.
9 changes: 8 additions & 1 deletion zk_prover/src/merkle_sum_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@ mod tree;
pub mod utils;
use halo2_proofs::halo2curves::bn256::Fr as Fp;

/// A struct representing a Merkle Proof.
///
/// Fields:
/// * `entry`: The entry for which the proof is generated
/// * `root`: The root of the Merkle Sum Tree
/// * `sibling_leaf_node_hash_preimage`: The hash preimage of the sibling leaf node. The hash preimage is equal to `[sibling_username, sibling.balance[0], sibling.balance[1], ... sibling.balance[N_ASSETS - 1]]`
/// * `sibling_middle_node_hash_preimages`: The hash preimages of the sibling middle nodes. The hash preimage is equal to `[sibling_left_child.balance[0] + sibling_right_child.balance[0], sibling_left_child.balance[1] + sibling_right_child.balance[1], ..., sibling_left_child.balance[N_ASSETS - 1] + sibling_right_child.balance[N_ASSETS - 1], sibling_left_child.hash, sibling_right_child.hash]`
#[derive(Clone, Debug)]
pub struct MerkleProof<const N_ASSETS: usize, const N_BYTES: usize>
where
[usize; N_ASSETS + 1]: Sized,
[usize; N_ASSETS + 2]: Sized,
[usize; N_ASSETS + 2]: Sized,
{
pub entry: Entry<N_ASSETS>,
pub root: Node<N_ASSETS>,
Expand Down
4 changes: 2 additions & 2 deletions zk_prover/src/merkle_sum_tree/mst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use num_bigint::BigUint;
///
/// A Merkle Sum Tree is a binary Merkle Tree with the following properties:
/// * Each Entry of a Merkle Sum Tree is a pair of a username and #N_ASSETS balances.
/// * Each Leaf Node contains a hash and #N_ASSETS balances. The hash is equal to `H(username, balance[0], balance[1], ... balance[N_ASSETS])`. The balances are equal to the balances associated to the entry
/// * Each Middle Node contains a hash and #N_ASSETS balances. The hash is equal to `H(LeftChild.balance[0] + RightChild.balance[0], LeftChild.balance[1] + RightChild.balance[1], ..., LeftChild.balance[N_ASSETS] + RightChild.balance[N_ASSETS], LeftChild.hash, RightChild.hash)`. The balances are equal to the sum of the balances of the child nodes per each asset.
/// * Each Leaf Node contains a hash and #N_ASSETS balances. The hash is equal to `H(username, balance[0], balance[1], ... balance[N_ASSETS - 1])`. The balances are equal to the balances associated to the entry
/// * Each Middle Node contains a hash and #N_ASSETS balances. The hash is equal to `H(LeftChild.balance[0] + RightChild.balance[0], LeftChild.balance[1] + RightChild.balance[1], ..., LeftChild.balance[N_ASSETS - 1] + RightChild.balance[N_ASSETS - 1], LeftChild.hash, RightChild.hash)`. The balances are equal to the sum of the balances of the child nodes per each asset.
/// * The Root Node represents the committed state of the Tree and contains the sum of all the entries' balances per each asset.
///
/// # Type Parameters
Expand Down
53 changes: 28 additions & 25 deletions zk_prover/src/merkle_sum_tree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,35 @@ pub struct Node<const N_ASSETS: usize> {
pub balances: [Fp; N_ASSETS],
}
impl<const N_ASSETS: usize> Node<N_ASSETS> {
/// Builds a leaf-level node of the MST
/// The leaf node hash is equal to `H(username, balance[0], balance[1], ... balance[N_ASSETS - 1])`
/// The balances are equal to `balance[0], balance[1], ... balance[N_ASSETS - 1]`
pub fn leaf(username: &BigUint, balances: &[BigUint; N_ASSETS]) -> Node<N_ASSETS>
where
[usize; N_ASSETS + 1]: Sized,
{
Node {
hash: Self::poseidon_hash_leaf(
big_uint_to_fp(username),
balances
.iter()
.map(big_uint_to_fp)
.collect::<Vec<Fp>>()
.try_into()
.unwrap(),
),
//Map the array of balances using big_int_to_fp:
balances: balances
.iter()
.map(big_uint_to_fp)
.collect::<Vec<Fp>>()
.try_into()
.unwrap(),
}
}
/// Builds a "middle" (non-leaf-level) node of the MST
/// The middle node hash is equal to `H(LeftChild.balance[0] + RightChild.balance[0], LeftChild.balance[1] + RightChild.balance[1], ..., LeftChild.balance[N_ASSETS - 1] + RightChild.balance[N_ASSETS - 1], LeftChild.hash, RightChild.hash)`
/// The balances are equal to `LeftChild.balance[0] + RightChild.balance[0], LeftChild.balance[1] + RightChild.balance[1], ..., LeftChild.balance[N_ASSETS - 1] + RightChild.balance[N_ASSETS - 1]`
pub fn middle(child_l: &Node<N_ASSETS>, child_r: &Node<N_ASSETS>) -> Node<N_ASSETS>
where
[(); N_ASSETS + 2]: Sized,
Expand All @@ -36,31 +64,6 @@ impl<const N_ASSETS: usize> Node<N_ASSETS> {
}
}

/// Builds a leaf-level node of the MST
pub fn leaf(username: &BigUint, balances: &[BigUint; N_ASSETS]) -> Node<N_ASSETS>
where
[usize; N_ASSETS + 1]: Sized,
{
Node {
hash: Self::poseidon_hash_leaf(
big_uint_to_fp(username),
balances
.iter()
.map(big_uint_to_fp)
.collect::<Vec<Fp>>()
.try_into()
.unwrap(),
),
//Map the array of balances using big_int_to_fp:
balances: balances
.iter()
.map(big_uint_to_fp)
.collect::<Vec<Fp>>()
.try_into()
.unwrap(),
}
}

pub fn leaf_node_from_preimage(preimage: [Fp; N_ASSETS + 1]) -> Node<N_ASSETS>
where
[usize; N_ASSETS + 1]: Sized,
Expand Down

0 comments on commit 94404ed

Please sign in to comment.