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.
This commit is contained in:
Libby Kent 2019-08-09 13:57:06 -04:00 committed by libby kent
parent c894c2d70e
commit 7e87e40340
3 changed files with 5 additions and 14 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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
}
}