aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/interpreter.go
diff options
context:
space:
mode:
authorGuillaume Ballet <gballet@gmail.com>2018-07-25 20:56:39 +0800
committerGitHub <noreply@github.com>2018-07-25 20:56:39 +0800
commit7abedf9bbb725da8d610762d051af43085be1cda (patch)
tree7640e475868c575115cbcfde8bddb7b4484eee20 /core/vm/interpreter.go
parent27a278e6e35836999ac8e4d9a19c406407db8ae5 (diff)
downloadgo-tangerine-7abedf9bbb725da8d610762d051af43085be1cda.tar
go-tangerine-7abedf9bbb725da8d610762d051af43085be1cda.tar.gz
go-tangerine-7abedf9bbb725da8d610762d051af43085be1cda.tar.bz2
go-tangerine-7abedf9bbb725da8d610762d051af43085be1cda.tar.lz
go-tangerine-7abedf9bbb725da8d610762d051af43085be1cda.tar.xz
go-tangerine-7abedf9bbb725da8d610762d051af43085be1cda.tar.zst
go-tangerine-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.go53
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
+}