@@ -176,7 +176,7 @@ where
176176{
177177 chain_tip : ValidatedBlockHeader ,
178178 chain_poller : P ,
179- chain_notifier : ChainNotifier < UnboundedCache , L > ,
179+ chain_notifier : ChainNotifier < HeaderCache , L > ,
180180}
181181
182182/// The `Cache` trait defines behavior for managing a block header cache, where block headers are
@@ -204,34 +204,47 @@ pub(crate) trait Cache {
204204 fn blocks_disconnected ( & mut self , fork_point : & ValidatedBlockHeader ) ;
205205}
206206
207- /// Unbounded cache of block headers keyed by block hash.
208- pub type UnboundedCache = std:: collections:: HashMap < BlockHash , ValidatedBlockHeader > ;
207+ /// Bounded cache of block headers keyed by block hash.
208+ ///
209+ /// Retains only the last `ANTI_REORG_DELAY * 2` block headers based on height.
210+ pub struct HeaderCache ( std:: collections:: HashMap < BlockHash , ValidatedBlockHeader > ) ;
209211
210- impl Cache for UnboundedCache {
212+ impl HeaderCache {
213+ /// Creates a new empty header cache.
214+ pub fn new ( ) -> Self {
215+ Self ( std:: collections:: HashMap :: new ( ) )
216+ }
217+ }
218+
219+ impl Cache for HeaderCache {
211220 fn look_up ( & self , block_hash : & BlockHash ) -> Option < & ValidatedBlockHeader > {
212- self . get ( block_hash)
221+ self . 0 . get ( block_hash)
213222 }
214223
215224 fn block_connected ( & mut self , block_hash : BlockHash , block_header : ValidatedBlockHeader ) {
216- self . insert ( block_hash, block_header) ;
225+ self . 0 . insert ( block_hash, block_header) ;
226+
227+ // Remove headers older than a week.
228+ let cutoff_height = block_header. height . saturating_sub ( 6 * 24 * 7 ) ;
229+ self . 0 . retain ( |_, header| header. height >= cutoff_height) ;
217230 }
218231
219232 fn blocks_disconnected ( & mut self , fork_point : & ValidatedBlockHeader ) {
220- self . retain ( |_, block_info| block_info. height < fork_point. height ) ;
233+ self . 0 . retain ( |_, block_info| block_info. height < fork_point. height ) ;
221234 }
222235}
223236
224- impl Cache for & mut UnboundedCache {
237+ impl Cache for & mut HeaderCache {
225238 fn look_up ( & self , block_hash : & BlockHash ) -> Option < & ValidatedBlockHeader > {
226- self . get ( block_hash)
239+ self . 0 . get ( block_hash)
227240 }
228241
229242 fn block_connected ( & mut self , block_hash : BlockHash , block_header : ValidatedBlockHeader ) {
230- self . insert ( block_hash, block_header) ;
243+ ( * self ) . block_connected ( block_hash, block_header) ;
231244 }
232245
233246 fn blocks_disconnected ( & mut self , fork_point : & ValidatedBlockHeader ) {
234- self . retain ( |_, block_info| block_info. height < fork_point. height ) ;
247+ self . 0 . retain ( |_, block_info| block_info. height < fork_point. height ) ;
235248 }
236249}
237250
@@ -250,7 +263,7 @@ where
250263 ///
251264 /// [`poll_best_tip`]: SpvClient::poll_best_tip
252265 pub fn new (
253- chain_tip : ValidatedBlockHeader , chain_poller : P , header_cache : UnboundedCache ,
266+ chain_tip : ValidatedBlockHeader , chain_poller : P , header_cache : HeaderCache ,
254267 chain_listener : L ,
255268 ) -> Self {
256269 let chain_notifier = ChainNotifier { header_cache, chain_listener } ;
@@ -490,7 +503,7 @@ mod spv_client_tests {
490503 let best_tip = chain. at_height ( 1 ) ;
491504
492505 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
493- let cache = UnboundedCache :: new ( ) ;
506+ let cache = HeaderCache :: new ( ) ;
494507 let mut listener = NullChainListener { } ;
495508 let mut client = SpvClient :: new ( best_tip, poller, cache, & mut listener) ;
496509 match client. poll_best_tip ( ) . await {
@@ -509,7 +522,7 @@ mod spv_client_tests {
509522 let common_tip = chain. tip ( ) ;
510523
511524 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
512- let cache = UnboundedCache :: new ( ) ;
525+ let cache = HeaderCache :: new ( ) ;
513526 let mut listener = NullChainListener { } ;
514527 let mut client = SpvClient :: new ( common_tip, poller, cache, & mut listener) ;
515528 match client. poll_best_tip ( ) . await {
@@ -529,7 +542,7 @@ mod spv_client_tests {
529542 let old_tip = chain. at_height ( 1 ) ;
530543
531544 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
532- let cache = UnboundedCache :: new ( ) ;
545+ let cache = HeaderCache :: new ( ) ;
533546 let mut listener = NullChainListener { } ;
534547 let mut client = SpvClient :: new ( old_tip, poller, cache, & mut listener) ;
535548 match client. poll_best_tip ( ) . await {
@@ -549,7 +562,7 @@ mod spv_client_tests {
549562 let old_tip = chain. at_height ( 1 ) ;
550563
551564 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
552- let cache = UnboundedCache :: new ( ) ;
565+ let cache = HeaderCache :: new ( ) ;
553566 let mut listener = NullChainListener { } ;
554567 let mut client = SpvClient :: new ( old_tip, poller, cache, & mut listener) ;
555568 match client. poll_best_tip ( ) . await {
@@ -569,7 +582,7 @@ mod spv_client_tests {
569582 let old_tip = chain. at_height ( 1 ) ;
570583
571584 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
572- let cache = UnboundedCache :: new ( ) ;
585+ let cache = HeaderCache :: new ( ) ;
573586 let mut listener = NullChainListener { } ;
574587 let mut client = SpvClient :: new ( old_tip, poller, cache, & mut listener) ;
575588 match client. poll_best_tip ( ) . await {
@@ -590,7 +603,7 @@ mod spv_client_tests {
590603 let worse_tip = chain. tip ( ) ;
591604
592605 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
593- let cache = UnboundedCache :: new ( ) ;
606+ let cache = HeaderCache :: new ( ) ;
594607 let mut listener = NullChainListener { } ;
595608 let mut client = SpvClient :: new ( best_tip, poller, cache, & mut listener) ;
596609 match client. poll_best_tip ( ) . await {
0 commit comments