mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-21 06:04:33 +00:00
* 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
83 lines
2.8 KiB
Go
83 lines
2.8 KiB
Go
package vm
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/params"
|
|
"github.com/holiman/uint256"
|
|
)
|
|
|
|
// evmCallArgs mirrors the parameters of the [EVM] methods Call(), CallCode(),
|
|
// DelegateCall() and StaticCall(). Its fields are identical to those of the
|
|
// parameters, prepended with the receiver name. As {Delegate,Static}Call don't
|
|
// accept a value, they MUST set the respective field to nil.
|
|
//
|
|
// Instantiation can be achieved by merely copying the parameter names, in
|
|
// order, which is trivially achieved with AST manipulation:
|
|
//
|
|
// func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) ... {
|
|
// ...
|
|
// args := &evmCallArgs{evm, caller, addr, input, gas, value}
|
|
type evmCallArgs struct {
|
|
evm *EVM
|
|
caller ContractRef
|
|
addr common.Address
|
|
input []byte
|
|
gas uint64
|
|
value *uint256.Int
|
|
}
|
|
|
|
// run runs the [PrecompiledContract], differentiating between stateful and
|
|
// regular types.
|
|
func (args *evmCallArgs) run(p PrecompiledContract, input []byte) (ret []byte, err error) {
|
|
if p, ok := p.(statefulPrecompile); ok {
|
|
return p.run(args.evm.StateDB, &args.evm.chainRules, args.caller.Address(), args.addr, input)
|
|
}
|
|
return p.Run(input)
|
|
}
|
|
|
|
// PrecompiledStatefulRun is the stateful equivalent of the Run() method of a
|
|
// [PrecompiledContract].
|
|
type PrecompiledStatefulRun func(_ StateDB, _ *params.Rules, caller, self common.Address, input []byte) ([]byte, error)
|
|
|
|
// NewStatefulPrecompile constructs a new PrecompiledContract that can be used
|
|
// via an [EVM] instance but MUST NOT be called directly; a direct call to Run()
|
|
// reserves the right to panic. See other requirements defined in the comments
|
|
// on [PrecompiledContract].
|
|
func NewStatefulPrecompile(run PrecompiledStatefulRun, requiredGas func([]byte) uint64) PrecompiledContract {
|
|
return statefulPrecompile{
|
|
gas: requiredGas,
|
|
run: run,
|
|
}
|
|
}
|
|
|
|
type statefulPrecompile struct {
|
|
gas func([]byte) uint64
|
|
run PrecompiledStatefulRun
|
|
}
|
|
|
|
func (p statefulPrecompile) RequiredGas(input []byte) uint64 {
|
|
return p.gas(input)
|
|
}
|
|
|
|
func (p statefulPrecompile) Run([]byte) ([]byte, error) {
|
|
// https://google.github.io/styleguide/go/best-practices.html#when-to-panic
|
|
// This would indicate an API misuse and would occur in tests, not in
|
|
// production.
|
|
panic(fmt.Sprintf("BUG: call to %T.Run(); MUST call %T", p, p.run))
|
|
}
|
|
|
|
var (
|
|
// These lock in the assumptions made when implementing [evmCallArgs]. If
|
|
// these break then the struct fields SHOULD be changed to match these
|
|
// signatures.
|
|
_ = [](func(ContractRef, common.Address, []byte, uint64, *uint256.Int) ([]byte, uint64, error)){
|
|
(*EVM)(nil).Call,
|
|
(*EVM)(nil).CallCode,
|
|
}
|
|
_ = [](func(ContractRef, common.Address, []byte, uint64) ([]byte, uint64, error)){
|
|
(*EVM)(nil).DelegateCall,
|
|
(*EVM)(nil).StaticCall,
|
|
}
|
|
)
|