diff options
author | Péter Szilágyi <peterke@gmail.com> | 2017-08-16 20:19:33 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-16 20:19:33 +0800 |
commit | 0b978f91b6adcc4b595391096a72db73bc625bcf (patch) | |
tree | 39fec54fa2601c10b57ccd00eebf494003c57b5f /core/vm | |
parent | 76069eef38082089d2eaf99661a80e1a953bf271 (diff) | |
parent | 64d199edf2c152072df92f31313e2c157d38c520 (diff) | |
download | go-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.go | 6 | ||||
-rw-r--r-- | core/vm/gas_table.go | 28 | ||||
-rw-r--r-- | core/vm/instructions.go | 78 | ||||
-rw-r--r-- | core/vm/interpreter.go | 17 | ||||
-rw-r--r-- | core/vm/jump_table.go | 30 | ||||
-rw-r--r-- | core/vm/memory.go | 1 | ||||
-rw-r--r-- | core/vm/memory_table.go | 6 | ||||
-rw-r--r-- | core/vm/opcodes.go | 307 |
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 { |