diff --git a/shardtree/src/lib.rs b/shardtree/src/lib.rs index c6acb7a..4b283ae 100644 --- a/shardtree/src/lib.rs +++ b/shardtree/src/lib.rs @@ -1,7 +1,6 @@ use bitflags::bitflags; use core::convert::TryFrom; use core::fmt::{self, Debug}; -use core::marker::PhantomData; use core::ops::{Deref, Range}; use either::Either; use std::collections::{BTreeMap, BTreeSet}; @@ -1417,20 +1416,22 @@ impl Checkpoint { /// A capability for storage of fragment subtrees of the `ShardTree` type. /// /// All fragment subtrees must have roots at level `SHARD_HEIGHT - 1` -pub trait ShardStore { +pub trait ShardStore { + type H; + type CheckpointId; type Error; /// Returns the subtree at the given root address, if any such subtree exists. - fn get_shard(&self, shard_root: Address) -> Option<&LocatedPrunableTree>; + fn get_shard(&self, shard_root: Address) -> Option<&LocatedPrunableTree>; /// Returns the subtree containing the maximum inserted leaf position. - fn last_shard(&self) -> Option<&LocatedPrunableTree>; + fn last_shard(&self) -> Option<&LocatedPrunableTree>; /// Inserts or replaces the subtree having the same root address as the provided tree. /// /// Implementations of this method MUST enforce the constraint that the root address /// of the provided subtree has level `SHARD_HEIGHT - 1`. - fn put_shard(&mut self, subtree: LocatedPrunableTree) -> Result<(), Self::Error>; + fn put_shard(&mut self, subtree: LocatedPrunableTree) -> Result<(), Self::Error>; /// Returns the vector of addresses corresponding to the roots of subtrees stored in this /// store. @@ -1450,15 +1451,15 @@ pub trait ShardStore { // cap_cache: Tree>, ()> /// Returns the identifier for the checkpoint with the lowest associated position value. - fn min_checkpoint_id(&self) -> Option<&C>; + fn min_checkpoint_id(&self) -> Option<&Self::CheckpointId>; /// Returns the identifier for the checkpoint with the highest associated position value. - fn max_checkpoint_id(&self) -> Option<&C>; + fn max_checkpoint_id(&self) -> Option<&Self::CheckpointId>; /// Adds a checkpoint to the data store. fn add_checkpoint( &mut self, - checkpoint_id: C, + checkpoint_id: Self::CheckpointId, checkpoint: Checkpoint, ) -> Result<(), Self::Error>; @@ -1468,13 +1469,16 @@ pub trait ShardStore { /// Returns the position of the checkpoint, if any, along with the number of subsequent /// checkpoints at the same position. Returns `None` if `checkpoint_depth == 0` or if /// insufficient checkpoints exist to seek back to the requested depth. - fn get_checkpoint_at_depth(&self, checkpoint_depth: usize) -> Option<(&C, &Checkpoint)>; + fn get_checkpoint_at_depth( + &self, + checkpoint_depth: usize, + ) -> Option<(&Self::CheckpointId, &Checkpoint)>; /// Iterates in checkpoint ID order over the first `limit` checkpoints, applying the /// given callback to each. fn with_checkpoints(&mut self, limit: usize, callback: F) -> Result<(), Self::Error> where - F: FnMut(&C, &Checkpoint) -> Result<(), Self::Error>; + F: FnMut(&Self::CheckpointId, &Checkpoint) -> Result<(), Self::Error>; /// Update the checkpoint having the given identifier by mutating it with the provided /// function, and persist the updated checkpoint to the data store. @@ -1483,31 +1487,36 @@ pub trait ShardStore { /// provided identifier exists in the data store, or an error if a storage error occurred. fn update_checkpoint_with( &mut self, - checkpoint_id: &C, + checkpoint_id: &Self::CheckpointId, update: F, ) -> Result where F: Fn(&mut Checkpoint) -> Result<(), Self::Error>; /// Removes a checkpoint from the data store. - fn remove_checkpoint(&mut self, checkpoint_id: &C) -> Result<(), Self::Error>; + fn remove_checkpoint(&mut self, checkpoint_id: &Self::CheckpointId) -> Result<(), Self::Error>; /// Removes checkpoints with identifiers greater than or equal to the given identifier - fn truncate_checkpoints(&mut self, checkpoint_id: &C) -> Result<(), Self::Error>; + fn truncate_checkpoints( + &mut self, + checkpoint_id: &Self::CheckpointId, + ) -> Result<(), Self::Error>; } -impl> ShardStore for &mut S { +impl ShardStore for &mut S { + type H = S::H; + type CheckpointId = S::CheckpointId; type Error = S::Error; - fn get_shard(&self, shard_root: Address) -> Option<&LocatedPrunableTree> { + fn get_shard(&self, shard_root: Address) -> Option<&LocatedPrunableTree> { S::get_shard(*self, shard_root) } - fn last_shard(&self) -> Option<&LocatedPrunableTree> { + fn last_shard(&self) -> Option<&LocatedPrunableTree> { S::last_shard(*self) } - fn put_shard(&mut self, subtree: LocatedPrunableTree) -> Result<(), Self::Error> { + fn put_shard(&mut self, subtree: LocatedPrunableTree) -> Result<(), Self::Error> { S::put_shard(*self, subtree) } @@ -1519,17 +1528,17 @@ impl> ShardStore for &mut S { S::truncate(*self, from) } - fn min_checkpoint_id(&self) -> Option<&C> { + fn min_checkpoint_id(&self) -> Option<&Self::CheckpointId> { S::min_checkpoint_id(self) } - fn max_checkpoint_id(&self) -> Option<&C> { + fn max_checkpoint_id(&self) -> Option<&Self::CheckpointId> { S::max_checkpoint_id(self) } fn add_checkpoint( &mut self, - checkpoint_id: C, + checkpoint_id: Self::CheckpointId, checkpoint: Checkpoint, ) -> Result<(), Self::Error> { S::add_checkpoint(self, checkpoint_id, checkpoint) @@ -1539,20 +1548,23 @@ impl> ShardStore for &mut S { S::checkpoint_count(self) } - fn get_checkpoint_at_depth(&self, checkpoint_depth: usize) -> Option<(&C, &Checkpoint)> { + fn get_checkpoint_at_depth( + &self, + checkpoint_depth: usize, + ) -> Option<(&Self::CheckpointId, &Checkpoint)> { S::get_checkpoint_at_depth(self, checkpoint_depth) } fn with_checkpoints(&mut self, limit: usize, callback: F) -> Result<(), Self::Error> where - F: FnMut(&C, &Checkpoint) -> Result<(), Self::Error>, + F: FnMut(&Self::CheckpointId, &Checkpoint) -> Result<(), Self::Error>, { S::with_checkpoints(self, limit, callback) } fn update_checkpoint_with( &mut self, - checkpoint_id: &C, + checkpoint_id: &Self::CheckpointId, update: F, ) -> Result where @@ -1561,11 +1573,14 @@ impl> ShardStore for &mut S { S::update_checkpoint_with(self, checkpoint_id, update) } - fn remove_checkpoint(&mut self, checkpoint_id: &C) -> Result<(), Self::Error> { + fn remove_checkpoint(&mut self, checkpoint_id: &Self::CheckpointId) -> Result<(), Self::Error> { S::remove_checkpoint(self, checkpoint_id) } - fn truncate_checkpoints(&mut self, checkpoint_id: &C) -> Result<(), Self::Error> { + fn truncate_checkpoints( + &mut self, + checkpoint_id: &Self::CheckpointId, + ) -> Result<(), Self::Error> { S::truncate_checkpoints(self, checkpoint_id) } } @@ -1585,7 +1600,9 @@ impl MemoryShardStore { } } -impl ShardStore for MemoryShardStore { +impl ShardStore for MemoryShardStore { + type H = H; + type CheckpointId = C; type Error = InsertionError; fn get_shard(&self, shard_root: Address) -> Option<&LocatedPrunableTree> { @@ -1699,22 +1716,20 @@ impl ShardStore for MemoryShardStore { /// front of the tree, that are maintained such that it's possible to truncate nodes to the right /// of the specified position. #[derive(Debug)] -pub struct ShardTree, const DEPTH: u8, const SHARD_HEIGHT: u8> { +pub struct ShardTree { /// The vector of tree shards. store: S, /// The maximum number of checkpoints to retain before pruning. max_checkpoints: usize, - _hash_type: PhantomData, - _checkpoint_id_type: PhantomData, } impl< H: Hashable + Clone + PartialEq, C: Clone + Ord, - S: ShardStore, + S: ShardStore, const DEPTH: u8, const SHARD_HEIGHT: u8, - > ShardTree + > ShardTree { /// Creates a new empty tree and establishes a checkpoint for the empty tree at the given /// checkpoint identifier. @@ -1726,8 +1741,6 @@ impl< let mut result = Self { store, max_checkpoints, - _hash_type: PhantomData, - _checkpoint_id_type: PhantomData, }; result .store @@ -1740,8 +1753,6 @@ impl< Self { store, max_checkpoints, - _hash_type: PhantomData, - _checkpoint_id_type: PhantomData, } } @@ -2770,7 +2781,7 @@ mod tests { #[test] fn shardtree_insertion() { - let mut tree: ShardTree, 4, 3> = + let mut tree: ShardTree, 4, 3> = ShardTree::empty(MemoryShardStore::empty(), 100, 0).unwrap(); assert_matches!( tree.batch_insert( @@ -2862,10 +2873,10 @@ mod tests { impl< H: Hashable + Ord + Clone, C: Clone + Ord + core::fmt::Debug, - S: ShardStore, + S: ShardStore, const DEPTH: u8, const SHARD_HEIGHT: u8, - > testing::Tree for ShardTree + > testing::Tree for ShardTree where S::Error: core::fmt::Debug + From, { @@ -2919,7 +2930,7 @@ mod tests { #[test] fn append() { check_append(|m| { - ShardTree::, 4, 3>::empty( + ShardTree::, 4, 3>::empty( MemoryShardStore::empty(), m, 0, @@ -2931,7 +2942,7 @@ mod tests { #[test] fn root_hashes() { check_root_hashes(|m| { - ShardTree::, 4, 3>::empty( + ShardTree::, 4, 3>::empty( MemoryShardStore::empty(), m, 0, @@ -2943,7 +2954,7 @@ mod tests { #[test] fn witnesses() { check_witnesses(|m| { - ShardTree::, 4, 3>::empty( + ShardTree::, 4, 3>::empty( MemoryShardStore::empty(), m, 0, @@ -2955,7 +2966,7 @@ mod tests { #[test] fn checkpoint_rewind() { check_checkpoint_rewind(|m| { - ShardTree::, 4, 3>::empty( + ShardTree::, 4, 3>::empty( MemoryShardStore::empty(), m, 0, @@ -2967,7 +2978,7 @@ mod tests { #[test] fn rewind_remove_mark() { check_rewind_remove_mark(|m| { - ShardTree::, 4, 3>::empty( + ShardTree::, 4, 3>::empty( MemoryShardStore::empty(), m, 0, @@ -2984,7 +2995,7 @@ mod tests { H, usize, CompleteTree, - ShardTree, 4, 3>, + ShardTree, 4, 3>, > { CombinedTree::new( CompleteTree::new(max_checkpoints, 0),