@@ -42,8 +42,8 @@ use near_store::{
4242 ColReceiptIdToShardId , ColState , ColStateChanges , ColStateDlInfos , ColStateHeaders ,
4343 ColStateParts , ColTransactionRefCount , ColTransactionResult , ColTransactions , ColTrieChanges ,
4444 DBCol , KeyForStateChanges , ShardTries , Store , StoreUpdate , TrieChanges , WrappedTrieChanges ,
45- CHUNK_TAIL_KEY , HEADER_HEAD_KEY , HEAD_KEY , LARGEST_TARGET_HEIGHT_KEY , LATEST_KNOWN_KEY ,
46- SHOULD_COL_GC , SYNC_HEAD_KEY , TAIL_KEY ,
45+ CHUNK_TAIL_KEY , FORK_TAIL_KEY , HEADER_HEAD_KEY , HEAD_KEY , LARGEST_TARGET_HEIGHT_KEY ,
46+ LATEST_KNOWN_KEY , SHOULD_COL_GC , SYNC_HEAD_KEY , TAIL_KEY ,
4747} ;
4848
4949use crate :: byzantine_assert;
@@ -85,6 +85,8 @@ pub trait ChainStoreAccess {
8585 fn tail ( & self ) -> Result < BlockHeight , Error > ;
8686 /// The chain Chunks Tail height.
8787 fn chunk_tail ( & self ) -> Result < BlockHeight , Error > ;
88+ /// Tail height of the fork cleaning process.
89+ fn fork_tail ( & self ) -> Result < BlockHeight , Error > ;
8890 /// Head of the header chain (not the same thing as head_header).
8991 fn header_head ( & self ) -> Result < Tip , Error > ;
9092 /// The "sync" head: last header we received from syncing.
@@ -182,8 +184,9 @@ pub trait ChainStoreAccess {
182184 hash = * header. prev_hash ( ) ;
183185 header = self . get_block_header ( & hash) ?;
184186 }
185- if header. height ( ) < height {
186- return Err ( ErrorKind :: InvalidBlockHeight . into ( ) ) ;
187+ let header_height = header. height ( ) ;
188+ if header_height < height {
189+ return Err ( ErrorKind :: InvalidBlockHeight ( header_height) . into ( ) ) ;
187190 }
188191 self . get_block_header ( & hash)
189192 }
@@ -527,6 +530,13 @@ impl ChainStoreAccess for ChainStore {
527530 . map_err ( |e| e. into ( ) )
528531 }
529532
533+ fn fork_tail ( & self ) -> Result < BlockHeight , Error > {
534+ self . store
535+ . get_ser ( ColBlockMisc , FORK_TAIL_KEY )
536+ . map ( |option| option. unwrap_or_else ( || self . genesis_height ) )
537+ . map_err ( |e| e. into ( ) )
538+ }
539+
530540 /// The "sync" head: last header we received from syncing.
531541 fn sync_head ( & self ) -> Result < Tip , Error > {
532542 option_to_not_found ( self . store . get_ser ( ColBlockMisc , SYNC_HEAD_KEY ) , "SYNC_HEAD" )
@@ -1138,6 +1148,7 @@ pub struct ChainStoreUpdate<'a> {
11381148 head : Option < Tip > ,
11391149 tail : Option < BlockHeight > ,
11401150 chunk_tail : Option < BlockHeight > ,
1151+ fork_tail : Option < BlockHeight > ,
11411152 header_head : Option < Tip > ,
11421153 sync_head : Option < Tip > ,
11431154 largest_target_height : Option < BlockHeight > ,
@@ -1161,6 +1172,7 @@ impl<'a> ChainStoreUpdate<'a> {
11611172 head : None ,
11621173 tail : None ,
11631174 chunk_tail : None ,
1175+ fork_tail : None ,
11641176 header_head : None ,
11651177 sync_head : None ,
11661178 largest_target_height : None ,
@@ -1249,6 +1261,15 @@ impl<'a> ChainStoreAccess for ChainStoreUpdate<'a> {
12491261 }
12501262 }
12511263
1264+ /// Fork tail used by GC
1265+ fn fork_tail ( & self ) -> Result < BlockHeight , Error > {
1266+ if let Some ( fork_tail) = & self . fork_tail {
1267+ Ok ( fork_tail. clone ( ) )
1268+ } else {
1269+ self . chain_store . fork_tail ( )
1270+ }
1271+ }
1272+
12521273 /// The "sync" head: last header we received from syncing.
12531274 fn sync_head ( & self ) -> Result < Tip , Error > {
12541275 if let Some ( sync_head) = & self . sync_head {
@@ -1932,18 +1953,28 @@ impl<'a> ChainStoreUpdate<'a> {
19321953 pub fn reset_tail ( & mut self ) {
19331954 self . tail = None ;
19341955 self . chunk_tail = None ;
1956+ self . fork_tail = None ;
19351957 }
19361958
19371959 pub fn update_tail ( & mut self , height : BlockHeight ) {
19381960 self . tail = Some ( height) ;
19391961 let genesis_height = self . get_genesis_height ( ) ;
1940- let chunk_tail = self . chunk_tail ( ) . unwrap_or_else ( |_| genesis_height) ;
1962+ // When fork tail is behind tail, it doesn't hurt to set it to tail for consistency.
1963+ if self . fork_tail . unwrap_or ( genesis_height) < height {
1964+ self . fork_tail = Some ( height) ;
1965+ }
1966+
1967+ let chunk_tail = self . chunk_tail ( ) . unwrap_or ( genesis_height) ;
19411968 if chunk_tail == genesis_height {
19421969 // For consistency, Chunk Tail should be set if Tail is set
19431970 self . chunk_tail = Some ( self . get_genesis_height ( ) ) ;
19441971 }
19451972 }
19461973
1974+ pub fn update_fork_tail ( & mut self , height : BlockHeight ) {
1975+ self . fork_tail = Some ( height) ;
1976+ }
1977+
19471978 pub fn update_chunk_tail ( & mut self , height : BlockHeight ) {
19481979 self . chunk_tail = Some ( height) ;
19491980 }
@@ -2366,6 +2397,7 @@ impl<'a> ChainStoreUpdate<'a> {
23662397 Self :: write_col_misc ( & mut store_update, HEAD_KEY , & mut self . head ) ?;
23672398 Self :: write_col_misc ( & mut store_update, TAIL_KEY , & mut self . tail ) ?;
23682399 Self :: write_col_misc ( & mut store_update, CHUNK_TAIL_KEY , & mut self . chunk_tail ) ?;
2400+ Self :: write_col_misc ( & mut store_update, FORK_TAIL_KEY , & mut self . fork_tail ) ?;
23692401 Self :: write_col_misc ( & mut store_update, SYNC_HEAD_KEY , & mut self . sync_head ) ?;
23702402 Self :: write_col_misc ( & mut store_update, HEADER_HEAD_KEY , & mut self . header_head ) ?;
23712403 Self :: write_col_misc (
0 commit comments