Merge pull request #91 from zcash/pre-release-cleanups

Pre-release cleanups
This commit is contained in:
str4d 2023-07-29 20:06:31 +01:00 committed by GitHub
commit 9e7f5f0d28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 140 additions and 19 deletions

View File

@ -6,13 +6,35 @@ and this project adheres to Rust's notion of
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
- `incrementalmerkletree::Address::common_ancestor` no longer produces incorrect
results for some pairs of addresses. It was previously using an arithmetic
distance between indices within a level, instead of a bitwise distance.
### Added
- `incrementalmerkletree::Address::{common_ancestor, is_left_child}`
- `incrementalmerkletree::Level::new`
- `impl From<incrementalmerkletree::Level> for {u32, u64}`
- `incrementalmerkletree::Position::is_right_child`
- `incrementalmerkletree::frontier`:
- `Frontier::take`
- `NonEmptyFrontier::into_parts`
- `CommitmentTree::{is_empty, leaf, ommers_iter}`
- `testing::arb_frontier`
- `incrementalmerkletree::testing`:
- `TestCheckpoint`
- `TestHashable`
- `TestTree`
- `incrementalmerkletree::witness`:
- `IncrementalWitness::{tip_position, witnessed_position}`
### Changed
- `incrementalmerkletree::Hashable` trait now has a `Debug` bound.
- The `incrementalmerkletree::testing::check_*` functions now work with trees
built over any node or checkpoint ID types implementing `TestHashable` or
`TestCheckpoint` respectively.
### Removed
- `incrementalmerkletree::Position::is_odd` (use `Position::is_right_child`
instead).
- `incrementalmerkletree::witness`:
- `IncrementalWitness::position` (use `IncrementalWitness::witnessed_position`
instead).
## [0.4.0] - 2023-06-05

View File

@ -13,6 +13,10 @@ repository = "https://github.com/zcash/incrementalmerkletree"
categories = ["algorithms", "data-structures"]
rust-version = "1.60"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
either = "1.8"
proptest = { version = "1.0.0", optional = true }
@ -21,10 +25,10 @@ proptest = { version = "1.0.0", optional = true }
proptest = "1.0.0"
[features]
# The legacy-api feature guards types and functions that were previously
# The legacy-api feature guards types and functions that were previously
# part of the `zcash_primitives` crate. Those types were removed in the
# `zcash_primitives` 0.12 release and are now maintained here.
legacy-api = []
# The test-dependencies feature guards types and functions that are
# The test-dependencies feature guards types and functions that are
# useful for testing incremental Merkle trees and Merkle tree frontiers.
test-dependencies = ["proptest"]

View File

