go-ethereum/params/hooks.libevm.go
Arran Schlosberg 5429fd87c8
chore: squash arr4n/libevm into libevm (#7)
* feat: pseudo-generic extra payloads in `params.ChainConfig` and `params.Rules`

* feat: `params.ExtraPayloadGetter` for end-user type safety

* refactor: payloads only available through `params.ExtraPayloadGetter`

* chore: make `libevm/examples/extraparams` a `params` testable example

* doc: `libevm/pseudo` package comments and improved readability

* doc: `params.*Extra*` comments and improved readability

* doc: `params.ExtraPayloadGetter` comments and improved readability

* doc: `params/config.libevm_test.go` comments and improved readability

* refactor: simplify `params.ChainConfig.UnmarshalJSON()`

* refactor: abstract new/nil-pointer creation into `pseudo.Constructor`s

* feat: precompile override via `params.Extras` hooks

* doc: flesh out `PrecompileOverride()` in example

* doc: complete commentary and improve readability

* refactor: `ChainConfig.Hooks()` + `Rules` equivalent

* chore: rename precompiles test file in keeping with geth equivalent

* feat: stateful precompiles + allowlist hooks

The allowlist hooks are included in this commit because they allow for the same functionality as stateful precompiles in `ava-labs/coreth` and `ava-labs/subnet-evm`.

* fix: `StateTransition.canExecuteTransaction()` used `msg.From` instead of `To`

* test: `params.RulesHooks.CanCreateContract` integration

* test: `params.RulesHooks.CanExecuteTransaction` integration

* test: `vm.NewStatefulPrecompile()` integration

* refactor: simplify test of `CanCreateContract`

* refactor: abstract generation of random `Address`/`Hash` values

* doc: full documentation + readability refactoring/renaming

* fix: remove circular dependency in tests
2024-09-10 19:20:32 +01:00

83 lines
3.1 KiB
Go

package params
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/libevm"
)
// ChainConfigHooks are required for all types registered as [Extras] for
// [ChainConfig] payloads.
type ChainConfigHooks interface{}
// TODO(arr4n): given the choice of whether a hook should be defined on a
// ChainConfig or on the Rules, what are the guiding principles? A ChainConfig
// carries the most general information while Rules benefit from "knowing" the
// block number and timestamp. I am leaning towards the default choice being
// on Rules (as it's trivial to copy information from ChainConfig to Rules in
// [Extras.NewRules]) unless the call site only has access to a ChainConfig.
// RulesHooks are required for all types registered as [Extras] for [Rules]
// payloads.
type RulesHooks interface {
RulesAllowlistHooks
// PrecompileOverride signals whether or not the EVM interpreter MUST
// override its treatment of the address when deciding if it is a
// precompiled contract. If PrecompileOverride returns `true` then the
// interpreter will treat the address as a precompile i.f.f the
// [PrecompiledContract] is non-nil. If it returns `false` then the default
// precompile behaviour is honoured.
PrecompileOverride(common.Address) (_ libevm.PrecompiledContract, override bool)
}
// RulesAllowlistHooks are a subset of [RulesHooks] that gate actions, signalled
// by returning a nil (allowed) or non-nil (blocked) error.
type RulesAllowlistHooks interface {
CanCreateContract(*libevm.AddressContext, libevm.StateReader) error
CanExecuteTransaction(from common.Address, to *common.Address, _ libevm.StateReader) error
}
// Hooks returns the hooks registered with [RegisterExtras], or [NOOPHooks] if
// none were registered.
func (c *ChainConfig) Hooks() ChainConfigHooks {
if e := registeredExtras; e != nil {
return e.getter.hooksFromChainConfig(c)
}
return NOOPHooks{}
}
// Hooks returns the hooks registered with [RegisterExtras], or [NOOPHooks] if
// none were registered.
func (r *Rules) Hooks() RulesHooks {
if e := registeredExtras; e != nil {
return e.getter.hooksFromRules(r)
}
return NOOPHooks{}
}
// NOOPHooks implements both [ChainConfigHooks] and [RulesHooks] such that every
// hook is a no-op. This allows it to be returned instead of a nil interface,
// which would otherwise require every usage site to perform a nil check. It can
// also be embedded in structs that only wish to implement a sub-set of hooks.
// Use of a NOOPHooks is equivalent to default Ethereum behaviour.
type NOOPHooks struct{}
var _ interface {
ChainConfigHooks
RulesHooks
} = NOOPHooks{}
// CanExecuteTransaction allows all (otherwise valid) transactions.
func (NOOPHooks) CanExecuteTransaction(_ common.Address, _ *common.Address, _ libevm.StateReader) error {
return nil
}
// CanCreateContract allows all (otherwise valid) contract deployment.
func (NOOPHooks) CanCreateContract(*libevm.AddressContext, libevm.StateReader) error {
return nil
}
// PrecompileOverride instructs the EVM interpreter to use the default
// precompile behaviour.
func (NOOPHooks) PrecompileOverride(common.Address) (libevm.PrecompiledContract, bool) {
return nil, false
}