Skip to content

Commit

Permalink
make backends configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
darioush committed Oct 9, 2024
1 parent e0fbaa5 commit ec7eda1
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 25 deletions.
56 changes: 33 additions & 23 deletions triedb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,14 @@ import (
"github.com/ethereum/go-ethereum/trie/triestate"
"github.com/ethereum/go-ethereum/triedb/database"
"github.com/ethereum/go-ethereum/triedb/hashdb"
"github.com/ethereum/go-ethereum/triedb/pathdb"
)

// Config defines all necessary options for database.
type Config struct {
Preimages bool // Flag whether the preimage of node key is recorded
IsVerkle bool // Flag whether the db is holding a verkle tree
HashDB *hashdb.Config // Configs for hash-based scheme
PathDB *pathdb.Config // Configs for experimental path-based scheme
Preimages bool // Flag whether the preimage of node key is recorded
IsVerkle bool // Flag whether the db is holding a verkle tree
HashDB hashBackender // Configs for hash-based scheme
PathDB pathBackender // Configs for experimental path-based scheme
}

// HashDefaults represents a config for using hash-based scheme with
Expand All @@ -45,6 +44,15 @@ var HashDefaults = &Config{
HashDB: hashdb.Defaults,
}

type Backend backend

type hashBackender interface {
New(diskdb ethdb.Database, resolver hashdb.ChildResolver) database.HashBackend
}
type pathBackender interface {
New(diskdb ethdb.Database) database.PathBackend
}

// backend defines the methods needed to access/update trie nodes in different
// state scheme.
type backend interface {
Expand Down Expand Up @@ -76,6 +84,10 @@ type backend interface {

// Close closes the trie database backend and releases all held resources.
Close() error

// Reader returns a node reader associated with the specific state.
// An error will be returned if the specified state is not available.
Reader(stateRoot common.Hash) (database.Reader, error)
}

// Database is the wrapper of the underlying backend which is shared by different
Expand Down Expand Up @@ -108,7 +120,7 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
log.Crit("Both 'hash' and 'path' mode are configured")
}
if config.PathDB != nil {
db.backend = pathdb.New(diskdb, config.PathDB)
db.backend = config.PathDB.New(diskdb)
} else {
var resolver hashdb.ChildResolver
if config.IsVerkle {
Expand All @@ -117,21 +129,19 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
} else {
resolver = trie.MerkleResolver{}
}
db.backend = hashdb.New(diskdb, config.HashDB, resolver)
if config.HashDB == nil {
// some tests don't set this yet pass a non-nil config
config.HashDB = hashdb.Defaults
}
db.backend = config.HashDB.New(diskdb, resolver)
}
return db
}

// 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.
func (db *Database) Reader(blockRoot common.Hash) (database.Reader, error) {
switch b := db.backend.(type) {
case *hashdb.Database:
return b.Reader(blockRoot)
case *pathdb.Database:
return b.Reader(blockRoot)
}
return nil, errors.New("unknown backend")
return db.backend.Reader(blockRoot)
}

// Update performs a state transition by committing dirty nodes contained in the
Expand Down Expand Up @@ -221,7 +231,7 @@ 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)
hdb, ok := db.backend.(database.HashBackend)
if !ok {
return errors.New("not supported")
}
Expand All @@ -237,7 +247,7 @@ 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)
hdb, ok := db.backend.(database.HashBackend)
if !ok {
return errors.New("not supported")
}
Expand All @@ -248,7 +258,7 @@ func (db *Database) Reference(root common.Hash, parent common.Hash) error {
// 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)
hdb, ok := db.backend.(database.HashBackend)
if !ok {
return errors.New("not supported")
}
Expand All @@ -261,7 +271,7 @@ 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)
pdb, ok := db.backend.(database.PathBackend)
if !ok {
return errors.New("not supported")
}
Expand All @@ -279,7 +289,7 @@ func (db *Database) Recover(target common.Hash) error {
// 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)
pdb, ok := db.backend.(database.PathBackend)
if !ok {
return false, errors.New("not supported")
}
Expand All @@ -292,7 +302,7 @@ 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)
pdb, ok := db.backend.(database.PathBackend)
if !ok {
return errors.New("not supported")
}
Expand All @@ -302,7 +312,7 @@ func (db *Database) Disable() error {
// 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)
pdb, ok := db.backend.(database.PathBackend)
if !ok {
return errors.New("not supported")
}
Expand All @@ -314,7 +324,7 @@ 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)
pdb, ok := db.backend.(database.PathBackend)
if !ok {
return errors.New("not supported")
}
Expand All @@ -325,7 +335,7 @@ func (db *Database) Journal(root common.Hash) error {
// 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)
pdb, ok := db.backend.(database.PathBackend)
if !ok {
return errors.New("not supported")
}
Expand Down
58 changes: 58 additions & 0 deletions triedb/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package database

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
)

