@@ -95,6 +95,12 @@ pub const REWARD_WINDOW_END: u64 = 144 * 90 + REWARD_WINDOW_START;
95
95
96
96
pub type BlockHeaderCache = HashMap < ConsensusHash , ( Option < BlockHeaderHash > , ConsensusHash ) > ;
97
97
98
+ pub enum FindIter < R > {
99
+ Found ( R ) ,
100
+ Continue ,
101
+ Halt ,
102
+ }
103
+
98
104
impl FromRow < SortitionId > for SortitionId {
99
105
fn from_row ( row : & Row ) -> Result < SortitionId , db_error > {
100
106
SortitionId :: from_column ( row, "sortition_id" )
@@ -4989,6 +4995,60 @@ impl SortitionDB {
4989
4995
Ok ( handle. get_reward_set_size_at ( & sort_id_of_start) ? > 0 )
4990
4996
}
4991
4997
4998
+ /// Find a sortition by traversing the sortition history backwards, starting
4999
+ /// from the current canonical burn tip.
5000
+ ///
5001
+ /// The supplied function `f` is applied to each traversed snapshot
5002
+ /// and the return value of `f` controls the iteration.
5003
+ ///
5004
+ /// FindIter::Found(x) => tells the search to stop, and return `Ok(Some(x))`
5005
+ /// FindIter::Halt => tells the search to stop, and return `Ok(None)`
5006
+ /// FindIter::Continue will continue the iteration
5007
+ ///
5008
+ /// This function exits early and returns the error if either `f` or a SortitionDB
5009
+ /// error occurs while processing.
5010
+ /// It returns `Ok(None)` if the traversal reaches the sortition root without finding `x`
5011
+ pub fn find_in_canonical < F , R , E > ( & self , f : F ) -> Result < Option < R > , E >
5012
+ where
5013
+ F : FnMut ( & BlockSnapshot ) -> Result < FindIter < R > , E > ,
5014
+ E : From < db_error > ,
5015
+ {
5016
+ let cursor = Self :: get_canonical_burn_chain_tip ( self . conn ( ) ) ?;
5017
+ self . find_from ( cursor, f)
5018
+ }
5019
+
5020
+ /// Find a sortition by traversing the sortition history backwards, starting
5021
+ /// from `sn`. The supplied function `f` is applied to each traversed snapshot
5022
+ /// and the return value of `f` controls the iteration.
5023
+ ///
5024
+ /// FindIter::Found(x) => tells the search to stop, and return `Ok(Some(x))`
5025
+ /// FindIter::Halt => tells the search to stop, and return `Ok(None)`
5026
+ /// FindIter::Continue will continue the iteration
5027
+ ///
5028
+ /// This function exits early and returns the error if either `f` or a SortitionDB
5029
+ /// error occurs while processing.
5030
+ /// It returns `Ok(None)` if the traversal reaches the sortition root without finding `x`
5031
+ pub fn find_from < F , R , E > ( & self , sn : BlockSnapshot , mut f : F ) -> Result < Option < R > , E >
5032
+ where
5033
+ F : FnMut ( & BlockSnapshot ) -> Result < FindIter < R > , E > ,
5034
+ E : From < db_error > ,
5035
+ {
5036
+ let mut cursor_opt = Some ( sn) ;
5037
+ loop {
5038
+ let Some ( ref cursor) = cursor_opt else {
5039
+ return Ok ( None ) ;
5040
+ } ;
5041
+ let next_id = & cursor. parent_sortition_id ;
5042
+ match f ( cursor) ? {
5043
+ FindIter :: Found ( x) => return Ok ( Some ( x) ) ,
5044
+ FindIter :: Halt => return Ok ( None ) ,
5045
+ FindIter :: Continue => {
5046
+ cursor_opt = Self :: get_block_snapshot ( self . conn ( ) , next_id) ?;
5047
+ }
5048
+ }
5049
+ }
5050
+ }
5051
+
4992
5052
/// Find out how any burn tokens were destroyed in a given block on a given fork.
4993
5053
pub fn get_block_burn_amount (
4994
5054
conn : & Connection ,
0 commit comments