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

Conversation

enricobottazzi
Copy link
Member

@enricobottazzi enricobottazzi commented Nov 21, 2023

#166

Major breaking changes in this PR:

  • Logic of building the middle nodes of the MerkleSumTree is modified. Before the pre-image of the hash was equal to balance_left, hash_left, balance_right, hash_right now it is balance_left + balance_right, hash_left, hash_right
  • Further constraints added to the circuit. Before the circuit would just take sibling_sums and sibling_hashes to be used inside the witness. Now we need to open the hash of each sibling. Because of that the MerkleProof now has fieldssibling_leaf_node_hash_preimage and sibling_middle_node_hash_preimages rather than sibling_hashes and sibling_sums. The logic of the circuit is modified to build each sibling_hash inside the circuit and constraint that the balances associated to a sibling are the same used as input to build the hash

To do:

  • As I modified the Tree trait, it might also have an impact on AggregationMerkleSumTree

Benchmarks:

  • Reduced Merkle Sum Tree generation time (2^20 users, 1 asset) -> 73.695 s vs 88.182s
  • Increased Proof of Inclusion generation time -> 517.98 ms vs 465.61 ms

Given that the focus of V1 is fast commitment time. I think that this is a reasonable tradeoff.

@enricobottazzi enricobottazzi linked an issue Nov 21, 2023 that may be closed by this pull request
1 task
@enricobottazzi enricobottazzi marked this pull request as ready for review November 21, 2023 18:46
.try_into()
.unwrap();

let sibling_leaf_node_hash = poseidon_entry::<N_ASSETS>(
Copy link
Contributor

Choose a reason for hiding this comment

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

poseidon_entry as well as poseidon_node are specific to Node creation and are always used in that context, so their implementations can be placed directly in the Node (no need to have them inside a separate file in utils). For example, here you first create the hash of sibling_leaf_node and then create the sibling_leaf_node Node using this hash, not using the hash for anything else. Meanwhile, Node already has the ::leaf constructor that takes username and balances as args. Moving both hashing operations into the Node would remove confusion over how to create the node.

Copy link
Member Author

@enricobottazzi enricobottazzi Nov 27, 2023

Choose a reason for hiding this comment

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

Thanks for the suggestion! Changes applied in fc44e01. I hope that now it looks cleaner

Copy link
Member

@sifnoc sifnoc left a comment

Choose a reason for hiding this comment

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

This is a good improvement, especially for large entry sets.
Also, thank you for the minor updates in the backend.

zk_prover/src/merkle_sum_tree/mod.rs Show resolved Hide resolved
backend/src/apis/round.rs Outdated Show resolved Hide resolved
backend/src/apis/round.rs Show resolved Hide resolved
zk_prover/src/circuits/merkle_sum_tree.rs Outdated Show resolved Hide resolved
@enricobottazzi
Copy link
Member Author

enricobottazzi commented Nov 27, 2023

I updated the code base according to your comments. A further thing that I noticed while reviewing the codebase is that there was an API generate_leaf_hash in zk_prover that was only used inside backend/examples. I therefore decided to move it back to backend as part of our effort to reduce the number of utils API inside zk_prover.

/// 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>
Copy link
Contributor

Choose a reason for hiding this comment

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

In the true spirit of DRY this could just call the Node::leaf_node_from_preimage() after converting the args :) Same with the middle calling Node::middle_from_preimage inside itself. Won't request changes, we can do this minor enhancement later.

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's DRY!

Gonna apply the changes now (:


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!

@enricobottazzi enricobottazzi merged commit a734d94 into v1-improvements-and-consolidation Nov 28, 2023
4 checks passed
@enricobottazzi enricobottazzi deleted the mst-efficiency-improvement branch November 28, 2023 11:13
alxkzmn pushed a commit to alxkzmn/summa-solvency that referenced this pull request Dec 5, 2023
* feat: tree building rules

* feat: add `get_middle_node_hash_preimage` and `get_middle_node_hash_preimage` methods

* feat: update `generate_proof`

* fix: `generate_proof`

* fix: modify middle nodes hashing logic in circuit

* feat: update `MerkleProof`

* feat: add further constraint on `MstInclusionCircuit`

* feat: rm `test_balance_not_in_range`

* refactor: update `MerkleProof`

* chore: fix `backend`

* test: fix `backend`

* fix: testing

* fix: modify `MstInclusionCircuit` struct

* Revert "fix: modify `MstInclusionCircuit` struct"

This reverts commit e3ba8e6.

* chore: update `benches`

* fix: move poseidon hasher APIs to `Node`

* chore: add guide on `MerkleProof `

* chore: update `where` clause in backend

* chore: update comments

* chore: move `generate_leaf_hash` outside of `zk_prover`

* chore: add `ethers` legacy feature

* chore: update verifier contract

* fix: removed minting erc20 on the backend test

* chore: rm unused imports

* feat: remove `Node::leaf()`

* feat: rm `Node::middle()`

* Revert "feat: remove `Node::leaf()`"

This reverts commit ae539a2.

* chore: DRY code

---------

Co-authored-by: sifnoc <[email protected]>
alxkzmn pushed a commit to alxkzmn/summa-solvency that referenced this pull request Dec 5, 2023
* feat: tree building rules

* feat: add `get_middle_node_hash_preimage` and `get_middle_node_hash_preimage` methods

* feat: update `generate_proof`

* fix: `generate_proof`

* fix: modify middle nodes hashing logic in circuit

* feat: update `MerkleProof`

* feat: add further constraint on `MstInclusionCircuit`

* feat: rm `test_balance_not_in_range`

* refactor: update `MerkleProof`

* chore: fix `backend`

* test: fix `backend`

* fix: testing

* fix: modify `MstInclusionCircuit` struct

* Revert "fix: modify `MstInclusionCircuit` struct"

This reverts commit e3ba8e6.

* chore: update `benches`

* fix: move poseidon hasher APIs to `Node`

* chore: add guide on `MerkleProof `

* chore: update `where` clause in backend

* chore: update comments

* chore: move `generate_leaf_hash` outside of `zk_prover`

* chore: add `ethers` legacy feature

* chore: update verifier contract

* fix: removed minting erc20 on the backend test

* chore: rm unused imports

* feat: remove `Node::leaf()`

* feat: rm `Node::middle()`

* Revert "feat: remove `Node::leaf()`"

This reverts commit ae539a2.

* chore: DRY code

---------

Co-authored-by: sifnoc <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Merkle Sum Tree Efficiency Improvement
3 participants