5050)
5151
5252const (
53- databaseVersion = 1 // reindexed if database version does not match
53+ databaseVersion = 2 // reindexed if database version does not match
5454 cachedLastBlocks = 1000 // last block of map pointers
5555 cachedLvPointers = 1000 // first log value pointer of block pointers
5656 cachedBaseRows = 100 // groups of base layer filter row data
@@ -244,6 +244,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
244244 disabledCh : make (chan struct {}),
245245 exportFileName : config .ExportFileName ,
246246 Params : params ,
247+ targetView : initView ,
248+ indexedView : initView ,
247249 indexedRange : filterMapsRange {
248250 initialized : initialized ,
249251 headIndexed : rs .HeadIndexed ,
@@ -265,16 +267,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
265267 baseRowsCache : lru.NewCache [uint64 , [][]uint32 ](cachedBaseRows ),
266268 renderSnapshots : lru.NewCache [uint64 , * renderedMap ](cachedRenderSnapshots ),
267269 }
270+ f .checkRevertRange () // revert maps that are inconsistent with the current chain view
268271
269- // Set initial indexer target.
270- f .targetView = initView
271- if f .indexedRange .initialized {
272- f .indexedView = f .initChainView (f .targetView )
273- f .indexedRange .headIndexed = f .indexedRange .blocks .AfterLast () == f .indexedView .HeadNumber ()+ 1
274- if ! f .indexedRange .headIndexed {
275- f .indexedRange .headDelimiter = 0
276- }
277- }
278272 if f .indexedRange .hasIndexedBlocks () {
279273 log .Info ("Initialized log indexer" ,
280274 "first block" , f .indexedRange .blocks .First (), "last block" , f .indexedRange .blocks .Last (),
@@ -303,29 +297,40 @@ func (f *FilterMaps) Stop() {
303297 f .closeWg .Wait ()
304298}
305299
306- // initChainView returns a chain view consistent with both the current target
307- // view and the current state of the log index as found in the database, based
308- // on the last block of stored maps.
309- // Note that the returned view might be shorter than the existing index if
310- // the latest maps are not consistent with targetView.
311- func (f * FilterMaps ) initChainView (chainView * ChainView ) * ChainView {
312- mapIndex := f .indexedRange .maps .AfterLast ()
313- for {
314- var ok bool
315- mapIndex , ok = f .lastMapBoundaryBefore (mapIndex )
316- if ! ok {
317- break
300+ // checkRevertRange checks whether the existing index is consistent with the
301+ // current indexed view and reverts inconsistent maps if necessary.
302+ func (f * FilterMaps ) checkRevertRange () {
303+ if f .indexedRange .maps .Count () == 0 {
304+ return
305+ }
306+ lastMap := f .indexedRange .maps .Last ()
307+ lastBlockNumber , lastBlockId , err := f .getLastBlockOfMap (lastMap )
308+ if err != nil {
309+ log .Error ("Error initializing log index database; resetting log index" , "error" , err )
310+ f .reset ()
311+ return
312+ }
313+ for lastBlockNumber > f .indexedView .HeadNumber () || f .indexedView .BlockId (lastBlockNumber ) != lastBlockId {
314+ // revert last map
315+ if f .indexedRange .maps .Count () == 1 {
316+ f .reset () // reset database if no rendered maps remained
317+ return
318318 }
319- lastBlockNumber , lastBlockId , err := f .getLastBlockOfMap (mapIndex )
319+ lastMap --
320+ newRange := f .indexedRange
321+ newRange .maps .SetLast (lastMap )
322+ lastBlockNumber , lastBlockId , err = f .getLastBlockOfMap (lastMap )
320323 if err != nil {
321- log .Error ("Could not initialize indexed chain view" , "error" , err )
322- break
323- }
324- if lastBlockNumber <= chainView .HeadNumber () && chainView .BlockId (lastBlockNumber ) == lastBlockId {
325- return chainView .limitedView (lastBlockNumber )
324+ log .Error ("Error initializing log index database; resetting log index" , "error" , err )
325+ f .reset ()
326+ return
326327 }
328+ newRange .blocks .SetAfterLast (lastBlockNumber ) // lastBlockNumber is probably partially indexed
329+ newRange .headIndexed = false
330+ newRange .headDelimiter = 0
331+ // only shorten range and leave map data; next head render will overwrite it
332+ f .setRange (f .db , f .indexedView , newRange , false )
327333 }
328- return chainView .limitedView (0 )
329334}
330335
331336// reset un-initializes the FilterMaps structure and removes all related data from
@@ -662,15 +667,11 @@ func (f *FilterMaps) mapRowIndex(mapIndex, rowIndex uint32) uint64 {
662667}
663668
664669// getBlockLvPointer returns the starting log value index where the log values
665- // generated by the given block are located. If blockNumber is beyond the current
666- // head then the first unoccupied log value index is returned.
670+ // generated by the given block are located.
667671//
668672// Note that this function assumes that the indexer read lock is being held when
669673// called from outside the indexerLoop goroutine.
670674func (f * FilterMaps ) getBlockLvPointer (blockNumber uint64 ) (uint64 , error ) {
671- if blockNumber >= f .indexedRange .blocks .AfterLast () && f .indexedRange .headIndexed {
672- return f .indexedRange .headDelimiter + 1 , nil
673- }
674675 if lvPointer , ok := f .lvPointerCache .Get (blockNumber ); ok {
675676 return lvPointer , nil
676677 }
0 commit comments