Skip to content

Commit

Permalink
Merge pull request #359 from OffchainLabs/snapshot-db-errors
Browse files Browse the repository at this point in the history
Bubble up errors reading snapshot info from db
  • Loading branch information
PlasmaPower authored Sep 12, 2024
2 parents fb79423 + ad31b75 commit 4e55bfe
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 17 deletions.
10 changes: 4 additions & 6 deletions core/rawdb/accessors_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down
26 changes: 26 additions & 0 deletions core/rawdb/arbitrum_not_found.go
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

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
}
32 changes: 32 additions & 0 deletions core/rawdb/arbitrum_not_found_native.go
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

//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)
}
30 changes: 30 additions & 0 deletions core/rawdb/arbitrum_not_found_wasm.go
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

//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)
}
10 changes: 8 additions & 2 deletions core/state/snapshot/disklayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions core/state/snapshot/disklayer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand All @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand Down
6 changes: 3 additions & 3 deletions core/state/snapshot/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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))
}
}
Expand Down Expand Up @@ -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))
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/state/snapshot/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 4e55bfe

Please sign in to comment.