diff --git a/triedb/database.go b/triedb/database.go
index c1e6f9af4e..d891130b68 100644
--- a/triedb/database.go
+++ b/triedb/database.go
@@ -17,8 +17,6 @@
package triedb
import (
- "errors"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
@@ -86,6 +84,21 @@ type backend interface {
// Reader returns a reader for accessing all trie nodes with provided state
// root. An error will be returned if the requested state is not available.
Reader(root common.Hash) (database.Reader, error)
+
+ // These methods have a one-to-one correspondence with methods exposed by
+ // [Database]. Refer to the respective documentation for their behavior.
+ Cap(limit common.StorageSize) error
+ Reference(root, parent common.Hash) error
+ Dereference(root common.Hash) error
+ Recover(target common.Hash) error
+ Recoverable(root common.Hash) (bool, error)
+ Disable() error
+ Enable(root common.Hash) error
+ Journal(root common.Hash) error
+ SetBufferSize(int) error
+ AccountHistory(_ common.Address, start, end uint64) (*pathdb.HistoryStats, error)
+ StorageHistory(_ common.Address, slot common.Hash, start, end uint64) (*pathdb.HistoryStats, error)
+ HistoryRange() (uint64, uint64, error)
}
// Database is the wrapper of the underlying backend which is shared by different
@@ -221,14 +234,10 @@ func (db *Database) InsertPreimage(preimages map[common.Hash][]byte) {
//
// It's only supported by hash-based database and will return an error for others.
func (db *Database) Cap(limit common.StorageSize) error {
- hdb, ok := db.backend.(*hashdb.Database)
- if !ok {
- return errors.New("not supported")
- }
if db.preimages != nil {
db.preimages.commit(false)
}
- return hdb.Cap(limit)
+ return db.backend.Cap(limit)
}
// Reference adds a new reference from a parent node to a child node. This function
@@ -237,23 +246,13 @@ func (db *Database) Cap(limit common.StorageSize) error {
//
// It's only supported by hash-based database and will return an error for others.
func (db *Database) Reference(root common.Hash, parent common.Hash) error {
- hdb, ok := db.backend.(*hashdb.Database)
- if !ok {
- return errors.New("not supported")
- }
- hdb.Reference(root, parent)
- return nil
+ return db.backend.Reference(root, parent)
}
// Dereference removes an existing reference from a root node. It's only
// supported by hash-based database and will return an error for others.
func (db *Database) Dereference(root common.Hash) error {
- hdb, ok := db.backend.(*hashdb.Database)
- if !ok {
- return errors.New("not supported")
- }
- hdb.Dereference(root)
- return nil
+ return db.backend.Dereference(root)
}
// Recover rollbacks the database to a specified historical point. The state is
@@ -261,22 +260,14 @@ func (db *Database) Dereference(root common.Hash) error {
// corresponding trie histories are existent. It's only supported by path-based
// database and will return an error for others.
func (db *Database) Recover(target common.Hash) error {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return errors.New("not supported")
- }
- return pdb.Recover(target)
+ return db.backend.Recover(target)
}
// Recoverable returns the indicator if the specified state is enabled to be
// recovered. It's only supported by path-based database and will return an
// error for others.
func (db *Database) Recoverable(root common.Hash) (bool, error) {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return false, errors.New("not supported")
- }
- return pdb.Recoverable(root), nil
+ return db.backend.Recoverable(root)
}
// Disable deactivates the database and invalidates all available state layers
@@ -285,21 +276,13 @@ func (db *Database) Recoverable(root common.Hash) (bool, error) {
//
// It's only supported by path-based database and will return an error for others.
func (db *Database) Disable() error {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return errors.New("not supported")
- }
- return pdb.Disable()
+ return db.backend.Disable()
}
// Enable activates database and resets the state tree with the provided persistent
// state root once the state sync is finished.
func (db *Database) Enable(root common.Hash) error {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return errors.New("not supported")
- }
- return pdb.Enable(root)
+ return db.backend.Enable(root)
}
// Journal commits an entire diff hierarchy to disk into a single journal entry.
@@ -307,22 +290,14 @@ func (db *Database) Enable(root common.Hash) error {
// flattening everything down (bad for reorgs). It's only supported by path-based
// database and will return an error for others.
func (db *Database) Journal(root common.Hash) error {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return errors.New("not supported")
- }
- return pdb.Journal(root)
+ return db.backend.Journal(root)
}
// SetBufferSize sets the node buffer size to the provided value(in bytes).
// It's only supported by path-based database and will return an error for
// others.
func (db *Database) SetBufferSize(size int) error {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return errors.New("not supported")
- }
- return pdb.SetBufferSize(size)
+ return db.backend.SetBufferSize(size)
}
// IsVerkle returns the indicator if the database is holding a verkle tree.
diff --git a/triedb/hashdb/database.go b/triedb/hashdb/database.go
index 4def10e338..6338d89a8a 100644
--- a/triedb/hashdb/database.go
+++ b/triedb/hashdb/database.go
@@ -217,12 +217,13 @@ func (db *Database) node(hash common.Hash) ([]byte, error) {
// Reference adds a new reference from a parent node to a child node.
// This function is used to add reference between internal trie node
// and external node(e.g. storage trie root), all internal trie nodes
-// are referenced together by database itself.
-func (db *Database) Reference(child common.Hash, parent common.Hash) {
+// are referenced together by database itself. It always returns a nil error.
+func (db *Database) Reference(child common.Hash, parent common.Hash) error {
db.lock.Lock()
defer db.lock.Unlock()
db.reference(child, parent)
+ return nil
}
// reference is the private locked version of Reference.
@@ -250,12 +251,13 @@ func (db *Database) reference(child common.Hash, parent common.Hash) {
db.childrenSize += common.HashLength
}
-// Dereference removes an existing reference from a root node.
-func (db *Database) Dereference(root common.Hash) {
+// Dereference removes an existing reference from a root node. It always returns
+// a nil error.
+func (db *Database) Dereference(root common.Hash) error {
// Sanity check to ensure that the meta-root is not removed
if root == (common.Hash{}) {
log.Error("Attempted to dereference the trie cache meta root")
- return
+ return nil
}
db.lock.Lock()
defer db.lock.Unlock()
@@ -273,6 +275,7 @@ func (db *Database) Dereference(root common.Hash) {
log.Debug("Dereferenced trie from memory database", "nodes", nodes-len(db.dirties), "size", storage-db.dirtiesSize, "time", time.Since(start),
"gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.dirties), "livesize", db.dirtiesSize)
+ return nil
}
// dereference is the private locked version of Dereference.
diff --git a/triedb/hashdb/unsupported.go b/triedb/hashdb/unsupported.go
new file mode 100644
index 0000000000..043603ffcb
--- /dev/null
+++ b/triedb/hashdb/unsupported.go
@@ -0,0 +1,60 @@
+// Copyright 2018 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 hashdb
+
+import (
+ "errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+)
+
+// These methods are implemented by pathdb but not supported by hashdb. They are
+// included for interface parity to avoid triedb having to check concrete types.
+
+var errUnsupported = errors.New("method not supported by hashdb")
+
+// Recover isn't supported and always returns an error.
+func (*Database) Recover(target common.Hash) error { return errUnsupported }
+
+// Recoverable isn't supported and always returns an error.
+func (*Database) Recoverable(root common.Hash) (bool, error) { return false, errUnsupported }
+
+// Disable isn't supported and always returns an error.
+func (*Database) Disable() error { return errUnsupported }
+
+// Enable isn't supported and always returns an error.
+func (*Database) Enable(root common.Hash) error { return errUnsupported }
+
+// Journal isn't supported and always returns an error.
+func (*Database) Journal(root common.Hash) error { return errUnsupported }
+
+// SetBufferSize isn't supported and always returns an error.
+func (*Database) SetBufferSize(int) error { return errUnsupported }
+
+// AccountHistory isn't supported and always returns an error.
+func (*Database) AccountHistory(_ common.Address, start, end uint64) (*pathdb.HistoryStats, error) {
+ return nil, errUnsupported
+}
+
+// StorageHistory isn't supported and always returns an error.
+func (*Database) StorageHistory(_ common.Address, slot common.Hash, start, end uint64) (*pathdb.HistoryStats, error) {
+ return nil, errUnsupported
+}
+
+// HistoryRange isn't supported and always returns an error.
+func (*Database) HistoryRange() (uint64, uint64, error) { return 0, 0, errUnsupported }
diff --git a/triedb/history.go b/triedb/history.go
index f663cdd7c2..769196a800 100644
--- a/triedb/history.go
+++ b/triedb/history.go
@@ -17,8 +17,6 @@
package triedb
import (
- "errors"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/triedb/pathdb"
)
@@ -33,11 +31,7 @@ import (
//
// This function is only supported by path mode database.
func (db *Database) AccountHistory(address common.Address, start, end uint64) (*pathdb.HistoryStats, error) {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return nil, errors.New("not supported")
- }
- return pdb.AccountHistory(address, start, end)
+ return db.backend.AccountHistory(address, start, end)
}
// StorageHistory inspects the storage history within the specified range.
@@ -52,11 +46,7 @@ func (db *Database) AccountHistory(address common.Address, start, end uint64) (*
//
// This function is only supported by path mode database.
func (db *Database) StorageHistory(address common.Address, slot common.Hash, start uint64, end uint64) (*pathdb.HistoryStats, error) {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return nil, errors.New("not supported")
- }
- return pdb.StorageHistory(address, slot, start, end)
+ return db.backend.StorageHistory(address, slot, start, end)
}
// HistoryRange returns the block numbers associated with earliest and latest
@@ -64,9 +54,5 @@ func (db *Database) StorageHistory(address common.Address, slot common.Hash, sta
//
// This function is only supported by path mode database.
func (db *Database) HistoryRange() (uint64, uint64, error) {
- pdb, ok := db.backend.(*pathdb.Database)
- if !ok {
- return 0, 0, errors.New("not supported")
- }
- return pdb.HistoryRange()
+ return db.backend.HistoryRange()
}
diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go
index 31e478117c..6920b91cb6 100644
--- a/triedb/pathdb/database.go
+++ b/triedb/pathdb/database.go
@@ -366,7 +366,7 @@ func (db *Database) Recover(root common.Hash) error {
}
// Short circuit if the target state is not recoverable.
root = types.TrieRootHash(root)
- if !db.Recoverable(root) {
+ if !db.recoverable(root) {
return errStateUnrecoverable
}
// Apply the state histories upon the disk layer in order.
@@ -397,8 +397,15 @@ func (db *Database) Recover(root common.Hash) error {
return nil
}
-// Recoverable returns the indicator if the specified state is recoverable.
-func (db *Database) Recoverable(root common.Hash) bool {
+// Recoverable returns the indicator if the specified state is recoverable. It
+// always returns a nil error.
+func (db *Database) Recoverable(root common.Hash) (bool, error) {
+ return db.recoverable(root), nil
+}
+
+// recoverable is the internal implementation of [Database.Recoverable], which
+// has to return an error for conformity with the triedb.backend interface.
+func (db *Database) recoverable(root common.Hash) bool {
// Ensure the requested state is a known state.
root = types.TrieRootHash(root)
id := rawdb.ReadStateID(db.diskdb, root)
diff --git a/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go
index f667944784..34a6d92a33 100644
--- a/triedb/pathdb/database_test.go
+++ b/triedb/pathdb/database_test.go
@@ -469,7 +469,13 @@ func TestDatabaseRecoverable(t *testing.T) {
{tester.roots[index+1], false},
}
for i, c := range cases {
- result := tester.db.Recoverable(c.root)
+ result, err := tester.db.Recoverable(c.root)
+ if err != nil {
+ // Recoverable() always returns nil so this should never happen. The
+ // signature only includes a returned error to conform with a
+ // triedb-internal interface.
+ t.Fatalf("case: %d, %T.Recoverable() got error %v", i, tester.db, err)
+ }
if result != c.expect {
t.Fatalf("case: %d, unexpected result, want %t, got %t", i, c.expect, result)
}
diff --git a/triedb/pathdb/unsupported.go b/triedb/pathdb/unsupported.go
new file mode 100644
index 0000000000..6816369bc6
--- /dev/null
+++ b/triedb/pathdb/unsupported.go
@@ -0,0 +1,37 @@
+// Copyright 2022 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 pathdb
+
+import (
+ "errors"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// These methods are implemented by hashdb but not supported by pathdb. They are
+// included for interface parity to avoid triedb having to check concrete types.
+
+var errUnsupported = errors.New("method not supported by pathdb")
+
+// Cap isn't supported and always returns an error.
+func (*Database) Cap(limit common.StorageSize) error { return errUnsupported }
+
+// Reference isn't supported and always returns an error.
+func (*Database) Reference(root, parent common.Hash) error { return errUnsupported }
+
+// Dereference isn't supported and always returns an error.
+func (*Database) Dereference(root common.Hash) error { return errUnsupported }