go-ethereum/libevm/stateconf/conf.go
Austin Larson 9b97d60230
feat: triedb.Database.Update options via statedb.Commit (#190)
## Why this should be merged

To allow more thorough handling of duplicate state roots (or any other
info other users would like), additional information can be provided to
a call of `statedb.Commit`. This change allows arbitrary types to be
sent to `triedb` as well as the `SnapshotTree`. However, this is a
breaking change for those using the functionality already, since the
snapshot commit option is wrapped with another call.

## How this works

See the edited libevm test for usage.

## How this was tested

Edited test case to include `TrieDBUpdateOption` and ensures the payload
is sent.
2025-06-18 17:54:37 +00:00

115 lines
4.5 KiB
Go

// Copyright 2024 the libevm authors.
//
// The libevm additions to go-ethereum are free software: you can redistribute
// them and/or modify them 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 libevm additions are distributed in the hope that they 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 stateconf configures state management.
package stateconf
import (
"github.com/ava-labs/libevm/common"
"github.com/ava-labs/libevm/libevm/options"
)
// A StateDBCommitOption configures the behaviour of state.StateDB.Commit()
type StateDBCommitOption = options.Option[stateDBCommitConfig]
type stateDBCommitConfig struct {
snapshotOpts []SnapshotUpdateOption
triedbOpts []TrieDBUpdateOption
}
// WithSnapshotUpdateOpts returns a StateDBCommitOption carrying a list of
// SnapshotUpdateOptions.
// If multiple such options are used, only the last will be applied as they overwrite each other.
func WithSnapshotUpdateOpts(opts ...SnapshotUpdateOption) StateDBCommitOption {
return options.Func[stateDBCommitConfig](func(c *stateDBCommitConfig) {
c.snapshotOpts = opts
})
}
// ExtractSnapshotUpdateOpts returns the list of SnapshotUpdateOptions carried
// by the provided slice of StateDBCommitOption.
func ExtractSnapshotUpdateOpts(opts ...StateDBCommitOption) []SnapshotUpdateOption {
return options.As(opts...).snapshotOpts
}
// WithTrieDBUpdateOpts returns a StateDBCommitOption carrying a list of
// TrieDBUpdateOptions. If multiple such options are used, only the last will be
// applied as they overwrite each other.
func WithTrieDBUpdateOpts(opts ...TrieDBUpdateOption) StateDBCommitOption {
return options.Func[stateDBCommitConfig](func(c *stateDBCommitConfig) {
c.triedbOpts = opts
})
}
// ExtractTrieDBUpdateOpts returns the list of TrieDBUpdateOptions carried by
// the provided slice of StateDBCommitOption.
func ExtractTrieDBUpdateOpts(opts ...StateDBCommitOption) []TrieDBUpdateOption {
return options.As(opts...).triedbOpts
}
// A SnapshotUpdateOption configures the behaviour of
// state.SnapshotTree.Update() implementations. This will be removed along with
// state.SnapshotTree.
type SnapshotUpdateOption = options.Option[snapshotUpdateConfig]
type snapshotUpdateConfig struct {
payload any
}
// WithSnapshotUpdatePayload returns a SnapshotUpdateOption carrying an arbitrary
// payload. It acts only as a carrier to exploit existing function plumbing and
// the effect on behaviour is left to the implementation receiving it.
func WithSnapshotUpdatePayload(p any) SnapshotUpdateOption {
return options.Func[snapshotUpdateConfig](func(c *snapshotUpdateConfig) {
c.payload = p
})
}
// ExtractSnapshotUpdatePayload returns the payload carried by a [WithSnapshotUpdatePayload]
// option. Only one such option can be used at once; behaviour is otherwise
// undefined.
func ExtractSnapshotUpdatePayload(opts ...SnapshotUpdateOption) any {
return options.As(opts...).payload
}
// A TrieDBUpdateOption configures the behaviour of triedb.Database.Update() implementations.
type TrieDBUpdateOption = options.Option[triedbUpdateConfig]
type triedbUpdateConfig struct {
parentBlockHash *common.Hash
currentBlockHash *common.Hash
}
// WithTrieDBUpdatePayload returns a TrieDBUpdateOption carrying two block hashes.
// It acts only as a carrier to exploit existing function plumbing and
// the effect on behaviour is left to the implementation receiving it.
func WithTrieDBUpdatePayload(parent common.Hash, current common.Hash) TrieDBUpdateOption {
return options.Func[triedbUpdateConfig](func(c *triedbUpdateConfig) {
c.parentBlockHash = &parent
c.currentBlockHash = &current
})
}
// ExtractTrieDBUpdatePayload returns the payload carried by a [WithTrieDBUpdatePayload]
// option. Only one such option can be used at once; behaviour is otherwise
// undefined.
func ExtractTrieDBUpdatePayload(opts ...TrieDBUpdateOption) (common.Hash, common.Hash, bool) {
conf := options.As(opts...)
if conf.parentBlockHash == nil && conf.currentBlockHash == nil {
return common.Hash{}, common.Hash{}, false
}
return *conf.parentBlockHash, *conf.currentBlockHash, true
}