Merge pull request #14981 from karalabe/metropolis-returndata
core/vm: implement RETURNDATA metropolis opcodes
This commit is contained in:
		@@ -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 (
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 (
 | 
			
		||||
		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))
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@ import "fmt"
 | 
			
		||||
type Memory struct {
 | 
			
		||||
	store       []byte
 | 
			
		||||
	lastGasCost uint64
 | 
			
		||||
	lastReturn  []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewMemory() *Memory {
 | 
			
		||||
 
 | 
			
		||||
@@ -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))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
 Submodule tests/testdata updated: 815151e4ce...85f6d7cc01
									
								
							
		Reference in New Issue
	
	Block a user