core/state/snapshot: fix BAD BLOCK error when snapshot is generating (#23635)

* 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 <martin@swende.se>
This commit is contained in:
Ziyuan Zhong 2021-10-20 16:05:27 +08:00 committed by GitHub
parent 0183256e7f
commit 312e02bca9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 13 additions and 1 deletions

View File

@ -560,6 +560,12 @@ func (dl *diskLayer) generate(stats *generatorStats) {
default: default:
} }
if batch.ValueSize() > ethdb.IdealBatchSize || abort != nil { 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. // Flush out the batch anyway no matter it's empty or not.
// It's possible that all the states are recovered and the // It's possible that all the states are recovered and the
// generation indeed makes progress. // generation indeed makes progress.
@ -634,8 +640,14 @@ func (dl *diskLayer) generate(stats *generatorStats) {
stats.storage += common.StorageSize(1 + common.HashLength + dataLen) stats.storage += common.StorageSize(1 + common.HashLength + dataLen)
stats.accounts++ 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 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 return err
} }
// If the iterated account is the contract, create a further loop to // If the iterated account is the contract, create a further loop to