-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace justified unwraps
in shardtree
with expect
s
#119
Changes from all commits
74410d0
1e81f3c
166872e
c05f2fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -358,6 +358,7 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
/// Note that no actual leaf value may exist at this position, as it may have previously been | ||||||
/// pruned. | ||||||
pub fn max_position(&self) -> Option<Position> { | ||||||
/// Pre-condition: `addr` must be the address of `root`. | ||||||
fn go<H>( | ||||||
addr: Address, | ||||||
root: &Tree<Option<Arc<H>>, (H, RetentionFlags)>, | ||||||
|
@@ -369,7 +370,9 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
if ann.is_some() { | ||||||
Some(addr.max_position()) | ||||||
} else { | ||||||
let (l_addr, r_addr) = addr.children().unwrap(); | ||||||
let (l_addr, r_addr) = addr | ||||||
.children() | ||||||
.expect("has children because we checked `root` is a parent"); | ||||||
go(r_addr, right.as_ref()).or_else(|| go(l_addr, left.as_ref())) | ||||||
} | ||||||
} | ||||||
|
@@ -406,14 +409,17 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
|
||||||
/// Returns the positions of marked leaves in the tree. | ||||||
pub fn marked_positions(&self) -> BTreeSet<Position> { | ||||||
/// Pre-condition: `root_addr` must be the address of `root`. | ||||||
fn go<H: Hashable + Clone + PartialEq>( | ||||||
root_addr: Address, | ||||||
root: &PrunableTree<H>, | ||||||
acc: &mut BTreeSet<Position>, | ||||||
) { | ||||||
match &root.0 { | ||||||
Node::Parent { left, right, .. } => { | ||||||
let (l_addr, r_addr) = root_addr.children().unwrap(); | ||||||
let (l_addr, r_addr) = root_addr | ||||||
.children() | ||||||
.expect("has children because we checked `root` is a parent"); | ||||||
go(l_addr, left.as_ref(), acc); | ||||||
go(r_addr, right.as_ref(), acc); | ||||||
} | ||||||
|
@@ -440,8 +446,10 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
/// Returns either the witness for the leaf at the specified position, or an error that | ||||||
/// describes the causes of failure. | ||||||
pub fn witness(&self, position: Position, truncate_at: Position) -> Result<Vec<H>, QueryError> { | ||||||
// traverse down to the desired leaf position, and then construct | ||||||
// the authentication path on the way back up. | ||||||
/// Traverse down to the desired leaf position, and then construct | ||||||
/// the authentication path on the way back up. | ||||||
// | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non-blocking nit:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't think that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I verified that |
||||||
/// Pre-condition: `root_addr` must be the address of `root`. | ||||||
fn go<H: Hashable + Clone + PartialEq>( | ||||||
root: &PrunableTree<H>, | ||||||
root_addr: Address, | ||||||
|
@@ -450,7 +458,9 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
) -> Result<Vec<H>, Vec<Address>> { | ||||||
match &root.0 { | ||||||
Node::Parent { left, right, .. } => { | ||||||
let (l_addr, r_addr) = root_addr.children().unwrap(); | ||||||
let (l_addr, r_addr) = root_addr | ||||||
.children() | ||||||
.expect("has children because we checked `root` is a parent"); | ||||||
if root_addr.level() > 1.into() { | ||||||
let r_start = r_addr.position_range_start(); | ||||||
if position < r_start { | ||||||
|
@@ -525,14 +535,17 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
/// subtree root with the specified position as its maximum position exists, or `None` | ||||||
/// otherwise. | ||||||
pub fn truncate_to_position(&self, position: Position) -> Option<Self> { | ||||||
/// Pre-condition: `root_addr` must be the address of `root`. | ||||||
fn go<H: Hashable + Clone + PartialEq>( | ||||||
position: Position, | ||||||
root_addr: Address, | ||||||
root: &PrunableTree<H>, | ||||||
) -> Option<PrunableTree<H>> { | ||||||
match &root.0 { | ||||||
Node::Parent { ann, left, right } => { | ||||||
let (l_child, r_child) = root_addr.children().unwrap(); | ||||||
let (l_child, r_child) = root_addr | ||||||
.children() | ||||||
.expect("has children because we checked `root` is a parent"); | ||||||
if position < r_child.position_range_start() { | ||||||
// we are truncating within the range of the left node, so recurse | ||||||
// to the left to truncate the left child and then reconstruct the | ||||||
|
@@ -586,8 +599,10 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
subtree: Self, | ||||||
contains_marked: bool, | ||||||
) -> Result<(Self, Vec<IncompleteAt>), InsertionError> { | ||||||
// A function to recursively dig into the tree, creating a path downward and introducing | ||||||
// empty nodes as necessary until we can insert the provided subtree. | ||||||
/// A function to recursively dig into the tree, creating a path downward and introducing | ||||||
/// empty nodes as necessary until we can insert the provided subtree. | ||||||
/// | ||||||
/// Pre-condition: `root_addr` must be the address of `into`. | ||||||
#[allow(clippy::type_complexity)] | ||||||
fn go<H: Hashable + Clone + PartialEq>( | ||||||
root_addr: Address, | ||||||
|
@@ -694,7 +709,9 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
Tree(Node::Parent { ann, left, right }) => { | ||||||
// In this case, we have an existing parent but we need to dig down farther | ||||||
// before we can insert the subtree that we're carrying for insertion. | ||||||
let (l_addr, r_addr) = root_addr.children().unwrap(); | ||||||
let (l_addr, r_addr) = root_addr | ||||||
.children() | ||||||
.expect("has children because we checked `into` is a parent"); | ||||||
if l_addr.contains(&subtree.root_addr) { | ||||||
let (new_left, incomplete) = | ||||||
go(l_addr, left.as_ref(), subtree, contains_marked)?; | ||||||
|
@@ -770,7 +787,7 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
if r.remainder.next().is_some() { | ||||||
Err(InsertionError::TreeFull) | ||||||
} else { | ||||||
Ok((r.subtree, r.max_insert_position.unwrap(), checkpoint_id)) | ||||||
Ok((r.subtree, r.max_insert_position, checkpoint_id)) | ||||||
} | ||||||
}) | ||||||
} | ||||||
|
@@ -892,6 +909,7 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
/// Clears the specified retention flags at all positions specified, pruning any branches | ||||||
/// that no longer need to be retained. | ||||||
pub fn clear_flags(&self, to_clear: BTreeMap<Position, RetentionFlags>) -> Self { | ||||||
/// Pre-condition: `root_addr` must be the address of `root`. | ||||||
fn go<H: Hashable + Clone + PartialEq>( | ||||||
to_clear: &[(Position, RetentionFlags)], | ||||||
root_addr: Address, | ||||||
|
@@ -903,7 +921,9 @@ impl<H: Hashable + Clone + PartialEq> LocatedPrunableTree<H> { | |||||
} else { | ||||||
match &root.0 { | ||||||
Node::Parent { ann, left, right } => { | ||||||
let (l_addr, r_addr) = root_addr.children().unwrap(); | ||||||
let (l_addr, r_addr) = root_addr | ||||||
.children() | ||||||
.expect("has children because we checked `root` is a parent"); | ||||||
|
||||||
let p = to_clear.partition_point(|(p, _)| p < &l_addr.position_range_end()); | ||||||
trace!( | ||||||
|
@@ -1228,7 +1248,7 @@ mod tests { | |||||
root in arb_prunable_tree(arb_char_str(), 8, 2^6) | ||||||
) { | ||||||
let root_addr = Address::from_parts(Level::from(7), 0); | ||||||
let tree = LocatedTree::from_parts(root_addr, root); | ||||||
let tree = LocatedTree::from_parts(root_addr, root).unwrap(); | ||||||
|
||||||
let (to_clear, to_retain) = tree.flag_positions().into_iter().enumerate().fold( | ||||||
(BTreeMap::new(), BTreeMap::new()), | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pre-condition (and all similar others in this PR) is verifiably upheld:
go(subtree.root_addr, &subtree.root)
; it is a programming error for these to be inconsistent.go(r_addr, right)
orgo(l_addr, left)
with values obtained fromroot_addr
androot
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I note that the public API
LocatedTree::from_parts
does not enforce that its arguments are consistent; we could potentially strengthen this by making that method fallible and checking that the actual encoded depth of the provided tree matches the provided root address (which would ensure that all parents within the provided tree correspond to a subtree node of the provided root address that can have children).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated this PR to add the consistency check to
LocatedTree::from_parts
.