From dddeb2920d0d15af0fe1d512e4efc3b58b50ee43 Mon Sep 17 00:00:00 2001 From: Libby Kent Date: Fri, 9 Aug 2019 13:57:06 -0400 Subject: [PATCH] VM read-only mode: check `operation.writes` not `op.isMutating`. `op.isMutating()` was added for checking mutating VM operation, but `operation.writes` should be used now as it registers all mutating ops and is consistent with upstream. Additionally, there is a new mutating opcode `CREATE2`, but `CREATE2` has not been added to the `op.isMutating()` set. The VM is in read-only mode when a private contract calls a public contract. --- core/vm/evm.go | 2 ++ core/vm/interpreter.go | 7 +++---- core/vm/opcodes.go | 10 ---------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index c0a14e746b..0135ace7b6 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -588,6 +588,8 @@ func (env *EVM) Push(statedb StateDB) { // Quorum : the read only depth to be set up only once for the entire // op code execution. This will be set first time transition from // private state to public state happens + // statedb will be the state of the contract being called. + // if a private contract is calling a public contract make it readonly. if !env.quorumReadOnly && env.privateState != statedb { env.quorumReadOnly = true env.readOnlyDepth = env.currentStateDepth diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 3440de3c4a..24f5c41bfb 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -207,10 +207,6 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // Get the memory location of pc op = contract.GetOp(pc) - if in.evm.quorumReadOnly && op.isMutating() { - return nil, fmt.Errorf("VM in read-only mode. Mutating opcode prohibited") - } - if in.cfg.Debug { // Capture pre-execution values for tracing. logged, pcCopy, gasCopy = false, pc, contract.Gas @@ -222,6 +218,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( if !operation.valid { return nil, fmt.Errorf("invalid opcode 0x%x", int(op)) } + if in.evm.quorumReadOnly && operation.writes { + return nil, fmt.Errorf("VM in read-only mode. Mutating opcode prohibited") + } if err := operation.validateStack(stack); err != nil { return nil, err } diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index 5494585819..4349ffd295 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -538,13 +538,3 @@ var stringToOp = map[string]OpCode{ func StringToOp(str string) OpCode { return stringToOp[str] } - -func (op OpCode) isMutating() bool { - switch op { - // TODO(joel): REVERT? - case SELFDESTRUCT, CREATE, SSTORE, LOG0, LOG1, LOG2, LOG3, LOG4: - return true - default: - return false - } -}