mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +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)
|
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.
|
// equalViews returns true if the two chain views are equivalent.
|
||||||
func equalViews(cv1, cv2 *ChainView) bool {
|
func equalViews(cv1, cv2 *ChainView) bool {
|
||||||
if cv1 == nil || cv2 == nil {
|
if cv1 == nil || cv2 == nil {
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
|
||||||
disabledCh: make(chan struct{}),
|
disabledCh: make(chan struct{}),
|
||||||
exportFileName: config.ExportFileName,
|
exportFileName: config.ExportFileName,
|
||||||
Params: params,
|
Params: params,
|
||||||
|
targetView: initView,
|
||||||
|
indexedView: initView,
|
||||||
indexedRange: filterMapsRange{
|
indexedRange: filterMapsRange{
|
||||||
initialized: initialized,
|
initialized: initialized,
|
||||||
headIndexed: rs.HeadIndexed,
|
headIndexed: rs.HeadIndexed,
|
||||||
|
|
@ -265,16 +267,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
|
||||||
baseRowsCache: lru.NewCache[uint64, [][]uint32](cachedBaseRows),
|
baseRowsCache: lru.NewCache[uint64, [][]uint32](cachedBaseRows),
|
||||||
renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots),
|
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() {
|
if f.indexedRange.hasIndexedBlocks() {
|
||||||
log.Info("Initialized log indexer",
|
log.Info("Initialized log indexer",
|
||||||
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
|
|
@ -303,29 +297,40 @@ func (f *FilterMaps) Stop() {
|
||||||
f.closeWg.Wait()
|
f.closeWg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// initChainView returns a chain view consistent with both the current target
|
// checkRevertRange checks whether the existing index is consistent with the
|
||||||
// view and the current state of the log index as found in the database, based
|
// current indexed view and reverts inconsistent maps if necessary.
|
||||||
// on the last block of stored maps.
|
func (f *FilterMaps) checkRevertRange() {
|
||||||
// Note that the returned view might be shorter than the existing index if
|
if f.indexedRange.maps.Count() == 0 {
|
||||||
// the latest maps are not consistent with targetView.
|
return
|
||||||
func (f *FilterMaps) initChainView(chainView *ChainView) *ChainView {
|
}
|
||||||
mapIndex := f.indexedRange.maps.AfterLast()
|
lastMap := f.indexedRange.maps.Last()
|
||||||
for {
|
lastBlockNumber, lastBlockId, err := f.getLastBlockOfMap(lastMap)
|
||||||
var ok bool
|
if err != nil {
|
||||||
mapIndex, ok = f.lastMapBoundaryBefore(mapIndex)
|
log.Error("Error initializing log index database; resetting log index", "error", err)
|
||||||
if !ok {
|
f.reset()
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
lastBlockNumber, lastBlockId, err := f.getLastBlockOfMap(mapIndex)
|
for lastBlockNumber > f.indexedView.HeadNumber() || f.indexedView.BlockId(lastBlockNumber) != lastBlockId {
|
||||||
if err != nil {
|
// revert last map
|
||||||
log.Error("Could not initialize indexed chain view", "error", err)
|
if f.indexedRange.maps.Count() == 1 {
|
||||||
break
|
f.reset() // reset database if no rendered maps remained
|
||||||
}
|
return
|
||||||
if lastBlockNumber <= chainView.HeadNumber() && chainView.BlockId(lastBlockNumber) == lastBlockId {
|
}
|
||||||
return chainView.limitedView(lastBlockNumber)
|
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
|
// reset un-initializes the FilterMaps structure and removes all related data from
|
||||||
|
|
|
||||||
|
|
@ -473,7 +473,7 @@ func (r *mapRenderer) writeFinishedMaps(pauseCb func() bool) error {
|
||||||
// in order to always ensure continuous block pointers, initialize
|
// in order to always ensure continuous block pointers, initialize
|
||||||
// blockNumber based on the last block of the previous map, then verify
|
// blockNumber based on the last block of the previous map, then verify
|
||||||
// against the first block associated with each rendered map
|
// against the first block associated with each rendered map
|
||||||
lastBlock, _, err := r.f.getLastBlockOfMap(r.finished.First()-1)
|
lastBlock, _, err := r.f.getLastBlockOfMap(r.finished.First() - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get last block of previous map %d: %v", r.finished.First()-1, err)
|
return fmt.Errorf("failed to get last block of previous map %d: %v", r.finished.First()-1, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue