@@ -20,7 +20,7 @@ use std::collections::{HashMap, HashSet};
20
20
use std:: io:: { ErrorKind , Write } ;
21
21
use std:: ops:: { Deref , DerefMut } ;
22
22
use std:: str:: FromStr ;
23
- use std:: sync:: { Arc , LazyLock , Mutex } ;
23
+ use std:: sync:: { Arc , LazyLock , Mutex , MutexGuard } ;
24
24
use std:: { cmp, fmt, fs} ;
25
25
26
26
use clarity:: util:: lru_cache:: LruCache ;
@@ -98,8 +98,9 @@ pub const REWARD_WINDOW_END: u64 = 144 * 90 + REWARD_WINDOW_START;
98
98
99
99
pub type BlockHeaderCache = HashMap < ConsensusHash , ( Option < BlockHeaderHash > , ConsensusHash ) > ;
100
100
101
+ const DESCENDANCY_CACHE_SIZE : usize = 2000 ;
101
102
static DESCENDANCY_CACHE : LazyLock < Arc < Mutex < LruCache < ( SortitionId , BlockHeaderHash ) , bool > > > > =
102
- LazyLock :: new ( || Arc :: new ( Mutex :: new ( LruCache :: new ( 2000 ) ) ) ) ;
103
+ LazyLock :: new ( || Arc :: new ( Mutex :: new ( LruCache :: new ( DESCENDANCY_CACHE_SIZE ) ) ) ) ;
103
104
104
105
pub enum FindIter < R > {
105
106
Found ( R ) ,
@@ -1091,6 +1092,38 @@ pub trait SortitionHandle {
1091
1092
Ok ( Some ( StacksBlockId :: new ( & ch, & bhh) ) )
1092
1093
}
1093
1094
1095
+ /// Check if the descendancy cache has an entry for whether or not the winning block in `key.0`
1096
+ /// descends from `key.1`
1097
+ ///
1098
+ /// If it does, return the cached entry
1099
+ fn descendancy_cache_get (
1100
+ cache : & mut MutexGuard < ' _ , LruCache < ( SortitionId , BlockHeaderHash ) , bool > > ,
1101
+ key : & ( SortitionId , BlockHeaderHash ) ,
1102
+ ) -> Option < bool > {
1103
+ match cache. get ( key) {
1104
+ Ok ( result) => result,
1105
+ // cache is broken, create a new one
1106
+ Err ( e) => {
1107
+ error ! ( "SortitionDB's descendant cache errored. Will continue operation with cleared cache" ; "err" => %e) ;
1108
+ * * cache = LruCache :: new ( DESCENDANCY_CACHE_SIZE ) ;
1109
+ None
1110
+ }
1111
+ }
1112
+ }
1113
+
1114
+ /// Cache the result of the descendancy check on whether or not the winning block in `key.0`
1115
+ /// descends from `key.1`
1116
+ fn descendancy_cache_put (
1117
+ cache : & mut MutexGuard < ' _ , LruCache < ( SortitionId , BlockHeaderHash ) , bool > > ,
1118
+ key : ( SortitionId , BlockHeaderHash ) ,
1119
+ is_descended : bool ,
1120
+ ) {
1121
+ if let Err ( e) = cache. insert_clean ( key, is_descended) {
1122
+ error ! ( "SortitionDB's descendant cache errored. Will continue operation with cleared cache" ; "err" => %e) ;
1123
+ * * cache = LruCache :: new ( DESCENDANCY_CACHE_SIZE ) ;
1124
+ }
1125
+ }
1126
+
1094
1127
/// is the given block a descendant of `potential_ancestor`?
1095
1128
/// * block_at_burn_height: the burn height of the sortition that chose the stacks block to check
1096
1129
/// * potential_ancestor: the stacks block hash of the potential ancestor
@@ -1125,39 +1158,36 @@ pub trait SortitionHandle {
1125
1158
. expect ( "FATAL: lock poisoned in SortitionDB" ) ;
1126
1159
1127
1160
while sn. block_height >= earliest_block_height {
1128
- match cache. get ( & ( sn. sortition_id , potential_ancestor. clone ( ) ) ) {
1129
- Ok ( Some ( result) ) => {
1161
+ let cache_check_key = ( sn. sortition_id , potential_ancestor. clone ( ) ) ;
1162
+ match Self :: descendancy_cache_get ( & mut cache, & cache_check_key) {
1163
+ Some ( result) => {
1130
1164
if sn. sortition_id != top_sortition_id {
1131
- if let Err ( _ ) = cache
1132
- . insert_clean ( ( top_sortition_id , potential_ancestor . clone ( ) ) , result )
1133
- {
1134
- * cache = LruCache :: new ( 2000 ) ;
1135
- }
1165
+ Self :: descendancy_cache_put (
1166
+ & mut cache ,
1167
+ ( top_sortition_id , cache_check_key . 1 ) ,
1168
+ result ,
1169
+ ) ;
1136
1170
}
1137
1171
return Ok ( result) ;
1138
1172
}
1139
1173
// not cached, don't need to do anything.
1140
- Ok ( None ) => { }
1141
- // cache is broken, create a new one
1142
- Err ( _) => {
1143
- * cache = LruCache :: new ( 2000 ) ;
1144
- }
1174
+ None => { }
1145
1175
}
1146
1176
1147
1177
if !sn. sortition {
1148
- if let Err ( _ ) =
1149
- cache. insert_clean ( ( top_sortition_id , potential_ancestor . clone ( ) ) , false )
1150
- {
1151
- * cache = LruCache :: new ( 2000 ) ;
1152
- }
1178
+ Self :: descendancy_cache_put (
1179
+ & mut cache,
1180
+ ( top_sortition_id , cache_check_key . 1 ) ,
1181
+ false ,
1182
+ ) ;
1153
1183
return Ok ( false ) ;
1154
1184
}
1155
1185
if & sn. winning_stacks_block_hash == potential_ancestor {
1156
- if let Err ( _ ) =
1157
- cache. insert_clean ( ( top_sortition_id , potential_ancestor . clone ( ) ) , true )
1158
- {
1159
- * cache = LruCache :: new ( 2000 ) ;
1160
- }
1186
+ Self :: descendancy_cache_put (
1187
+ & mut cache,
1188
+ ( top_sortition_id , cache_check_key . 1 ) ,
1189
+ true ,
1190
+ ) ;
1161
1191
return Ok ( true ) ;
1162
1192
}
1163
1193
@@ -1193,9 +1223,11 @@ pub trait SortitionHandle {
1193
1223
}
1194
1224
}
1195
1225
}
1196
- if let Err ( _) = cache. insert_clean ( ( top_sortition_id, potential_ancestor. clone ( ) ) , false ) {
1197
- * cache = LruCache :: new ( 2000 ) ;
1198
- }
1226
+ Self :: descendancy_cache_put (
1227
+ & mut cache,
1228
+ ( top_sortition_id, potential_ancestor. clone ( ) ) ,
1229
+ false ,
1230
+ ) ;
1199
1231
return Ok ( false ) ;
1200
1232
}
1201
1233
}
0 commit comments