aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2019-03-12 17:40:05 +0800
committerPéter Szilágyi <peterke@gmail.com>2019-03-12 17:40:05 +0800
commit7504dbd6eb3f62371f86b06b03ffd665690951f2 (patch)
treed16b8f9989a4f994966d1325de791b698432f8e3 /core/vm
parentda5de012c35c677e2e7a43373951ba18b6749e9b (diff)
downloadgo-tangerine-7504dbd6eb3f62371f86b06b03ffd665690951f2.tar
go-tangerine-7504dbd6eb3f62371f86b06b03ffd665690951f2.tar.gz
go-tangerine-7504dbd6eb3f62371f86b06b03ffd665690951f2.tar.bz2
go-tangerine-7504dbd6eb3f62371f86b06b03ffd665690951f2.tar.lz
go-tangerine-7504dbd6eb3f62371f86b06b03ffd665690951f2.tar.xz
go-tangerine-7504dbd6eb3f62371f86b06b03ffd665690951f2.tar.zst
go-tangerine-7504dbd6eb3f62371f86b06b03ffd665690951f2.zip
core/vm: 64 bit memory and gas calculations (#19210)
* core/vm: remove function call for stack validation from evm runloop * core/vm: separate gas calc into static + dynamic * core/vm: optimize push1 * core/vm: reuse pooled bigints for ADDRESS, ORIGIN and CALLER * core/vm: use generic error message for jump/jumpi, to avoid string interpolation * testdata: fix tests for new error message * core/vm: use 64-bit memory calculations * core/vm: fix error in memory calculation * core/vm: address review concerns * core/vm: avoid unnecessary use of big.Int:BitLen()
Diffstat (limited to 'core/vm')
-rw-r--r--core/vm/common.go30
-rw-r--r--core/vm/gas.go4
-rw-r--r--core/vm/gas_table.go18
-rw-r--r--core/vm/instructions.go37
-rw-r--r--core/vm/interpreter.go51
-rw-r--r--core/vm/jump_table.go1358
-rw-r--r--core/vm/memory_table.go114
-rw-r--r--core/vm/stack_table.go32
8 files changed, 908 insertions, 736 deletions
diff --git a/core/vm/common.go b/core/vm/common.go
index 17de38dec..d592a9410 100644
--- a/core/vm/common.go
+++ b/core/vm/common.go
@@ -23,13 +23,31 @@ import (
"github.com/ethereum/go-ethereum/common/math"
)
-// calculates the memory size required for a step
-func calcMemSize(off, l *big.Int) *big.Int {
- if l.Sign() == 0 {
- return common.Big0
+// calcMemSize64 calculates the required memory size, and returns
+// the size and whether the result overflowed uint64
+func calcMemSize64(off, l *big.Int) (uint64, bool) {
+ if !l.IsUint64() {
+ return 0, true
}
+ return calcMemSize64WithUint(off, l.Uint64())
+}
- return new(big.Int).Add(off, l)
+// calcMemSize64WithUint calculates the required memory size, and returns
+// the size and whether the result overflowed uint64
+// Identical to calcMemSize64, but length is a uint64
+func calcMemSize64WithUint(off *big.Int, length64 uint64) (uint64, bool) {
+ // if length is zero, memsize is always zero, regardless of offset
+ if length64 == 0 {
+ return 0, false
+ }
+ // Check that offset doesn't overflow
+ if !off.IsUint64() {
+ return 0, true
+ }
+ offset64 := off.Uint64()
+ val := offset64 + length64
+ // if value < either of it's parts, then it overflowed
+ return val, val < offset64
}
// getData returns a slice from the data based on the start and size and pads
@@ -59,7 +77,7 @@ func getDataBig(data []byte, start *big.Int, size *big.Int) []byte {
// bigUint64 returns the integer casted to a uint64 and returns whether it
// overflowed in the process.
func bigUint64(v *big.Int) (uint64, bool) {
- return v.Uint64(), v.BitLen() > 64
+ return v.Uint64(), !v.IsUint64()
}
// toWordSize returns the ceiled word size required for memory expansion.
diff --git a/core/vm/gas.go b/core/vm/gas.go
index dba1b3a02..022a84f24 100644
--- a/core/vm/gas.go
+++ b/core/vm/gas.go
@@ -43,11 +43,11 @@ func callGas(gasTable params.GasTable, availableGas, base uint64, callCost *big.
// If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150
// is smaller than the requested amount. Therefor we return the new gas instead
// of returning an error.
- if callCost.BitLen() > 64 || gas < callCost.Uint64() {
+ if !callCost.IsUint64() || gas < callCost.Uint64() {
return gas, nil
}
}
- if callCost.BitLen() > 64 {
+ if !callCost.IsUint64() {
return 0, errGasUintOverflow
}
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index f22463c33..6400c1324 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -57,12 +57,6 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
return 0, nil
}
-func constGasFunc(gas uint64) gasFunc {
- return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return gas, nil
- }
-}
-
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 {
@@ -521,15 +515,3 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stac
}
return gas, nil
}
-
-func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return GasFastestStep, nil
-}
-
-func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return GasFastestStep, nil
-}
-
-func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return GasFastestStep, nil
-}
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 5195e716b..2a062d7e7 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -18,7 +18,6 @@ package vm
import (
"errors"
- "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -35,6 +34,7 @@ var (
errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
errExecutionReverted = errors.New("evm: execution reverted")
errMaxCodeSizeExceeded = errors.New("evm: max code size exceeded")
+ errInvalidJump = errors.New("evm: invalid jump destination")
)
func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
@@ -405,7 +405,7 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
}
func opAddress(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(contract.Address().Big())
+ stack.push(interpreter.intPool.get().SetBytes(contract.Address().Bytes()))
return nil, nil
}
@@ -416,12 +416,12 @@ func opBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
}
func opOrigin(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.evm.Origin.Big())
+ stack.push(interpreter.intPool.get().SetBytes(interpreter.evm.Origin.Bytes()))
return nil, nil
}
func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(contract.Caller().Big())
+ stack.push(interpreter.intPool.get().SetBytes(contract.Caller().Bytes()))
return nil, nil
}
@@ -467,7 +467,7 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contrac
)
defer interpreter.intPool.put(memOffset, dataOffset, length, end)
- if end.BitLen() > 64 || uint64(len(interpreter.returnData)) < end.Uint64() {
+ if !end.IsUint64() || uint64(len(interpreter.returnData)) < end.Uint64() {
return nil, errReturnDataOutOfBounds
}
memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[dataOffset.Uint64():end.Uint64()])
@@ -572,7 +572,7 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, me
}
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.evm.Coinbase.Big())
+ stack.push(interpreter.intPool.get().SetBytes(interpreter.evm.Coinbase.Bytes()))
return nil, nil
}
@@ -645,8 +645,7 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
func opJump(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
pos := stack.pop()
if !contract.validJumpdest(pos) {
- nop := contract.GetOp(pos.Uint64())
- return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
+ return nil, errInvalidJump
}
*pc = pos.Uint64()
@@ -658,8 +657,7 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
pos, cond := stack.pop(), stack.pop()
if cond.Sign() != 0 {
if !contract.validJumpdest(pos) {
- nop := contract.GetOp(pos.Uint64())
- return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
+ return nil, errInvalidJump
}
*pc = pos.Uint64()
} else {
@@ -711,7 +709,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
stack.push(interpreter.intPool.getZero())
} else {
- stack.push(addr.Big())
+ stack.push(interpreter.intPool.get().SetBytes(addr.Bytes()))
}
contract.Gas += returnGas
interpreter.intPool.put(value, offset, size)
@@ -739,7 +737,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
if suberr != nil {
stack.push(interpreter.intPool.getZero())
} else {
- stack.push(addr.Big())
+ stack.push(interpreter.intPool.get().SetBytes(addr.Bytes()))
}
contract.Gas += returnGas
interpreter.intPool.put(endowment, offset, size, salt)
@@ -912,6 +910,21 @@ func makeLog(size int) executionFunc {
}
}
+// opPush1 is a specialized version of pushN
+func opPush1(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ var (
+ codeLen = uint64(len(contract.Code))
+ integer = interpreter.intPool.get()
+ )
+ *pc += 1
+ if *pc < codeLen {
+ stack.push(integer.SetUint64(uint64(contract.Code[*pc])))
+ } else {
+ stack.push(integer.SetUint64(0))
+ }
+ return nil, nil
+}
+
// make push instruction function
func makePush(size uint64, pushByteSize int) executionFunc {
return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index c9dc3c00c..417665370 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -118,22 +118,6 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
}
}
-func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
- if in.evm.chainRules.IsByzantium {
- 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. Transferring value from one
- // account to the others means the state is modified and should also
- // return with an error.
- if operation.writes || (op == CALL && stack.Back(2).BitLen() > 0) {
- return errWriteProtection
- }
- }
- }
- return nil
-}
-
// Run loops and evaluates the contract's code with the given input data and returns
// the return byte-slice and an error if one occurred.
//
@@ -217,19 +201,35 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
if !operation.valid {
return nil, fmt.Errorf("invalid opcode 0x%x", int(op))
}
- if err = operation.validateStack(stack); err != nil {
- return nil, err
+ // Validate stack
+ if sLen := stack.len(); sLen < operation.minStack {
+ return nil, fmt.Errorf("stack underflow (%d <=> %d)", sLen, operation.minStack)
+ } else if sLen > operation.maxStack {
+ return nil, fmt.Errorf("stack limit reached %d (%d)", sLen, operation.maxStack)
}
// If the operation is valid, enforce and write restrictions
- if err = in.enforceRestrictions(op, operation, stack); err != nil {
- return nil, err
+ if in.readOnly && in.evm.chainRules.IsByzantium {
+ // 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. Transferring value from one
+ // account to the others means the state is modified and should also
+ // return with an error.
+ if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) {
+ return nil, errWriteProtection
+ }
+ }
+ // Static portion of gas
+ if !contract.UseGas(operation.constantGas) {
+ return nil, ErrOutOfGas
}
var memorySize uint64
// calculate the new memory size and expand the memory to fit
// the operation
+ // Memory check needs to be done prior to evaluating the dynamic gas portion,
+ // to detect calculation overflows
if operation.memorySize != nil {
- memSize, overflow := bigUint64(operation.memorySize(stack))
+ memSize, overflow := operation.memorySize(stack)
if overflow {
return nil, errGasUintOverflow
}
@@ -239,11 +239,14 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
return nil, errGasUintOverflow
}
}
+ // Dynamic portion of gas
// consume the gas and return an error if not enough gas is available.
// cost is explicitly set so that the capture state defer method can get the proper cost
- cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize)
- if err != nil || !contract.UseGas(cost) {
- return nil, ErrOutOfGas
+ if operation.dynamicGas != nil {
+ cost, err = operation.dynamicGas(in.gasTable, in.evm, contract, stack, mem, memorySize)
+ if err != nil || !contract.UseGas(cost) {
+ return nil, ErrOutOfGas
+ }
}
if memorySize > 0 {
mem.Resize(memorySize)
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index deedf70cd..425436f9e 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -18,27 +18,30 @@ package vm
import (
"errors"
- "math/big"
"github.com/ethereum/go-ethereum/params"
)
type (
- executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
- gasFunc func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
- stackValidationFunc func(*Stack) error
- memorySizeFunc func(*Stack) *big.Int
+ executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
+ gasFunc func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
+ // memorySizeFunc returns the required size, and whether the operation overflowed a uint64
+ memorySizeFunc func(*Stack) (size uint64, overflow bool)
)
var errGasUintOverflow = errors.New("gas uint64 overflow")
type operation struct {
// execute is the operation function
- execute executionFunc
- // gasCost is the gas function and returns the gas required for execution
- gasCost gasFunc
- // validateStack validates the stack (size) for the operation
- validateStack stackValidationFunc
+ execute executionFunc
+ constantGas uint64
+ dynamicGas gasFunc
+ // minStack tells how many stack items are required
+ minStack int
+ // maxStack specifies the max length the stack can have for this operation
+ // to not overflow the stack.
+ maxStack int
+
// memorySize returns the memory size required for the operation
memorySize memorySizeFunc
@@ -63,37 +66,42 @@ func newConstantinopleInstructionSet() [256]operation {
// instructions that can be executed during the byzantium phase.
instructionSet := newByzantiumInstructionSet()
instructionSet[SHL] = operation{
- execute: opSHL,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSHL,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
}
instructionSet[SHR] = operation{
- execute: opSHR,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSHR,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
}
instructionSet[SAR] = operation{
- execute: opSAR,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSAR,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
}
instructionSet[EXTCODEHASH] = operation{
- execute: opExtCodeHash,
- gasCost: gasExtCodeHash,
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opExtCodeHash,
+ dynamicGas: gasExtCodeHash,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
}
instructionSet[CREATE2] = operation{
- execute: opCreate2,
- gasCost: gasCreate2,
- validateStack: makeStackFunc(4, 1),
- memorySize: memoryCreate2,
- valid: true,
- writes: true,
- returns: true,
+ execute: opCreate2,
+ dynamicGas: gasCreate2,
+ minStack: minStack(4, 1),
+ maxStack: maxStack(4, 1),
+ memorySize: memoryCreate2,
+ valid: true,
+ writes: true,
+ returns: true,
}
return instructionSet
}
@@ -104,34 +112,38 @@ func newByzantiumInstructionSet() [256]operation {
// instructions that can be executed during the homestead phase.
instructionSet := newHomesteadInstructionSet()
instructionSet[STATICCALL] = operation{
- execute: opStaticCall,
- gasCost: gasStaticCall,
- validateStack: makeStackFunc(6, 1),
- memorySize: memoryStaticCall,
- valid: true,
- returns: true,
+ execute: opStaticCall,
+ dynamicGas: gasStaticCall,
+ minStack: minStack(6, 1),
+ maxStack: maxStack(6, 1),
+ memorySize: memoryStaticCall,
+ valid: true,
+ returns: true,
}
instructionSet[RETURNDATASIZE] = operation{
- execute: opReturnDataSize,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opReturnDataSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
}
instructionSet[RETURNDATACOPY] = operation{
- execute: opReturnDataCopy,
- gasCost: gasReturnDataCopy,
- validateStack: makeStackFunc(3, 0),
- memorySize: memoryReturnDataCopy,
- valid: true,
+ execute: opReturnDataCopy,
+ dynamicGas: gasReturnDataCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryReturnDataCopy,
+ valid: true,
}
instructionSet[REVERT] = operation{
- execute: opRevert,
- gasCost: gasRevert,
- validateStack: makeStackFunc(2, 0),
- memorySize: memoryRevert,
- valid: true,
- reverts: true,
- returns: true,
+ execute: opRevert,
+ dynamicGas: gasRevert,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryRevert,
+ valid: true,
+ reverts: true,
+ returns: true,
}
return instructionSet
}
@@ -141,12 +153,13 @@ func newByzantiumInstructionSet() [256]operation {
func newHomesteadInstructionSet() [256]operation {
instructionSet := newFrontierInstructionSet()
instructionSet[DELEGATECALL] = operation{
- execute: opDelegateCall,
- gasCost: gasDelegateCall,
- validateStack: makeStackFunc(6, 1),
- memorySize: memoryDelegateCall,
- valid: true,
- returns: true,
+ execute: opDelegateCall,
+ dynamicGas: gasDelegateCall,
+ minStack: minStack(6, 1),
+ maxStack: maxStack(6, 1),
+ memorySize: memoryDelegateCall,
+ valid: true,
+ returns: true,
}
return instructionSet
}
@@ -156,811 +169,940 @@ func newHomesteadInstructionSet() [256]operation {
func newFrontierInstructionSet() [256]operation {
return [256]operation{
STOP: {
- execute: opStop,
- gasCost: constGasFunc(0),
- validateStack: makeStackFunc(0, 0),
- halts: true,
- valid: true,
+ execute: opStop,
+ constantGas: 0,
+ minStack: minStack(0, 0),
+ maxStack: maxStack(0, 0),
+ halts: true,
+ valid: true,
},
ADD: {
- execute: opAdd,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opAdd,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
MUL: {
- execute: opMul,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opMul,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SUB: {
- execute: opSub,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSub,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
DIV: {
- execute: opDiv,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opDiv,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SDIV: {
- execute: opSdiv,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSdiv,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
MOD: {
- execute: opMod,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opMod,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SMOD: {
- execute: opSmod,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSmod,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
ADDMOD: {
- execute: opAddmod,
- gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(3, 1),
- valid: true,
+ execute: opAddmod,
+ constantGas: GasMidStep,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ valid: true,
},
MULMOD: {
- execute: opMulmod,
- gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(3, 1),
- valid: true,
+ execute: opMulmod,
+ constantGas: GasMidStep,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ valid: true,
},
EXP: {
- execute: opExp,
- gasCost: gasExp,
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opExp,
+ dynamicGas: gasExp,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SIGNEXTEND: {
- execute: opSignExtend,
- gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSignExtend,
+ constantGas: GasFastStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
LT: {
- execute: opLt,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opLt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
GT: {
- execute: opGt,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opGt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SLT: {
- execute: opSlt,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSlt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SGT: {
- execute: opSgt,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opSgt,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
EQ: {
- execute: opEq,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opEq,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
ISZERO: {
- execute: opIszero,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opIszero,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
AND: {
- execute: opAnd,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opAnd,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
XOR: {
- execute: opXor,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opXor,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
OR: {
- execute: opOr,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opOr,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
NOT: {
- execute: opNot,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opNot,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
BYTE: {
- execute: opByte,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
- valid: true,
+ execute: opByte,
+ constantGas: GasFastestStep,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ valid: true,
},
SHA3: {
- execute: opSha3,
- gasCost: gasSha3,
- validateStack: makeStackFunc(2, 1),
- memorySize: memorySha3,
- valid: true,
+ execute: opSha3,
+ dynamicGas: gasSha3,
+ minStack: minStack(2, 1),
+ maxStack: maxStack(2, 1),
+ memorySize: memorySha3,
+ valid: true,
},
ADDRESS: {
- execute: opAddress,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opAddress,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
BALANCE: {
- execute: opBalance,
- gasCost: gasBalance,
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opBalance,
+ dynamicGas: gasBalance,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
ORIGIN: {
- execute: opOrigin,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opOrigin,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CALLER: {
- execute: opCaller,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCaller,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CALLVALUE: {
- execute: opCallValue,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCallValue,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CALLDATALOAD: {
- execute: opCallDataLoad,
- gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opCallDataLoad,
+ constantGas: GasFastestStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
CALLDATASIZE: {
- execute: opCallDataSize,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCallDataSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CALLDATACOPY: {
- execute: opCallDataCopy,
- gasCost: gasCallDataCopy,
- validateStack: makeStackFunc(3, 0),
- memorySize: memoryCallDataCopy,
- valid: true,
+ execute: opCallDataCopy,
+ dynamicGas: gasCallDataCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryCallDataCopy,
+ valid: true,
},
CODESIZE: {
- execute: opCodeSize,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCodeSize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
CODECOPY: {
- execute: opCodeCopy,
- gasCost: gasCodeCopy,
- validateStack: makeStackFunc(3, 0),
- memorySize: memoryCodeCopy,
- valid: true,
+ execute: opCodeCopy,
+ dynamicGas: gasCodeCopy,
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryCodeCopy,
+ valid: true,
},
GASPRICE: {
- execute: opGasprice,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opGasprice,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
EXTCODESIZE: {
- execute: opExtCodeSize,
- gasCost: gasExtCodeSize,
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opExtCodeSize,
+ dynamicGas: gasExtCodeSize,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
EXTCODECOPY: {
- execute: opExtCodeCopy,
- gasCost: gasExtCodeCopy,
- validateStack: makeStackFunc(4, 0),
- memorySize: memoryExtCodeCopy,
- valid: true,
+ execute: opExtCodeCopy,
+ dynamicGas: gasExtCodeCopy,
+ minStack: minStack(4, 0),
+ maxStack: maxStack(4, 0),
+ memorySize: memoryExtCodeCopy,
+ valid: true,
},
BLOCKHASH: {
- execute: opBlockhash,
- gasCost: constGasFunc(GasExtStep),
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opBlockhash,
+ constantGas: GasExtStep,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
COINBASE: {
- execute: opCoinbase,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opCoinbase,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
TIMESTAMP: {
- execute: opTimestamp,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opTimestamp,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
NUMBER: {
- execute: opNumber,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opNumber,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
DIFFICULTY: {
- execute: opDifficulty,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opDifficulty,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
GASLIMIT: {
- execute: opGasLimit,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opGasLimit,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
POP: {
- execute: opPop,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(1, 0),
- valid: true,
+ execute: opPop,
+ constantGas: GasQuickStep,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ valid: true,
},
MLOAD: {
- execute: opMload,
- gasCost: gasMLoad,
- validateStack: makeStackFunc(1, 1),
- memorySize: memoryMLoad,
- valid: true,
+ execute: opMload,
+ dynamicGas: gasMLoad,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ memorySize: memoryMLoad,
+ valid: true,
},
MSTORE: {
- execute: opMstore,
- gasCost: gasMStore,
- validateStack: makeStackFunc(2, 0),
- memorySize: memoryMStore,
- valid: true,
+ execute: opMstore,
+ dynamicGas: gasMStore,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryMStore,
+ valid: true,
},
MSTORE8: {
- execute: opMstore8,
- gasCost: gasMStore8,
- memorySize: memoryMStore8,
- validateStack: makeStackFunc(2, 0),
+ execute: opMstore8,
+ dynamicGas: gasMStore8,
+ memorySize: memoryMStore8,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
valid: true,
},
SLOAD: {
- execute: opSload,
- gasCost: gasSLoad,
- validateStack: makeStackFunc(1, 1),
- valid: true,
+ execute: opSload,
+ dynamicGas: gasSLoad,
+ minStack: minStack(1, 1),
+ maxStack: maxStack(1, 1),
+ valid: true,
},
SSTORE: {
- execute: opSstore,
- gasCost: gasSStore,
- validateStack: makeStackFunc(2, 0),
- valid: true,
- writes: true,
+ execute: opSstore,
+ dynamicGas: gasSStore,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ valid: true,
+ writes: true,
},
JUMP: {
- execute: opJump,
- gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(1, 0),
- jumps: true,
- valid: true,
+ execute: opJump,
+ constantGas: GasMidStep,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ jumps: true,
+ valid: true,
},
JUMPI: {
- execute: opJumpi,
- gasCost: constGasFunc(GasSlowStep),
- validateStack: makeStackFunc(2, 0),
- jumps: true,
- valid: true,
+ execute: opJumpi,
+ constantGas: GasSlowStep,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ jumps: true,
+ valid: true,
},
PC: {
- execute: opPc,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opPc,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
MSIZE: {
- execute: opMsize,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opMsize,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
GAS: {
- execute: opGas,
- gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opGas,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
JUMPDEST: {
- execute: opJumpdest,
- gasCost: constGasFunc(params.JumpdestGas),
- validateStack: makeStackFunc(0, 0),
- valid: true,
+ execute: opJumpdest,
+ constantGas: params.JumpdestGas,
+ minStack: minStack(0, 0),
+ maxStack: maxStack(0, 0),
+ valid: true,
},
PUSH1: {
- execute: makePush(1, 1),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: opPush1,
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH2: {
- execute: makePush(2, 2),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(2, 2),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH3: {
- execute: makePush(3, 3),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(3, 3),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH4: {
- execute: makePush(4, 4),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(4, 4),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH5: {
- execute: makePush(5, 5),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(5, 5),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH6: {
- execute: makePush(6, 6),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(6, 6),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH7: {
- execute: makePush(7, 7),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(7, 7),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH8: {
- execute: makePush(8, 8),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(8, 8),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH9: {
- execute: makePush(9, 9),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(9, 9),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH10: {
- execute: makePush(10, 10),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(10, 10),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH11: {
- execute: makePush(11, 11),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(11, 11),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH12: {
- execute: makePush(12, 12),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(12, 12),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH13: {
- execute: makePush(13, 13),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(13, 13),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH14: {
- execute: makePush(14, 14),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(14, 14),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH15: {
- execute: makePush(15, 15),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(15, 15),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH16: {
- execute: makePush(16, 16),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(16, 16),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH17: {
- execute: makePush(17, 17),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(17, 17),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH18: {
- execute: makePush(18, 18),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(18, 18),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH19: {
- execute: makePush(19, 19),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(19, 19),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH20: {
- execute: makePush(20, 20),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(20, 20),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH21: {
- execute: makePush(21, 21),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(21, 21),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH22: {
- execute: makePush(22, 22),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(22, 22),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH23: {
- execute: makePush(23, 23),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(23, 23),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH24: {
- execute: makePush(24, 24),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(24, 24),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH25: {
- execute: makePush(25, 25),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(25, 25),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH26: {
- execute: makePush(26, 26),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(26, 26),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH27: {
- execute: makePush(27, 27),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(27, 27),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH28: {
- execute: makePush(28, 28),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(28, 28),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH29: {
- execute: makePush(29, 29),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(29, 29),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH30: {
- execute: makePush(30, 30),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(30, 30),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH31: {
- execute: makePush(31, 31),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(31, 31),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
PUSH32: {
- execute: makePush(32, 32),
- gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
- valid: true,
+ execute: makePush(32, 32),
+ constantGas: GasFastestStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ valid: true,
},
DUP1: {
- execute: makeDup(1),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(1),
- valid: true,
+ execute: makeDup(1),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(1),
+ maxStack: maxDupStack(1),
+ valid: true,
},
DUP2: {
- execute: makeDup(2),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(2),
- valid: true,
+ execute: makeDup(2),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(2),
+ maxStack: maxDupStack(2),
+ valid: true,
},
DUP3: {
- execute: makeDup(3),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(3),
- valid: true,
+ execute: makeDup(3),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(3),
+ maxStack: maxDupStack(3),
+ valid: true,
},
DUP4: {
- execute: makeDup(4),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(4),
- valid: true,
+ execute: makeDup(4),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(4),
+ maxStack: maxDupStack(4),
+ valid: true,
},
DUP5: {
- execute: makeDup(5),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(5),
- valid: true,
+ execute: makeDup(5),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(5),
+ maxStack: maxDupStack(5),
+ valid: true,
},
DUP6: {
- execute: makeDup(6),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(6),
- valid: true,
+ execute: makeDup(6),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(6),
+ maxStack: maxDupStack(6),
+ valid: true,
},
DUP7: {
- execute: makeDup(7),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(7),
- valid: true,
+ execute: makeDup(7),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(7),
+ maxStack: maxDupStack(7),
+ valid: true,
},
DUP8: {
- execute: makeDup(8),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(8),
- valid: true,
+ execute: makeDup(8),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(8),
+ maxStack: maxDupStack(8),
+ valid: true,
},
DUP9: {
- execute: makeDup(9),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(9),
- valid: true,
+ execute: makeDup(9),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(9),
+ maxStack: maxDupStack(9),
+ valid: true,
},
DUP10: {
- execute: makeDup(10),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(10),
- valid: true,
+ execute: makeDup(10),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(10),
+ maxStack: maxDupStack(10),
+ valid: true,
},
DUP11: {
- execute: makeDup(11),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(11),
- valid: true,
+ execute: makeDup(11),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(11),
+ maxStack: maxDupStack(11),
+ valid: true,
},
DUP12: {
- execute: makeDup(12),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(12),
- valid: true,
+ execute: makeDup(12),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(12),
+ maxStack: maxDupStack(12),
+ valid: true,
},
DUP13: {
- execute: makeDup(13),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(13),
- valid: true,
+ execute: makeDup(13),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(13),
+ maxStack: maxDupStack(13),
+ valid: true,
},
DUP14: {
- execute: makeDup(14),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(14),
- valid: true,
+ execute: makeDup(14),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(14),
+ maxStack: maxDupStack(14),
+ valid: true,
},
DUP15: {
- execute: makeDup(15),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(15),
- valid: true,
+ execute: makeDup(15),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(15),
+ maxStack: maxDupStack(15),
+ valid: true,
},
DUP16: {
- execute: makeDup(16),
- gasCost: gasDup,
- validateStack: makeDupStackFunc(16),
- valid: true,
+ execute: makeDup(16),
+ constantGas: GasFastestStep,
+ minStack: minDupStack(16),
+ maxStack: maxDupStack(16),
+ valid: true,
},
SWAP1: {
- execute: makeSwap(1),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(2),
- valid: true,
+ execute: makeSwap(1),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(2),
+ maxStack: maxSwapStack(2),
+ valid: true,
},
SWAP2: {
- execute: makeSwap(2),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(3),
- valid: true,
+ execute: makeSwap(2),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(3),
+ maxStack: maxSwapStack(3),
+ valid: true,
},
SWAP3: {
- execute: makeSwap(3),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(4),
- valid: true,
+ execute: makeSwap(3),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(4),
+ maxStack: maxSwapStack(4),
+ valid: true,
},
SWAP4: {
- execute: makeSwap(4),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(5),
- valid: true,
+ execute: makeSwap(4),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(5),
+ maxStack: maxSwapStack(5),
+ valid: true,
},
SWAP5: {
- execute: makeSwap(5),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(6),
- valid: true,
+ execute: makeSwap(5),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(6),
+ maxStack: maxSwapStack(6),
+ valid: true,
},
SWAP6: {
- execute: makeSwap(6),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(7),
- valid: true,
+ execute: makeSwap(6),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(7),
+ maxStack: maxSwapStack(7),
+ valid: true,
},
SWAP7: {
- execute: makeSwap(7),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(8),
- valid: true,
+ execute: makeSwap(7),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(8),
+ maxStack: maxSwapStack(8),
+ valid: true,
},
SWAP8: {
- execute: makeSwap(8),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(9),
- valid: true,
+ execute: makeSwap(8),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(9),
+ maxStack: maxSwapStack(9),
+ valid: true,
},
SWAP9: {
- execute: makeSwap(9),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(10),
- valid: true,
+ execute: makeSwap(9),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(10),
+ maxStack: maxSwapStack(10),
+ valid: true,
},
SWAP10: {
- execute: makeSwap(10),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(11),
- valid: true,
+ execute: makeSwap(10),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(11),
+ maxStack: maxSwapStack(11),
+ valid: true,
},
SWAP11: {
- execute: makeSwap(11),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(12),
- valid: true,
+ execute: makeSwap(11),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(12),
+ maxStack: maxSwapStack(12),
+ valid: true,
},
SWAP12: {
- execute: makeSwap(12),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(13),
- valid: true,
+ execute: makeSwap(12),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(13),
+ maxStack: maxSwapStack(13),
+ valid: true,
},
SWAP13: {
- execute: makeSwap(13),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(14),
- valid: true,
+ execute: makeSwap(13),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(14),
+ maxStack: maxSwapStack(14),
+ valid: true,
},
SWAP14: {
- execute: makeSwap(14),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(15),
- valid: true,
+ execute: makeSwap(14),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(15),
+ maxStack: maxSwapStack(15),
+ valid: true,
},
SWAP15: {
- execute: makeSwap(15),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(16),
- valid: true,
+ execute: makeSwap(15),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(16),
+ maxStack: maxSwapStack(16),
+ valid: true,
},
SWAP16: {
- execute: makeSwap(16),
- gasCost: gasSwap,
- validateStack: makeSwapStackFunc(17),
- valid: true,
+ execute: makeSwap(16),
+ constantGas: GasFastestStep,
+ minStack: minSwapStack(17),
+ maxStack: maxSwapStack(17),
+ valid: true,
},
LOG0: {
- execute: makeLog(0),
- gasCost: makeGasLog(0),
- validateStack: makeStackFunc(2, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(0),
+ dynamicGas: makeGasLog(0),
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
LOG1: {
- execute: makeLog(1),
- gasCost: makeGasLog(1),
- validateStack: makeStackFunc(3, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(1),
+ dynamicGas: makeGasLog(1),
+ minStack: minStack(3, 0),
+ maxStack: maxStack(3, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
LOG2: {
- execute: makeLog(2),
- gasCost: makeGasLog(2),
- validateStack: makeStackFunc(4, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(2),
+ dynamicGas: makeGasLog(2),
+ minStack: minStack(4, 0),
+ maxStack: maxStack(4, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
LOG3: {
- execute: makeLog(3),
- gasCost: makeGasLog(3),
- validateStack: makeStackFunc(5, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(3),
+ dynamicGas: makeGasLog(3),
+ minStack: minStack(5, 0),
+ maxStack: maxStack(5, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
LOG4: {
- execute: makeLog(4),
- gasCost: makeGasLog(4),
- validateStack: makeStackFunc(6, 0),
- memorySize: memoryLog,
- valid: true,
- writes: true,
+ execute: makeLog(4),
+ dynamicGas: makeGasLog(4),
+ minStack: minStack(6, 0),
+ maxStack: maxStack(6, 0),
+ memorySize: memoryLog,
+ valid: true,
+ writes: true,
},
CREATE: {
- execute: opCreate,
- gasCost: gasCreate,
- validateStack: makeStackFunc(3, 1),
- memorySize: memoryCreate,
- valid: true,
- writes: true,
- returns: true,
+ execute: opCreate,
+ dynamicGas: gasCreate,
+ minStack: minStack(3, 1),
+ maxStack: maxStack(3, 1),
+ memorySize: memoryCreate,
+ valid: true,
+ writes: true,
+ returns: true,
},
CALL: {
- execute: opCall,
- gasCost: gasCall,
- validateStack: makeStackFunc(7, 1),
- memorySize: memoryCall,
- valid: true,
- returns: true,
+ execute: opCall,
+ dynamicGas: gasCall,
+ minStack: minStack(7, 1),
+ maxStack: maxStack(7, 1),
+ memorySize: memoryCall,
+ valid: true,
+ returns: true,
},
CALLCODE: {
- execute: opCallCode,
- gasCost: gasCallCode,
- validateStack: makeStackFunc(7, 1),
- memorySize: memoryCall,
- valid: true,
- returns: true,
+ execute: opCallCode,
+ dynamicGas: gasCallCode,
+ minStack: minStack(7, 1),
+ maxStack: maxStack(7, 1),
+ memorySize: memoryCall,
+ valid: true,
+ returns: true,
},
RETURN: {
- execute: opReturn,
- gasCost: gasReturn,
- validateStack: makeStackFunc(2, 0),
- memorySize: memoryReturn,
- halts: true,
- valid: true,
+ execute: opReturn,
+ dynamicGas: gasReturn,
+ minStack: minStack(2, 0),
+ maxStack: maxStack(2, 0),
+ memorySize: memoryReturn,
+ halts: true,
+ valid: true,
},
SELFDESTRUCT: {
- execute: opSuicide,
- gasCost: gasSuicide,
- validateStack: makeStackFunc(1, 0),
- halts: true,
- valid: true,
- writes: true,
+ execute: opSuicide,
+ dynamicGas: gasSuicide,
+ minStack: minStack(1, 0),
+ maxStack: maxStack(1, 0),
+ halts: true,
+ valid: true,
+ writes: true,
},
}
}
diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go
index 8fa6c90ca..4fcb41442 100644
--- a/core/vm/memory_table.go
+++ b/core/vm/memory_table.go
@@ -16,82 +16,98 @@
package vm
-import (
- "math/big"
-
- "github.com/ethereum/go-ethereum/common/math"
-)
-
-func memorySha3(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
+func memorySha3(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
}
-func memoryCallDataCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
+func memoryCallDataCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
}
-func memoryReturnDataCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
+func memoryReturnDataCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
}
-func memoryCodeCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
+func memoryCodeCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(2))
}
-func memoryExtCodeCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(3))
+func memoryExtCodeCopy(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(3))
}
-func memoryMLoad(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big.NewInt(32))
+func memoryMLoad(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 32)
}
-func memoryMStore8(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big.NewInt(1))
+func memoryMStore8(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 1)
}
-func memoryMStore(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big.NewInt(32))
+func memoryMStore(stack *Stack) (uint64, bool) {
+ return calcMemSize64WithUint(stack.Back(0), 32)
}
-func memoryCreate(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(2))
+func memoryCreate(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(2))
}
-func memoryCreate2(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(2))
+func memoryCreate2(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(1), stack.Back(2))
}
-func memoryCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(5), stack.Back(6))
- y := calcMemSize(stack.Back(3), stack.Back(4))
-
- return math.BigMax(x, y)
+func memoryCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(5), stack.Back(6))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(3), stack.Back(4))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
}
-
-func memoryDelegateCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(4), stack.Back(5))
- y := calcMemSize(stack.Back(2), stack.Back(3))
-
- return math.BigMax(x, y)
+func memoryDelegateCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
}
-func memoryStaticCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(4), stack.Back(5))
- y := calcMemSize(stack.Back(2), stack.Back(3))
-
- return math.BigMax(x, y)
+func memoryStaticCall(stack *Stack) (uint64, bool) {
+ x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
+ if overflow {
+ return 0, true
+ }
+ y, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
+ if overflow {
+ return 0, true
+ }
+ if x > y {
+ return x, false
+ }
+ return y, false
}
-func memoryReturn(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
+func memoryReturn(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
}
-func memoryRevert(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
+func memoryRevert(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
}
-func memoryLog(stack *Stack) *big.Int {
- mSize, mStart := stack.Back(1), stack.Back(0)
- return calcMemSize(mStart, mSize)
+func memoryLog(stack *Stack) (uint64, bool) {
+ return calcMemSize64(stack.Back(0), stack.Back(1))
}
diff --git a/core/vm/stack_table.go b/core/vm/stack_table.go
index a4b1cfcd8..10c12901a 100644
--- a/core/vm/stack_table.go
+++ b/core/vm/stack_table.go
@@ -17,28 +17,26 @@
package vm
import (
- "fmt"
-
"github.com/ethereum/go-ethereum/params"
)
-func makeStackFunc(pop, push int) stackValidationFunc {
- return func(stack *Stack) error {
- if err := stack.require(pop); err != nil {
- return err
- }
-
- if stack.len()+push-pop > int(params.StackLimit) {
- return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit)
- }
- return nil
- }
+func minSwapStack(n int) int {
+ return minStack(n, n)
+}
+func maxSwapStack(n int) int {
+ return maxStack(n, n)
}
-func makeDupStackFunc(n int) stackValidationFunc {
- return makeStackFunc(n, n+1)
+func minDupStack(n int) int {
+ return minStack(n, n+1)
+}
+func maxDupStack(n int) int {
+ return maxStack(n, n+1)
}
-func makeSwapStackFunc(n int) stackValidationFunc {
- return makeStackFunc(n, n)
+func maxStack(pop, push int) int {
+ return int(params.StackLimit) + pop - push
+}
+func minStack(pops, push int) int {
+ return pops
}