mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 21:54:30 +00:00
refactor: abstract options package (#74)
## Why this should be merged Simplifies the creation and application of variadic options; this is also applicable to many of my other WIP branches (e.g. `snapshot`). ## How this works See `libevm/options/options.go`, which is very simple. ## How this was tested Existing tests of `vm.PrecompileEnvironment.Call()`, which itself uses refactored options.
This commit is contained in:
parent
594abd9f42
commit
44068c8bab
3 changed files with 61 additions and 23 deletions
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/ava-labs/libevm/common"
|
||||
"github.com/ava-labs/libevm/core/types"
|
||||
"github.com/ava-labs/libevm/libevm"
|
||||
"github.com/ava-labs/libevm/libevm/options"
|
||||
"github.com/ava-labs/libevm/params"
|
||||
)
|
||||
|
||||
|
|
@ -105,20 +106,14 @@ func (e *environment) callContract(typ CallType, addr common.Address, input []by
|
|||
}
|
||||
|
||||
var caller ContractRef = e.self
|
||||
for _, o := range opts {
|
||||
switch o := o.(type) {
|
||||
case callOptUNSAFECallerAddressProxy:
|
||||
// Note that, in addition to being unsafe, this breaks an EVM
|
||||
// assumption that the caller ContractRef is always a *Contract.
|
||||
caller = AccountRef(e.self.CallerAddress)
|
||||
if e.callType == DelegateCall {
|
||||
// self was created with AsDelegate(), which means that
|
||||
// CallerAddress was inherited.
|
||||
caller = AccountRef(e.self.Address())
|
||||
}
|
||||
case nil:
|
||||
default:
|
||||
return nil, gas, fmt.Errorf("unsupported option %T", o)
|
||||
if options.As[callConfig](opts...).unsafeCallerAddressProxying {
|
||||
// Note that, in addition to being unsafe, this breaks an EVM
|
||||
// assumption that the caller ContractRef is always a *Contract.
|
||||
caller = AccountRef(e.self.CallerAddress)
|
||||
if e.callType == DelegateCall {
|
||||
// self was created with AsDelegate(), which means that
|
||||
// CallerAddress was inherited.
|
||||
caller = AccountRef(e.self.Address())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,15 @@
|
|||
|
||||
package vm
|
||||
|
||||
// A CallOption modifies the default behaviour of a contract call.
|
||||
type CallOption interface {
|
||||
libevmCallOption() // noop to only allow internally defined options
|
||||
import "github.com/ava-labs/libevm/libevm/options"
|
||||
|
||||
type callConfig struct {
|
||||
unsafeCallerAddressProxying bool
|
||||
}
|
||||
|
||||
// A CallOption modifies the default behaviour of a contract call.
|
||||
type CallOption = options.Option[callConfig]
|
||||
|
||||
// WithUNSAFECallerAddressProxying results in precompiles making contract calls
|
||||
// specifying their own caller's address as the caller. This is NOT SAFE for
|
||||
// regular use as callers of the precompile may not understand that they are
|
||||
|
|
@ -29,10 +33,7 @@ type CallOption interface {
|
|||
// Deprecated: this option MUST NOT be used other than to allow migration to
|
||||
// libevm when backwards compatibility is required.
|
||||
func WithUNSAFECallerAddressProxying() CallOption {
|
||||
return callOptUNSAFECallerAddressProxy{}
|
||||
return options.Func[callConfig](func(c *callConfig) {
|
||||
c.unsafeCallerAddressProxying = true
|
||||
})
|
||||
}
|
||||
|
||||
// Deprecated: see [WithUNSAFECallerAddressProxying].
|
||||
type callOptUNSAFECallerAddressProxy struct{}
|
||||
|
||||
func (callOptUNSAFECallerAddressProxy) libevmCallOption() {}
|
||||
|
|
|
|||
42
libevm/options/options.go
Normal file
42
libevm/options/options.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// 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 options provides a generic mechanism for defining configuration of
|
||||
// arbitrary types.
|
||||
package options
|
||||
|
||||
// An Option configures values of arbitrary type.
|
||||
type Option[T any] interface {
|
||||
Configure(*T)
|
||||
}
|
||||
|
||||
// As applies Options to a zero-value T, which it then returns.
|
||||
func As[T any](opts ...Option[T]) *T {
|
||||
var t T
|
||||
for _, o := range opts {
|
||||
o.Configure(&t)
|
||||
}
|
||||
return &t
|
||||
}
|
||||
|
||||
// A Func converts a function into an [Option], using itself as the Configure
|
||||
// method.
|
||||
type Func[T any] func(*T)
|
||||
|
||||
var _ Option[struct{}] = Func[struct{}](nil)
|
||||
|
||||
// Configure implements the [Option] interface.
|
||||
func (f Func[T]) Configure(t *T) { f(t) }
|
||||
Loading…
Reference in a new issue