diff --git a/core/rawdb/accessors_snapshot.go b/core/rawdb/accessors_snapshot.go index 3c82b3f731..8c72c28482 100644 --- a/core/rawdb/accessors_snapshot.go +++ b/core/rawdb/accessors_snapshot.go @@ -73,9 +73,8 @@ func DeleteSnapshotRoot(db ethdb.KeyValueWriter) { } // ReadAccountSnapshot retrieves the snapshot entry of an account trie leaf. -func ReadAccountSnapshot(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, _ := db.Get(accountSnapshotKey(hash)) - return data +func ReadAccountSnapshot(db ethdb.KeyValueReader, hash common.Hash) ([]byte, error) { + return ignoreNotFound(db.Get(accountSnapshotKey(hash))) } // WriteAccountSnapshot stores the snapshot entry of an account trie leaf. @@ -93,9 +92,8 @@ func DeleteAccountSnapshot(db ethdb.KeyValueWriter, hash common.Hash) { } // ReadStorageSnapshot retrieves the snapshot entry of an storage trie leaf. -func ReadStorageSnapshot(db ethdb.KeyValueReader, accountHash, storageHash common.Hash) []byte { - data, _ := db.Get(storageSnapshotKey(accountHash, storageHash)) - return data +func ReadStorageSnapshot(db ethdb.KeyValueReader, accountHash, storageHash common.Hash) ([]byte, error) { + return ignoreNotFound(db.Get(storageSnapshotKey(accountHash, storageHash))) } // WriteStorageSnapshot stores the snapshot entry of an storage trie leaf. diff --git a/core/rawdb/arbitrum_not_found.go b/core/rawdb/arbitrum_not_found.go new file mode 100644 index 0000000000..2c335a4e34 --- /dev/null +++ b/core/rawdb/arbitrum_not_found.go @@ -0,0 +1,26 @@ +// Copyright 2024 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +// Arbitrum specific code to handle database errors + +func ignoreNotFound(blob []byte, err error) ([]byte, error) { + if isDbErrNotFound(err) { + return nil, nil + } + return blob, err +} diff --git a/core/rawdb/arbitrum_not_found_native.go b/core/rawdb/arbitrum_not_found_native.go new file mode 100644 index 0000000000..3543aedc8d --- /dev/null +++ b/core/rawdb/arbitrum_not_found_native.go @@ -0,0 +1,32 @@ +// Copyright 2024 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +//go:build !wasm +// +build !wasm + +package rawdb + +import ( + "errors" + + "github.com/cockroachdb/pebble" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/syndtr/goleveldb/leveldb" +) + +func isDbErrNotFound(err error) bool { + return errors.Is(err, leveldb.ErrNotFound) || errors.Is(err, pebble.ErrNotFound) || errors.Is(err, memorydb.ErrMemorydbNotFound) +} diff --git a/core/rawdb/arbitrum_not_found_wasm.go b/core/rawdb/arbitrum_not_found_wasm.go new file mode 100644 index 0000000000..d49c96848e --- /dev/null +++ b/core/rawdb/arbitrum_not_found_wasm.go @@ -0,0 +1,30 @@ +// Copyright 2024 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +//go:build wasm +// +build wasm + +package rawdb + +import ( + "errors" + + "github.com/ethereum/go-ethereum/ethdb/memorydb" +) + +func isDbErrNotFound(err error) bool { + return errors.Is(err, memorydb.ErrMemorydbNotFound) +} diff --git a/core/state/snapshot/disklayer.go b/core/state/snapshot/disklayer.go index f5518a204c..29a590d24f 100644 --- a/core/state/snapshot/disklayer.go +++ b/core/state/snapshot/disklayer.go @@ -117,7 +117,10 @@ func (dl *diskLayer) AccountRLP(hash common.Hash) ([]byte, error) { return blob, nil } // Cache doesn't contain account, pull from disk and cache for later - blob := rawdb.ReadAccountSnapshot(dl.diskdb, hash) + blob, err := rawdb.ReadAccountSnapshot(dl.diskdb, hash) + if err != nil { + return nil, err + } dl.cache.Set(hash[:], blob) snapshotCleanAccountMissMeter.Mark(1) @@ -157,7 +160,10 @@ func (dl *diskLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro return blob, nil } // Cache doesn't contain storage slot, pull from disk and cache for later - blob := rawdb.ReadStorageSnapshot(dl.diskdb, accountHash, storageHash) + blob, err := rawdb.ReadStorageSnapshot(dl.diskdb, accountHash, storageHash) + if err != nil { + return nil, err + } dl.cache.Set(key, blob) snapshotCleanStorageMissMeter.Mark(1) diff --git a/core/state/snapshot/disklayer_test.go b/core/state/snapshot/disklayer_test.go index 168458c405..5854e8fcd3 100644 --- a/core/state/snapshot/disklayer_test.go +++ b/core/state/snapshot/disklayer_test.go @@ -183,7 +183,7 @@ func TestDiskMerge(t *testing.T) { // assertDatabaseAccount ensures that an account from the database matches the given blob. assertDatabaseAccount := func(account common.Hash, data []byte) { t.Helper() - if blob := rawdb.ReadAccountSnapshot(db, account); !bytes.Equal(blob, data) { + if blob, _ := rawdb.ReadAccountSnapshot(db, account); !bytes.Equal(blob, data) { t.Errorf("account database access (%x) mismatch: have %x, want %x", account, blob, data) } } @@ -197,7 +197,7 @@ func TestDiskMerge(t *testing.T) { // assertDatabaseStorage ensures that a storage slot from the database matches the given blob. assertDatabaseStorage := func(account common.Hash, slot common.Hash, data []byte) { t.Helper() - if blob := rawdb.ReadStorageSnapshot(db, account, slot); !bytes.Equal(blob, data) { + if blob, _ := rawdb.ReadStorageSnapshot(db, account, slot); !bytes.Equal(blob, data) { t.Errorf("storage database access (%x:%x) mismatch: have %x, want %x", account, slot, blob, data) } } @@ -387,7 +387,7 @@ func TestDiskPartialMerge(t *testing.T) { // exist otherwise. assertDatabaseAccount := func(account common.Hash, data []byte) { t.Helper() - blob := rawdb.ReadAccountSnapshot(db, account) + blob, _ := rawdb.ReadAccountSnapshot(db, account) if bytes.Compare(account[:], genMarker) > 0 && blob != nil { t.Fatalf("test %d: post-marker (%x) account database access (%x) succeeded: %x", i, genMarker, account, blob) } @@ -407,7 +407,7 @@ func TestDiskPartialMerge(t *testing.T) { // and does not exist otherwise. assertDatabaseStorage := func(account common.Hash, slot common.Hash, data []byte) { t.Helper() - blob := rawdb.ReadStorageSnapshot(db, account, slot) + blob, _ := rawdb.ReadStorageSnapshot(db, account, slot) if bytes.Compare(append(account[:], slot[:]...), genMarker) > 0 && blob != nil { t.Fatalf("test %d: post-marker (%x) storage database access (%x:%x) succeeded: %x", i, genMarker, account, slot, blob) } diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go index da93ebc875..f1be172fd4 100644 --- a/core/state/snapshot/generate_test.go +++ b/core/state/snapshot/generate_test.go @@ -578,7 +578,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) { root := helper.Commit() // To verify the test: If we now inspect the snap db, there should exist extraneous storage items - if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil { + if data, _ := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil { t.Fatalf("expected snap storage to exist") } snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) @@ -596,7 +596,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) { snap.genAbort <- stop <-stop // If we now inspect the snap db, there should exist no extraneous storage items - if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { + if data, _ := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { t.Fatalf("expected slot to be removed, got %v", string(data)) } } @@ -746,7 +746,7 @@ func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) { snap.genAbort <- stop <-stop // If we now inspect the snap db, there should exist no extraneous storage items - if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { + if data, _ := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { t.Fatalf("expected slot to be removed, got %v", string(data)) } } diff --git a/core/state/snapshot/utils.go b/core/state/snapshot/utils.go index 62f073d2e1..ba94804743 100644 --- a/core/state/snapshot/utils.go +++ b/core/state/snapshot/utils.go @@ -61,7 +61,7 @@ func checkDanglingDiskStorage(chaindb ethdb.KeyValueStore) error { log.Info("Iterating snap storage", "at", fmt.Sprintf("%#x", accKey), "elapsed", common.PrettyDuration(time.Since(start))) lastReport = time.Now() } - if data := rawdb.ReadAccountSnapshot(chaindb, common.BytesToHash(accKey)); len(data) == 0 { + if data, _ := rawdb.ReadAccountSnapshot(chaindb, common.BytesToHash(accKey)); len(data) == 0 { log.Warn("Dangling storage - missing account", "account", fmt.Sprintf("%#x", accKey), "storagekey", fmt.Sprintf("%#x", k)) return fmt.Errorf("dangling snapshot storage account %#x", accKey) } @@ -97,7 +97,7 @@ func CheckJournalAccount(db ethdb.KeyValueStore, hash common.Hash) error { // Look up the disk layer first baseRoot := rawdb.ReadSnapshotRoot(db) fmt.Printf("Disklayer: Root: %x\n", baseRoot) - if data := rawdb.ReadAccountSnapshot(db, hash); data != nil { + if data, _ := rawdb.ReadAccountSnapshot(db, hash); data != nil { account, err := types.FullAccount(data) if err != nil { panic(err)