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

Calculate incremental note commitment trees #2407

Merged
merged 18 commits into from
Jul 15, 2021

Conversation

dconnolly
Copy link
Contributor

@dconnolly dconnolly commented Jun 28, 2021

Motivation

We need to compute Orchard, Sapling, and Sprout note commitment trees incrementally (and thus their roots) as note commitments are produced as part of shielded transactions on the blockchain. We can then use these updatable data structures to check that anchors in future transactions are pointing to the roots of note commitment trees we have observed and computed ourselves before.

Specifications

Implementing an incremental merkle tree is not directly specified in the spec but the MerkleCRH hash functions are:

https://zips.z.cash/protocol/protocol.pdf#merklecrh
https://zips.z.cash/protocol/protocol.pdf#merklepath

Designs

The draft Treestate design RFC is related: https://github.com/ZcashFoundation/zebra/blob/main/book/src/dev/rfcs/drafts/0005-treestate.md

Solution

Implement the Sapling and Orchard incremental note commitment trees, supporting append(), and checking conformance with empty root test vectors and incrementally added note commitments test vectors.

Resolves the sapling and orchard parts of #1287

Review

#2425 relies on this

Reviewer Checklist

  • Code implements Specs and Designs
  • Tests for Expected Behavior
  • Tests for Errors

Follow Up Work

Sprout

@dconnolly dconnolly added A-rust Area: Updates to Rust code NU-5 Network Upgrade: NU5 specific tasks labels Jun 28, 2021
@dconnolly dconnolly requested review from conradoplg and teor2345 July 5, 2021 22:28
Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Thanks for this PR.

My top priority is making sure we have good Orchard test coverage, and that we've fixed any potential bugs. (Or explained why they can't happen.)

I've also made a bunch of comments about code readability, but they are a lower priority.

zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
@dconnolly dconnolly marked this pull request as ready for review July 6, 2021 08:52
@mpguerra
Copy link
Contributor

mpguerra commented Jul 6, 2021

@dconnolly: does this PR also cover #1320? I remember we discussed something along those lines previously but I'm not 100% sure

@conradoplg
Copy link
Collaborator

@dconnolly just to confirm: is the PR ready, and I'll just need to address the comments, or is some part of it incomplete?

Also I'm bit confused about the context, the PR basically replaces and old implementation. What was that old implementation? Just a placeholder?

@teor2345 teor2345 changed the title Incremental note commitment trees Calculate incremental note commitment trees Jul 7, 2021
@teor2345
Copy link
Contributor

teor2345 commented Jul 7, 2021

@dconnolly: does this PR also cover #1320? I remember we discussed something along those lines previously but I'm not 100% sure

This PR only calculates the incremental note commitment trees for sapling and orchard.

Here is the remaining work:

The design for #1320 will be very similar to the chain history tree, but we won't need to validate anchors in the state.

@teor2345
Copy link
Contributor

teor2345 commented Jul 7, 2021

Also I'm bit confused about the context, the PR basically replaces and old implementation. What was that old implementation? Just a placeholder?

It was a buggy implementation based on an incorrect understanding of the spec (or possible an unclear spec).

@str4d
Copy link
Contributor

str4d commented Jul 8, 2021

FYI we've published (and are using in zcashd) the incrementalmerkletree crate, which you could either use directly or leverage in tests for cross-checking.

Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Most of this PR was copied from librustzcash, specifically https://github.com/zcash/librustzcash/blob/4c4d226f404aef64df6a77caa289b30cc875ae4f/zcash_primitives/src/merkle_tree.rs#L91

The code looks ok, but I'm a bit concerned we now have 3 copies of almost the same incremental merkle tree code:

  • a generic implementation in librustzcash,
  • a Zebra Sapling implementation, and
  • a Zebra Orchard implementation.

There is also a risk that we might have introduced bugs by copying and modifying the librustzcash code. So we'll need to add tests for Zebra's Orchard note commitments.

All these extra risks and tests make me wonder if we should just import librustzcash, like we did for the history trees.

We made a decision to do our own design and implementation a few weeks ago. But I didn't realise we were going to copy so much librustzcash code. So I'm not sure how to move forward here.

What is the fastest way to correctly implement sapling and orchard anchors?
(I don't want to spend a lot of time on this, because it's blocking other work.)

zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Show resolved Hide resolved
Copy link
Collaborator

@conradoplg conradoplg left a comment

Choose a reason for hiding this comment

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

Added the suggestions and answered some comments, but haven't changed the code yet.

I've studied the code and incrementalmerkletree too and now I understand it much better.

I've managed to expand the Sapling test in this PR to also use incrementalmerkletree and compare the result and it works. So I think it will be really quick to change this PR to use it instead.

I'll start working on that.

zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Outdated Show resolved Hide resolved
@conradoplg
Copy link
Collaborator

I've added the test in 42a8d6f if you want to take a look. It's a bit ugly, it was just to validate the idea.

@teor2345
Copy link
Contributor

I've added the test in 42a8d6f if you want to take a look. It's a bit ugly, it was just to validate the idea.

This looks great!

Looking forward to seeing the final PR.

@conradoplg conradoplg force-pushed the incremental-note-commitment-trees branch from 42a8d6f to 4c50cca Compare July 12, 2021 22:04
@conradoplg
Copy link
Collaborator

Update: I've changed it to use incrementalmerkletree but I need to solve a bug. No need to review this right now unless you want to.

@conradoplg conradoplg force-pushed the incremental-note-commitment-trees branch from 3607b27 to c3e556d Compare July 13, 2021 23:14
Copy link
Collaborator

@conradoplg conradoplg left a comment

Choose a reason for hiding this comment

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

I've updated the code. This should be now ready for review.

  • Solved the bug; it was a confusion between "layers" (what the spec uses, root is layer 0) and "levels" or Altitudes (what incrementalmerkletree uses, root level is 31).
  • In an attempt to make that clearer, I've changed the code such that we use layers everywhere and convert any levels to layers when needed. Not sure if I succeeded 😅
  • I've incorporated the recent spec change to MerkleCRH^Orchard that encodes "null" values as a zero byte vector, which simplifies some of the code by avoiding Options
  • I've added test vectors for Orchard from zcash-test-vectors
  • I've tried to organized the tests by moving them (and the vectors) to their own files. But the vectors.rs / test_vectors.rs split is a bit weird. Suggestions are welcome. (Maybe move test_vectors.rs to zebra-tests?

zebra-chain/src/orchard/tests.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tests/vectors.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tests/vectors.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Show resolved Hide resolved
zebra-chain/src/orchard/tree.rs Show resolved Hide resolved
zebra-chain/src/sapling/tests.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Show resolved Hide resolved
zebra-chain/src/sapling/tree.rs Show resolved Hide resolved
@dconnolly
Copy link
Contributor Author

I've updated the code. This should be now ready for review.

  • Solved the bug; it was a confusion between "layers" (what the spec uses, root is layer 0) and "levels" or Altitudes (what incrementalmerkletree uses, root level is 31).
  • In an attempt to make that clearer, I've changed the code such that we use layers everywhere and convert any levels to layers when needed. Not sure if I succeeded 😅
  • I've incorporated the recent spec change to MerkleCRH^Orchard that encodes "null" values as a zero byte vector, which simplifies some of the code by avoiding Options
  • I've added test vectors for Orchard from zcash-test-vectors
  • I've tried to organized the tests by moving them (and the vectors) to their own files. But the vectors.rs / test_vectors.rs split is a bit weird. Suggestions are welcome. (Maybe move test_vectors.rs to zebra-tests?

Levels, layers, leaves, altitudes, positions, 😵

Copy link
Collaborator

@conradoplg conradoplg left a comment

Choose a reason for hiding this comment

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

Comments addressed, thanks!

zebra-chain/src/orchard/tests/vectors.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tests/vectors.rs Outdated Show resolved Hide resolved
zebra-chain/src/sapling/tests.rs Outdated Show resolved Hide resolved
zebra-chain/src/orchard/tests.rs Outdated Show resolved Hide resolved
@teor2345 teor2345 added A-consensus Area: Consensus rule updates A-dependencies Area: Dependency file updates labels Jul 14, 2021
Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Looks great, let's merge.

(We can tweak the module structure later as needed.)

@conradoplg conradoplg enabled auto-merge (squash) July 15, 2021 13:37
@conradoplg
Copy link
Collaborator

I took the liberty of resolving the remaining of @dconnolly's comments since: they were small; I believe they were properly addressed; @teor2345 approved the PR; and I don't want to bother her vacations just for those 🤣

@conradoplg conradoplg merged commit 48cf527 into main Jul 15, 2021
@conradoplg conradoplg deleted the incremental-note-commitment-trees branch July 15, 2021 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-consensus Area: Consensus rule updates A-dependencies Area: Dependency file updates A-rust Area: Updates to Rust code NU-5 Network Upgrade: NU5 specific tasks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants