From 354d0a4dab2597b90563d6b5638262f4205fac1a Mon Sep 17 00:00:00 2001 From: "John.h" <25290445+Mercybudda@users.noreply.github.com> Date: Mon, 1 Nov 2021 20:34:58 +0800 Subject: [PATCH] core/state/snapshot: fix BAD BLOCK error when snapshot is generating (#23635) (#485) * core/state/snapshot: fix BAD BLOCK error when snapshot is generating * core/state/snapshot: alternative fix for the snapshot generator * add comments and minor update Co-authored-by: Martin Holst Swende * core/state/snapshot: fix BAD BLOCK error when snapshot is generating * core/state/snapshot: alternative fix for the snapshot generator * add comments and minor update Co-authored-by: Martin Holst Swende Co-authored-by: Ziyuan Zhong Co-authored-by: Martin Holst Swende --- core/state/snapshot/generate.go | 14 +++++++++++++- eth/downloader/downloader.go | 4 ++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index 7e29e51b21..a9f89b20b5 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -560,6 +560,12 @@ func (dl *diskLayer) generate(stats *generatorStats) { default: } if batch.ValueSize() > ethdb.IdealBatchSize || abort != nil { + if bytes.Compare(currentLocation, dl.genMarker) < 0 { + log.Error("Snapshot generator went backwards", + "currentLocation", fmt.Sprintf("%x", currentLocation), + "genMarker", fmt.Sprintf("%x", dl.genMarker)) + } + // Flush out the batch anyway no matter it's empty or not. // It's possible that all the states are recovered and the // generation indeed makes progress. @@ -634,8 +640,14 @@ func (dl *diskLayer) generate(stats *generatorStats) { stats.storage += common.StorageSize(1 + common.HashLength + dataLen) stats.accounts++ } + marker := accountHash[:] + // If the snap generation goes here after interrupted, genMarker may go backward + // when last genMarker is consisted of accountHash and storageHash + if accMarker != nil && bytes.Equal(marker, accMarker) && len(dl.genMarker) > common.HashLength { + marker = dl.genMarker[:] + } // If we've exceeded our batch allowance or termination was requested, flush to disk - if err := checkAndFlush(accountHash[:]); err != nil { + if err := checkAndFlush(marker); err != nil { return err } // If the iterated account is the contract, create a further loop to diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 55be200d59..5da80c9d3a 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -1028,8 +1028,8 @@ func (d *Downloader) findAncestorBinarySearch(p *peerConnection, mode SyncMode, } header := d.lightchain.GetHeaderByHash(h) // Independent of sync mode, header surely exists if header == nil { - p.log.Error("header not found", "number", header.Number, "hash", header.Hash(), "request", check) - return 0, fmt.Errorf("%w: header no found (%d)", errBadPeer, header.Number) + p.log.Error("header not found", "hash", h, "request", check) + return 0, fmt.Errorf("%w: header no found (%s)", errBadPeer, h) } if header.Number.Uint64() != check { p.log.Warn("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check)