-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: `Code.Run()` implementation with hard-coded params * feat: `runopts` package to configure `Code.Run()` calls
- Loading branch information
1 parent
a1e570a
commit aa08c2b
Showing
4 changed files
with
116 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package specialops | ||
|
||
import ( | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/vm" | ||
"github.com/ethereum/go-ethereum/params" | ||
"github.com/solidifylabs/specialops/runopts" | ||
) | ||
|
||
// Run calls c.Compile() and runs the compiled bytecode on a freshly | ||
// instantiated vm.EVMInterpreter. The default EVM parameters MUST NOT be | ||
// considered stable: they are currently such that code runs on the Cancun fork | ||
// with no state DB. | ||
func (c Code) Run(callData []byte, opts ...runopts.Option) ([]byte, error) { | ||
compiled, err := c.Compile() | ||
if err != nil { | ||
return nil, fmt.Errorf("%T.Compile(): %v", c, err) | ||
} | ||
return runBytecode(compiled, callData, opts...) | ||
} | ||
|
||
func runBytecode(compiled, callData []byte, opts ...runopts.Option) ([]byte, error) { | ||
cfg, err := newRunConfig(opts...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
interp := vm.NewEVM( | ||
cfg.BlockCtx, | ||
cfg.TxCtx, | ||
cfg.StateDB, | ||
cfg.ChainConfig, | ||
cfg.VMConfig, | ||
).Interpreter() | ||
|
||
cc := &vm.Contract{ | ||
Code: compiled, | ||
Gas: 30e6, | ||
} | ||
|
||
out, err := interp.Run(cc, callData, cfg.ReadOnly) | ||
if err != nil { | ||
return nil, fmt.Errorf("%T.Run([%T.Compile()], [callData], readOnly=%t): %v", interp, Code{}, cfg.ReadOnly, err) | ||
} | ||
return out, nil | ||
} | ||
|
||
func newRunConfig(opts ...runopts.Option) (*runopts.Configuration, error) { | ||
cfg := &runopts.Configuration{ | ||
BlockCtx: vm.BlockContext{ | ||
BlockNumber: big.NewInt(0), | ||
Random: &common.Hash{}, // post merge | ||
}, | ||
ChainConfig: ¶ms.ChainConfig{ | ||
LondonBlock: big.NewInt(0), | ||
CancunTime: new(uint64), | ||
}, | ||
} | ||
for _, o := range opts { | ||
if err := o.Apply(cfg); err != nil { | ||
return nil, fmt.Errorf("runopts.Option[%T].Apply(): %v", o, err) | ||
} | ||
} | ||
return cfg, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Package runopts provides configuration options for specialops.Code.Run(). | ||
package runopts | ||
|
||
import ( | ||
"github.com/ethereum/go-ethereum/core/vm" | ||
"github.com/ethereum/go-ethereum/params" | ||
) | ||
|
||
// A Configuration carries all values that can be modified to configure a call | ||
// to specialops.Code.Run(). It is intially set by Run() and then passed to all | ||
// Options to be modified. | ||
type Configuration struct { | ||
// vm.NewEVM() | ||
BlockCtx vm.BlockContext | ||
TxCtx vm.TxContext | ||
StateDB vm.StateDB | ||
ChainConfig *params.ChainConfig | ||
VMConfig vm.Config | ||
// EVMInterpreter.Run() | ||
ReadOnly bool // static call | ||
} | ||
|
||
// An Option modifies a Configuration. | ||
type Option interface { | ||
Apply(*Configuration) error | ||
} | ||
|
||
// A FuncOption converts any function into an Option by calling itself as | ||
// Apply(). | ||
type FuncOption func(*Configuration) error | ||
|
||
// Apply returns f(c). | ||
func (f FuncOption) Apply(c *Configuration) error { | ||
return f(c) | ||
} | ||
|
||
// ReadOnly sets the `readOnly` argument to true when calling | ||
// EVMInterpreter.Run(), equivalent to a static call. | ||
func ReadOnly() Option { | ||
return FuncOption(func(c *Configuration) error { | ||
c.ReadOnly = true | ||
return nil | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters