From d8a00938a7e370a9aea4ac439148809f6b703aa3 Mon Sep 17 00:00:00 2001 From: zzyalbert Date: Thu, 23 Sep 2021 19:39:23 +0800 Subject: [PATCH 1/3] core/state/snapshot: fix BAD BLOCK error when snapshot is generating --- core/state/snapshot/generate.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index 3e11b4ac6b94..59f2da3689f3 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -560,6 +560,15 @@ func (dl *diskLayer) generate(stats *generatorStats) { default: } if batch.ValueSize() > ethdb.IdealBatchSize || abort != nil { + // currentLocation may lost its `storageHash` part, when currentLocation + // and dl.genMarker has the same `accountHash` part and abort generation + // before this function is firstly called in onAccount function, + // which will result in ignoring updating the storage snapshot of + // that `accountHash`, thus the value in the cache of diskLayer will be an old one. + if bytes.Compare(currentLocation, dl.genMarker) < 0 { + currentLocation = 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. From 3f98d0e76e3e8014482b58b2fa2ae84899cc49bc Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 19 Oct 2021 21:39:04 +0200 Subject: [PATCH 2/3] core/state/snapshot: alternative fix for the snapshot generator --- core/state/snapshot/generate.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index 59f2da3689f3..198668aefe88 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -560,13 +560,10 @@ func (dl *diskLayer) generate(stats *generatorStats) { default: } if batch.ValueSize() > ethdb.IdealBatchSize || abort != nil { - // currentLocation may lost its `storageHash` part, when currentLocation - // and dl.genMarker has the same `accountHash` part and abort generation - // before this function is firstly called in onAccount function, - // which will result in ignoring updating the storage snapshot of - // that `accountHash`, thus the value in the cache of diskLayer will be an old one. if bytes.Compare(currentLocation, dl.genMarker) < 0 { - currentLocation = dl.genMarker + 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. @@ -644,7 +641,11 @@ func (dl *diskLayer) generate(stats *generatorStats) { stats.accounts++ } // If we've exceeded our batch allowance or termination was requested, flush to disk - if err := checkAndFlush(accountHash[:]); err != nil { + marker := accountHash[:] + if accMarker != nil && bytes.Equal(accountHash[:], accMarker) && len(dl.genMarker) > common.HashLength { + marker = append(marker, dl.genMarker[common.HashLength:]...) + } + if err := checkAndFlush(marker); err != nil { return err } // If the iterated account is the contract, create a further loop to From 7432f665b546f2a8691ea9e918e193a43a84c97a Mon Sep 17 00:00:00 2001 From: zzyalbert Date: Wed, 20 Oct 2021 11:11:36 +0800 Subject: [PATCH 3/3] add comments and minor update --- core/state/snapshot/generate.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index 198668aefe88..a4373d8bcdab 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -640,11 +640,13 @@ func (dl *diskLayer) generate(stats *generatorStats) { stats.storage += common.StorageSize(1 + common.HashLength + dataLen) stats.accounts++ } - // If we've exceeded our batch allowance or termination was requested, flush to disk marker := accountHash[:] - if accMarker != nil && bytes.Equal(accountHash[:], accMarker) && len(dl.genMarker) > common.HashLength { - marker = append(marker, dl.genMarker[common.HashLength:]...) + // 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(marker); err != nil { return err }