Skip to content

Commit

Permalink
evmc: Simplify EVMC initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Aug 7, 2019
1 parent 1aa1499 commit 98be39e
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 67 deletions.
4 changes: 3 additions & 1 deletion cmd/evm/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ func runCmd(ctx *cli.Context) error {
},
}

vm.InitEVMC(runtimeConfig.EVMConfig.EVMInterpreter, runtimeConfig.EVMConfig.EWASMInterpreter)
if runtimeConfig.EVMConfig.EVMInterpreter != "" {
vm.InitEVMCEVM(runtimeConfig.EVMConfig.EVMInterpreter)
}

if cpuProfilePath := ctx.GlobalString(CPUProfileFlag.Name); cpuProfilePath != "" {
f, err := os.Create(cpuProfilePath)
Expand Down
4 changes: 2 additions & 2 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1449,10 +1449,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {

if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) {
cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name)
vm.InitEVMCEwasm(cfg.EWASMInterpreter)
}

if ctx.GlobalIsSet(EVMInterpreterFlag.Name) {
cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name)
vm.InitEVMCEVM(cfg.EVMInterpreter)
}
if ctx.GlobalIsSet(RPCGlobalGasCap.Name) {
cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name))
Expand Down Expand Up @@ -1502,8 +1504,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
cfg.Miner.GasPrice = big.NewInt(1)
}
}

vm.InitEVMC(cfg.EVMInterpreter, cfg.EWASMInterpreter)
}

// SetDashboardConfig applies dashboard related command line flags to the config.
Expand Down
4 changes: 2 additions & 2 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon

if chainConfig.IsEWASM(ctx.BlockNumber) {
if vmConfig.EWASMInterpreter != "" {
evm.interpreters = append(evm.interpreters, NewEVMC(evmc.CapabilityEWASM, vmConfig.EWASMInterpreter, evm))
evm.interpreters = append(evm.interpreters, &EVMC{ewasmModule, evm, evmc.CapabilityEWASM, false})
} else {
panic("The default ewasm interpreter not supported yet.")
}
}

if vmConfig.EVMInterpreter != "" {
evm.interpreters = append(evm.interpreters, NewEVMC(evmc.CapabilityEVM1, vmConfig.EVMInterpreter, evm))
evm.interpreters = append(evm.interpreters, &EVMC{evmModule, evm, evmc.CapabilityEVM1, false})
} else {
evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig))
}
Expand Down
95 changes: 34 additions & 61 deletions core/vm/evmc.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"fmt"
"math/big"
"strings"
"sync"

"github.com/ethereum/evmc/bindings/go/evmc"
"github.com/ethereum/go-ethereum/common"
Expand All @@ -42,77 +41,51 @@ type EVMC struct {
readOnly bool // The readOnly flag (TODO: Try to get rid of it).
}

// EVMCModule represents the loaded EVMC module.
type EVMCModule struct {
instance *evmc.Instance // The EVMC VM instance.
once sync.Once // The mutex protecting EVMC VM instance creation.
}

var (
evmModule EVMCModule
ewasmModule EVMCModule
evmModule *evmc.Instance
ewasmModule *evmc.Instance
)

// InitEVMC initializes the EVMC modules.
func InitEVMC(evmConfig string, ewasmConfig string) {
if evmConfig != "" {
initEVMC(&evmModule, evmc.CapabilityEVM1, evmConfig)
}
if ewasmConfig != "" {
initEVMC(&ewasmModule, evmc.CapabilityEWASM, ewasmConfig)
}
func InitEVMCEVM(config string) {
evmModule = initEVMC(evmc.CapabilityEVM1, config)
}

func initEVMC(module *EVMCModule, cap evmc.Capability, config string) {
module.once.Do(func() {
options := strings.Split(config, ",")
path := options[0]
func InitEVMCEwasm(config string) {
ewasmModule = initEVMC(evmc.CapabilityEWASM, config)
}

if path == "" {
panic("EVMC VM path not provided, set --vm.(evm|ewasm)=/path/to/vm")
}
func initEVMC(cap evmc.Capability, config string) *evmc.Instance {
options := strings.Split(config, ",")
path := options[0]

var err error
module.instance, err = evmc.Load(path)
if err != nil {
panic(err.Error())
}
log.Info("EVMC VM loaded", "name", module.instance.Name(), "version", module.instance.Version(), "path", path)

// Set options before checking capabilities.
for _, option := range options[1:] {
if idx := strings.Index(option, "="); idx >= 0 {
name := option[:idx]
value := option[idx+1:]
err := module.instance.SetOption(name, value)
if err == nil {
log.Info("EVMC VM option set", "name", name, "value", value)
} else {
log.Warn("EVMC VM option setting failed", "name", name, "error", err)
}
}
}
if path == "" {
panic("EVMC VM path not provided, set --vm.(evm|ewasm)=/path/to/vm")
}

if !module.instance.HasCapability(cap) {
panic(fmt.Errorf("The EVMC module %s does not have requested capability %d", path, cap))
instance, err := evmc.Load(path)
if err != nil {
panic(err.Error())
}
log.Info("EVMC VM loaded", "name", instance.Name(), "version", instance.Version(), "path", path)

// Set options before checking capabilities.
for _, option := range options[1:] {
if idx := strings.Index(option, "="); idx >= 0 {
name := option[:idx]
value := option[idx+1:]
err := instance.SetOption(name, value)
if err == nil {
log.Info("EVMC VM option set", "name", name, "value", value)
} else {
log.Warn("EVMC VM option setting failed", "name", name, "error", err)
}
}
})
}

// NewEVMC creates new EVMC-based VM execution context.
func NewEVMC(cap evmc.Capability, config string, env *EVM) *EVMC {
var module *EVMCModule

switch cap {
case evmc.CapabilityEVM1:
module = &evmModule
case evmc.CapabilityEWASM:
module = &ewasmModule
default:
panic(fmt.Errorf("EVMC: Unknown capability %d", cap))
}

return &EVMC{module.instance, env, cap, false}
if !instance.HasCapability(cap) {
panic(fmt.Errorf("The EVMC module %s does not have requested capability %d", path, cap))
}
return instance
}

// hostContext implements evmc.HostContext interface.
Expand Down
7 changes: 6 additions & 1 deletion tests/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ var testVMConfig = func() vm.Config {
flag.StringVar(&vmconfig.EVMInterpreter, utils.EVMInterpreterFlag.Name, utils.EVMInterpreterFlag.Value, utils.EVMInterpreterFlag.Usage)
flag.StringVar(&vmconfig.EWASMInterpreter, utils.EWASMInterpreterFlag.Name, utils.EWASMInterpreterFlag.Value, utils.EWASMInterpreterFlag.Usage)
flag.Parse()
vm.InitEVMC(vmconfig.EVMInterpreter, vmconfig.EWASMInterpreter)
if vmconfig.EVMInterpreter != "" {
vm.InitEVMCEVM(vmconfig.EVMInterpreter)
}
if vmconfig.EWASMInterpreter != "" {
vm.InitEVMCEwasm(vmconfig.EWASMInterpreter)
}
return vmconfig
}()

Expand Down

0 comments on commit 98be39e

Please sign in to comment.