aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-08-16 20:19:33 +0800
committerGitHub <noreply@github.com>2017-08-16 20:19:33 +0800
commit0b978f91b6adcc4b595391096a72db73bc625bcf (patch)
tree39fec54fa2601c10b57ccd00eebf494003c57b5f /core/vm
parent76069eef38082089d2eaf99661a80e1a953bf271 (diff)
parent64d199edf2c152072df92f31313e2c157d38c520 (diff)
downloadgo-tangerine-0b978f91b6adcc4b595391096a72db73bc625bcf.tar.gz
go-tangerine-0b978f91b6adcc4b595391096a72db73bc625bcf.tar.zst
go-tangerine-0b978f91b6adcc4b595391096a72db73bc625bcf.zip
Merge pull request #14981 from karalabe/metropolis-returndata
core/vm: implement RETURNDATA metropolis opcodes
Diffstat (limited to 'core/vm')
-rw-r--r--core/vm/evm.go6
-rw-r--r--core/vm/gas_table.go28
-rw-r--r--core/vm/instructions.go78
-rw-r--r--core/vm/interpreter.go17
-rw-r--r--core/vm/jump_table.go30
-rw-r--r--core/vm/memory.go1
-rw-r--r--core/vm/memory_table.go6
-rw-r--r--core/vm/opcodes.go307
8 files changed, 279 insertions, 194 deletions
diff --git a/core/vm/evm.go b/core/vm/evm.go
index cc4214a16..448acd469 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -261,9 +261,9 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// Make sure the readonly is only set if we aren't in readonly yet
// this makes also sure that the readonly flag isn't removed for
// child calls.
- if !evm.interpreter.readonly {
- evm.interpreter.readonly = true
- defer func() { evm.interpreter.readonly = false }()
+ if !evm.interpreter.readOnly {
+ evm.interpreter.readOnly = true
+ defer func() { evm.interpreter.readOnly = false }()
}
var (
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index 8a6c2741d..a6346bd80 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -65,7 +65,33 @@ func constGasFunc(gas uint64) gasFunc {
}
}
-func gasCalldataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ gas, err := memoryGasCost(mem, memorySize)
+ if err != nil {
+ return 0, err
+ }
+
+ var overflow bool
+ if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
+ return 0, errGasUintOverflow
+ }
+
+ words, overflow := bigUint64(stack.Back(2))
+ if overflow {
+ return 0, errGasUintOverflow
+ }
+
+ if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
+ return 0, errGasUintOverflow
+ }
+
+ if gas, overflow = math.SafeAdd(gas, words); overflow {
+ return 0, errGasUintOverflow
+ }
+ return gas, nil
+}
+
+func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index aaa8d7945..4d6197912 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -29,8 +29,9 @@ import (
)
var (
- bigZero = new(big.Int)
- errWriteProtection = errors.New("evm: write protection")
+ bigZero = new(big.Int)
+ errWriteProtection = errors.New("evm: write protection")
+ errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
)
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
@@ -242,6 +243,7 @@ func opAnd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
evm.interpreter.intPool.put(y)
return nil, nil
}
+
func opOr(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop()
stack.push(x.Or(x, y))
@@ -249,6 +251,7 @@ func opOr(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack
evm.interpreter.intPool.put(y)
return nil, nil
}
+
func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop()
stack.push(x.Xor(x, y))
@@ -268,6 +271,7 @@ func opByte(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
evm.interpreter.intPool.put(th)
return nil, nil
}
+
func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y, z := stack.pop(), stack.pop(), stack.pop()
if z.Cmp(bigZero) > 0 {
@@ -281,6 +285,7 @@ func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
evm.interpreter.intPool.put(y, z)
return nil, nil
}
+
func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y, z := stack.pop(), stack.pop(), stack.pop()
if z.Cmp(bigZero) > 0 {
@@ -338,25 +343,47 @@ func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
return nil, nil
}
-func opCalldataLoad(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCallDataLoad(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
stack.push(new(big.Int).SetBytes(getDataBig(contract.Input, stack.pop(), big32)))
return nil, nil
}
-func opCalldataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCallDataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
stack.push(evm.interpreter.intPool.get().SetInt64(int64(len(contract.Input))))
return nil, nil
}
-func opCalldataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCallDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ var (
+ memOffset = stack.pop()
+ dataOffset = stack.pop()
+ length = stack.pop()
+ )
+ memory.Set(memOffset.Uint64(), length.Uint64(), getDataBig(contract.Input, dataOffset, length))
+
+ evm.interpreter.intPool.put(memOffset, dataOffset, length)
+ return nil, nil
+}
+
+func opReturnDataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ stack.push(evm.interpreter.intPool.get().SetUint64(uint64(len(evm.interpreter.returnData))))
+ return nil, nil
+}
+
+func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
var (
- mOff = stack.pop()
- cOff = stack.pop()
- l = stack.pop()
+ memOffset = stack.pop()
+ dataOffset = stack.pop()
+ length = stack.pop()
)
- memory.Set(mOff.Uint64(), l.Uint64(), getDataBig(contract.Input, cOff, l))
+ defer evm.interpreter.intPool.put(memOffset, dataOffset, length)
+
+ end := new(big.Int).Add(dataOffset, length)
+ if end.BitLen() > 64 || uint64(len(evm.interpreter.returnData)) < end.Uint64() {
+ return nil, errReturnDataOutOfBounds
+ }
+ memory.Set(memOffset.Uint64(), length.Uint64(), evm.interpreter.returnData[dataOffset.Uint64():end.Uint64()])
- evm.interpreter.intPool.put(mOff, cOff, l)
return nil, nil
}
@@ -378,31 +405,28 @@ func opCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
func opCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
var (
- mOff = stack.pop()
- cOff = stack.pop()
- l = stack.pop()
+ memOffset = stack.pop()
+ codeOffset = stack.pop()
+ length = stack.pop()
)
- codeCopy := getDataBig(contract.Code, cOff, l)
+ codeCopy := getDataBig(contract.Code, codeOffset, length)
+ memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
- memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
-
- evm.interpreter.intPool.put(mOff, cOff, l)
+ evm.interpreter.intPool.put(memOffset, codeOffset, length)
return nil, nil
}
func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
var (
- addr = common.BigToAddress(stack.pop())
- mOff = stack.pop()
- cOff = stack.pop()
- l = stack.pop()
+ addr = common.BigToAddress(stack.pop())
+ memOffset = stack.pop()
+ codeOffset = stack.pop()
+ length = stack.pop()
)
- codeCopy := getDataBig(evm.StateDB.GetCode(addr), cOff, l)
-
- memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
-
- evm.interpreter.intPool.put(mOff, cOff, l)
+ codeCopy := getDataBig(evm.StateDB.GetCode(addr), codeOffset, length)
+ memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
+ evm.interpreter.intPool.put(memOffset, codeOffset, length)
return nil, nil
}
@@ -507,6 +531,7 @@ func opJump(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
evm.interpreter.intPool.put(pos)
return nil, nil
}
+
func opJumpi(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
pos, cond := stack.pop(), stack.pop()
if cond.Sign() != 0 {
@@ -522,6 +547,7 @@ func opJumpi(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *St
evm.interpreter.intPool.put(pos, cond)
return nil, nil
}
+
func opJumpdest(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
return nil, nil
}
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 661ada691..954839f2e 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -59,7 +59,8 @@ type Interpreter struct {
gasTable params.GasTable
intPool *intPool
- readonly bool
+ readOnly bool // Whether to throw on stateful modifications
+ returnData []byte // Last CALL's return data for subsequent reuse
}
// NewInterpreter returns a new instance of the Interpreter.
@@ -88,7 +89,7 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
if in.evm.chainRules.IsMetropolis {
- if in.readonly {
+ if in.readOnly {
// If the interpreter is operating in readonly mode, make sure no
// state-modifying operation is performed. The 3rd stack item
// for a call operation is the value. Transfering value from one
@@ -113,6 +114,10 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret
in.evm.depth++
defer func() { in.evm.depth-- }()
+ // Reset the previous call's return data. It's unimportant to preserve the old buffer
+ // as every returning call will return new data anyway.
+ in.returnData = nil
+
// Don't bother with the execution if there's no code.
if len(contract.Code) == 0 {
return nil, nil
@@ -213,10 +218,10 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret
case !operation.jumps:
pc++
}
- // if the operation returned a value make sure that is also set
- // the last return data.
- if res != nil {
- mem.lastReturn = ret
+ // if the operation clears the return data (e.g. it has returning data)
+ // set the last return to the result of the operation.
+ if operation.returns {
+ in.returnData = res
}
}
return nil, nil
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index f6e8dae66..2d238f7a1 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -53,6 +53,8 @@ type operation struct {
valid bool
// reverts determined whether the operation reverts state
reverts bool
+ // returns determines whether the opertions sets the return data
+ returns bool
}
var (
@@ -72,6 +74,20 @@ func NewMetropolisInstructionSet() [256]operation {
validateStack: makeStackFunc(6, 1),
memorySize: memoryStaticCall,
valid: true,
+ returns: true,
+ }
+ instructionSet[RETURNDATASIZE] = operation{
+ execute: opReturnDataSize,
+ gasCost: constGasFunc(GasQuickStep),
+ validateStack: makeStackFunc(0, 1),
+ valid: true,
+ }
+ instructionSet[RETURNDATACOPY] = operation{
+ execute: opReturnDataCopy,
+ gasCost: gasReturnDataCopy,
+ validateStack: makeStackFunc(3, 0),
+ memorySize: memoryReturnDataCopy,
+ valid: true,
}
return instructionSet
}
@@ -86,6 +102,7 @@ func NewHomesteadInstructionSet() [256]operation {
validateStack: makeStackFunc(6, 1),
memorySize: memoryDelegateCall,
valid: true,
+ returns: true,
}
return instructionSet
}
@@ -271,22 +288,22 @@ func NewFrontierInstructionSet() [256]operation {
valid: true,
},
CALLDATALOAD: {
- execute: opCalldataLoad,
+ execute: opCallDataLoad,
gasCost: constGasFunc(GasFastestStep),
validateStack: makeStackFunc(1, 1),
valid: true,
},
CALLDATASIZE: {
- execute: opCalldataSize,
+ execute: opCallDataSize,
gasCost: constGasFunc(GasQuickStep),
validateStack: makeStackFunc(0, 1),
valid: true,
},
CALLDATACOPY: {
- execute: opCalldataCopy,
- gasCost: gasCalldataCopy,
+ execute: opCallDataCopy,
+ gasCost: gasCallDataCopy,
validateStack: makeStackFunc(3, 0),
- memorySize: memoryCalldataCopy,
+ memorySize: memoryCallDataCopy,
valid: true,
},
CODESIZE: {
@@ -867,6 +884,7 @@ func NewFrontierInstructionSet() [256]operation {
memorySize: memoryCreate,
valid: true,
writes: true,
+ returns: true,
},
CALL: {
execute: opCall,
@@ -874,6 +892,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack: makeStackFunc(7, 1),
memorySize: memoryCall,
valid: true,
+ returns: true,
},
CALLCODE: {
execute: opCallCode,
@@ -881,6 +900,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack: makeStackFunc(7, 1),
memorySize: memoryCall,
valid: true,
+ returns: true,
},
RETURN: {
execute: opReturn,
diff --git a/core/vm/memory.go b/core/vm/memory.go
index 6dbee94ef..99a84d227 100644
--- a/core/vm/memory.go
+++ b/core/vm/memory.go
@@ -22,7 +22,6 @@ import "fmt"
type Memory struct {
store []byte
lastGasCost uint64
- lastReturn []byte
}
func NewMemory() *Memory {
diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go
index 9d293a2f2..f1b671adc 100644
--- a/core/vm/memory_table.go
+++ b/core/vm/memory_table.go
@@ -26,7 +26,11 @@ func memorySha3(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(1))
}
-func memoryCalldataCopy(stack *Stack) *big.Int {
+func memoryCallDataCopy(stack *Stack) *big.Int {
+ return calcMemSize(stack.Back(0), stack.Back(2))
+}
+
+func memoryReturnDataCopy(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(2))
}
diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go
index 51925e8dd..be87cae18 100644
--- a/core/vm/opcodes.go
+++ b/core/vm/opcodes.go
@@ -82,10 +82,11 @@ const (
GASPRICE
EXTCODESIZE
EXTCODECOPY
+ RETURNDATASIZE
+ RETURNDATACOPY
)
const (
-
// 0x40 range - block operations
BLOCKHASH OpCode = 0x40 + iota
COINBASE
@@ -239,27 +240,29 @@ var opCodeToString = map[OpCode]string{
SHA3: "SHA3",
// 0x30 range - closure state
- ADDRESS: "ADDRESS",
- BALANCE: "BALANCE",
- ORIGIN: "ORIGIN",
- CALLER: "CALLER",
- CALLVALUE: "CALLVALUE",
- CALLDATALOAD: "CALLDATALOAD",
- CALLDATASIZE: "CALLDATASIZE",
- CALLDATACOPY: "CALLDATACOPY",
- CODESIZE: "CODESIZE",
- CODECOPY: "CODECOPY",
- GASPRICE: "GASPRICE",
+ ADDRESS: "ADDRESS",
+ BALANCE: "BALANCE",
+ ORIGIN: "ORIGIN",
+ CALLER: "CALLER",
+ CALLVALUE: "CALLVALUE",
+ CALLDATALOAD: "CALLDATALOAD",
+ CALLDATASIZE: "CALLDATASIZE",
+ CALLDATACOPY: "CALLDATACOPY",
+ CODESIZE: "CODESIZE",
+ CODECOPY: "CODECOPY",
+ GASPRICE: "GASPRICE",
+ EXTCODESIZE: "EXTCODESIZE",
+ EXTCODECOPY: "EXTCODECOPY",
+ RETURNDATASIZE: "RETURNDATASIZE",
+ RETURNDATACOPY: "RETURNDATACOPY",
// 0x40 range - block operations
- BLOCKHASH: "BLOCKHASH",
- COINBASE: "COINBASE",
- TIMESTAMP: "TIMESTAMP",
- NUMBER: "NUMBER",
- DIFFICULTY: "DIFFICULTY",
- GASLIMIT: "GASLIMIT",
- EXTCODESIZE: "EXTCODESIZE",
- EXTCODECOPY: "EXTCODECOPY",
+ BLOCKHASH: "BLOCKHASH",
+ COINBASE: "COINBASE",
+ TIMESTAMP: "TIMESTAMP",
+ NUMBER: "NUMBER",
+ DIFFICULTY: "DIFFICULTY",
+ GASLIMIT: "GASLIMIT",
// 0x50 range - 'storage' and execution
POP: "POP",
@@ -374,137 +377,139 @@ func (o OpCode) String() string {
}
var stringToOp = map[string]OpCode{
- "STOP": STOP,
- "ADD": ADD,
- "MUL": MUL,
- "SUB": SUB,
- "DIV": DIV,
- "SDIV": SDIV,
- "MOD": MOD,
- "SMOD": SMOD,
- "EXP": EXP,
- "NOT": NOT,
- "LT": LT,
- "GT": GT,
- "SLT": SLT,
- "SGT": SGT,
- "EQ": EQ,
- "ISZERO": ISZERO,
- "SIGNEXTEND": SIGNEXTEND,
- "AND": AND,
- "OR": OR,
- "XOR": XOR,
- "BYTE": BYTE,
- "ADDMOD": ADDMOD,
- "MULMOD": MULMOD,
- "SHA3": SHA3,
- "ADDRESS": ADDRESS,
- "BALANCE": BALANCE,
- "ORIGIN": ORIGIN,
- "CALLER": CALLER,
- "CALLVALUE": CALLVALUE,
- "CALLDATALOAD": CALLDATALOAD,
- "CALLDATASIZE": CALLDATASIZE,
- "CALLDATACOPY": CALLDATACOPY,
- "DELEGATECALL": DELEGATECALL,
- "STATICCALL": STATICCALL,
- "CODESIZE": CODESIZE,
- "CODECOPY": CODECOPY,
- "GASPRICE": GASPRICE,
- "BLOCKHASH": BLOCKHASH,
- "COINBASE": COINBASE,
- "TIMESTAMP": TIMESTAMP,
- "NUMBER": NUMBER,
- "DIFFICULTY": DIFFICULTY,
- "GASLIMIT": GASLIMIT,
- "EXTCODESIZE": EXTCODESIZE,
- "EXTCODECOPY": EXTCODECOPY,
- "POP": POP,
- "MLOAD": MLOAD,
- "MSTORE": MSTORE,
- "MSTORE8": MSTORE8,
- "SLOAD": SLOAD,
- "SSTORE": SSTORE,
- "JUMP": JUMP,
- "JUMPI": JUMPI,
- "PC": PC,
- "MSIZE": MSIZE,
- "GAS": GAS,
- "JUMPDEST": JUMPDEST,
- "PUSH1": PUSH1,
- "PUSH2": PUSH2,
- "PUSH3": PUSH3,
- "PUSH4": PUSH4,
- "PUSH5": PUSH5,
- "PUSH6": PUSH6,
- "PUSH7": PUSH7,
- "PUSH8": PUSH8,
- "PUSH9": PUSH9,
- "PUSH10": PUSH10,
- "PUSH11": PUSH11,
- "PUSH12": PUSH12,
- "PUSH13": PUSH13,
- "PUSH14": PUSH14,
- "PUSH15": PUSH15,
- "PUSH16": PUSH16,
- "PUSH17": PUSH17,
- "PUSH18": PUSH18,
- "PUSH19": PUSH19,
- "PUSH20": PUSH20,
- "PUSH21": PUSH21,
- "PUSH22": PUSH22,
- "PUSH23": PUSH23,
- "PUSH24": PUSH24,
- "PUSH25": PUSH25,
- "PUSH26": PUSH26,
- "PUSH27": PUSH27,
- "PUSH28": PUSH28,
- "PUSH29": PUSH29,
- "PUSH30": PUSH30,
- "PUSH31": PUSH31,
- "PUSH32": PUSH32,
- "DUP1": DUP1,
- "DUP2": DUP2,
- "DUP3": DUP3,
- "DUP4": DUP4,
- "DUP5": DUP5,
- "DUP6": DUP6,
- "DUP7": DUP7,
- "DUP8": DUP8,
- "DUP9": DUP9,
- "DUP10": DUP10,
- "DUP11": DUP11,
- "DUP12": DUP12,
- "DUP13": DUP13,
- "DUP14": DUP14,
- "DUP15": DUP15,
- "DUP16": DUP16,
- "SWAP1": SWAP1,
- "SWAP2": SWAP2,
- "SWAP3": SWAP3,
- "SWAP4": SWAP4,
- "SWAP5": SWAP5,
- "SWAP6": SWAP6,
- "SWAP7": SWAP7,
- "SWAP8": SWAP8,
- "SWAP9": SWAP9,
- "SWAP10": SWAP10,
- "SWAP11": SWAP11,
- "SWAP12": SWAP12,
- "SWAP13": SWAP13,
- "SWAP14": SWAP14,
- "SWAP15": SWAP15,
- "SWAP16": SWAP16,
- "LOG0": LOG0,
- "LOG1": LOG1,
- "LOG2": LOG2,
- "LOG3": LOG3,
- "LOG4": LOG4,
- "CREATE": CREATE,
- "CALL": CALL,
- "RETURN": RETURN,
- "CALLCODE": CALLCODE,
- "SELFDESTRUCT": SELFDESTRUCT,
+ "STOP": STOP,
+ "ADD": ADD,
+ "MUL": MUL,
+ "SUB": SUB,
+ "DIV": DIV,
+ "SDIV": SDIV,
+ "MOD": MOD,
+ "SMOD": SMOD,
+ "EXP": EXP,
+ "NOT": NOT,
+ "LT": LT,
+ "GT": GT,
+ "SLT": SLT,
+ "SGT": SGT,
+ "EQ": EQ,
+ "ISZERO": ISZERO,
+ "SIGNEXTEND": SIGNEXTEND,
+ "AND": AND,
+ "OR": OR,
+ "XOR": XOR,
+ "BYTE": BYTE,
+ "ADDMOD": ADDMOD,
+ "MULMOD": MULMOD,
+ "SHA3": SHA3,
+ "ADDRESS": ADDRESS,
+ "BALANCE": BALANCE,
+ "ORIGIN": ORIGIN,
+ "CALLER": CALLER,
+ "CALLVALUE": CALLVALUE,
+ "CALLDATALOAD": CALLDATALOAD,
+ "CALLDATASIZE": CALLDATASIZE,
+ "CALLDATACOPY": CALLDATACOPY,
+ "DELEGATECALL": DELEGATECALL,
+ "STATICCALL": STATICCALL,
+ "CODESIZE": CODESIZE,
+ "CODECOPY": CODECOPY,
+ "GASPRICE": GASPRICE,
+ "EXTCODESIZE": EXTCODESIZE,
+ "EXTCODECOPY": EXTCODECOPY,
+ "RETURNDATASIZE": RETURNDATASIZE,
+ "RETURNDATACOPY": RETURNDATACOPY,
+ "BLOCKHASH": BLOCKHASH,
+ "COINBASE": COINBASE,
+ "TIMESTAMP": TIMESTAMP,
+ "NUMBER": NUMBER,
+ "DIFFICULTY": DIFFICULTY,
+ "GASLIMIT": GASLIMIT,
+ "POP": POP,
+ "MLOAD": MLOAD,
+ "MSTORE": MSTORE,
+ "MSTORE8": MSTORE8,
+ "SLOAD": SLOAD,
+ "SSTORE": SSTORE,
+ "JUMP": JUMP,
+ "JUMPI": JUMPI,
+ "PC": PC,
+ "MSIZE": MSIZE,
+ "GAS": GAS,
+ "JUMPDEST": JUMPDEST,
+ "PUSH1": PUSH1,
+ "PUSH2": PUSH2,
+ "PUSH3": PUSH3,
+ "PUSH4": PUSH4,
+ "PUSH5": PUSH5,
+ "PUSH6": PUSH6,
+ "PUSH7": PUSH7,
+ "PUSH8": PUSH8,
+ "PUSH9": PUSH9,
+ "PUSH10": PUSH10,
+ "PUSH11": PUSH11,
+ "PUSH12": PUSH12,
+ "PUSH13": PUSH13,
+ "PUSH14": PUSH14,
+ "PUSH15": PUSH15,
+ "PUSH16": PUSH16,
+ "PUSH17": PUSH17,
+ "PUSH18": PUSH18,
+ "PUSH19": PUSH19,
+ "PUSH20": PUSH20,
+ "PUSH21": PUSH21,
+ "PUSH22": PUSH22,
+ "PUSH23": PUSH23,
+ "PUSH24": PUSH24,
+ "PUSH25": PUSH25,
+ "PUSH26": PUSH26,
+ "PUSH27": PUSH27,
+ "PUSH28": PUSH28,
+ "PUSH29": PUSH29,
+ "PUSH30": PUSH30,
+ "PUSH31": PUSH31,
+ "PUSH32": PUSH32,
+ "DUP1": DUP1,
+ "DUP2": DUP2,
+ "DUP3": DUP3,
+ "DUP4": DUP4,
+ "DUP5": DUP5,
+ "DUP6": DUP6,
+ "DUP7": DUP7,
+ "DUP8": DUP8,
+ "DUP9": DUP9,
+ "DUP10": DUP10,
+ "DUP11": DUP11,
+ "DUP12": DUP12,
+ "DUP13": DUP13,
+ "DUP14": DUP14,
+ "DUP15": DUP15,
+ "DUP16": DUP16,
+ "SWAP1": SWAP1,
+ "SWAP2": SWAP2,
+ "SWAP3": SWAP3,
+ "SWAP4": SWAP4,
+ "SWAP5": SWAP5,
+ "SWAP6": SWAP6,
+ "SWAP7": SWAP7,
+ "SWAP8": SWAP8,
+ "SWAP9": SWAP9,
+ "SWAP10": SWAP10,
+ "SWAP11": SWAP11,
+ "SWAP12": SWAP12,
+ "SWAP13": SWAP13,
+ "SWAP14": SWAP14,
+ "SWAP15": SWAP15,
+ "SWAP16": SWAP16,
+ "LOG0": LOG0,
+ "LOG1": LOG1,
+ "LOG2": LOG2,
+ "LOG3": LOG3,
+ "LOG4": LOG4,
+ "CREATE": CREATE,
+ "CALL": CALL,
+ "RETURN": RETURN,
+ "CALLCODE": CALLCODE,
+ "SELFDESTRUCT": SELFDESTRUCT,
}
func StringToOp(str string) OpCode {