forked from cerc-io/plugeth
Merge pull request #14981 from karalabe/metropolis-returndata
core/vm: implement RETURNDATA metropolis opcodes
This commit is contained in:
commit
0b978f91b6
@ -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 (
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user