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
|
||||
}
|
||||
|
||||
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) {
|
||||
var (
|
||||
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
|
||||
|
||||
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) {
|
||||
|
|
@ -637,7 +637,7 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
|
|||
contract.Gas += returnGas
|
||||
|
||||
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) {
|
||||
|
|
@ -671,7 +671,7 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
|
|||
contract.Gas += returnGas
|
||||
|
||||
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) {
|
||||
|
|
@ -696,7 +696,7 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
|
|||
contract.Gas += returnGas
|
||||
|
||||
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) {
|
||||
|
|
@ -704,6 +704,7 @@ func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
|
|||
ret := memory.GetPtr(offset.Int64(), size.Int64())
|
||||
|
||||
evm.interpreter.intPool.put(offset, size)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
|
|
@ -734,6 +735,31 @@ func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *
|
|||
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
|
||||
|
||||
// make log instruction function
|
||||
|
|
|
|||
|
|
@ -216,6 +216,11 @@ func (evm *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
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -829,6 +829,19 @@ func NewJumpTable() [256]operation {
|
|||
memorySize: memoryLog,
|
||||
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: {
|
||||
execute: opCreate,
|
||||
gasCost: gasCreate,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import "fmt"
|
|||
type Memory struct {
|
||||
store []byte
|
||||
lastGasCost uint64
|
||||
lastReturn []byte
|
||||
}
|
||||
|
||||
func NewMemory() *Memory {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ 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))
|
||||
}
|
||||
|
||||
func memoryCodeCopy(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,6 +194,11 @@ const (
|
|||
SWAP
|
||||
)
|
||||
|
||||
const (
|
||||
RETURNDATASIZE OpCode = 0xd0 + iota
|
||||
RETURNDATACOPY
|
||||
)
|
||||
|
||||
const (
|
||||
// 0xf0 range - closures
|
||||
CREATE OpCode = 0xf0 + iota
|
||||
|
|
@ -351,6 +356,8 @@ var opCodeToString = map[OpCode]string{
|
|||
LOG3: "LOG3",
|
||||
LOG4: "LOG4",
|
||||
|
||||
RETURNDATASIZE: "RETURNDATASIZE",
|
||||
RETURNDATACOPY: "RETURNDATACOPY",
|
||||
// 0xf0 range
|
||||
CREATE: "CREATE",
|
||||
CALL: "CALL",
|
||||
|
|
@ -508,6 +515,8 @@ var stringToOp = map[string]OpCode{
|
|||
"REVERT": REVERT,
|
||||
"CALLCODE": CALLCODE,
|
||||
"SELFDESTRUCT": SELFDESTRUCT,
|
||||
"RETURNDATASIZE": RETURNDATASIZE,
|
||||
"RETURNDATACOPY": RETURNDATACOPY,
|
||||
}
|
||||
|
||||
func StringToOp(str string) OpCode {
|
||||
|
|
|
|||
Loading…
Reference in a new issue