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

Add support for tracking legacy frontiers and witnesses in ShardTree instances. #69

Merged
merged 28 commits into from
Jul 3, 2023

Conversation

nuttycom
Copy link
Contributor

@nuttycom nuttycom commented May 16, 2023

No description provided.

@nuttycom nuttycom force-pushed the cap_cache branch 2 times, most recently from 390fa2b to 9510fc9 Compare May 17, 2023 21:58
@dconnolly
Copy link

A linter blurp

image

@nuttycom nuttycom force-pushed the cap_cache branch 10 times, most recently from d9e51bd to 2dbdd34 Compare May 25, 2023 14:09
Copy link

@nathan-at-least nathan-at-least left a comment

Choose a reason for hiding this comment

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

Partial utACK from commits 3d5810f through 3d5810f.

I'm posting now because I'm anxious about losing state or getting pulled off on other stuff on Monday, but I will attempt to review the remaining commits on Monday.

No blockers. Lots of clarifying questions, some api doc & code style suggestions.

shardtree/src/lib.rs Show resolved Hide resolved
shardtree/src/lib.rs Outdated Show resolved Hide resolved
shardtree/src/lib.rs Show resolved Hide resolved
/// allowed depth or if the list of ommers provided is not consistent
/// with the position of the leaf.
/// Returns `None` if the new frontier would exceed the maximum allowed depth or if the list of
/// ommers provided is not consistent with the position of the leaf.

Choose a reason for hiding this comment

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

[Non-blocking future nice-to-have:] I wish we had automated tooling for comment whitespace formatting and could then compartmentalize all such changes in a single tool-generated commit. Without that I had to spend a couple seconds squinting to see if there was a substantial change here. Not a big deal, but a tiny context switching cost.

shardtree/src/lib.rs Show resolved Hide resolved
shardtree/src/lib.rs Show resolved Hide resolved
shardtree/src/lib.rs Outdated Show resolved Hide resolved
fn from(err: InsertionError) -> Self {
ShardTreeError::Insert(err)
}
}

Choose a reason for hiding this comment

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

In my personal code, I make heavy use of "boiler-plate removal" dependencies. In this case derive_more crate enables #[derive(derive_more::From)] on enums that remove this boilerplate. Do we have a policy for or against such crates?

Choose a reason for hiding this comment

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

I just checked that derive_more::From can be instructed to ignore the ::Storage variant (which would otherwise attempt an incoherent blanket impl).

shardtree/src/lib.rs Outdated Show resolved Hide resolved
shardtree/src/lib.rs Outdated Show resolved Hide resolved
shardtree/src/lib.rs Outdated Show resolved Hide resolved
shardtree/src/lib.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

utACK 4732ea6 (modulo conflicts).

Copy link

@nathan-at-least nathan-at-least left a comment

Choose a reason for hiding this comment

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

utACK - Reviewed the remaining commits that I didn't cover last week.

shardtree/src/lib.rs Outdated Show resolved Hide resolved
@nuttycom nuttycom force-pushed the cap_cache branch 2 times, most recently from 1ae6fc3 to e57c252 Compare June 5, 2023 19:52
@nathan-at-least
Copy link

ACK w/ local cargo test to complement my source review.

shardtree/src/lib.rs Outdated Show resolved Hide resolved
nuttycom added 7 commits June 6, 2023 16:50
The cap is a truncated tree that can be used to cache precomputed
subtree roots at tree heights greater than `SHARD_HEIGHT`. Only roots
whose hashes cannot be altered by rewinds or by the addition of data to
the tree may be persisted to the cap.
This introduces a `ShardTreeError` type that is used to wrap errors
that arise from the undelying `ShardStore` when used in `ShardTree`
methods. The previous approach that relied on `From<QueryError> +
From<InsertionError>` bounds resulted in a situation where the shard
store error was forced to encompass the bounds of these types, even
though the methods on the `ShardStore` itself could never generate them.
This resulted in a number of awkward problems for error conversion.
@nuttycom
Copy link
Contributor Author

nuttycom commented Jun 19, 2023

@daira @nathan-at-least here are the changes since your previous approvals; these are substantial enough to require a re-review if you don't mind.

legacy-api = []
# The test-depenencies feature guards types and functions that are
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
# The test-depenencies feature guards types and functions that are
# The test-dependencies feature guards types and functions that are

Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

utACK, but I did not review new logic with any thoroughness (so this should not be merged based on my review alone).

Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

utACK accb8d7 (single commit; caveats about thoroughness of my previous review still apply).

Copy link
Contributor

@AloeareV AloeareV 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 reviewed all of the changes not inside shardtree/src/lib.rs. I'm partway through reading that file, and it's proving extensive enough I'm gonna break it off into its own review.

A note on terminology: The standard lingo in use here is that the root of the tree is the most-ancestral node. Each non-root node has one parent, and each non-leaf node has two children. Intuitively (from the genetic meaning of the word ancestor), the leaves would be ancestors, and two nodes would be hashed together to create a child node. Hashing two nodes together to create the ancestor of those nodes is the opposite what I expect the term 'ancestor' to mean.

I don't think this is something that could (or should) be changed, as flipping the meaning of already established terms would just cause more confusion. Maybe it could be better clarified somewhere?

Edit: The terms ancestor/child is going to get more and more baked in...but as the codebase stands, there's only a few instances of the terms. I don't think the terms have crystallized yet, and I think it would be more intuitive to flip them before they're too baked into the vocabulary.

incrementalmerkletree/src/lib.rs Show resolved Hide resolved
incrementalmerkletree/src/witness.rs Show resolved Hide resolved
incrementalmerkletree/src/lib.rs Show resolved Hide resolved
incrementalmerkletree/src/witness.rs Outdated Show resolved Hide resolved
incrementalmerkletree/src/witness.rs Show resolved Hide resolved
Copy link
Contributor

@AloeareV AloeareV left a comment

Choose a reason for hiding this comment

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

utACK, this looks great. I'm not sure to draw the line between a long review process where my end result is three sentences, but it's that or add another dozen comments saying "This bit took me a long time to grok but seems correct"

shardtree/src/lib.rs Show resolved Hide resolved
shardtree/src/lib.rs Show resolved Hide resolved
@zancas
Copy link
Contributor

zancas commented Jun 27, 2023

I've reviewed all of the changes not inside shardtree/src/lib.rs. I'm partway through reading that file, and it's proving extensive enough I'm gonna break it off into its own review.

A note on terminology: The standard lingo in use here is that the root of the tree is the most-ancestral node. Each non-root node has one parent, and each non-leaf node has two children. Intuitively (from the genetic meaning of the word ancestor), the leaves would be ancestors, and two nodes would be hashed together to create a child node. Hashing two nodes together to create the ancestor of those nodes is the opposite what I expect the term 'ancestor' to mean.

I don't think this is something that could (or should) be changed, as flipping the meaning of already established terms would just cause more confusion. Maybe it could be better clarified somewhere?

Edit: The terms ancestor/child is going to get more and more baked in...but as the codebase stands, there's only a few instances of the terms. I don't think the terms have crystallized yet, and I think it would be more intuitive to flip them before they're too baked into the vocabulary.

Hi! It also seems to me that this use of word ancestor is inverted relative to the meaning in genetics/genealogy.

I proposed some commits that would refine terminology and replace ancestor with descendant.

nuttycom#2

Since that proposal changes the public API I grepped the librustzcash repo to check for the pattern -i -e"ancestor" and didn't see it. Given that, my guess is that the impact on consumers would be minimal.

@nuttycom
Copy link
Contributor Author

Hi! It also seems to me that this use of word ancestor is inverted relative to the meaning in genetics/genealogy.

The reason that ancestor nodes are named as they are is that, in generic tree terminology, the nodes closer to the root are named "parents" and nodes closer to the leaves are named "children". Inverting this relationship would run afoul of a ton of computer science precedent; the fact that in our use case parent nodes are derived via a computation over their children is incidental. So I'm strongly opposed to changing this relationship.

/// Returns `None` if the new frontier would exceed the maximum
/// allowed depth or if the list of ommers provided is not consistent
/// with the position of the leaf.
/// Returns `None` if the new frontier would exceed the maximum allowed depth or if the list of
Copy link
Contributor

Choose a reason for hiding this comment

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

This returns Err, not None, in the failure case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed in 701d3e6

Comment on lines 428 to 429
/// Returns whether this address is the right-hand child of its parent
pub fn is_left_child(&self) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

This should say left-hand child.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 701d3e6

}
})
.take(self.filled.len())
.fold(0u64, |acc, addr| acc + 2u64.pow(addr.level().into()));
Copy link
Contributor

Choose a reason for hiding this comment

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

nonblocking nit: acc + (1u64 << addr.level().into()) might be more consistent with the other arithmetic in these crates.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 701d3e6

Tree::leaf((right.clone(), RetentionFlags::EPHEMERAL)),
);
} else {
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

Tests don't appear to be exercising this scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 082109d

subtree =
Tree::parent(None, Tree::leaf((left, RetentionFlags::EPHEMERAL)), subtree);
} else {
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

Tests don't appear to be exercising this scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 082109d

@AloeareV
Copy link
Contributor

Hi! It also seems to me that this use of word ancestor is inverted relative to the meaning in genetics/genealogy.

The reason that ancestor nodes are named as they are is that, in generic tree terminology, the nodes closer to the root are named "parents" and nodes closer to the leaves are named "children". Inverting this relationship would run afoul of a ton of computer science precedent; the fact that in our use case parent nodes are derived via a computation over their children is incidental. So I'm strongly opposed to changing this relationship.

Yeah, I suspected as much. I find it extremely confusing for merkle trees, but I'll accept that it's a lesser confusion than using terms opposite to everyone else.

@nuttycom nuttycom requested a review from ebfull June 29, 2023 21:32
@nuttycom nuttycom merged commit 313c072 into zcash:master Jul 3, 2023
@nuttycom nuttycom deleted the cap_cache branch July 3, 2023 17:28
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.

7 participants