core/state/snapshot: check difflayer staleness early (#27255)

This PR adds a staleness-check to AccountRLP, before checking the bloom-filter and potentially going directly into the disklayer.

---------

Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
This commit is contained in:
Martin Holst Swende 2023-05-16 09:18:39 -04:00 committed by GitHub
parent d46f69dc7a
commit eb83e7c540
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 1 deletions

View File

@ -292,9 +292,14 @@ func (dl *diffLayer) Account(hash common.Hash) (*Account, error) {
// //
// Note the returned account is not a copy, please don't modify it. // Note the returned account is not a copy, please don't modify it.
func (dl *diffLayer) AccountRLP(hash common.Hash) ([]byte, error) { func (dl *diffLayer) AccountRLP(hash common.Hash) ([]byte, error) {
dl.lock.RLock()
// Check staleness before reaching further.
if dl.Stale() {
dl.lock.RUnlock()
return nil, ErrSnapshotStale
}
// Check the bloom filter first whether there's even a point in reaching into // Check the bloom filter first whether there's even a point in reaching into
// all the maps in all the layers below // all the maps in all the layers below
dl.lock.RLock()
hit := dl.diffed.Contains(accountBloomHasher(hash)) hit := dl.diffed.Contains(accountBloomHasher(hash))
if !hit { if !hit {
hit = dl.diffed.Contains(destructBloomHasher(hash)) hit = dl.diffed.Contains(destructBloomHasher(hash))
@ -361,6 +366,11 @@ func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
// Check the bloom filter first whether there's even a point in reaching into // Check the bloom filter first whether there's even a point in reaching into
// all the maps in all the layers below // all the maps in all the layers below
dl.lock.RLock() dl.lock.RLock()
// Check staleness before reaching further.
if dl.Stale() {
dl.lock.RUnlock()
return nil, ErrSnapshotStale
}
hit := dl.diffed.Contains(storageBloomHasher{accountHash, storageHash}) hit := dl.diffed.Contains(storageBloomHasher{accountHash, storageHash})
if !hit { if !hit {
hit = dl.diffed.Contains(destructBloomHasher(accountHash)) hit = dl.diffed.Contains(destructBloomHasher(accountHash))

View File

@ -185,6 +185,10 @@ func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) {
// be returned with junk data. This version of the test retains the bottom diff // be returned with junk data. This version of the test retains the bottom diff
// layer to check the usual mode of operation where the accumulator is retained. // layer to check the usual mode of operation where the accumulator is retained.
func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) { func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) {
// Un-commenting this triggers the bloom set to be deterministic. The values below
// were used to trigger the flaw described in https://github.com/ethereum/go-ethereum/issues/27254.
// bloomDestructHasherOffset, bloomAccountHasherOffset, bloomStorageHasherOffset = 14, 24, 5
// Create an empty base layer and a snapshot tree out of it // Create an empty base layer and a snapshot tree out of it
base := &diskLayer{ base := &diskLayer{
diskdb: rawdb.NewMemoryDatabase(), diskdb: rawdb.NewMemoryDatabase(),