Merge pull request #14981 from karalabe/metropolis-returndata

core/vm: implement RETURNDATA metropolis opcodes
This commit is contained in:
Péter Szilágyi 2017-08-16 15:19:33 +03:00 committed by GitHub
commit 0b978f91b6
9 changed files with 280 additions and 195 deletions

View File

@ -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 // 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 // this makes also sure that the readonly flag isn't removed for
// child calls. // child calls.
if !evm.interpreter.readonly { if !evm.interpreter.readOnly {
evm.interpreter.readonly = true evm.interpreter.readOnly = true
defer func() { evm.interpreter.readonly = false }() defer func() { evm.interpreter.readOnly = false }()
} }
var ( var (

View File

@ -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) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
return 0, err return 0, err

View File

@ -29,8 +29,9 @@ import (
) )
var ( var (
bigZero = new(big.Int) bigZero = new(big.Int)
errWriteProtection = errors.New("evm: write protection") 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) { 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) evm.interpreter.intPool.put(y)
return nil, nil return nil, nil
} }
func opOr(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { func opOr(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop() x, y := stack.pop(), stack.pop()
stack.push(x.Or(x, y)) 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) evm.interpreter.intPool.put(y)
return nil, nil return nil, nil
} }
func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop() x, y := stack.pop(), stack.pop()
stack.push(x.Xor(x, y)) 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) evm.interpreter.intPool.put(th)
return nil, nil return nil, nil
} }
func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y, z := stack.pop(), stack.pop(), stack.pop() x, y, z := stack.pop(), stack.pop(), stack.pop()
if z.Cmp(bigZero) > 0 { 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) evm.interpreter.intPool.put(y, z)
return nil, nil return nil, nil
} }
func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y, z := stack.pop(), stack.pop(), stack.pop() x, y, z := stack.pop(), stack.pop(), stack.pop()
if z.Cmp(bigZero) > 0 { if z.Cmp(bigZero) > 0 {
@ -338,25 +343,47 @@ func opCallValue(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
return nil, nil 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))) stack.push(new(big.Int).SetBytes(getDataBig(contract.Input, stack.pop(), big32)))
return nil, nil 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)))) stack.push(evm.interpreter.intPool.get().SetInt64(int64(len(contract.Input))))
return nil, nil 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 ( var (
mOff = stack.pop() memOffset = stack.pop()
cOff = stack.pop() dataOffset = stack.pop()
l = stack.pop() length = stack.pop()
) )
memory.Set(mOff.Uint64(), l.Uint64(), getDataBig(contract.Input, cOff, l)) 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 (
memOffset = stack.pop()
dataOffset = stack.pop()
length = stack.pop()
)
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 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) { func opCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
var ( var (
mOff = stack.pop() memOffset = stack.pop()
cOff = stack.pop() codeOffset = stack.pop()
l = 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(memOffset, codeOffset, length)
evm.interpreter.intPool.put(mOff, cOff, l)
return nil, nil return nil, nil
} }
func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
var ( var (
addr = common.BigToAddress(stack.pop()) addr = common.BigToAddress(stack.pop())
mOff = stack.pop() memOffset = stack.pop()
cOff = stack.pop() codeOffset = stack.pop()
l = stack.pop() length = stack.pop()
) )
codeCopy := getDataBig(evm.StateDB.GetCode(addr), cOff, l) codeCopy := getDataBig(evm.StateDB.GetCode(addr), 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 return nil, nil
} }
@ -507,6 +531,7 @@ func opJump(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
evm.interpreter.intPool.put(pos) evm.interpreter.intPool.put(pos)
return nil, nil return nil, nil
} }
func opJumpi(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { func opJumpi(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
pos, cond := stack.pop(), stack.pop() pos, cond := stack.pop(), stack.pop()
if cond.Sign() != 0 { 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) evm.interpreter.intPool.put(pos, cond)
return nil, nil return nil, nil
} }
func opJumpdest(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { func opJumpdest(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
return nil, nil return nil, nil
} }

View File

@ -59,7 +59,8 @@ type Interpreter struct {
gasTable params.GasTable gasTable params.GasTable
intPool *intPool 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. // 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 { func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
if in.evm.chainRules.IsMetropolis { if in.evm.chainRules.IsMetropolis {
if in.readonly { if in.readOnly {
// If the interpreter is operating in readonly mode, make sure no // If the interpreter is operating in readonly mode, make sure no
// state-modifying operation is performed. The 3rd stack item // state-modifying operation is performed. The 3rd stack item
// for a call operation is the value. Transfering value from one // 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++ in.evm.depth++
defer func() { 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. // Don't bother with the execution if there's no code.
if len(contract.Code) == 0 { if len(contract.Code) == 0 {
return nil, nil return nil, nil
@ -213,10 +218,10 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret
case !operation.jumps: case !operation.jumps:
pc++ pc++
} }
// if the operation returned a value make sure that is also set // if the operation clears the return data (e.g. it has returning data)
// the last return data. // set the last return to the result of the operation.
if res != nil { if operation.returns {
mem.lastReturn = ret in.returnData = res
} }
} }
return nil, nil return nil, nil

View File

@ -53,6 +53,8 @@ type operation struct {
valid bool valid bool
// reverts determined whether the operation reverts state // reverts determined whether the operation reverts state
reverts bool reverts bool
// returns determines whether the opertions sets the return data
returns bool
} }
var ( var (
@ -72,6 +74,20 @@ func NewMetropolisInstructionSet() [256]operation {
validateStack: makeStackFunc(6, 1), validateStack: makeStackFunc(6, 1),
memorySize: memoryStaticCall, memorySize: memoryStaticCall,
valid: true, 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 return instructionSet
} }
@ -86,6 +102,7 @@ func NewHomesteadInstructionSet() [256]operation {
validateStack: makeStackFunc(6, 1), validateStack: makeStackFunc(6, 1),
memorySize: memoryDelegateCall, memorySize: memoryDelegateCall,
valid: true, valid: true,
returns: true,
} }
return instructionSet return instructionSet
} }
@ -271,22 +288,22 @@ func NewFrontierInstructionSet() [256]operation {
valid: true, valid: true,
}, },
CALLDATALOAD: { CALLDATALOAD: {
execute: opCalldataLoad, execute: opCallDataLoad,
gasCost: constGasFunc(GasFastestStep), gasCost: constGasFunc(GasFastestStep),
validateStack: makeStackFunc(1, 1), validateStack: makeStackFunc(1, 1),
valid: true, valid: true,
}, },
CALLDATASIZE: { CALLDATASIZE: {
execute: opCalldataSize, execute: opCallDataSize,
gasCost: constGasFunc(GasQuickStep), gasCost: constGasFunc(GasQuickStep),
validateStack: makeStackFunc(0, 1), validateStack: makeStackFunc(0, 1),
valid: true, valid: true,
}, },
CALLDATACOPY: { CALLDATACOPY: {
execute: opCalldataCopy, execute: opCallDataCopy,
gasCost: gasCalldataCopy, gasCost: gasCallDataCopy,
validateStack: makeStackFunc(3, 0), validateStack: makeStackFunc(3, 0),
memorySize: memoryCalldataCopy, memorySize: memoryCallDataCopy,
valid: true, valid: true,
}, },
CODESIZE: { CODESIZE: {
@ -867,6 +884,7 @@ func NewFrontierInstructionSet() [256]operation {
memorySize: memoryCreate, memorySize: memoryCreate,
valid: true, valid: true,
writes: true, writes: true,
returns: true,
}, },
CALL: { CALL: {
execute: opCall, execute: opCall,
@ -874,6 +892,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack: makeStackFunc(7, 1), validateStack: makeStackFunc(7, 1),
memorySize: memoryCall, memorySize: memoryCall,
valid: true, valid: true,
returns: true,
}, },
CALLCODE: { CALLCODE: {
execute: opCallCode, execute: opCallCode,
@ -881,6 +900,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack: makeStackFunc(7, 1), validateStack: makeStackFunc(7, 1),
memorySize: memoryCall, memorySize: memoryCall,
valid: true, valid: true,
returns: true,
}, },
RETURN: { RETURN: {
execute: opReturn, execute: opReturn,

View File

@ -22,7 +22,6 @@ import "fmt"
type Memory struct { type Memory struct {
store []byte store []byte
lastGasCost uint64 lastGasCost uint64
lastReturn []byte
} }
func NewMemory() *Memory { func NewMemory() *Memory {

View File

@ -26,7 +26,11 @@ func memorySha3(stack *Stack) *big.Int {
return calcMemSize(stack.Back(0), stack.Back(1)) 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)) return calcMemSize(stack.Back(0), stack.Back(2))
} }

View File

@ -82,10 +82,11 @@ const (
GASPRICE GASPRICE
EXTCODESIZE EXTCODESIZE
EXTCODECOPY EXTCODECOPY
RETURNDATASIZE
RETURNDATACOPY
) )
const ( const (
// 0x40 range - block operations // 0x40 range - block operations
BLOCKHASH OpCode = 0x40 + iota BLOCKHASH OpCode = 0x40 + iota
COINBASE COINBASE
@ -239,27 +240,29 @@ var opCodeToString = map[OpCode]string{
SHA3: "SHA3", SHA3: "SHA3",
// 0x30 range - closure state // 0x30 range - closure state
ADDRESS: "ADDRESS", ADDRESS: "ADDRESS",
BALANCE: "BALANCE", BALANCE: "BALANCE",
ORIGIN: "ORIGIN", ORIGIN: "ORIGIN",
CALLER: "CALLER", CALLER: "CALLER",
CALLVALUE: "CALLVALUE", CALLVALUE: "CALLVALUE",
CALLDATALOAD: "CALLDATALOAD", CALLDATALOAD: "CALLDATALOAD",
CALLDATASIZE: "CALLDATASIZE", CALLDATASIZE: "CALLDATASIZE",
CALLDATACOPY: "CALLDATACOPY", CALLDATACOPY: "CALLDATACOPY",
CODESIZE: "CODESIZE", CODESIZE: "CODESIZE",
CODECOPY: "CODECOPY", CODECOPY: "CODECOPY",
GASPRICE: "GASPRICE", GASPRICE: "GASPRICE",
EXTCODESIZE: "EXTCODESIZE",
EXTCODECOPY: "EXTCODECOPY",
RETURNDATASIZE: "RETURNDATASIZE",
RETURNDATACOPY: "RETURNDATACOPY",
// 0x40 range - block operations // 0x40 range - block operations
BLOCKHASH: "BLOCKHASH", BLOCKHASH: "BLOCKHASH",
COINBASE: "COINBASE", COINBASE: "COINBASE",
TIMESTAMP: "TIMESTAMP", TIMESTAMP: "TIMESTAMP",
NUMBER: "NUMBER", NUMBER: "NUMBER",
DIFFICULTY: "DIFFICULTY", DIFFICULTY: "DIFFICULTY",
GASLIMIT: "GASLIMIT", GASLIMIT: "GASLIMIT",
EXTCODESIZE: "EXTCODESIZE",
EXTCODECOPY: "EXTCODECOPY",
// 0x50 range - 'storage' and execution // 0x50 range - 'storage' and execution
POP: "POP", POP: "POP",
@ -374,137 +377,139 @@ func (o OpCode) String() string {
} }
var stringToOp = map[string]OpCode{ var stringToOp = map[string]OpCode{
"STOP": STOP, "STOP": STOP,
"ADD": ADD, "ADD": ADD,
"MUL": MUL, "MUL": MUL,
"SUB": SUB, "SUB": SUB,
"DIV": DIV, "DIV": DIV,
"SDIV": SDIV, "SDIV": SDIV,
"MOD": MOD, "MOD": MOD,
"SMOD": SMOD, "SMOD": SMOD,
"EXP": EXP, "EXP": EXP,
"NOT": NOT, "NOT": NOT,
"LT": LT, "LT": LT,
"GT": GT, "GT": GT,
"SLT": SLT, "SLT": SLT,
"SGT": SGT, "SGT": SGT,
"EQ": EQ, "EQ": EQ,
"ISZERO": ISZERO, "ISZERO": ISZERO,
"SIGNEXTEND": SIGNEXTEND, "SIGNEXTEND": SIGNEXTEND,
"AND": AND, "AND": AND,
"OR": OR, "OR": OR,
"XOR": XOR, "XOR": XOR,
"BYTE": BYTE, "BYTE": BYTE,
"ADDMOD": ADDMOD, "ADDMOD": ADDMOD,
"MULMOD": MULMOD, "MULMOD": MULMOD,
"SHA3": SHA3, "SHA3": SHA3,
"ADDRESS": ADDRESS, "ADDRESS": ADDRESS,
"BALANCE": BALANCE, "BALANCE": BALANCE,
"ORIGIN": ORIGIN, "ORIGIN": ORIGIN,
"CALLER": CALLER, "CALLER": CALLER,
"CALLVALUE": CALLVALUE, "CALLVALUE": CALLVALUE,
"CALLDATALOAD": CALLDATALOAD, "CALLDATALOAD": CALLDATALOAD,
"CALLDATASIZE": CALLDATASIZE, "CALLDATASIZE": CALLDATASIZE,
"CALLDATACOPY": CALLDATACOPY, "CALLDATACOPY": CALLDATACOPY,
"DELEGATECALL": DELEGATECALL, "DELEGATECALL": DELEGATECALL,
"STATICCALL": STATICCALL, "STATICCALL": STATICCALL,
"CODESIZE": CODESIZE, "CODESIZE": CODESIZE,
"CODECOPY": CODECOPY, "CODECOPY": CODECOPY,
"GASPRICE": GASPRICE, "GASPRICE": GASPRICE,
"BLOCKHASH": BLOCKHASH, "EXTCODESIZE": EXTCODESIZE,
"COINBASE": COINBASE, "EXTCODECOPY": EXTCODECOPY,
"TIMESTAMP": TIMESTAMP, "RETURNDATASIZE": RETURNDATASIZE,
"NUMBER": NUMBER, "RETURNDATACOPY": RETURNDATACOPY,
"DIFFICULTY": DIFFICULTY, "BLOCKHASH": BLOCKHASH,
"GASLIMIT": GASLIMIT, "COINBASE": COINBASE,
"EXTCODESIZE": EXTCODESIZE, "TIMESTAMP": TIMESTAMP,
"EXTCODECOPY": EXTCODECOPY, "NUMBER": NUMBER,
"POP": POP, "DIFFICULTY": DIFFICULTY,
"MLOAD": MLOAD, "GASLIMIT": GASLIMIT,
"MSTORE": MSTORE, "POP": POP,
"MSTORE8": MSTORE8, "MLOAD": MLOAD,
"SLOAD": SLOAD, "MSTORE": MSTORE,
"SSTORE": SSTORE, "MSTORE8": MSTORE8,
"JUMP": JUMP, "SLOAD": SLOAD,
"JUMPI": JUMPI, "SSTORE": SSTORE,
"PC": PC, "JUMP": JUMP,
"MSIZE": MSIZE, "JUMPI": JUMPI,
"GAS": GAS, "PC": PC,
"JUMPDEST": JUMPDEST, "MSIZE": MSIZE,
"PUSH1": PUSH1, "GAS": GAS,
"PUSH2": PUSH2, "JUMPDEST": JUMPDEST,
"PUSH3": PUSH3, "PUSH1": PUSH1,
"PUSH4": PUSH4, "PUSH2": PUSH2,
"PUSH5": PUSH5, "PUSH3": PUSH3,
"PUSH6": PUSH6, "PUSH4": PUSH4,
"PUSH7": PUSH7, "PUSH5": PUSH5,
"PUSH8": PUSH8, "PUSH6": PUSH6,
"PUSH9": PUSH9, "PUSH7": PUSH7,
"PUSH10": PUSH10, "PUSH8": PUSH8,
"PUSH11": PUSH11, "PUSH9": PUSH9,
"PUSH12": PUSH12, "PUSH10": PUSH10,
"PUSH13": PUSH13, "PUSH11": PUSH11,
"PUSH14": PUSH14, "PUSH12": PUSH12,
"PUSH15": PUSH15, "PUSH13": PUSH13,
"PUSH16": PUSH16, "PUSH14": PUSH14,
"PUSH17": PUSH17, "PUSH15": PUSH15,
"PUSH18": PUSH18, "PUSH16": PUSH16,
"PUSH19": PUSH19, "PUSH17": PUSH17,
"PUSH20": PUSH20, "PUSH18": PUSH18,
"PUSH21": PUSH21, "PUSH19": PUSH19,
"PUSH22": PUSH22, "PUSH20": PUSH20,
"PUSH23": PUSH23, "PUSH21": PUSH21,
"PUSH24": PUSH24, "PUSH22": PUSH22,
"PUSH25": PUSH25, "PUSH23": PUSH23,
"PUSH26": PUSH26, "PUSH24": PUSH24,
"PUSH27": PUSH27, "PUSH25": PUSH25,
"PUSH28": PUSH28, "PUSH26": PUSH26,
"PUSH29": PUSH29, "PUSH27": PUSH27,
"PUSH30": PUSH30, "PUSH28": PUSH28,
"PUSH31": PUSH31, "PUSH29": PUSH29,
"PUSH32": PUSH32, "PUSH30": PUSH30,
"DUP1": DUP1, "PUSH31": PUSH31,
"DUP2": DUP2, "PUSH32": PUSH32,
"DUP3": DUP3, "DUP1": DUP1,
"DUP4": DUP4, "DUP2": DUP2,
"DUP5": DUP5, "DUP3": DUP3,
"DUP6": DUP6, "DUP4": DUP4,
"DUP7": DUP7, "DUP5": DUP5,
"DUP8": DUP8, "DUP6": DUP6,
"DUP9": DUP9, "DUP7": DUP7,
"DUP10": DUP10, "DUP8": DUP8,
"DUP11": DUP11, "DUP9": DUP9,
"DUP12": DUP12, "DUP10": DUP10,
"DUP13": DUP13, "DUP11": DUP11,
"DUP14": DUP14, "DUP12": DUP12,
"DUP15": DUP15, "DUP13": DUP13,
"DUP16": DUP16, "DUP14": DUP14,
"SWAP1": SWAP1, "DUP15": DUP15,
"SWAP2": SWAP2, "DUP16": DUP16,
"SWAP3": SWAP3, "SWAP1": SWAP1,
"SWAP4": SWAP4, "SWAP2": SWAP2,
"SWAP5": SWAP5, "SWAP3": SWAP3,
"SWAP6": SWAP6, "SWAP4": SWAP4,
"SWAP7": SWAP7, "SWAP5": SWAP5,
"SWAP8": SWAP8, "SWAP6": SWAP6,
"SWAP9": SWAP9, "SWAP7": SWAP7,
"SWAP10": SWAP10, "SWAP8": SWAP8,
"SWAP11": SWAP11, "SWAP9": SWAP9,
"SWAP12": SWAP12, "SWAP10": SWAP10,
"SWAP13": SWAP13, "SWAP11": SWAP11,
"SWAP14": SWAP14, "SWAP12": SWAP12,
"SWAP15": SWAP15, "SWAP13": SWAP13,
"SWAP16": SWAP16, "SWAP14": SWAP14,
"LOG0": LOG0, "SWAP15": SWAP15,
"LOG1": LOG1, "SWAP16": SWAP16,
"LOG2": LOG2, "LOG0": LOG0,
"LOG3": LOG3, "LOG1": LOG1,
"LOG4": LOG4, "LOG2": LOG2,
"CREATE": CREATE, "LOG3": LOG3,
"CALL": CALL, "LOG4": LOG4,
"RETURN": RETURN, "CREATE": CREATE,
"CALLCODE": CALLCODE, "CALL": CALL,
"SELFDESTRUCT": SELFDESTRUCT, "RETURN": RETURN,
"CALLCODE": CALLCODE,
"SELFDESTRUCT": SELFDESTRUCT,
} }
func StringToOp(str string) OpCode { func StringToOp(str string) OpCode {

@ -1 +1 @@
Subproject commit 815151e4cea4e73328f8586b4e61c3d7e1e9e543 Subproject commit 85f6d7cc01b6bd04e071f5ba579fc675cfd2043b