core/vm: reimplemented RETURNDATA{SIZE, COPY}

Reimplemented RETURNDATA such that the returndata buffer is isolated
inside the interpreter rather than the memory object.
This commit is contained in:
Jeffrey Wilcke 2017-05-29 09:10:23 +02:00
parent f7212a43df
commit ad0a31f9a4
3 changed files with 9 additions and 4 deletions

View file

@ -718,7 +718,7 @@ func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *
}
func opReturnDataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
stack.push(evm.interpreter.intPool.get().SetUint64(uint64(len(memory.lastReturn))))
stack.push(evm.interpreter.intPool.get().SetUint64(uint64(len(evm.interpreter.returnData))))
return nil, nil
}
@ -728,7 +728,7 @@ func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory,
cOff = stack.pop()
l = stack.pop()
)
memory.Set(mOff.Uint64(), l.Uint64(), getData(memory.lastReturn, cOff, l))
memory.Set(mOff.Uint64(), l.Uint64(), getData(evm.interpreter.returnData, cOff, l))
evm.interpreter.intPool.put(mOff, cOff, l)
return nil, nil

View file

@ -61,6 +61,8 @@ type Interpreter struct {
intPool *intPool
readonly bool
// returnData contains the last call's return data
returnData []byte
}
// NewInterpreter returns a new instance of the Interpreter.
@ -108,8 +110,12 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack
// considered a revert-and-consume-all-gas operation. No error specific checks
// should be handled to reduce complexity and errors further down the in.
func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret []byte, err error) {
// Increment the call depth which is restricted to 1024.
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 {
@ -228,7 +234,7 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret
// if the operation returned a value make sure that is also set
// the last return data.
if res != nil {
mem.lastReturn = ret
in.returnData = res
}
}
return nil, nil

View file

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