aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-08-16 18:36:48 +0800
committerPéter Szilágyi <peterke@gmail.com>2017-08-16 18:43:14 +0800
commit4e0fea4d30e922c1cc0e8e2f33e5ad8ae55053d6 (patch)
tree83afa01b7768105ad8f6b76ff13c07232f3a369e /core
parent9bd6068fefe5687735bed342f3545f515fa717c8 (diff)
downloadgo-tangerine-4e0fea4d30e922c1cc0e8e2f33e5ad8ae55053d6.tar
go-tangerine-4e0fea4d30e922c1cc0e8e2f33e5ad8ae55053d6.tar.gz
go-tangerine-4e0fea4d30e922c1cc0e8e2f33e5ad8ae55053d6.tar.bz2
go-tangerine-4e0fea4d30e922c1cc0e8e2f33e5ad8ae55053d6.tar.lz
go-tangerine-4e0fea4d30e922c1cc0e8e2f33e5ad8ae55053d6.tar.xz
go-tangerine-4e0fea4d30e922c1cc0e8e2f33e5ad8ae55053d6.tar.zst
go-tangerine-4e0fea4d30e922c1cc0e8e2f33e5ad8ae55053d6.zip
core/vm: polish RETURNDATA, add missing returns to CALL*
Diffstat (limited to 'core')
-rw-r--r--core/vm/evm.go6
-rw-r--r--core/vm/gas_table.go2
-rw-r--r--core/vm/instructions.go73
-rw-r--r--core/vm/interpreter.go9
-rw-r--r--core/vm/jump_table.go54
-rw-r--r--core/vm/memory.go1
-rw-r--r--core/vm/memory_table.go2
7 files changed, 75 insertions, 72 deletions
diff --git a/core/vm/evm.go b/core/vm/evm.go
index cc4214a16..448acd469 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -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 (
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index 6cdbc5c39..a6346bd80 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -65,7 +65,7 @@ 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
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 0dd9af096..4d6197912 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -29,9 +29,9 @@ import (
)
var (
- bigZero = new(big.Int)
- errWriteProtection = errors.New("evm: write protection")
- errReadOutOfBound = errors.New("evm: read out of bound")
+ 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) {
@@ -243,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))
@@ -250,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))
@@ -269,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 {
@@ -282,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 {
@@ -339,25 +343,25 @@ 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(mOff, cOff, l)
+ evm.interpreter.intPool.put(memOffset, dataOffset, length)
return nil, nil
}
@@ -368,17 +372,17 @@ func opReturnDataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory,
func opReturnDataCopy(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()
)
- defer evm.interpreter.intPool.put(mOff, cOff, l)
+ defer evm.interpreter.intPool.put(memOffset, dataOffset, length)
- cEnd := new(big.Int).Add(cOff, l)
- if cEnd.BitLen() > 64 || uint64(len(evm.interpreter.returnData)) < cEnd.Uint64() {
- return nil, errReadOutOfBound
+ end := new(big.Int).Add(dataOffset, length)
+ if end.BitLen() > 64 || uint64(len(evm.interpreter.returnData)) < end.Uint64() {
+ return nil, errReturnDataOutOfBounds
}
- memory.Set(mOff.Uint64(), l.Uint64(), evm.interpreter.returnData[cOff.Uint64():cEnd.Uint64()])
+ memory.Set(memOffset.Uint64(), length.Uint64(), evm.interpreter.returnData[dataOffset.Uint64():end.Uint64()])
return nil, nil
}
@@ -401,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)
-
- memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
+ codeCopy := getDataBig(contract.Code, codeOffset, length)
+ memory.Set(memOffset.Uint64(), length.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
}
@@ -530,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 {
@@ -545,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
}
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 1c7481bc5..954839f2e 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -59,9 +59,8 @@ type Interpreter struct {
gasTable params.GasTable
intPool *intPool
- readonly bool
- // returnData contains the last call's return data
- returnData []byte
+ 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.
@@ -90,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
@@ -221,7 +220,7 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (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.clearsReturndata {
+ if operation.returns {
in.returnData = res
}
}
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 7fb11021f..2d238f7a1 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -53,8 +53,8 @@ type operation struct {
valid bool
// reverts determined whether the operation reverts state
reverts bool
- // clearsReturndata determines whether the opertions clears the return data
- clearsReturndata bool
+ // returns determines whether the opertions sets the return data
+ returns bool
}
var (
@@ -74,6 +74,7 @@ func NewMetropolisInstructionSet() [256]operation {
validateStack: makeStackFunc(6, 1),
memorySize: memoryStaticCall,
valid: true,
+ returns: true,
}
instructionSet[RETURNDATASIZE] = operation{
execute: opReturnDataSize,
@@ -101,6 +102,7 @@ func NewHomesteadInstructionSet() [256]operation {
validateStack: makeStackFunc(6, 1),
memorySize: memoryDelegateCall,
valid: true,
+ returns: true,
}
return instructionSet
}
@@ -286,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: {
@@ -876,29 +878,29 @@ func NewFrontierInstructionSet() [256]operation {
writes: true,
},
CREATE: {
- execute: opCreate,
- gasCost: gasCreate,
- validateStack: makeStackFunc(3, 1),
- memorySize: memoryCreate,
- valid: true,
- writes: true,
- clearsReturndata: true,
+ execute: opCreate,
+ gasCost: gasCreate,
+ validateStack: makeStackFunc(3, 1),
+ memorySize: memoryCreate,
+ valid: true,
+ writes: true,
+ returns: true,
},
CALL: {
- execute: opCall,
- gasCost: gasCall,
- validateStack: makeStackFunc(7, 1),
- memorySize: memoryCall,
- valid: true,
- clearsReturndata: true,
+ execute: opCall,
+ gasCost: gasCall,
+ validateStack: makeStackFunc(7, 1),
+ memorySize: memoryCall,
+ valid: true,
+ returns: true,
},
CALLCODE: {
- execute: opCallCode,
- gasCost: gasCallCode,
- validateStack: makeStackFunc(7, 1),
- memorySize: memoryCall,
- valid: true,
- clearsReturndata: true,
+ execute: opCallCode,
+ gasCost: gasCallCode,
+ validateStack: makeStackFunc(7, 1),
+ memorySize: memoryCall,
+ valid: true,
+ returns: true,
},
RETURN: {
execute: opReturn,
diff --git a/core/vm/memory.go b/core/vm/memory.go
index 6dbee94ef..99a84d227 100644
--- a/core/vm/memory.go
+++ b/core/vm/memory.go
@@ -22,7 +22,6 @@ import "fmt"
type Memory struct {
store []byte
lastGasCost uint64
- lastReturn []byte
}
func NewMemory() *Memory {
diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go
index 9f6533bbc..f1b671adc 100644
--- a/core/vm/memory_table.go
+++ b/core/vm/memory_table.go
@@ -26,7 +26,7 @@ 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))
}