Commit Graph

135 Commits

Author SHA1 Message Date
Jack Grigg 8a62290ffe shardtree: Add tests comparing `insert_tree` to `batch_insert` 2023-07-24 17:22:28 +00:00
Jack Grigg faabef3106 shardtree: Extract an `arb_leaves` strategy from `arb_shardtree` 2023-07-24 02:16:12 +00:00
Jack Grigg 5b4dce85ca shardtree: Switch from `Rc` to `Arc` to make trees `Send` 2023-07-17 21:02:33 +00:00
Jack Grigg 7ec75fdd91 shardtree: Clarify documentation for `ShardStore::remove_checkpoint`
`CachingShardStore` relies on this method being a no-op when the
checkpoint doesn't exist.
2023-07-17 20:56:53 +00:00
Jack Grigg f5160a4790 shardtree: Pin `dashmap < 5.5.0` in dev-dependencies to keep MSRV 2023-07-14 19:26:32 +00:00
Jack Grigg 2715a24943 Add `CachingShardStore` for batching writes to a backend `ShardStore` 2023-07-14 19:26:32 +00:00
Jack Grigg d87a85786c shardtree: Move batch construction methods into a submodule 2023-07-10 17:39:10 +00:00
Jack Grigg 2d28ed6d19 shardtree: Move methods behind `legacy-api` feature flag into a submodule
This doesn't affect the public API, as `impl` blocks for a struct can be
anywhere within the crate.
2023-07-10 17:39:06 +00:00
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 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
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
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 082109deac Add tests to verify frontier & witness insertion behavior for sub-shard-sized values. 2023-06-29 15:30:21 -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 cb8ef79648 Generalize remaining tests to arbitrary checkpoint id types. 2023-06-16 13:53:24 -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
Kris Nuttycombe 4a871a5840 Add LocatedTree::from_parts 2023-06-06 16:50:27 -06:00
Kris Nuttycombe a397ba9d46 There is no longer a distinction between `ShardTree::empty` and `ShardTree::load`. 2023-06-06 16:50:27 -06:00
Kris Nuttycombe 1721d46571 Wrap ShardTree errors explicitly, instead of relying on `From` impls.
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.
2023-06-06 16:50:27 -06:00
Kris Nuttycombe 290b66d5c8 Add caching of the "cap" to root & witness computation. 2023-06-06 16:50:27 -06:00
Kris Nuttycombe f8c13d17de Add insertion of legacy incremental witness data to `ShardTree` 2023-06-06 16:50:27 -06:00
Kris Nuttycombe f5b06c8e8b Add construction of `LocatedPrunableTree` from `IncrementalWitness` 2023-06-06 16:50:27 -06:00
Kris Nuttycombe d350d43fd7 Add "shardtree cap" support to `ShardStore` and `ShardTree`.
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.
2023-06-06 16:50:27 -06:00
Kris Nuttycombe 19c514b8cf Add insertion of frontier nodes into a `ShardTree` 2023-06-06 16:50:27 -06:00
Kris Nuttycombe aab7c969b3 Add a mechanism to insert the nodes from a `Frontier` into a `LocatedPrunableTree` 2023-06-06 16:50:27 -06:00
Kris Nuttycombe 4c79a7d065 Release incrementalmerkletree-v0.4.0 and bridgetree-v0.3.0 2023-06-05 19:39:49 -06:00
Kris Nuttycombe 2f65d483ee
Update shardtree/src/lib.rs
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2023-05-30 12:40:11 -06:00
Kris Nuttycombe 51c3997ee6 Fix incorrect documentation and `cargo doc` issues. 2023-05-24 14:50:52 -06:00
Kris Nuttycombe 2b8e2d62fa Address comments from code review.
This also provides a minor performance and correctness improvement to
`remove_mark`.
2023-05-24 09:30:14 -06:00
Kris Nuttycombe 4efe39eaa6 Remove initial checkpoints.
The choice to use an initial checkpoint as an anchor for removals in
`unmark` operations produced an awkward situation where it was necessary
to choose a checkpoint identifier just to construct an empty tree. This
removes that decision in favor of eagerly removing data if there is no
checkpoint to tie the removal to.
2023-05-22 12:11:34 -06:00
Kris Nuttycombe 5691b70947 Restore the relevant part of a deleted comment. 2023-05-22 10:29:40 -06:00
Kris Nuttycombe e2fa0a44c7 Make all `ShardStore` methods return `Result`
When implementing `ShardStore` atop a persistent data store, we need to
be able to reflect failures of the storage layer that are independent of
the presence or absence of data.
2023-05-19 15:45:03 -06:00
Kris Nuttycombe f292a271ac Return owned types from `ShardStore` getter methods.
The primary implementations of `ShardStore` will be constructing
owned values from an underlying persistence layer, and it is not
possible to return a reference to an owned value.
2023-05-19 15:43:06 -06:00
Kris Nuttycombe dbb2a8f9c5 Make hash and checkpoint ID type parameters associated types of `ShardStore` 2023-05-11 12:04:37 -06:00
Kris Nuttycombe 666e72482a Address Clippy lints. 2023-05-10 20:44:58 -06:00
Kris Nuttycombe 247b38f336 Invert the relationship between shardtree errors and storage errors. 2023-05-10 20:44:57 -06:00
Kris Nuttycombe 0e502e3832 Add `Display` impl for `shardtree::InsertionError` 2023-05-10 20:43:56 -06:00
Kris Nuttycombe 10e5ee59a4 Distinguish between creating a new empty tree and loading data for an existing tree. 2023-05-10 20:43:20 -06:00
Kris Nuttycombe e15440bd37 Add checkpoint management APIs to `ShardStore`. 2023-05-10 20:43:20 -06:00
Kris Nuttycombe ed78bc2e56 Add dedicated `MemoryShardStore` type. 2023-05-10 20:43:18 -06:00
Kris Nuttycombe 62acf235a7
Merge pull request #68 from nuttycom/u64_positions
Use `u64` for the internal state of `Position` and `Address::index`
2023-05-10 20:34:59 -06:00
Kris Nuttycombe 34d9aa25bc Use `u64` for the internal state of `Position` and `Address::index` 2023-05-10 16:46:23 -06:00
Kris Nuttycombe 465f2ff0d8 Add a blanket implementation of ShardStore for mutable references to ShardStores. 2023-05-04 13:46:02 -06:00
Kris Nuttycombe 873a72ff98 Return `MerklePath` from `ShardTree::witness` 2023-04-06 19:48:10 -06:00
Kris Nuttycombe 257402db53 Address comments from review. 2023-03-20 16:12:30 -06:00
Kris Nuttycombe d7a04122ea Fix clippy complaints. 2023-03-13 11:42:57 -06:00
Kris Nuttycombe ac6e8e8212 Use direct recursion in shardtree instead of reduce/try_reduce
These more general functions weren't carrying their weight.
2023-03-09 16:29:24 -07:00
Kris Nuttycombe 664cead68b Use `bitflags` crate instead of hand-rolled `RetentionFlags` bit flags. 2023-03-09 13:51:56 -07:00
Kris Nuttycombe 37be939c0f Apply suggestions from code review
Co-authored-by: ebfull <ewillbefull@gmail.com>
2023-03-09 13:37:22 -07:00
Kris Nuttycombe fa7c6673fd Make `LocatedTree` and `LocatedPrunableTree` type aliases public. 2023-03-08 11:12:17 -07:00
Kris Nuttycombe 0cb1cec21f Add `shardtree` witness operation & implement property tests. 2023-03-08 11:12:17 -07:00
Kris Nuttycombe a7bb8bb749 Add `shardtree` batch insertion. 2023-03-08 11:12:17 -07:00
Kris Nuttycombe e209f3bf20 Add `shardtree` checkpointing & root computation. 2023-03-08 11:12:17 -07:00
Kris Nuttycombe ebe3efa135 Add ShardTree types & implement append operation. 2023-03-08 11:12:17 -07:00
Kris Nuttycombe dc5a3ed0e7 Add types & operations for individual shards.
This adds the `LocatedPrunableTree` type, which provides the complete
set of operations for individual shards within a larger tree.
2023-03-08 11:11:16 -07:00
Kris Nuttycombe 34f6bd7ce5 Add a `LocatedTree` type that pairs tree roots with address information. 2023-03-08 11:09:43 -07:00
Kris Nuttycombe 8644372c4e Add types and methods to support tree pruning.
Each leaf of the tree is annotated with retention metadata, and
ephemeral leaves can be aggressively pruned when performing insertions
into the tree.
2023-03-08 11:08:59 -07:00
Kris Nuttycombe 8864a84d19 Introduce a simple binary tree type. 2023-03-08 11:07:58 -07:00
Kris Nuttycombe 0ae9b499cc Introduce the `shardtree` crate: a sparse Merkle tree type. 2023-03-07 12:11:48 -07:00