mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
core/filtermaps: safely revert reorged log index during init
This commit is contained in:
parent
6ed74f0e60
commit
18b3664bd1
3 changed files with 37 additions and 40 deletions
|
|
@ -135,14 +135,6 @@ func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
|
|||
return common.NewRange(0, sharedLen)
|
||||
}
|
||||
|
||||
// limitedView returns a new chain view that is a truncated version of the parent view.
|
||||
func (cv *ChainView) limitedView(newHead uint64) *ChainView {
|
||||
if newHead >= cv.headNumber {
|
||||
return cv
|
||||
}
|
||||
return NewChainView(cv.chain, newHead, cv.BlockHash(newHead))
|
||||
}
|
||||
|
||||
// equalViews returns true if the two chain views are equivalent.
|
||||
func equalViews(cv1, cv2 *ChainView) bool {
|
||||
if cv1 == nil || cv2 == nil {
|
||||
|
|
|
|||
|
|
@ -244,6 +244,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
|
|||
disabledCh: make(chan struct{}),
|
||||
exportFileName: config.ExportFileName,
|
||||
Params: params,
|
||||
targetView: initView,
|
||||
indexedView: initView,
|
||||
indexedRange: filterMapsRange{
|
||||
initialized: initialized,
|
||||
headIndexed: rs.HeadIndexed,
|
||||
|
|
@ -265,16 +267,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
|
|||
baseRowsCache: lru.NewCache[uint64, [][]uint32](cachedBaseRows),
|
||||
renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots),
|
||||
}
|
||||
f.checkRevertRange() // revert maps that are inconsistent with the current chain view
|
||||
|
||||
// Set initial indexer target.
|
||||
f.targetView = initView
|
||||
if f.indexedRange.initialized {
|
||||
f.indexedView = f.initChainView(f.targetView)
|
||||
f.indexedRange.headIndexed = f.indexedRange.blocks.AfterLast() == f.indexedView.HeadNumber()+1
|
||||
if !f.indexedRange.headIndexed {
|
||||
f.indexedRange.headDelimiter = 0
|
||||
}
|
||||
}
|
||||
if f.indexedRange.hasIndexedBlocks() {
|
||||
log.Info("Initialized log indexer",
|
||||
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||
|
|
@ -303,29 +297,40 @@ func (f *FilterMaps) Stop() {
|
|||
f.closeWg.Wait()
|
||||
}
|
||||
|
||||
// initChainView returns a chain view consistent with both the current target
|
||||
// view and the current state of the log index as found in the database, based
|
||||
// on the last block of stored maps.
|
||||
// Note that the returned view might be shorter than the existing index if
|
||||
// the latest maps are not consistent with targetView.
|
||||
func (f *FilterMaps) initChainView(chainView *ChainView) *ChainView {
|
||||
mapIndex := f.indexedRange.maps.AfterLast()
|
||||
for {
|
||||
var ok bool
|
||||
mapIndex, ok = f.lastMapBoundaryBefore(mapIndex)
|
||||
if !ok {
|
||||
break
|
||||
// checkRevertRange checks whether the existing index is consistent with the
|
||||
// current indexed view and reverts inconsistent maps if necessary.
|
||||
func (f *FilterMaps) checkRevertRange() {
|
||||
if f.indexedRange.maps.Count() == 0 {
|
||||
return
|
||||
}
|
||||
lastBlockNumber, lastBlockId, err := f.getLastBlockOfMap(mapIndex)
|
||||
lastMap := f.indexedRange.maps.Last()
|
||||
lastBlockNumber, lastBlockId, err := f.getLastBlockOfMap(lastMap)
|
||||
if err != nil {
|
||||
log.Error("Could not initialize indexed chain view", "error", err)
|
||||
break
|
||||
log.Error("Error initializing log index database; resetting log index", "error", err)
|
||||
f.reset()
|
||||
return
|
||||
}
|
||||
if lastBlockNumber <= chainView.HeadNumber() && chainView.BlockId(lastBlockNumber) == lastBlockId {
|
||||
return chainView.limitedView(lastBlockNumber)
|
||||
for lastBlockNumber > f.indexedView.HeadNumber() || f.indexedView.BlockId(lastBlockNumber) != lastBlockId {
|
||||
// revert last map
|
||||
if f.indexedRange.maps.Count() == 1 {
|
||||
f.reset() // reset database if no rendered maps remained
|
||||
return
|
||||
}
|
||||
lastMap--
|
||||
newRange := f.indexedRange
|
||||
newRange.maps.SetLast(lastMap)
|
||||
lastBlockNumber, lastBlockId, err = f.getLastBlockOfMap(lastMap)
|
||||
if err != nil {
|
||||
log.Error("Error initializing log index database; resetting log index", "error", err)
|
||||
f.reset()
|
||||
return
|
||||
}
|
||||
newRange.blocks.SetAfterLast(lastBlockNumber) // lastBlockNumber is probably partially indexed
|
||||
newRange.headIndexed = false
|
||||
newRange.headDelimiter = 0
|
||||
// only shorten range and leave map data; next head render will overwrite it
|
||||
f.setRange(f.db, f.indexedView, newRange, false)
|
||||
}
|
||||
return chainView.limitedView(0)
|
||||
}
|
||||
|
||||
// reset un-initializes the FilterMaps structure and removes all related data from
|
||||
|
|
|
|||
Loading…
Reference in a new issue