From 4caa9dec46e1f2bf3b18d00382e481d48ebc521a Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sun, 3 Mar 2019 20:47:30 +0100 Subject: [PATCH 1/6] core/vm: remove function call for stack validation from evm runloop --- core/vm/interpreter.go | 36 +- core/vm/jump_table.go | 1351 ++++++++++++++++++++++------------------ core/vm/stack_table.go | 32 +- 3 files changed, 778 insertions(+), 641 deletions(-) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index c9dc3c00c6ce..e0909a186813 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,12 +201,24 @@ 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).BitLen() > 0) { + return nil, errWriteProtection + } } var memorySize uint64 diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index deedf70cdb7d..0eff6c844869 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -24,10 +24,10 @@ import ( ) 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 + //stackValidationFunc func(*Stack) error + memorySizeFunc func(*Stack) *big.Int ) var errGasUintOverflow = errors.New("gas uint64 overflow") @@ -37,8 +37,12 @@ type operation struct { 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 + // 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 +67,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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: 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, + gasCost: gasCreate2, + minStack: minStack(4, 1), + maxStack: maxStack(4, 1), + memorySize: memoryCreate2, + valid: true, + writes: true, + returns: true, } return instructionSet } @@ -104,34 +113,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, + gasCost: 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, + gasCost: constGasFunc(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, + gasCost: 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, + gasCost: gasRevert, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryRevert, + valid: true, + reverts: true, + returns: true, } return instructionSet } @@ -141,12 +154,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, + gasCost: gasDelegateCall, + minStack: minStack(6, 1), + maxStack: maxStack(6, 1), + memorySize: memoryDelegateCall, + valid: true, + returns: true, } return instructionSet } @@ -156,811 +170,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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(GasMidStep), + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + valid: true, }, EXP: { - execute: opExp, - gasCost: gasExp, - validateStack: makeStackFunc(2, 1), - valid: true, + execute: opExp, + gasCost: 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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: 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, + gasCost: constGasFunc(GasQuickStep), + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, BALANCE: { - execute: opBalance, - gasCost: gasBalance, - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opBalance, + gasCost: 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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: 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, + gasCost: constGasFunc(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, + gasCost: 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, + gasCost: constGasFunc(GasQuickStep), + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, EXTCODESIZE: { - execute: opExtCodeSize, - gasCost: gasExtCodeSize, - validateStack: makeStackFunc(1, 1), - valid: true, + execute: opExtCodeSize, + gasCost: 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, + gasCost: 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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: 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, + gasCost: 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, + gasCost: 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, + gasCost: 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, + gasCost: 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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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, + gasCost: constGasFunc(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: makePush(1, 1), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + 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), + gasCost: gasPush, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, DUP1: { - execute: makeDup(1), - gasCost: gasDup, - validateStack: makeDupStackFunc(1), - valid: true, + execute: makeDup(1), + gasCost: gasDup, + minStack: minDupStack(1), + maxStack: maxDupStack(1), + valid: true, }, DUP2: { - execute: makeDup(2), - gasCost: gasDup, - validateStack: makeDupStackFunc(2), - valid: true, + execute: makeDup(2), + gasCost: gasDup, + minStack: minDupStack(2), + maxStack: maxDupStack(2), + valid: true, }, DUP3: { - execute: makeDup(3), - gasCost: gasDup, - validateStack: makeDupStackFunc(3), - valid: true, + execute: makeDup(3), + gasCost: gasDup, + minStack: minDupStack(3), + maxStack: maxDupStack(3), + valid: true, }, DUP4: { - execute: makeDup(4), - gasCost: gasDup, - validateStack: makeDupStackFunc(4), - valid: true, + execute: makeDup(4), + gasCost: gasDup, + minStack: minDupStack(4), + maxStack: maxDupStack(4), + valid: true, }, DUP5: { - execute: makeDup(5), - gasCost: gasDup, - validateStack: makeDupStackFunc(5), - valid: true, + execute: makeDup(5), + gasCost: gasDup, + minStack: minDupStack(5), + maxStack: maxDupStack(5), + valid: true, }, DUP6: { - execute: makeDup(6), - gasCost: gasDup, - validateStack: makeDupStackFunc(6), - valid: true, + execute: makeDup(6), + gasCost: gasDup, + minStack: minDupStack(6), + maxStack: maxDupStack(6), + valid: true, }, DUP7: { - execute: makeDup(7), - gasCost: gasDup, - validateStack: makeDupStackFunc(7), - valid: true, + execute: makeDup(7), + gasCost: gasDup, + minStack: minDupStack(7), + maxStack: maxDupStack(7), + valid: true, }, DUP8: { - execute: makeDup(8), - gasCost: gasDup, - validateStack: makeDupStackFunc(8), - valid: true, + execute: makeDup(8), + gasCost: gasDup, + minStack: minDupStack(8), + maxStack: maxDupStack(8), + valid: true, }, DUP9: { - execute: makeDup(9), - gasCost: gasDup, - validateStack: makeDupStackFunc(9), - valid: true, + execute: makeDup(9), + gasCost: gasDup, + minStack: minDupStack(9), + maxStack: maxDupStack(9), + valid: true, }, DUP10: { - execute: makeDup(10), - gasCost: gasDup, - validateStack: makeDupStackFunc(10), - valid: true, + execute: makeDup(10), + gasCost: gasDup, + minStack: minDupStack(10), + maxStack: maxDupStack(10), + valid: true, }, DUP11: { - execute: makeDup(11), - gasCost: gasDup, - validateStack: makeDupStackFunc(11), - valid: true, + execute: makeDup(11), + gasCost: gasDup, + minStack: minDupStack(11), + maxStack: maxDupStack(11), + valid: true, }, DUP12: { - execute: makeDup(12), - gasCost: gasDup, - validateStack: makeDupStackFunc(12), - valid: true, + execute: makeDup(12), + gasCost: gasDup, + minStack: minDupStack(12), + maxStack: maxDupStack(12), + valid: true, }, DUP13: { - execute: makeDup(13), - gasCost: gasDup, - validateStack: makeDupStackFunc(13), - valid: true, + execute: makeDup(13), + gasCost: gasDup, + minStack: minDupStack(13), + maxStack: maxDupStack(13), + valid: true, }, DUP14: { - execute: makeDup(14), - gasCost: gasDup, - validateStack: makeDupStackFunc(14), - valid: true, + execute: makeDup(14), + gasCost: gasDup, + minStack: minDupStack(14), + maxStack: maxDupStack(14), + valid: true, }, DUP15: { - execute: makeDup(15), - gasCost: gasDup, - validateStack: makeDupStackFunc(15), - valid: true, + execute: makeDup(15), + gasCost: gasDup, + minStack: minDupStack(15), + maxStack: maxDupStack(15), + valid: true, }, DUP16: { - execute: makeDup(16), - gasCost: gasDup, - validateStack: makeDupStackFunc(16), - valid: true, + execute: makeDup(16), + gasCost: gasDup, + minStack: minDupStack(16), + maxStack: maxDupStack(16), + valid: true, }, SWAP1: { - execute: makeSwap(1), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(2), - valid: true, + execute: makeSwap(1), + gasCost: gasSwap, + minStack: minSwapStack(2), + maxStack: maxSwapStack(2), + valid: true, }, SWAP2: { - execute: makeSwap(2), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(3), - valid: true, + execute: makeSwap(2), + gasCost: gasSwap, + minStack: minSwapStack(3), + maxStack: maxSwapStack(3), + valid: true, }, SWAP3: { - execute: makeSwap(3), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(4), - valid: true, + execute: makeSwap(3), + gasCost: gasSwap, + minStack: minSwapStack(4), + maxStack: maxSwapStack(4), + valid: true, }, SWAP4: { - execute: makeSwap(4), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(5), - valid: true, + execute: makeSwap(4), + gasCost: gasSwap, + minStack: minSwapStack(5), + maxStack: maxSwapStack(5), + valid: true, }, SWAP5: { - execute: makeSwap(5), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(6), - valid: true, + execute: makeSwap(5), + gasCost: gasSwap, + minStack: minSwapStack(6), + maxStack: maxSwapStack(6), + valid: true, }, SWAP6: { - execute: makeSwap(6), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(7), - valid: true, + execute: makeSwap(6), + gasCost: gasSwap, + minStack: minSwapStack(7), + maxStack: maxSwapStack(7), + valid: true, }, SWAP7: { - execute: makeSwap(7), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(8), - valid: true, + execute: makeSwap(7), + gasCost: gasSwap, + minStack: minSwapStack(8), + maxStack: maxSwapStack(8), + valid: true, }, SWAP8: { - execute: makeSwap(8), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(9), - valid: true, + execute: makeSwap(8), + gasCost: gasSwap, + minStack: minSwapStack(9), + maxStack: maxSwapStack(9), + valid: true, }, SWAP9: { - execute: makeSwap(9), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(10), - valid: true, + execute: makeSwap(9), + gasCost: gasSwap, + minStack: minSwapStack(10), + maxStack: maxSwapStack(10), + valid: true, }, SWAP10: { - execute: makeSwap(10), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(11), - valid: true, + execute: makeSwap(10), + gasCost: gasSwap, + minStack: minSwapStack(11), + maxStack: maxSwapStack(11), + valid: true, }, SWAP11: { - execute: makeSwap(11), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(12), - valid: true, + execute: makeSwap(11), + gasCost: gasSwap, + minStack: minSwapStack(12), + maxStack: maxSwapStack(12), + valid: true, }, SWAP12: { - execute: makeSwap(12), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(13), - valid: true, + execute: makeSwap(12), + gasCost: gasSwap, + minStack: minSwapStack(13), + maxStack: maxSwapStack(13), + valid: true, }, SWAP13: { - execute: makeSwap(13), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(14), - valid: true, + execute: makeSwap(13), + gasCost: gasSwap, + minStack: minSwapStack(14), + maxStack: maxSwapStack(14), + valid: true, }, SWAP14: { - execute: makeSwap(14), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(15), - valid: true, + execute: makeSwap(14), + gasCost: gasSwap, + minStack: minSwapStack(15), + maxStack: maxSwapStack(15), + valid: true, }, SWAP15: { - execute: makeSwap(15), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(16), - valid: true, + execute: makeSwap(15), + gasCost: gasSwap, + minStack: minSwapStack(16), + maxStack: maxSwapStack(16), + valid: true, }, SWAP16: { - execute: makeSwap(16), - gasCost: gasSwap, - validateStack: makeSwapStackFunc(17), - valid: true, + execute: makeSwap(16), + gasCost: gasSwap, + 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), + gasCost: 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), + gasCost: 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), + gasCost: 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), + gasCost: 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), + gasCost: 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, + gasCost: 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, + gasCost: 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, + gasCost: 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, + gasCost: 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, + gasCost: gasSuicide, + minStack: minStack(1, 0), + maxStack: maxStack(1, 0), + halts: true, + valid: true, + writes: true, }, } } diff --git a/core/vm/stack_table.go b/core/vm/stack_table.go index a4b1cfcd896e..10c12901afdb 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 } From 97ab46ba196c162fb41c4eedd37c946d90ad3a67 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sun, 3 Mar 2019 22:41:54 +0100 Subject: [PATCH 2/6] core/vm: separate gas calc into static + dynamic --- core/vm/gas_table.go | 18 - core/vm/interpreter.go | 35 +- core/vm/jump_table.go | 1240 ++++++++++++++++++++-------------------- 3 files changed, 641 insertions(+), 652 deletions(-) diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index f22463c33123..6400c1324f4d 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/interpreter.go b/core/vm/interpreter.go index e0909a186813..019210174fe4 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -202,23 +202,27 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( return nil, fmt.Errorf("invalid opcode 0x%x", int(op)) } // Validate stack - if sLen := stack.len(); sLen < operation.minStack{ + if sLen := stack.len(); sLen < operation.minStack { return nil, fmt.Errorf("stack underflow (%d <=> %d)", sLen, operation.minStack) - }else{ - if sLen > operation.maxStack{ + } 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 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).BitLen() > 0) { - return nil, errWriteProtection - } + // 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 nil, errWriteProtection + } + } + // Static portion of gas + if !contract.UseGas(operation.constantGas) { + return nil, ErrOutOfGas } var memorySize uint64 @@ -235,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 0eff6c844869..dde11dacf1e5 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -34,9 +34,9 @@ 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 + 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 @@ -67,36 +67,36 @@ func newConstantinopleInstructionSet() [256]operation { // instructions that can be executed during the byzantium phase. instructionSet := newByzantiumInstructionSet() instructionSet[SHL] = operation{ - execute: opSHL, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(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), - minStack: minStack(2, 1), - maxStack: maxStack(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), - minStack: minStack(2, 1), - maxStack: maxStack(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, - minStack: minStack(1, 1), - maxStack: maxStack(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, + dynamicGas: gasCreate2, minStack: minStack(4, 1), maxStack: maxStack(4, 1), memorySize: memoryCreate2, @@ -114,7 +114,7 @@ func newByzantiumInstructionSet() [256]operation { instructionSet := newHomesteadInstructionSet() instructionSet[STATICCALL] = operation{ execute: opStaticCall, - gasCost: gasStaticCall, + dynamicGas: gasStaticCall, minStack: minStack(6, 1), maxStack: maxStack(6, 1), memorySize: memoryStaticCall, @@ -122,15 +122,15 @@ func newByzantiumInstructionSet() [256]operation { returns: true, } instructionSet[RETURNDATASIZE] = operation{ - execute: opReturnDataSize, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(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, + dynamicGas: gasReturnDataCopy, minStack: minStack(3, 0), maxStack: maxStack(3, 0), memorySize: memoryReturnDataCopy, @@ -138,7 +138,7 @@ func newByzantiumInstructionSet() [256]operation { } instructionSet[REVERT] = operation{ execute: opRevert, - gasCost: gasRevert, + dynamicGas: gasRevert, minStack: minStack(2, 0), maxStack: maxStack(2, 0), memorySize: memoryRevert, @@ -155,7 +155,7 @@ func newHomesteadInstructionSet() [256]operation { instructionSet := newFrontierInstructionSet() instructionSet[DELEGATECALL] = operation{ execute: opDelegateCall, - gasCost: gasDelegateCall, + dynamicGas: gasDelegateCall, minStack: minStack(6, 1), maxStack: maxStack(6, 1), memorySize: memoryDelegateCall, @@ -170,321 +170,321 @@ func newHomesteadInstructionSet() [256]operation { func newFrontierInstructionSet() [256]operation { return [256]operation{ STOP: { - execute: opStop, - gasCost: constGasFunc(0), - minStack: minStack(0, 0), - maxStack: maxStack(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), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opAdd, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, MUL: { - execute: opMul, - gasCost: constGasFunc(GasFastStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opMul, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SUB: { - execute: opSub, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opSub, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, DIV: { - execute: opDiv, - gasCost: constGasFunc(GasFastStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opDiv, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SDIV: { - execute: opSdiv, - gasCost: constGasFunc(GasFastStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opSdiv, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, MOD: { - execute: opMod, - gasCost: constGasFunc(GasFastStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opMod, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SMOD: { - execute: opSmod, - gasCost: constGasFunc(GasFastStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opSmod, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, ADDMOD: { - execute: opAddmod, - gasCost: constGasFunc(GasMidStep), - minStack: minStack(3, 1), - maxStack: maxStack(3, 1), - valid: true, + execute: opAddmod, + constantGas: GasMidStep, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + valid: true, }, MULMOD: { - execute: opMulmod, - gasCost: constGasFunc(GasMidStep), - minStack: minStack(3, 1), - maxStack: maxStack(3, 1), - valid: true, + execute: opMulmod, + constantGas: GasMidStep, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + valid: true, }, EXP: { - execute: opExp, - gasCost: gasExp, - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opExp, + dynamicGas: gasExp, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SIGNEXTEND: { - execute: opSignExtend, - gasCost: constGasFunc(GasFastStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opSignExtend, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, LT: { - execute: opLt, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opLt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, GT: { - execute: opGt, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opGt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SLT: { - execute: opSlt, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opSlt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SGT: { - execute: opSgt, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opSgt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, EQ: { - execute: opEq, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opEq, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, ISZERO: { - execute: opIszero, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opIszero, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, AND: { - execute: opAnd, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opAnd, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, XOR: { - execute: opXor, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opXor, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, OR: { - execute: opOr, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opOr, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, NOT: { - execute: opNot, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opNot, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, BYTE: { - execute: opByte, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(2, 1), - maxStack: maxStack(2, 1), - valid: true, + execute: opByte, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + valid: true, }, SHA3: { execute: opSha3, - gasCost: gasSha3, + dynamicGas: gasSha3, minStack: minStack(2, 1), maxStack: maxStack(2, 1), memorySize: memorySha3, valid: true, }, ADDRESS: { - execute: opAddress, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opAddress, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, BALANCE: { - execute: opBalance, - gasCost: gasBalance, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opBalance, + dynamicGas: gasBalance, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, ORIGIN: { - execute: opOrigin, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opOrigin, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CALLER: { - execute: opCaller, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opCaller, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CALLVALUE: { - execute: opCallValue, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opCallValue, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CALLDATALOAD: { - execute: opCallDataLoad, - gasCost: constGasFunc(GasFastestStep), - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opCallDataLoad, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, CALLDATASIZE: { - execute: opCallDataSize, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opCallDataSize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CALLDATACOPY: { execute: opCallDataCopy, - gasCost: gasCallDataCopy, + dynamicGas: gasCallDataCopy, minStack: minStack(3, 0), maxStack: maxStack(3, 0), memorySize: memoryCallDataCopy, valid: true, }, CODESIZE: { - execute: opCodeSize, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opCodeSize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, CODECOPY: { execute: opCodeCopy, - gasCost: gasCodeCopy, + dynamicGas: gasCodeCopy, minStack: minStack(3, 0), maxStack: maxStack(3, 0), memorySize: memoryCodeCopy, valid: true, }, GASPRICE: { - execute: opGasprice, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opGasprice, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, EXTCODESIZE: { - execute: opExtCodeSize, - gasCost: gasExtCodeSize, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opExtCodeSize, + dynamicGas: gasExtCodeSize, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, EXTCODECOPY: { execute: opExtCodeCopy, - gasCost: gasExtCodeCopy, + dynamicGas: gasExtCodeCopy, minStack: minStack(4, 0), maxStack: maxStack(4, 0), memorySize: memoryExtCodeCopy, valid: true, }, BLOCKHASH: { - execute: opBlockhash, - gasCost: constGasFunc(GasExtStep), - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opBlockhash, + constantGas: GasExtStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, COINBASE: { - execute: opCoinbase, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opCoinbase, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, TIMESTAMP: { - execute: opTimestamp, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opTimestamp, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, NUMBER: { - execute: opNumber, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opNumber, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, DIFFICULTY: { - execute: opDifficulty, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opDifficulty, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, GASLIMIT: { - execute: opGasLimit, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opGasLimit, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, POP: { - execute: opPop, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(1, 0), - maxStack: maxStack(1, 0), - valid: true, + execute: opPop, + constantGas: GasQuickStep, + minStack: minStack(1, 0), + maxStack: maxStack(1, 0), + valid: true, }, MLOAD: { execute: opMload, - gasCost: gasMLoad, + dynamicGas: gasMLoad, minStack: minStack(1, 1), maxStack: maxStack(1, 1), memorySize: memoryMLoad, @@ -492,7 +492,7 @@ func newFrontierInstructionSet() [256]operation { }, MSTORE: { execute: opMstore, - gasCost: gasMStore, + dynamicGas: gasMStore, minStack: minStack(2, 0), maxStack: maxStack(2, 0), memorySize: memoryMStore, @@ -500,7 +500,7 @@ func newFrontierInstructionSet() [256]operation { }, MSTORE8: { execute: opMstore8, - gasCost: gasMStore8, + dynamicGas: gasMStore8, memorySize: memoryMStore8, minStack: minStack(2, 0), maxStack: maxStack(2, 0), @@ -508,515 +508,515 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, SLOAD: { - execute: opSload, - gasCost: gasSLoad, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - valid: true, + execute: opSload, + dynamicGas: gasSLoad, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + valid: true, }, SSTORE: { - execute: opSstore, - gasCost: gasSStore, - minStack: minStack(2, 0), - maxStack: maxStack(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), - minStack: minStack(1, 0), - maxStack: maxStack(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), - minStack: minStack(2, 0), - maxStack: maxStack(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), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opPc, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, MSIZE: { - execute: opMsize, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: opMsize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, GAS: { - execute: opGas, - gasCost: constGasFunc(GasQuickStep), - minStack: minStack(0, 1), - maxStack: maxStack(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), - minStack: minStack(0, 0), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - valid: true, + execute: makePush(1, 1), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, }, PUSH2: { - execute: makePush(2, 2), - gasCost: gasPush, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minStack(0, 1), - maxStack: maxStack(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, - minStack: minDupStack(1), - maxStack: maxDupStack(1), - valid: true, + execute: makeDup(1), + constantGas: GasFastestStep, + minStack: minDupStack(1), + maxStack: maxDupStack(1), + valid: true, }, DUP2: { - execute: makeDup(2), - gasCost: gasDup, - minStack: minDupStack(2), - maxStack: maxDupStack(2), - valid: true, + execute: makeDup(2), + constantGas: GasFastestStep, + minStack: minDupStack(2), + maxStack: maxDupStack(2), + valid: true, }, DUP3: { - execute: makeDup(3), - gasCost: gasDup, - minStack: minDupStack(3), - maxStack: maxDupStack(3), - valid: true, + execute: makeDup(3), + constantGas: GasFastestStep, + minStack: minDupStack(3), + maxStack: maxDupStack(3), + valid: true, }, DUP4: { - execute: makeDup(4), - gasCost: gasDup, - minStack: minDupStack(4), - maxStack: maxDupStack(4), - valid: true, + execute: makeDup(4), + constantGas: GasFastestStep, + minStack: minDupStack(4), + maxStack: maxDupStack(4), + valid: true, }, DUP5: { - execute: makeDup(5), - gasCost: gasDup, - minStack: minDupStack(5), - maxStack: maxDupStack(5), - valid: true, + execute: makeDup(5), + constantGas: GasFastestStep, + minStack: minDupStack(5), + maxStack: maxDupStack(5), + valid: true, }, DUP6: { - execute: makeDup(6), - gasCost: gasDup, - minStack: minDupStack(6), - maxStack: maxDupStack(6), - valid: true, + execute: makeDup(6), + constantGas: GasFastestStep, + minStack: minDupStack(6), + maxStack: maxDupStack(6), + valid: true, }, DUP7: { - execute: makeDup(7), - gasCost: gasDup, - minStack: minDupStack(7), - maxStack: maxDupStack(7), - valid: true, + execute: makeDup(7), + constantGas: GasFastestStep, + minStack: minDupStack(7), + maxStack: maxDupStack(7), + valid: true, }, DUP8: { - execute: makeDup(8), - gasCost: gasDup, - minStack: minDupStack(8), - maxStack: maxDupStack(8), - valid: true, + execute: makeDup(8), + constantGas: GasFastestStep, + minStack: minDupStack(8), + maxStack: maxDupStack(8), + valid: true, }, DUP9: { - execute: makeDup(9), - gasCost: gasDup, - minStack: minDupStack(9), - maxStack: maxDupStack(9), - valid: true, + execute: makeDup(9), + constantGas: GasFastestStep, + minStack: minDupStack(9), + maxStack: maxDupStack(9), + valid: true, }, DUP10: { - execute: makeDup(10), - gasCost: gasDup, - minStack: minDupStack(10), - maxStack: maxDupStack(10), - valid: true, + execute: makeDup(10), + constantGas: GasFastestStep, + minStack: minDupStack(10), + maxStack: maxDupStack(10), + valid: true, }, DUP11: { - execute: makeDup(11), - gasCost: gasDup, - minStack: minDupStack(11), - maxStack: maxDupStack(11), - valid: true, + execute: makeDup(11), + constantGas: GasFastestStep, + minStack: minDupStack(11), + maxStack: maxDupStack(11), + valid: true, }, DUP12: { - execute: makeDup(12), - gasCost: gasDup, - minStack: minDupStack(12), - maxStack: maxDupStack(12), - valid: true, + execute: makeDup(12), + constantGas: GasFastestStep, + minStack: minDupStack(12), + maxStack: maxDupStack(12), + valid: true, }, DUP13: { - execute: makeDup(13), - gasCost: gasDup, - minStack: minDupStack(13), - maxStack: maxDupStack(13), - valid: true, + execute: makeDup(13), + constantGas: GasFastestStep, + minStack: minDupStack(13), + maxStack: maxDupStack(13), + valid: true, }, DUP14: { - execute: makeDup(14), - gasCost: gasDup, - minStack: minDupStack(14), - maxStack: maxDupStack(14), - valid: true, + execute: makeDup(14), + constantGas: GasFastestStep, + minStack: minDupStack(14), + maxStack: maxDupStack(14), + valid: true, }, DUP15: { - execute: makeDup(15), - gasCost: gasDup, - minStack: minDupStack(15), - maxStack: maxDupStack(15), - valid: true, + execute: makeDup(15), + constantGas: GasFastestStep, + minStack: minDupStack(15), + maxStack: maxDupStack(15), + valid: true, }, DUP16: { - execute: makeDup(16), - gasCost: gasDup, - minStack: minDupStack(16), - maxStack: maxDupStack(16), - valid: true, + execute: makeDup(16), + constantGas: GasFastestStep, + minStack: minDupStack(16), + maxStack: maxDupStack(16), + valid: true, }, SWAP1: { - execute: makeSwap(1), - gasCost: gasSwap, - minStack: minSwapStack(2), - maxStack: maxSwapStack(2), - valid: true, + execute: makeSwap(1), + constantGas: GasFastestStep, + minStack: minSwapStack(2), + maxStack: maxSwapStack(2), + valid: true, }, SWAP2: { - execute: makeSwap(2), - gasCost: gasSwap, - minStack: minSwapStack(3), - maxStack: maxSwapStack(3), - valid: true, + execute: makeSwap(2), + constantGas: GasFastestStep, + minStack: minSwapStack(3), + maxStack: maxSwapStack(3), + valid: true, }, SWAP3: { - execute: makeSwap(3), - gasCost: gasSwap, - minStack: minSwapStack(4), - maxStack: maxSwapStack(4), - valid: true, + execute: makeSwap(3), + constantGas: GasFastestStep, + minStack: minSwapStack(4), + maxStack: maxSwapStack(4), + valid: true, }, SWAP4: { - execute: makeSwap(4), - gasCost: gasSwap, - minStack: minSwapStack(5), - maxStack: maxSwapStack(5), - valid: true, + execute: makeSwap(4), + constantGas: GasFastestStep, + minStack: minSwapStack(5), + maxStack: maxSwapStack(5), + valid: true, }, SWAP5: { - execute: makeSwap(5), - gasCost: gasSwap, - minStack: minSwapStack(6), - maxStack: maxSwapStack(6), - valid: true, + execute: makeSwap(5), + constantGas: GasFastestStep, + minStack: minSwapStack(6), + maxStack: maxSwapStack(6), + valid: true, }, SWAP6: { - execute: makeSwap(6), - gasCost: gasSwap, - minStack: minSwapStack(7), - maxStack: maxSwapStack(7), - valid: true, + execute: makeSwap(6), + constantGas: GasFastestStep, + minStack: minSwapStack(7), + maxStack: maxSwapStack(7), + valid: true, }, SWAP7: { - execute: makeSwap(7), - gasCost: gasSwap, - minStack: minSwapStack(8), - maxStack: maxSwapStack(8), - valid: true, + execute: makeSwap(7), + constantGas: GasFastestStep, + minStack: minSwapStack(8), + maxStack: maxSwapStack(8), + valid: true, }, SWAP8: { - execute: makeSwap(8), - gasCost: gasSwap, - minStack: minSwapStack(9), - maxStack: maxSwapStack(9), - valid: true, + execute: makeSwap(8), + constantGas: GasFastestStep, + minStack: minSwapStack(9), + maxStack: maxSwapStack(9), + valid: true, }, SWAP9: { - execute: makeSwap(9), - gasCost: gasSwap, - minStack: minSwapStack(10), - maxStack: maxSwapStack(10), - valid: true, + execute: makeSwap(9), + constantGas: GasFastestStep, + minStack: minSwapStack(10), + maxStack: maxSwapStack(10), + valid: true, }, SWAP10: { - execute: makeSwap(10), - gasCost: gasSwap, - minStack: minSwapStack(11), - maxStack: maxSwapStack(11), - valid: true, + execute: makeSwap(10), + constantGas: GasFastestStep, + minStack: minSwapStack(11), + maxStack: maxSwapStack(11), + valid: true, }, SWAP11: { - execute: makeSwap(11), - gasCost: gasSwap, - minStack: minSwapStack(12), - maxStack: maxSwapStack(12), - valid: true, + execute: makeSwap(11), + constantGas: GasFastestStep, + minStack: minSwapStack(12), + maxStack: maxSwapStack(12), + valid: true, }, SWAP12: { - execute: makeSwap(12), - gasCost: gasSwap, - minStack: minSwapStack(13), - maxStack: maxSwapStack(13), - valid: true, + execute: makeSwap(12), + constantGas: GasFastestStep, + minStack: minSwapStack(13), + maxStack: maxSwapStack(13), + valid: true, }, SWAP13: { - execute: makeSwap(13), - gasCost: gasSwap, - minStack: minSwapStack(14), - maxStack: maxSwapStack(14), - valid: true, + execute: makeSwap(13), + constantGas: GasFastestStep, + minStack: minSwapStack(14), + maxStack: maxSwapStack(14), + valid: true, }, SWAP14: { - execute: makeSwap(14), - gasCost: gasSwap, - minStack: minSwapStack(15), - maxStack: maxSwapStack(15), - valid: true, + execute: makeSwap(14), + constantGas: GasFastestStep, + minStack: minSwapStack(15), + maxStack: maxSwapStack(15), + valid: true, }, SWAP15: { - execute: makeSwap(15), - gasCost: gasSwap, - minStack: minSwapStack(16), - maxStack: maxSwapStack(16), - valid: true, + execute: makeSwap(15), + constantGas: GasFastestStep, + minStack: minSwapStack(16), + maxStack: maxSwapStack(16), + valid: true, }, SWAP16: { - execute: makeSwap(16), - gasCost: gasSwap, - minStack: minSwapStack(17), - maxStack: maxSwapStack(17), - valid: true, + execute: makeSwap(16), + constantGas: GasFastestStep, + minStack: minSwapStack(17), + maxStack: maxSwapStack(17), + valid: true, }, LOG0: { execute: makeLog(0), - gasCost: makeGasLog(0), + dynamicGas: makeGasLog(0), minStack: minStack(2, 0), maxStack: maxStack(2, 0), memorySize: memoryLog, @@ -1025,7 +1025,7 @@ func newFrontierInstructionSet() [256]operation { }, LOG1: { execute: makeLog(1), - gasCost: makeGasLog(1), + dynamicGas: makeGasLog(1), minStack: minStack(3, 0), maxStack: maxStack(3, 0), memorySize: memoryLog, @@ -1034,7 +1034,7 @@ func newFrontierInstructionSet() [256]operation { }, LOG2: { execute: makeLog(2), - gasCost: makeGasLog(2), + dynamicGas: makeGasLog(2), minStack: minStack(4, 0), maxStack: maxStack(4, 0), memorySize: memoryLog, @@ -1043,7 +1043,7 @@ func newFrontierInstructionSet() [256]operation { }, LOG3: { execute: makeLog(3), - gasCost: makeGasLog(3), + dynamicGas: makeGasLog(3), minStack: minStack(5, 0), maxStack: maxStack(5, 0), memorySize: memoryLog, @@ -1052,7 +1052,7 @@ func newFrontierInstructionSet() [256]operation { }, LOG4: { execute: makeLog(4), - gasCost: makeGasLog(4), + dynamicGas: makeGasLog(4), minStack: minStack(6, 0), maxStack: maxStack(6, 0), memorySize: memoryLog, @@ -1061,7 +1061,7 @@ func newFrontierInstructionSet() [256]operation { }, CREATE: { execute: opCreate, - gasCost: gasCreate, + dynamicGas: gasCreate, minStack: minStack(3, 1), maxStack: maxStack(3, 1), memorySize: memoryCreate, @@ -1071,7 +1071,7 @@ func newFrontierInstructionSet() [256]operation { }, CALL: { execute: opCall, - gasCost: gasCall, + dynamicGas: gasCall, minStack: minStack(7, 1), maxStack: maxStack(7, 1), memorySize: memoryCall, @@ -1080,7 +1080,7 @@ func newFrontierInstructionSet() [256]operation { }, CALLCODE: { execute: opCallCode, - gasCost: gasCallCode, + dynamicGas: gasCallCode, minStack: minStack(7, 1), maxStack: maxStack(7, 1), memorySize: memoryCall, @@ -1089,7 +1089,7 @@ func newFrontierInstructionSet() [256]operation { }, RETURN: { execute: opReturn, - gasCost: gasReturn, + dynamicGas: gasReturn, minStack: minStack(2, 0), maxStack: maxStack(2, 0), memorySize: memoryReturn, @@ -1097,13 +1097,13 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, SELFDESTRUCT: { - execute: opSuicide, - gasCost: gasSuicide, - minStack: minStack(1, 0), - maxStack: maxStack(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, }, } } From bda409a02a90ec1c1eaea7940df613eb3db469cf Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 4 Mar 2019 08:59:17 +0100 Subject: [PATCH 3/6] core/vm: optimize push1 --- core/vm/instructions.go | 15 +++++++++++++++ core/vm/jump_table.go | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 5195e716b295..a1188848dc75 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -886,6 +886,21 @@ func opSuicide(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo return nil, nil } +// 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 +} + // following functions are used by the instruction jump table // make log instruction function diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index dde11dacf1e5..90d8e64dbaeb 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -567,7 +567,7 @@ func newFrontierInstructionSet() [256]operation { valid: true, }, PUSH1: { - execute: makePush(1, 1), + execute: opPush1, constantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), From e5945d58f070b21fd9833583905b808b38138544 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 4 Mar 2019 09:45:56 +0100 Subject: [PATCH 4/6] core/vm: reuse pooled bigints for ADDRESS, ORIGIN and CALLER --- common/types.go | 3 +++ core/vm/instructions.go | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common/types.go b/common/types.go index 48043788fd32..e42239d8a8b0 100644 --- a/common/types.go +++ b/common/types.go @@ -205,6 +205,9 @@ func (a Address) Bytes() []byte { return a[:] } // Big converts an address to a big integer. func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } +// SetBig converts an address to a given big integer. +func (a Address) SetBig(int *big.Int) *big.Int { return int.SetBytes(a[:]) } + // Hash converts an address to a hash by left-padding it with zeros. func (a Address) Hash() Hash { return BytesToHash(a[:]) } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index a1188848dc75..04ecea47184f 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -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(contract.Address().SetBig(interpreter.intPool.get())) 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.evm.Origin.SetBig(interpreter.intPool.get())) return nil, nil } func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(contract.Caller().Big()) + stack.push(contract.Caller().SetBig(interpreter.intPool.get())) return nil, nil } From df98ba391a3e52df3b653cefb9d66964c35b733a Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 4 Mar 2019 11:39:20 +0100 Subject: [PATCH 5/6] core/vm: use generic error message for jump/jumpi, to avoid string interpolation --- core/vm/instructions.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 04ecea47184f..0cdafff416d4 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) { @@ -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 { From 6a4bf5d697b03a648140d3306f0b286927265447 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 7 Mar 2019 11:46:12 +0100 Subject: [PATCH 6/6] testdata: fix tests for new error message --- .../testdata/call_tracer_inner_create_oog_outer_throw.json | 2 +- eth/tracers/testdata/call_tracer_throw.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eth/tracers/testdata/call_tracer_inner_create_oog_outer_throw.json b/eth/tracers/testdata/call_tracer_inner_create_oog_outer_throw.json index b8a4cdd23359..d1c8ac913c54 100644 --- a/eth/tracers/testdata/call_tracer_inner_create_oog_outer_throw.json +++ b/eth/tracers/testdata/call_tracer_inner_create_oog_outer_throw.json @@ -65,7 +65,7 @@ "value": "0x0" } ], - "error": "invalid jump destination (PUSH1) 0", + "error": "evm: invalid jump destination", "from": "0xe4a13bc304682a903e9472f469c33801dd18d9e8", "gas": "0x435c8", "gasUsed": "0x435c8", diff --git a/eth/tracers/testdata/call_tracer_throw.json b/eth/tracers/testdata/call_tracer_throw.json index 60d4d1071d02..d66f1ffa61de 100644 --- a/eth/tracers/testdata/call_tracer_throw.json +++ b/eth/tracers/testdata/call_tracer_throw.json @@ -50,7 +50,7 @@ }, "input": "0xf88b8206668504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb8000000000000000000000000000000000000000000000027fad02094277c000029a0692a3b4e7b2842f8dd7832e712c21e09f451f416c8976d5b8d02e8c0c2b4bea9a07645e90fc421b63dd755767fd93d3c03b4ec0c4d8fafa059558d08cf11d59750", "result": { - "error": "invalid jump destination (PUSH1) 2", + "error": "evm: invalid jump destination", "from": "0x70c9217d814985faef62b124420f8dfbddd96433", "gas": "0x37b38", "gasUsed": "0x37b38",