@@ -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 } ;
@@ -489,7 +502,7 @@ mod spv_client_tests {
489502 let best_tip = chain. at_height ( 1 ) ;
490503
491504 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
492- let cache = UnboundedCache :: new ( ) ;
505+ let cache = HeaderCache :: new ( ) ;
493506 let mut listener = NullChainListener { } ;
494507 let mut client = SpvClient :: new ( best_tip, poller, cache, & mut listener) ;
495508 match client. poll_best_tip ( ) . await {
@@ -508,7 +521,7 @@ mod spv_client_tests {
508521 let common_tip = chain. tip ( ) ;
509522
510523 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
511- let cache = UnboundedCache :: new ( ) ;
524+ let cache = HeaderCache :: new ( ) ;
512525 let mut listener = NullChainListener { } ;
513526 let mut client = SpvClient :: new ( common_tip, poller, cache, & mut listener) ;
514527 match client. poll_best_tip ( ) . await {
@@ -528,7 +541,7 @@ mod spv_client_tests {
528541 let old_tip = chain. at_height ( 1 ) ;
529542
530543 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
531- let cache = UnboundedCache :: new ( ) ;
544+ let cache = HeaderCache :: new ( ) ;
532545 let mut listener = NullChainListener { } ;
533546 let mut client = SpvClient :: new ( old_tip, poller, cache, & mut listener) ;
534547 match client. poll_best_tip ( ) . await {
@@ -548,7 +561,7 @@ mod spv_client_tests {
548561 let old_tip = chain. at_height ( 1 ) ;
549562
550563 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
551- let cache = UnboundedCache :: new ( ) ;
564+ let cache = HeaderCache :: new ( ) ;
552565 let mut listener = NullChainListener { } ;
553566 let mut client = SpvClient :: new ( old_tip, poller, cache, & mut listener) ;
554567 match client. poll_best_tip ( ) . await {
@@ -568,7 +581,7 @@ mod spv_client_tests {
568581 let old_tip = chain. at_height ( 1 ) ;
569582
570583 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
571- let cache = UnboundedCache :: new ( ) ;
584+ let cache = HeaderCache :: new ( ) ;
572585 let mut listener = NullChainListener { } ;
573586 let mut client = SpvClient :: new ( old_tip, poller, cache, & mut listener) ;
574587 match client. poll_best_tip ( ) . await {
@@ -589,7 +602,7 @@ mod spv_client_tests {
589602 let worse_tip = chain. tip ( ) ;
590603
591604 let poller = poll:: ChainPoller :: new ( & mut chain, Network :: Testnet ) ;
592- let cache = UnboundedCache :: new ( ) ;
605+ let cache = HeaderCache :: new ( ) ;
593606 let mut listener = NullChainListener { } ;
594607 let mut client = SpvClient :: new ( best_tip, poller, cache, & mut listener) ;
595608 match client. poll_best_tip ( ) . await {
0 commit comments