diff --git a/zebra-chain/src/subtree.rs b/zebra-chain/src/subtree.rs index 52e3ef3d7d0..b4a74343379 100644 --- a/zebra-chain/src/subtree.rs +++ b/zebra-chain/src/subtree.rs @@ -14,7 +14,7 @@ pub const TRACKED_SUBTREE_HEIGHT: u8 = 16; /// A note commitment subtree index, used to identify a subtree in a shielded pool. /// Also used to count subtrees. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Default)] #[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] #[serde(transparent)] pub struct NoteCommitmentSubtreeIndex(pub u16); diff --git a/zebra-state/src/service/read/tests/vectors.rs b/zebra-state/src/service/read/tests/vectors.rs index 0c59782f311..7236b70ab66 100644 --- a/zebra-state/src/service/read/tests/vectors.rs +++ b/zebra-state/src/service/read/tests/vectors.rs @@ -104,6 +104,8 @@ async fn populated_read_state_responds_correctly() -> Result<()> { /// non-finalized states correctly. #[tokio::test] async fn test_read_subtrees() -> Result<()> { + use std::ops::Bound::{self, *}; + let dummy_subtree = |(index, height)| { NoteCommitmentSubtree::new( u16::try_from(index).expect("should fit in u16"), @@ -179,6 +181,31 @@ async fn test_read_subtrees() -> Result<()> { assert_eq!(first_chain_index, index, "subtree indexes should match"); assert_eq!(end_height, subtree.end, "subtree end heights should match"); + // Check that Zebra retrieves subtrees correctly when using a range with an Excluded start bound + + #[derive(Clone, Default, PartialEq, Eq, Hash)] + struct RangeExclusiveStart { + pub start: Idx, + pub end: Option, + } + + impl std::ops::RangeBounds for RangeExclusiveStart { + fn start_bound(&self) -> Bound<&T> { + Excluded(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + self.end.as_ref().map(Excluded).unwrap_or(Unbounded) + } + } + + let range = RangeExclusiveStart::default(); + let subtrees = sapling_subtrees(Some(chain), &db, range.clone()); + assert_eq!(subtrees.len(), 11); + assert!( + !subtrees.contains_key(&range.start), + "should not contain excluded start bound" + ); + Ok(()) }