diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 1f2df1212458..2a8420e56a8b 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -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) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 1b88bc413f34..508325e63801 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -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)) @@ -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. diff --git a/core/vm/evm.go b/core/vm/evm.go index 8c3febb287df..0ce1549ea480 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -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)) } diff --git a/core/vm/evmc.go b/core/vm/evmc.go index 085a08c1232c..6550c8e8f6d9 100644 --- a/core/vm/evmc.go +++ b/core/vm/evmc.go @@ -24,7 +24,6 @@ import ( "fmt" "math/big" "strings" - "sync" "github.com/ethereum/evmc/bindings/go/evmc" "github.com/ethereum/go-ethereum/common" @@ -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. diff --git a/tests/state_test.go b/tests/state_test.go index 8507f323f410..8a3b35c5efa2 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -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 }()