Commit Graph

421 Commits

Author SHA1 Message Date
Jack Grigg 52b8de33e5 shardtree: Extract helper function inside `LocatedPrunableTree::from_iter` 2023-07-06 14:58:52 +00:00
Jack Grigg 278e4d2320 shardtree: Fix `LocatedPrunableTree::from_iter`
The general logic in this function is:
- Build a stack that contains all of the complete subtrees contained
  within the iterator.
- Take nodes off the top of the stack, and combine them together with
  each other and empty nodes until the resulting right-hand subtree is
  larger than all remaining subtrees on the stack.
- Make a single pass over the stack from bottom to top, accumulating
  subtrees and adding empty nodes on the left until a single tree is
  obtained.

The bug was that the second step was not leaving the right-hand subtree
sufficiently large. The final single-pass step expects every subtree in
the stack to be no smaller than the accumulated tree up to that point,
and in particular the right-hand subtree must be the direct right child
of the final tree. Some specific sequences of leaves were leaving the
right-hand subtree in a state where it was the same size as the largest
individual subtree of the rest of the stack, but smaller than their
accumulated tree.

The solution is to pre-compute what the address of the final tree will
be, and then add empty nodes on the right to the right-hand subtree
until it is the direct right child.

Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-06 13:02:40 +00:00
Jack Grigg bddf6684e3 shardtree: Turn `LocatedPrunableTree::from_iter` test failure into panic
The logic in `LocatedPrunableTree::from_iter` is violating an invariant
of the `unite` helper function. The new assertion prevents an invalid
tree state from being returned.
2023-07-06 13:01:08 +00:00
Jack Grigg b325399f0d shardtree: Add test exposing `LocatedPrunableTree::from_iter` bug 2023-07-06 12:57:16 +00:00
Jack Grigg 0eff26f313 incrementalmerkletree: Refactor `Address::common_ancestor` 2023-07-06 12:45:42 +00:00
Jack Grigg 1292d478b6 incrementalmerkletree: Fix `Address::common_ancestor`
After correcting for differing levels, the tree distance between indices
within a level was being computed via `u64::abs_diff`. This had failures
in cases where the indices were numerically close but the nodes were
much farther apart in the tree (e.g. adjacent non-sibling leaves).

The XOR distance is the correct metric to use here: the leading prefix
bits corresponding to the path from the tree root to the common ancestor
will be identical and thus zeroed out; the number of bits after that
gives the level difference between the compared indices and their common
ancestor.
2023-07-06 12:28:58 +00:00
Jack Grigg 2a5f27eb5f incrementalmerkletree: Add `Address::common_ancestor` failing test cases 2023-07-06 12:22:57 +00:00
Jack Grigg 4a34bf0032 incrementalmerkletree: Document `Address::common_ancestor` test cases
Also adds a couple more test cases that pass.
2023-07-06 12:22:22 +00:00
Jack Grigg b604c801a8 Add more TRACE-level logging to `shardtree` internals 2023-07-06 11:51:43 +00:00
Jack Grigg f254ebcf67 shardtree: Simplify `LocatedPrunableTree::insert_subtree` node logic
The previous logic had the non-obvious behaviour that if the inserted
subtree was a leaf, then the `.iter().all()` was not rejecting subtrees
with non-matching values, because `Node::annotation` returns `None` for
leaves. This didn't cause a bug, because this behaviour is actually
intentionally triggered by the previous `is_complete` branch of the
conditional (as leaves are by definition complete subtrees).

The simplified logic is more obvious, because `PrunableTree::node_value`
returns the value of leaves and the annotation of nodes (which are the
same type for `PrunableTree`). It does change how leaves are treated by
this branch of the conditional, so a test has been added to ensure that
the intended behaviour is preserved if the `is_complete` branch is
refactored in future.

Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 23:59:56 +00:00
Jack Grigg 54e8ab759c shardtree: Compare leaves by value when merging, and merge their flags
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 21:45:56 +00:00
Jack Grigg 2ef96ba4ba shardtree: Add test exposing `PrunableTree::merge_checked` bug 2023-07-05 21:41:25 +00:00
Jack Grigg 1be68e5c64 shardtree: Preserve flags at positions with multiple checkpoints
If we have a retained checkpoint at the same position and with the same
flags as a pruned checkpoint, we need to preserve the flags on the node.
The flags are cleared when the last of the checkpoints at the position
is removed.

Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 21:36:15 +00:00
Jack Grigg a54f4e198f shardtree: Add test exposing `ShardTree::prune_excess_checkpoints` bug 2023-07-05 21:16:22 +00:00
Jack Grigg 7643b16261 Add TRACE-level logging to `shardtree` internals 2023-07-05 21:04:02 +00:00
Kris Nuttycombe 8c927ce11e
Merge pull request #80 from zingolabs/clarify_position_is_leaf
Fix doc comments to clarify that positions are always leaves, not inner nodes
2023-07-05 14:02:54 -06:00
Kris Nuttycombe 2d86458e1e
Merge pull request #81 from zcash/refactor
Refactor codebase into submodules
2023-07-05 14:02:39 -06:00
Jack Grigg 46592bf466 Move `accumulate_result_with` helper function into `prunable` submodule
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 19:24:57 +00:00
Jack Grigg 4152961f77 Move `testing` submodule into a separate file
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 19:23:21 +00:00
Jack Grigg f2d2bd3719 Move `MemoryShardStore` into `memory` submodule
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 19:18:41 +00:00
Jack Grigg e9c32bf3dd Move `LocatedPrunableTree` and its helper types into `prunable` submodule
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 19:11:54 +00:00
Jack Grigg 0d531d9309 Move `LocatedTree` into `tree` submodule
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 19:04:40 +00:00
Hazel OHearn b0328a3637
Fix doc comments to clarify that positions are always leaves, not inner nodes 2023-07-05 15:58:44 -03:00
Jack Grigg 0f15a57cb5 Move `PrunableTree` and `RetentionFlags` into `prunable` submodule
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 18:57:06 +00:00
Jack Grigg 3b05192538 Move `Node` and `Tree` into `tree` submodule
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2023-07-05 18:50:37 +00:00
Kris Nuttycombe 109f805fdf
Merge pull request #79 from zancas/tweak_docs
allowing level 0 nodes means that Addresses are used for non-internal…
2023-07-05 12:32:01 -06:00
Kris Nuttycombe 313c072afb
Merge pull request #69 from nuttycom/cap_cache
Add support for tracking legacy frontiers and witnesses in `ShardTree` instances.
2023-07-03 11:27:57 -06:00
zancas 5c14ab8882
allowing level 0 nodes means that Addresses are used for non-internal nodes 2023-06-30 18:25:50 -06:00
Kris Nuttycombe 082109deac Add tests to verify frontier & witness insertion behavior for sub-shard-sized values. 2023-06-29 15:30:21 -06:00
Kris Nuttycombe 701d3e6311 Apply suggestions from code review. 2023-06-29 15:26:56 -06:00
Kris Nuttycombe 30c592a0b3 Add tests that verify `ShardTree` state post-truncation. 2023-06-29 14:52:57 -06:00
Kris Nuttycombe 3c4a660c86 Add `shardtree::LocatedTree::take_root` 2023-06-22 19:18:57 -06:00
Kris Nuttycombe 00eb47f391 Replace `put_root` with single-node insertion. 2023-06-22 14:46:30 -06:00
Kris Nuttycombe accb8d7d8d Refactor to make shardtree tests reusable for checking ShardStore impls. 2023-06-22 08:25:42 -06:00
Kris Nuttycombe f5889dffa5 Address comments from code review. 2023-06-16 17:12:55 -06:00
Kris Nuttycombe 6d6f3fd4e3
Merge pull request #78 from nathan-at-least/api-docs-for-location-and-node-relations
`incrementalmerkletree` API docs for location and node relations.
2023-06-16 16:31:25 -06:00
Kris Nuttycombe d9fbd00e91 Wrap long lines & fix emmer/ommer typo. 2023-06-16 16:30:42 -06:00
Nate Wilcox 964e71b79d Clarify the ommer-path context for `ommers`. 2023-06-16 16:30:42 -06:00
Kris Nuttycombe cb8ef79648 Generalize remaining tests to arbitrary checkpoint id types. 2023-06-16 13:53:24 -06:00
Kris Nuttycombe 33ad80814f Generalize `check_remove_mark` and `check_checkpoint_rewind` 2023-06-16 12:59:55 -06:00
Kris Nuttycombe 405f1100da Generalize `check_witnesses` 2023-06-16 12:59:55 -06:00
Kris Nuttycombe 527f561816 Generalize `check_append` and `check_root_hashes`. 2023-06-16 12:59:55 -06:00
Kris Nuttycombe 614079271a Improve error reporting from the `Tree` impl for `ShardTree` 2023-06-16 12:59:55 -06:00
Kris Nuttycombe 456102b2ad Make the `Tree` impl for `ShardTree` available under `test-dependencies` 2023-06-15 19:05:45 -06:00
Kris Nuttycombe 6dd0c175b0 Bugfix: shard roots should be at level SHARD_HEIGHT, not SHARD_HEIGHT - 1
The intent of SHARD_HEIGHT is that each subtree should contain
2^SHARD_HEIGHT nodes. The `ShardTree::subtree_level` function was
incorrectly computing the level of the root address, and consequently
the resulting subtrees were too small.
2023-06-15 09:43:38 -06:00
Kris Nuttycombe dbc46b1157 Add shardtree::Checkpoint::from_parts 2023-06-15 09:43:38 -06:00
Kris Nuttycombe 7617a5574f Add ability to truncate `ShardTree` to a checkpoint by identifier. 2023-06-06 16:50:27 -06:00
Nate Wilcox e2d59d42e1 Do comment line-wrapping at ~100 columns. 2023-06-06 16:50:27 -06:00
Nate Wilcox c0b8c4d783 Fix all `cargo doc` warnings about dangling refs. 2023-06-06 16:50:27 -06:00
Kris Nuttycombe 6e5c50d149 Add shardtree::testing::arb_prunable_tree 2023-06-06 16:50:27 -06:00