@@ -119,7 +119,7 @@ impl<DB: Blockstore> ChainIndex<DB> {
119119 pub fn tipset_by_height (
120120 & self ,
121121 to : ChainEpoch ,
122- from : Arc < Tipset > ,
122+ mut from : Arc < Tipset > ,
123123 resolve : ResolveNullTipset ,
124124 ) -> Result < Arc < Tipset > , Error > {
125125 const CHECKPOINT_INTERVAL : ChainEpoch = 1000 ;
@@ -135,9 +135,16 @@ impl<DB: Blockstore> ChainIndex<DB> {
135135 epoch - epoch. mod_floor ( & CHECKPOINT_INTERVAL ) + CHECKPOINT_INTERVAL
136136 }
137137
138- let checkpoint_from_epoch = next_checkpoint ( to) ;
139- let checkpoint_from = CACHE . get_cloned ( & checkpoint_from_epoch) ;
140- let from = checkpoint_from. unwrap_or ( from) ;
138+ let from_epoch = from. epoch ( ) ;
139+
140+ let mut checkpoint_from_epoch = to;
141+ while checkpoint_from_epoch < from_epoch {
142+ if let Some ( checkpoint_from) = CACHE . get_cloned ( & checkpoint_from_epoch) {
143+ from = checkpoint_from;
144+ break ;
145+ }
146+ checkpoint_from_epoch = next_checkpoint ( checkpoint_from_epoch) ;
147+ }
141148
142149 if to == 0 {
143150 return Ok ( Arc :: new ( Tipset :: from ( from. genesis ( & self . db ) ?) ) ) ;
@@ -150,7 +157,11 @@ impl<DB: Blockstore> ChainIndex<DB> {
150157 }
151158
152159 for ( child, parent) in self . chain ( from) . tuple_windows ( ) {
153- if child. epoch ( ) % CHECKPOINT_INTERVAL == 0 {
160+ // use `child.epoch() + CHECKPOINT_INTERVAL <= from_epoch` where `CHECKPOINT_INTERVAL>=CHAIN_FINALITY && CHECKPOINT_INTERVAL>=F3_CHAIN_FINALITY`
161+ // to ensure the cached child is finalized(not on a fork).
162+ if child. epoch ( ) % CHECKPOINT_INTERVAL == 0
163+ && child. epoch ( ) + CHECKPOINT_INTERVAL <= from_epoch
164+ {
154165 CACHE . push ( child. epoch ( ) , child. clone ( ) ) ;
155166 }
156167
0 commit comments