diff options
author | Guillaume Ballet <gballet@gmail.com> | 2018-07-25 20:56:39 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-25 20:56:39 +0800 |
commit | 7abedf9bbb725da8d610762d051af43085be1cda (patch) | |
tree | 7640e475868c575115cbcfde8bddb7b4484eee20 /core/vm/interpreter.go | |
parent | 27a278e6e35836999ac8e4d9a19c406407db8ae5 (diff) | |
download | dexon-7abedf9bbb725da8d610762d051af43085be1cda.tar.gz dexon-7abedf9bbb725da8d610762d051af43085be1cda.tar.zst dexon-7abedf9bbb725da8d610762d051af43085be1cda.zip |
core/vm: support for multiple interpreters (#17093)
- Define an Interpreter interface
- One contract can call contracts from other interpreter types.
- Pass the interpreter to the operands instead of the evm.
This is meant to prevent type assertions in operands.
Diffstat (limited to 'core/vm/interpreter.go')
-rw-r--r-- | core/vm/interpreter.go | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 0d6038cbb..1e9202424 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -45,7 +45,30 @@ type Config struct { // passed environment to query external sources for state information. // The Interpreter will run the byte code VM based on the passed // configuration. -type Interpreter struct { +type Interpreter interface { + // Run loops and evaluates the contract's code with the given input data and returns + // the return byte-slice and an error if one occurred. + Run(contract *Contract, input []byte) ([]byte, error) + // CanRun tells if the contract, passed as an argument, can be + // run by the current interpreter. This is meant so that the + // caller can do something like: + // + // ```golang + // for _, interpreter := range interpreters { + // if interpreter.CanRun(contract.code) { + // interpreter.Run(contract.code, input) + // } + // } + // ``` + CanRun([]byte) bool + // IsReadOnly reports if the interpreter is in read only mode. + IsReadOnly() bool + // SetReadOnly sets (or unsets) read only mode in the interpreter. + SetReadOnly(bool) +} + +// EVMInterpreter represents an EVM interpreter +type EVMInterpreter struct { evm *EVM cfg Config gasTable params.GasTable @@ -55,8 +78,8 @@ type Interpreter struct { returnData []byte // Last CALL's return data for subsequent reuse } -// NewInterpreter returns a new instance of the Interpreter. -func NewInterpreter(evm *EVM, cfg Config) *Interpreter { +// NewEVMInterpreter returns a new instance of the Interpreter. +func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { // We use the STOP instruction whether to see // the jump table was initialised. If it was not // we'll set the default jump table. @@ -73,14 +96,14 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter { } } - return &Interpreter{ + return &EVMInterpreter{ evm: evm, cfg: cfg, gasTable: evm.ChainConfig().GasTable(evm.BlockNumber), } } -func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error { +func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error { if in.evm.chainRules.IsByzantium { if in.readOnly { // If the interpreter is operating in readonly mode, make sure no @@ -102,7 +125,7 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack // It's important to note that any errors returned by the interpreter should be // considered a revert-and-consume-all-gas operation except for // errExecutionReverted which means revert-and-keep-gas-left. -func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err error) { +func (in *EVMInterpreter) Run(contract *Contract, input []byte) (ret []byte, err error) { if in.intPool == nil { in.intPool = poolOfIntPools.get() defer func() { @@ -209,7 +232,7 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er } // execute the operation - res, err := operation.execute(&pc, in.evm, contract, mem, stack) + res, err := operation.execute(&pc, in, contract, mem, stack) // verifyPool is a build flag. Pool verification makes sure the integrity // of the integer pool by comparing values to a default value. if verifyPool { @@ -234,3 +257,19 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er } return nil, nil } + +// CanRun tells if the contract, passed as an argument, can be +// run by the current interpreter. +func (in *EVMInterpreter) CanRun(code []byte) bool { + return true +} + +// IsReadOnly reports if the interpreter is in read only mode. +func (in *EVMInterpreter) IsReadOnly() bool { + return in.readOnly +} + +// SetReadOnly sets (or unsets) read only mode in the interpreter. +func (in *EVMInterpreter) SetReadOnly(ro bool) { + in.readOnly = ro +} |