@ -281,6 +281,7 @@ impl<H: Hashable + Clone, const DEPTH: u8> Frontier<H, DEPTH> {
}
#[cfg(feature = "legacy-api")]
#[cfg_attr(docsrs, doc(cfg(feature = "legacy-api")))]
pub struct PathFiller<H> {
queue: VecDeque<H>,
}
@ -307,6 +308,7 @@ impl<H: Hashable> PathFiller<H> {
/// A Merkle tree of note commitments.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg(feature = "legacy-api")]
#[cfg_attr(docsrs, doc(cfg(feature = "legacy-api")))]
pub struct CommitmentTree<H, const DEPTH: u8> {
pub(crate) left: Option<H>,
pub(crate) right: Option<H>,
@ -600,6 +602,7 @@ pub mod testing {
use crate::frontier::CommitmentTree;
#[cfg(feature = "legacy-api")]
#[cfg_attr(docsrs, doc(cfg(feature = "legacy-api")))]
pub fn arb_commitment_tree<
H: Hashable + Clone + Debug,
T: Strategy<Value = H>,

View File

@ -43,6 +43,8 @@
//! Note: we often refer to `ommers` (plural) when describing leaf-to-root paths, so in that
//! context `ommers` refers to the node's ommer, plus each ancestor's ommer.
#![cfg_attr(docsrs, feature(doc_cfg))]
use either::Either;
use std::cmp::Ordering;
use std::convert::{TryFrom, TryInto};
@ -53,9 +55,11 @@ use std::ops::{Add, AddAssign, Range, Sub};
pub mod frontier;
#[cfg(feature = "legacy-api")]
#[cfg_attr(docsrs, doc(cfg(feature = "legacy-api")))]
pub mod witness;
#[cfg(feature = "test-dependencies")]
#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))]
pub mod testing;
/// A type for metadata that is used to determine when and how a leaf can be pruned from a tree.

9
shardtree/CHANGELOG.md Normal file
View File

@ -0,0 +1,9 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to Rust's notion of
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
Initial release!

View File

@ -4,16 +4,21 @@ version = "0.0.0"
authors = [
"Kris Nuttycombe <kris@nutty.land>",
]
edition = "2018"
edition = "2021"
rust-version = "1.60"
license = "MIT OR Apache-2.0"
description = "A space-efficient Merkle tree with witnessing of marked leaves, checkpointing & state restoration."
homepage = "https://github.com/zcash/incrementalmerkletree"
repository = "https://github.com/zcash/incrementalmerkletree"
categories = ["algorithms", "data-structures"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
assert_matches = { version = "1.5", optional = true }
bitflags = "1.3"
bitflags = "2"
either = "1.8"
incrementalmerkletree = { version = "0.4", path = "../incrementalmerkletree" }
proptest = { version = "1.0.0", optional = true }
@ -21,7 +26,6 @@ tracing = "0.1"
[dev-dependencies]
assert_matches = "1.5"
criterion = "0.3"
incrementalmerkletree = { version = "0.4", path = "../incrementalmerkletree", features = ["test-dependencies"] }
proptest = "1.0.0"
@ -35,7 +39,4 @@ legacy-api = ["incrementalmerkletree/legacy-api"]
test-dependencies = ["proptest", "assert_matches"]
[target.'cfg(unix)'.dev-dependencies]
pprof = { version = "0.9", features = ["criterion", "flamegraph"] } # MSRV 1.56
dashmap = ">=5, <5.5.0" # 5.5 has MSRV > 1.60
inferno = ">=0.11, <0.11.5" # MSRV 1.59
tempfile = ">=3, <3.7.0" # 3.7 has MSRV 1.63

57
shardtree/README.md Normal file
View File

@ -0,0 +1,57 @@
# `shardtree`
This is a Rust crate that provides an implementation of a fixed-depth Merkle
tree structure that is densely filled from the left. It supports:
- *Out-of-order insertion*: leaves and nodes may be inserted into the tree in
arbitrary order. The structure will keep track of the right-most filled
position as the frontier of the tree; any unfilled leaves to the left of this
position are considered "missing", while any unfilled leaves to the right of
this position are considered "empty".
- *Witnessing*: Individual leaves of the Merkle tree may be marked such that
witnesses will be maintained for the marked leaves as additional nodes are
inserted into the tree, but leaf and node data not specifically required to
maintain these witnesses is not retained, for space efficiency.
- *Checkpointing*: the tree may be reset to a previously checkpointed state, up
to a fixed number of checkpoints.
The tree is represented as an ordered collection of fixed-depth subtrees, or
"shards". The roots of the shards form the leaves in the "cap".
```
Level
3 root \
/ \ |
/ \ |
2 / \ } cap
/ \ / \ |
/ \ / \ |
1 A B C D / \
/ \ / \ / \ / \ } shards
0 /\ /\ /\ /\ /\ /\ /\ /\ /
```
This structure enables witnesses for marked leaves to be advanced up to recent
checkpoints or the latest state of the tree, without having to insert each
intermediate leaf individually. Instead, only the roots of all complete shards
between the one containing the marked leaf and the tree frontier need to be
inserted, along with the necessary nodes to build a path from the marked leaf to
the root of the shard containing it.
## [`Documentation`](https://docs.rs/shardtree)
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.

View File

@ -1,7 +1,26 @@
//! `shardtree` is a space-efficient fixed-depth Merkle tree that supports:
//! - Out-of-order insertion.
//! - Witnessing of marked leaves.
//! - Checkpointing, and state restoration to a checkpoint.
//! `shardtree` is a space-efficient fixed-depth Merkle tree structure that is densely
//! filled from the left. It supports:
//!
//! - *Out-of-order insertion*: leaves and nodes may be inserted into the tree in
//! arbitrary order. The structure will keep track of the right-most filled position as
//! the frontier of the tree; any unfilled leaves to the left of this position are
//! considered "missing", while any unfilled leaves to the right of this position are
//! considered "empty".
//! - *Witnessing*: Individual leaves of the Merkle tree may be marked such that witnesses
//! will be maintained for the marked leaves as additional nodes are inserted into the
//! tree, but leaf and node data not specifically required to maintain these witnesses
//! is not retained, for space efficiency.
//! - *Checkpointing*: the tree may be reset to a previously checkpointed state, up to a
//! fixed number of checkpoints.
//!
//! Due to its structure (described in the [`store`] module), witnesses for marked leaves
//! can be advanced up to recent checkpoints or the latest state of the tree, without
//! having to insert each intermediate leaf individually. Instead, only the roots of all
//! complete shards between the one containing the marked leaf and the tree frontier need
//! to be inserted, along with the necessary nodes to build a path from the marked leaf to
//! the root of the shard containing it.
#![cfg_attr(docsrs, feature(doc_cfg))]
use core::fmt::Debug;
use either::Either;
@ -34,6 +53,7 @@ pub mod store;
pub mod testing;
#[cfg(feature = "legacy-api")]
#[cfg_attr(docsrs, doc(cfg(feature = "legacy-api")))]
mod legacy;
/// A sparse binary Merkle tree of the specified depth, represented as an ordered collection of

View File

@ -14,6 +14,7 @@ use crate::{LocatedTree, Node, Tree};
bitflags! {
/// Flags storing the [`Retention`] state of a leaf.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RetentionFlags: u8 {
/// An leaf with `EPHEMERAL` retention can be pruned as soon as we are certain that it is not part
/// of the witness for a leaf with [`CHECKPOINT`] or [`MARKED`] retention.

View File

@ -16,9 +16,9 @@
//! 2 / \ } cap
//! / \ / \ |
//! / \ / \ |
//! 1 A B C D / \
//! / \ / \ / \ / \ } shards
//! 0 /\ /\ /\ /\ /\ /\ /\ /\ /
//! 1 A B C D / \
//! / \ / \ / \ / \ } shards
//! 0 /\ /\ /\ /\ /\ /\ /\ /\ /
//! ```
use std::collections::BTreeSet;