mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
core/vm: implemented RETURNDATA{COPY, SIZE}
This commit is contained in:
parent
1e5725f03b
commit
5f972398ae
7 changed files with 220 additions and 136 deletions
|
|
@ -71,6 +71,32 @@ func gasCalldataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *St
|
||||||
return gas, nil
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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 gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
var (
|
var (
|
||||||
y, x = stack.Back(1), stack.Back(0)
|
y, x = stack.Back(1), stack.Back(0)
|
||||||
|
|
|
||||||
|
|
@ -604,7 +604,7 @@ func opStaticCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac
|
||||||
contract.Gas += returnGas
|
contract.Gas += returnGas
|
||||||
|
|
||||||
evm.interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize)
|
evm.interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize)
|
||||||
return nil, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
|
@ -637,7 +637,7 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
|
||||||
contract.Gas += returnGas
|
contract.Gas += returnGas
|
||||||
|
|
||||||
evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
|
evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
|
||||||
return nil, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
|
@ -671,7 +671,7 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
|
||||||
contract.Gas += returnGas
|
contract.Gas += returnGas
|
||||||
|
|
||||||
evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
|
evm.interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
|
||||||
return nil, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
|
@ -696,7 +696,7 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
|
||||||
contract.Gas += returnGas
|
contract.Gas += returnGas
|
||||||
|
|
||||||
evm.interpreter.intPool.put(to, inOffset, inSize, outOffset, outSize)
|
evm.interpreter.intPool.put(to, inOffset, inSize, outOffset, outSize)
|
||||||
return nil, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
|
@ -704,6 +704,7 @@ func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
|
||||||
ret := memory.GetPtr(offset.Int64(), size.Int64())
|
ret := memory.GetPtr(offset.Int64(), size.Int64())
|
||||||
|
|
||||||
evm.interpreter.intPool.put(offset, size)
|
evm.interpreter.intPool.put(offset, size)
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -734,6 +735,31 @@ func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func opReturnDataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
if !evm.ChainConfig().IsMetropolis(evm.BlockNumber) {
|
||||||
|
return nil, fmt.Errorf("invalid opcode %x", RETURNDATASIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.push(evm.interpreter.intPool.get().SetUint64(uint64(len(memory.lastReturn))))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
|
if !evm.ChainConfig().IsMetropolis(evm.BlockNumber) {
|
||||||
|
return nil, fmt.Errorf("invalid opcode %x", RETURNDATACOPY)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
mOff = stack.pop()
|
||||||
|
cOff = stack.pop()
|
||||||
|
l = stack.pop()
|
||||||
|
)
|
||||||
|
memory.Set(mOff.Uint64(), l.Uint64(), getData(memory.lastReturn, cOff, l))
|
||||||
|
|
||||||
|
evm.interpreter.intPool.put(mOff, cOff, l)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// following functions are used by the instruction jump table
|
// following functions are used by the instruction jump table
|
||||||
|
|
||||||
// make log instruction function
|
// make log instruction function
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,11 @@ func (evm *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
|
||||||
|
// the last return data.
|
||||||
|
if res != nil {
|
||||||
|
mem.lastReturn = ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -829,6 +829,19 @@ func NewJumpTable() [256]operation {
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
valid: true,
|
valid: true,
|
||||||
},
|
},
|
||||||
|
RETURNDATASIZE: {
|
||||||
|
execute: opReturnDataSize,
|
||||||
|
gasCost: constGasFunc(0), // TODO
|
||||||
|
validateStack: makeStackFunc(0, 1),
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
RETURNDATACOPY: {
|
||||||
|
execute: opReturnDataCopy,
|
||||||
|
gasCost: gasReturnDataCopy,
|
||||||
|
validateStack: makeStackFunc(3, 0),
|
||||||
|
memorySize: memoryReturnDataCopy,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
CREATE: {
|
CREATE: {
|
||||||
execute: opCreate,
|
execute: opCreate,
|
||||||
gasCost: gasCreate,
|
gasCost: gasCreate,
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import "fmt"
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
store []byte
|
store []byte
|
||||||
lastGasCost uint64
|
lastGasCost uint64
|
||||||
|
lastReturn []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemory() *Memory {
|
func NewMemory() *Memory {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ func memoryCalldataCopy(stack *Stack) *big.Int {
|
||||||
return calcMemSize(stack.Back(0), stack.Back(2))
|
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func memoryReturnDataCopy(stack *Stack) *big.Int {
|
||||||
|
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||||
|
}
|
||||||
|
|
||||||
func memoryCodeCopy(stack *Stack) *big.Int {
|
func memoryCodeCopy(stack *Stack) *big.Int {
|
||||||
return calcMemSize(stack.Back(0), stack.Back(2))
|
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,11 @@ const (
|
||||||
SWAP
|
SWAP
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RETURNDATASIZE OpCode = 0xd0 + iota
|
||||||
|
RETURNDATACOPY
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// 0xf0 range - closures
|
// 0xf0 range - closures
|
||||||
CREATE OpCode = 0xf0 + iota
|
CREATE OpCode = 0xf0 + iota
|
||||||
|
|
@ -351,6 +356,8 @@ var opCodeToString = map[OpCode]string{
|
||||||
LOG3: "LOG3",
|
LOG3: "LOG3",
|
||||||
LOG4: "LOG4",
|
LOG4: "LOG4",
|
||||||
|
|
||||||
|
RETURNDATASIZE: "RETURNDATASIZE",
|
||||||
|
RETURNDATACOPY: "RETURNDATACOPY",
|
||||||
// 0xf0 range
|
// 0xf0 range
|
||||||
CREATE: "CREATE",
|
CREATE: "CREATE",
|
||||||
CALL: "CALL",
|
CALL: "CALL",
|
||||||
|
|
@ -376,138 +383,140 @@ 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,
|
||||||
"STATIC_CALL": STATIC_CALL,
|
"STATIC_CALL": STATIC_CALL,
|
||||||
"CODESIZE": CODESIZE,
|
"CODESIZE": CODESIZE,
|
||||||
"CODECOPY": CODECOPY,
|
"CODECOPY": CODECOPY,
|
||||||
"GASPRICE": GASPRICE,
|
"GASPRICE": GASPRICE,
|
||||||
"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,
|
"EXTCODESIZE": EXTCODESIZE,
|
||||||
"EXTCODECOPY": EXTCODECOPY,
|
"EXTCODECOPY": EXTCODECOPY,
|
||||||
"POP": POP,
|
"POP": POP,
|
||||||
"MLOAD": MLOAD,
|
"MLOAD": MLOAD,
|
||||||
"MSTORE": MSTORE,
|
"MSTORE": MSTORE,
|
||||||
"MSTORE8": MSTORE8,
|
"MSTORE8": MSTORE8,
|
||||||
"SLOAD": SLOAD,
|
"SLOAD": SLOAD,
|
||||||
"SSTORE": SSTORE,
|
"SSTORE": SSTORE,
|
||||||
"JUMP": JUMP,
|
"JUMP": JUMP,
|
||||||
"JUMPI": JUMPI,
|
"JUMPI": JUMPI,
|
||||||
"PC": PC,
|
"PC": PC,
|
||||||
"MSIZE": MSIZE,
|
"MSIZE": MSIZE,
|
||||||
"GAS": GAS,
|
"GAS": GAS,
|
||||||
"JUMPDEST": JUMPDEST,
|
"JUMPDEST": JUMPDEST,
|
||||||
"PUSH1": PUSH1,
|
"PUSH1": PUSH1,
|
||||||
"PUSH2": PUSH2,
|
"PUSH2": PUSH2,
|
||||||
"PUSH3": PUSH3,
|
"PUSH3": PUSH3,
|
||||||
"PUSH4": PUSH4,
|
"PUSH4": PUSH4,
|
||||||
"PUSH5": PUSH5,
|
"PUSH5": PUSH5,
|
||||||
"PUSH6": PUSH6,
|
"PUSH6": PUSH6,
|
||||||
"PUSH7": PUSH7,
|
"PUSH7": PUSH7,
|
||||||
"PUSH8": PUSH8,
|
"PUSH8": PUSH8,
|
||||||
"PUSH9": PUSH9,
|
"PUSH9": PUSH9,
|
||||||
"PUSH10": PUSH10,
|
"PUSH10": PUSH10,
|
||||||
"PUSH11": PUSH11,
|
"PUSH11": PUSH11,
|
||||||
"PUSH12": PUSH12,
|
"PUSH12": PUSH12,
|
||||||
"PUSH13": PUSH13,
|
"PUSH13": PUSH13,
|
||||||
"PUSH14": PUSH14,
|
"PUSH14": PUSH14,
|
||||||
"PUSH15": PUSH15,
|
"PUSH15": PUSH15,
|
||||||
"PUSH16": PUSH16,
|
"PUSH16": PUSH16,
|
||||||
"PUSH17": PUSH17,
|
"PUSH17": PUSH17,
|
||||||
"PUSH18": PUSH18,
|
"PUSH18": PUSH18,
|
||||||
"PUSH19": PUSH19,
|
"PUSH19": PUSH19,
|
||||||
"PUSH20": PUSH20,
|
"PUSH20": PUSH20,
|
||||||
"PUSH21": PUSH21,
|
"PUSH21": PUSH21,
|
||||||
"PUSH22": PUSH22,
|
"PUSH22": PUSH22,
|
||||||
"PUSH23": PUSH23,
|
"PUSH23": PUSH23,
|
||||||
"PUSH24": PUSH24,
|
"PUSH24": PUSH24,
|
||||||
"PUSH25": PUSH25,
|
"PUSH25": PUSH25,
|
||||||
"PUSH26": PUSH26,
|
"PUSH26": PUSH26,
|
||||||
"PUSH27": PUSH27,
|
"PUSH27": PUSH27,
|
||||||
"PUSH28": PUSH28,
|
"PUSH28": PUSH28,
|
||||||
"PUSH29": PUSH29,
|
"PUSH29": PUSH29,
|
||||||
"PUSH30": PUSH30,
|
"PUSH30": PUSH30,
|
||||||
"PUSH31": PUSH31,
|
"PUSH31": PUSH31,
|
||||||
"PUSH32": PUSH32,
|
"PUSH32": PUSH32,
|
||||||
"DUP1": DUP1,
|
"DUP1": DUP1,
|
||||||
"DUP2": DUP2,
|
"DUP2": DUP2,
|
||||||
"DUP3": DUP3,
|
"DUP3": DUP3,
|
||||||
"DUP4": DUP4,
|
"DUP4": DUP4,
|
||||||
"DUP5": DUP5,
|
"DUP5": DUP5,
|
||||||
"DUP6": DUP6,
|
"DUP6": DUP6,
|
||||||
"DUP7": DUP7,
|
"DUP7": DUP7,
|
||||||
"DUP8": DUP8,
|
"DUP8": DUP8,
|
||||||
"DUP9": DUP9,
|
"DUP9": DUP9,
|
||||||
"DUP10": DUP10,
|
"DUP10": DUP10,
|
||||||
"DUP11": DUP11,
|
"DUP11": DUP11,
|
||||||
"DUP12": DUP12,
|
"DUP12": DUP12,
|
||||||
"DUP13": DUP13,
|
"DUP13": DUP13,
|
||||||
"DUP14": DUP14,
|
"DUP14": DUP14,
|
||||||
"DUP15": DUP15,
|
"DUP15": DUP15,
|
||||||
"DUP16": DUP16,
|
"DUP16": DUP16,
|
||||||
"SWAP1": SWAP1,
|
"SWAP1": SWAP1,
|
||||||
"SWAP2": SWAP2,
|
"SWAP2": SWAP2,
|
||||||
"SWAP3": SWAP3,
|
"SWAP3": SWAP3,
|
||||||
"SWAP4": SWAP4,
|
"SWAP4": SWAP4,
|
||||||
"SWAP5": SWAP5,
|
"SWAP5": SWAP5,
|
||||||
"SWAP6": SWAP6,
|
"SWAP6": SWAP6,
|
||||||
"SWAP7": SWAP7,
|
"SWAP7": SWAP7,
|
||||||
"SWAP8": SWAP8,
|
"SWAP8": SWAP8,
|
||||||
"SWAP9": SWAP9,
|
"SWAP9": SWAP9,
|
||||||
"SWAP10": SWAP10,
|
"SWAP10": SWAP10,
|
||||||
"SWAP11": SWAP11,
|
"SWAP11": SWAP11,
|
||||||
"SWAP12": SWAP12,
|
"SWAP12": SWAP12,
|
||||||
"SWAP13": SWAP13,
|
"SWAP13": SWAP13,
|
||||||
"SWAP14": SWAP14,
|
"SWAP14": SWAP14,
|
||||||
"SWAP15": SWAP15,
|
"SWAP15": SWAP15,
|
||||||
"SWAP16": SWAP16,
|
"SWAP16": SWAP16,
|
||||||
"LOG0": LOG0,
|
"LOG0": LOG0,
|
||||||
"LOG1": LOG1,
|
"LOG1": LOG1,
|
||||||
"LOG2": LOG2,
|
"LOG2": LOG2,
|
||||||
"LOG3": LOG3,
|
"LOG3": LOG3,
|
||||||
"LOG4": LOG4,
|
"LOG4": LOG4,
|
||||||
"CREATE": CREATE,
|
"CREATE": CREATE,
|
||||||
"CALL": CALL,
|
"CALL": CALL,
|
||||||
"RETURN": RETURN,
|
"RETURN": RETURN,
|
||||||
"REVERT": REVERT,
|
"REVERT": REVERT,
|
||||||
"CALLCODE": CALLCODE,
|
"CALLCODE": CALLCODE,
|
||||||
"SELFDESTRUCT": SELFDESTRUCT,
|
"SELFDESTRUCT": SELFDESTRUCT,
|
||||||
|
"RETURNDATASIZE": RETURNDATASIZE,
|
||||||
|
"RETURNDATACOPY": RETURNDATACOPY,
|
||||||
}
|
}
|
||||||
|
|
||||||
func StringToOp(str string) OpCode {
|
func StringToOp(str string) OpCode {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue