Skip to content

Commit

Permalink
Merge pull request #91 from zcash/pre-release-cleanups
Browse files Browse the repository at this point in the history
Pre-release cleanups
  • Loading branch information
str4d authored Jul 29, 2023
2 parents da97e6c + 3f89998 commit 9e7f5f0
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 19 deletions.
30 changes: 26 additions & 4 deletions incrementalmerkletree/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 6 additions & 2 deletions incrementalmerkletree/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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"]
3 changes: 3 additions & 0 deletions incrementalmerkletree/src/frontier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
}
Expand All @@ -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>,
Expand Down Expand Up @@ -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>,
Expand Down
4 changes: 4 additions & 0 deletions incrementalmerkletree/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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.
Expand Down
9 changes: 9 additions & 0 deletions shardtree/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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!
13 changes: 7 additions & 6 deletions shardtree/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@ version = "0.0.0"
authors = [
"Kris Nuttycombe <[email protected]>",
]
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 }
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"

Expand All @@ -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 changes: 57 additions & 0 deletions shardtree/README.md
Original file line number Diff line number Diff line change
@@ -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.
28 changes: 24 additions & 4 deletions shardtree/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions shardtree/src/prunable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions shardtree/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
//! 2 / \ } cap
//! / \ / \ |
//! / \ / \ |
//! 1 A B C D / \
//! / \ / \ / \ / \ } shards
//! 0 /\ /\ /\ /\ /\ /\ /\ /\ /
//! 1 A B C D / \
//! / \ / \ / \ / \ } shards
//! 0 /\ /\ /\ /\ /\ /\ /\ /\ /
//! ```

use std::collections::BTreeSet;
Expand Down

0 comments on commit 9e7f5f0

Please sign in to comment.