// Reader wraps the Node method of a backing trie reader.
Expand Down Expand Up @@ -46,3 +48,59 @@ type Database interface {
// An error will be returned if the specified state is not available.
Reader(stateRoot common.Hash) (Reader, error)
}

// Backend defines the methods needed to access/update trie nodes in different
// state scheme.
type Backend interface {
// Scheme returns the identifier of used storage scheme.
Scheme() string

// Initialized returns an indicator if the state data is already initialized
// according to the state scheme.
Initialized(genesisRoot common.Hash) bool

// Size returns the current storage size of the diff layers on top of the
// disk layer and the storage size of the nodes cached in the disk layer.
//
// For hash scheme, there is no differentiation between diff layer nodes
// and dirty disk layer nodes, so both are merged into the second return.
Size() (common.StorageSize, common.StorageSize)

// Update performs a state transition by committing dirty nodes contained
// in the given set in order to update state from the specified parent to
// the specified root.
//
// The passed in maps(nodes, states) will be retained to avoid copying
// everything. Therefore, these maps must not be changed afterwards.
Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error

// Commit writes all relevant trie nodes belonging to the specified state
// to disk. Report specifies whether logs will be displayed in info level.
Commit(root common.Hash, report bool) error

// Close closes the trie database backend and releases all held resources.
Close() error

// Reader returns a node reader associated with the specific state.
// An error will be returned if the specified state is not available.
Reader(stateRoot common.Hash) (Reader, error)
}

type HashBackend interface {
Backend

Cap(limit common.StorageSize) error
Reference(root common.Hash, parent common.Hash)
Dereference(root common.Hash)
}

type PathBackend interface {
Backend

Recover(root common.Hash, loader triestate.TrieLoader) error
Recoverable(root common.Hash) bool
Disable() error
Enable(root common.Hash) error
Journal(root common.Hash) error
SetBufferSize(size int) error
}
7 changes: 6 additions & 1 deletion triedb/hashdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
"github.com/ethereum/go-ethereum/triedb/database"
)

var (
Expand Down Expand Up @@ -79,6 +80,10 @@ var Defaults = &Config{
CleanCacheSize: 0,
}

func (c *Config) New(diskdb ethdb.Database, resolver ChildResolver) database.HashBackend {
return New(diskdb, c, resolver)
}

// Database is an intermediate write layer between the trie data structures and
// the disk database. The aim is to accumulate trie writes in-memory and only
// periodically flush a couple tries to disk, garbage collecting the remainder.
Expand Down Expand Up @@ -631,7 +636,7 @@ func (db *Database) Scheme() string {

// Reader retrieves a node reader belonging to the given state root.
// An error will be returned if the requested state is not available.
func (db *Database) Reader(root common.Hash) (*reader, error) {
func (db *Database) Reader(root common.Hash) (database.Reader, error) {
if _, err := db.node(root); err != nil {
return nil, fmt.Errorf("state %#x is not available, %v", root, err)
}
Expand Down
7 changes: 6 additions & 1 deletion triedb/pathdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
"github.com/ethereum/go-ethereum/triedb/database"
)

const (
Expand Down Expand Up @@ -92,6 +93,10 @@ type Config struct {
ReadOnly bool // Flag whether the database is opened in read only mode.
}

func (c *Config) New(diskdb ethdb.Database) database.PathBackend {
return New(diskdb, c)
}

// sanitize checks the provided user configurations and changes anything that's
// unreasonable or unworkable.
func (c *Config) sanitize() *Config {
Expand Down Expand Up @@ -208,7 +213,7 @@ func New(diskdb ethdb.Database, config *Config) *Database {
}

// Reader retrieves a layer belonging to the given state root.
func (db *Database) Reader(root common.Hash) (layer, error) {
func (db *Database) Reader(root common.Hash) (database.Reader, error) {
l := db.tree.get(root)
if l == nil {
return nil, fmt.Errorf("state %#x is not available", root)
Expand Down

0 comments on commit ec7eda1

Please sign in to comment.