incrementalmerkletree: Check `IncrementalWitness` at construction

A witness cannot exist for an empty tree.

Part of zcash/incrementalmerkletree#118.
This commit is contained in:
Jack Grigg 2024-11-23 01:27:58 +00:00
parent c06b836e3f
commit 2edacb0191
2 changed files with 27 additions and 14 deletions

View File

@ -7,6 +7,11 @@ and this project adheres to Rust's notion of
## Unreleased
### Changed
- `incrementalmerkletree::witness`:
- `IncrementalWitness::{from_tree, from_parts}` now return `Option<Self>`
(returning `None` if a witness cannot be constructed).
## [0.7.0] - 2024-09-25
### Changed

View File

@ -25,7 +25,7 @@ use crate::{
///
/// tree.append(TestNode(0));
/// tree.append(TestNode(1));
/// let mut witness = IncrementalWitness::from_tree(tree.clone());
/// let mut witness = IncrementalWitness::from_tree(tree.clone()).expect("tree is not empty");
/// assert_eq!(witness.witnessed_position(), Position::from(1));
/// assert_eq!(tree.root(), witness.root());
///
@ -45,30 +45,38 @@ pub struct IncrementalWitness<H, const DEPTH: u8> {
impl<H, const DEPTH: u8> IncrementalWitness<H, DEPTH> {
/// Creates an `IncrementalWitness` for the most recent commitment added to the given
/// [`CommitmentTree`].
pub fn from_tree(tree: CommitmentTree<H, DEPTH>) -> Self {
IncrementalWitness {
///
/// Returns `None` if `tree` is empty (and thus there is no position to witness).
pub fn from_tree(tree: CommitmentTree<H, DEPTH>) -> Option<Self> {
(!tree.is_empty()).then(|| IncrementalWitness {
tree,
filled: vec![],
cursor_depth: 0,
cursor: None,
}
})
}
/// Constructs an `IncrementalWitness` from its parts.
///
/// Returns `None` if the parts do not form a valid witness, for example if `tree` is
/// empty (and thus there is no position to witness).
pub fn from_parts(
tree: CommitmentTree<H, DEPTH>,
filled: Vec<H>,
cursor: Option<CommitmentTree<H, DEPTH>>,
) -> Self {
let mut witness = IncrementalWitness {
tree,
filled,
cursor_depth: 0,
cursor,
};
) -> Option<Self> {
(!tree.is_empty()).then(|| {
let mut witness = IncrementalWitness {
tree,
filled,
cursor_depth: 0,
cursor,
};
witness.cursor_depth = witness.next_depth();
witness.cursor_depth = witness.next_depth();
witness
witness
})
}
pub fn tree(&self) -> &CommitmentTree<H, DEPTH> {
@ -248,7 +256,7 @@ mod tests {
for c in 'a'..'h' {
base_tree.append(c.to_string()).unwrap();
}
let mut witness = IncrementalWitness::from_tree(base_tree);
let mut witness = IncrementalWitness::from_tree(base_tree).unwrap();
for c in 'h'..'z' {
witness.append(c.to_string()).unwrap();
}