Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mst efficiency improvement #188

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e0e8ce2
feat: tree building rules
enricobottazzi Nov 21, 2023
134020c
feat: add `get_middle_node_hash_preimage` and `get_middle_node_hash_p…
enricobottazzi Nov 21, 2023
b236bfa
feat: update `generate_proof`
enricobottazzi Nov 21, 2023
698dce6
fix: `generate_proof`
enricobottazzi Nov 21, 2023
d62f231
fix: modify middle nodes hashing logic in circuit
enricobottazzi Nov 21, 2023
63f89d0
feat: update `MerkleProof`
enricobottazzi Nov 21, 2023
d95feef
feat: add further constraint on `MstInclusionCircuit`
enricobottazzi Nov 21, 2023
68ab601
feat: rm `test_balance_not_in_range`
enricobottazzi Nov 21, 2023
eda4ad2
refactor: update `MerkleProof`
enricobottazzi Nov 21, 2023
41f2257
chore: fix `backend`
enricobottazzi Nov 21, 2023
efe6b87
test: fix `backend`
enricobottazzi Nov 21, 2023
ac0cecd
fix: testing
enricobottazzi Nov 21, 2023
e3ba8e6
fix: modify `MstInclusionCircuit` struct
enricobottazzi Nov 21, 2023
8d9ee86
Revert "fix: modify `MstInclusionCircuit` struct"
enricobottazzi Nov 21, 2023
11f533f
chore: update `benches`
enricobottazzi Nov 21, 2023
fc44e01
fix: move poseidon hasher APIs to `Node`
enricobottazzi Nov 27, 2023
94404ed
chore: add guide on `MerkleProof `
enricobottazzi Nov 27, 2023
fe9a72f
chore: update `where` clause in backend
enricobottazzi Nov 27, 2023
1775ca7
chore: update comments
enricobottazzi Nov 27, 2023
06a15e4
chore: move `generate_leaf_hash` outside of `zk_prover`
enricobottazzi Nov 27, 2023
559ac3a
chore: add `ethers` legacy feature
enricobottazzi Nov 27, 2023
cc7d02e
Merge branch 'v1-improvements-and-consolidation' into mst-efficiency-…
enricobottazzi Nov 27, 2023
79cbe2c
chore: update verifier contract
enricobottazzi Nov 27, 2023
d84aa36
fix: removed minting erc20 on the backend test
sifnoc Nov 27, 2023
be15a56
chore: rm unused imports
enricobottazzi Nov 28, 2023
ae539a2
feat: remove `Node::leaf()`
enricobottazzi Nov 28, 2023
ac396ce
feat: rm `Node::middle()`
enricobottazzi Nov 28, 2023
69d049c
Revert "feat: remove `Node::leaf()`"
enricobottazzi Nov 28, 2023
5dea9ed
chore: DRY code
enricobottazzi Nov 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion zk_prover/src/merkle_sum_tree/mst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::merkle_sum_tree::utils::{
build_leaves_from_entries, build_merkle_tree_from_leaves, parse_csv_to_entries,
};
use crate::merkle_sum_tree::{Entry, Node, Tree};
use halo2_proofs::halo2curves::bn256::Fr as Fp;
use num_bigint::BigUint;

/// Merkle Sum Tree Data Structure.
Expand Down Expand Up @@ -154,7 +155,15 @@ impl<const N_ASSETS: usize, const N_BYTES: usize> MerkleSumTree<N_ASSETS, N_BYTE
let parent_index = current_index / 2;
let left_child = &self.nodes[depth - 1][2 * parent_index];
let right_child = &self.nodes[depth - 1][2 * parent_index + 1];
self.nodes[depth][parent_index] = Node::<N_ASSETS>::middle(left_child, right_child);

let mut hash_preimage = [Fp::zero(); N_ASSETS + 2];
for (i, balance) in hash_preimage.iter_mut().enumerate().take(N_ASSETS) {
*balance = left_child.balances[i] + right_child.balances[i];
}
hash_preimage[N_ASSETS] = left_child.hash;
hash_preimage[N_ASSETS + 1] = right_child.hash;

self.nodes[depth][parent_index] = Node::middle_node_from_preimage(&hash_preimage);
current_index = parent_index;
}

Expand Down
23 changes: 4 additions & 19 deletions zk_prover/src/merkle_sum_tree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,6 @@ pub struct Node<const N_ASSETS: usize> {
pub balances: [Fp; N_ASSETS],
}
impl<const N_ASSETS: usize> Node<N_ASSETS> {
/// 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,
{
let mut balances_sum = [Fp::zero(); N_ASSETS];
for (i, balance) in balances_sum.iter_mut().enumerate() {
*balance = child_l.balances[i] + child_r.balances[i];
}

Node {
hash: Self::poseidon_hash_middle(balances_sum, child_l.hash, child_r.hash),
balances: balances_sum,
}
}

pub fn init_empty() -> Node<N_ASSETS>
where
[usize; N_ASSETS + 1]: Sized,
Expand All @@ -49,7 +31,10 @@ impl<const N_ASSETS: usize> Node<N_ASSETS> {
}
}

pub fn middle_node_from_preimage(preimage: [Fp; N_ASSETS + 2]) -> Node<N_ASSETS>
/// Builds a middle-level node of the MST
/// The hash preimage must be equal to `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_node_from_preimage(preimage: &[Fp; N_ASSETS + 2]) -> Node<N_ASSETS>
where
[usize; N_ASSETS + 2]: Sized,
{
Expand Down
2 changes: 1 addition & 1 deletion zk_prover/src/merkle_sum_tree/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ mod test {
.get_middle_node_hash_preimage(level, index)
.unwrap();

let computed_middle_node = Node::<N_ASSETS>::middle_node_from_preimage(hash_preimage);
let computed_middle_node = Node::<N_ASSETS>::middle_node_from_preimage(&hash_preimage);

// The hash of the middle node should match the hash computed from the hash preimage
assert_eq!(middle_node.hash, computed_middle_node.hash);
Expand Down
30 changes: 24 additions & 6 deletions zk_prover/src/merkle_sum_tree/tree.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::merkle_sum_tree::utils::big_uint_to_fp;
use crate::merkle_sum_tree::Cryptocurrency;
use crate::merkle_sum_tree::{Entry, MerkleProof, Node};
use halo2_proofs::halo2curves::bn256::Fr as Fp;
use crate::merkle_sum_tree::Cryptocurrency;

/// A trait representing the basic operations for a Merkle-Sum-like Tree.
pub trait Tree<const N_ASSETS: usize, const N_BYTES: usize> {
Expand Down Expand Up @@ -152,21 +152,39 @@ pub trait Tree<const N_ASSETS: usize, const N_BYTES: usize> {
let sibling_leaf_node =
Node::<N_ASSETS>::leaf_node_from_preimage(proof.sibling_leaf_node_hash_preimage);

let mut hash_preimage = [Fp::zero(); N_ASSETS + 2];
for (i, balance) in hash_preimage.iter_mut().enumerate().take(N_ASSETS) {
*balance = node.balances[i] + sibling_leaf_node.balances[i];
}

if proof.path_indices[0] == 0.into() {
node = Node::middle(&node, &sibling_leaf_node);
hash_preimage[N_ASSETS] = node.hash;
hash_preimage[N_ASSETS + 1] = sibling_leaf_node.hash;
node = Node::middle_node_from_preimage(&hash_preimage);
} else {
node = Node::middle(&sibling_leaf_node, &node);
hash_preimage[N_ASSETS] = sibling_leaf_node.hash;
hash_preimage[N_ASSETS + 1] = node.hash;
node = Node::middle_node_from_preimage(&hash_preimage);
}

for i in 1..proof.path_indices.len() {
let sibling_node = Node::<N_ASSETS>::middle_node_from_preimage(
proof.sibling_middle_node_hash_preimages[i - 1],
&proof.sibling_middle_node_hash_preimages[i - 1],
);

let mut hash_preimage = [Fp::zero(); N_ASSETS + 2];
for (i, balance) in hash_preimage.iter_mut().enumerate().take(N_ASSETS) {
*balance = node.balances[i] + sibling_node.balances[i];
}

if proof.path_indices[i] == 0.into() {
node = Node::middle(&node, &sibling_node);
hash_preimage[N_ASSETS] = node.hash;
hash_preimage[N_ASSETS + 1] = sibling_node.hash;
node = Node::middle_node_from_preimage(&hash_preimage);
} else {
node = Node::middle(&sibling_node, &node);
hash_preimage[N_ASSETS] = sibling_node.hash;
hash_preimage[N_ASSETS + 1] = node.hash;
node = Node::middle_node_from_preimage(&hash_preimage);
}
}

Expand Down
13 changes: 12 additions & 1 deletion zk_prover/src/merkle_sum_tree/utils/build_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,18 @@ where
let results: Vec<Node<N_ASSETS>> = (0..tree[level - 1].len())
.into_par_iter()
.step_by(2)
.map(|index| Node::middle(&tree[level - 1][index], &tree[level - 1][index + 1]))
.map(|index| {
let mut hash_preimage = [Fp::zero(); N_ASSETS + 2];

for (i, balance) in hash_preimage.iter_mut().enumerate().take(N_ASSETS) {
*balance =
tree[level - 1][index].balances[i] + tree[level - 1][index + 1].balances[i];
}

hash_preimage[N_ASSETS] = tree[level - 1][index].hash;
hash_preimage[N_ASSETS + 1] = tree[level - 1][index + 1].hash;
Node::middle_node_from_preimage(&hash_preimage)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually that's why we could have both constructors. I just meant that one could call the other inside itself.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, I misunderstood your point

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied changes in last commit!

})
.collect();

for (index, new_node) in results.into_iter().enumerate() {
Expand Down