| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- // Copyright 2015 The go-ethereum Authors
- // This file is part of the go-ethereum library.
- //
- // The go-ethereum library is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // The go-ethereum library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public License
- // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
- package vm
- import (
- "fmt"
- "math/big"
- "github.com/ethereum/go-ethereum/params"
- )
- var (
- GasQuickStep = big.NewInt(2)
- GasFastestStep = big.NewInt(3)
- GasFastStep = big.NewInt(5)
- GasMidStep = big.NewInt(8)
- GasSlowStep = big.NewInt(10)
- GasExtStep = big.NewInt(20)
- GasReturn = big.NewInt(0)
- GasStop = big.NewInt(0)
- GasContractByte = big.NewInt(200)
- )
- // baseCheck checks for any stack error underflows
- func baseCheck(op OpCode, stack *stack, gas *big.Int) error {
- // PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
- // PUSH is also allowed to calculate the same price for all PUSHes
- // DUP requirements are handled elsewhere (except for the stack limit check)
- if op >= PUSH1 && op <= PUSH32 {
- op = PUSH1
- }
- if op >= DUP1 && op <= DUP16 {
- op = DUP1
- }
- if r, ok := _baseCheck[op]; ok {
- err := stack.require(r.stackPop)
- if err != nil {
- return err
- }
- if r.stackPush > 0 && stack.len()-r.stackPop+r.stackPush > int(params.StackLimit.Int64()) {
- return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64())
- }
- gas.Add(gas, r.gas)
- }
- return nil
- }
- // casts a arbitrary number to the amount of words (sets of 32 bytes)
- func toWordSize(size *big.Int) *big.Int {
- tmp := new(big.Int)
- tmp.Add(size, u256(31))
- tmp.Div(tmp, u256(32))
- return tmp
- }
- type req struct {
- stackPop int
- gas *big.Int
- stackPush int
- }
- var _baseCheck = map[OpCode]req{
- // opcode | stack pop | gas price | stack push
- ADD: {2, GasFastestStep, 1},
- LT: {2, GasFastestStep, 1},
- GT: {2, GasFastestStep, 1},
- SLT: {2, GasFastestStep, 1},
- SGT: {2, GasFastestStep, 1},
- EQ: {2, GasFastestStep, 1},
- ISZERO: {1, GasFastestStep, 1},
- SUB: {2, GasFastestStep, 1},
- AND: {2, GasFastestStep, 1},
- OR: {2, GasFastestStep, 1},
- XOR: {2, GasFastestStep, 1},
- NOT: {1, GasFastestStep, 1},
- BYTE: {2, GasFastestStep, 1},
- CALLDATALOAD: {1, GasFastestStep, 1},
- CALLDATACOPY: {3, GasFastestStep, 1},
- MLOAD: {1, GasFastestStep, 1},
- MSTORE: {2, GasFastestStep, 0},
- MSTORE8: {2, GasFastestStep, 0},
- CODECOPY: {3, GasFastestStep, 0},
- MUL: {2, GasFastStep, 1},
- DIV: {2, GasFastStep, 1},
- SDIV: {2, GasFastStep, 1},
- MOD: {2, GasFastStep, 1},
- SMOD: {2, GasFastStep, 1},
- SIGNEXTEND: {2, GasFastStep, 1},
- ADDMOD: {3, GasMidStep, 1},
- MULMOD: {3, GasMidStep, 1},
- JUMP: {1, GasMidStep, 0},
- JUMPI: {2, GasSlowStep, 0},
- EXP: {2, GasSlowStep, 1},
- ADDRESS: {0, GasQuickStep, 1},
- ORIGIN: {0, GasQuickStep, 1},
- CALLER: {0, GasQuickStep, 1},
- CALLVALUE: {0, GasQuickStep, 1},
- CODESIZE: {0, GasQuickStep, 1},
- GASPRICE: {0, GasQuickStep, 1},
- COINBASE: {0, GasQuickStep, 1},
- TIMESTAMP: {0, GasQuickStep, 1},
- NUMBER: {0, GasQuickStep, 1},
- CALLDATASIZE: {0, GasQuickStep, 1},
- DIFFICULTY: {0, GasQuickStep, 1},
- GASLIMIT: {0, GasQuickStep, 1},
- POP: {1, GasQuickStep, 0},
- PC: {0, GasQuickStep, 1},
- MSIZE: {0, GasQuickStep, 1},
- GAS: {0, GasQuickStep, 1},
- BLOCKHASH: {1, GasExtStep, 1},
- BALANCE: {1, GasExtStep, 1},
- EXTCODESIZE: {1, GasExtStep, 1},
- EXTCODECOPY: {4, GasExtStep, 0},
- SLOAD: {1, params.SloadGas, 1},
- SSTORE: {2, Zero, 0},
- SHA3: {2, params.Sha3Gas, 1},
- CREATE: {3, params.CreateGas, 1},
- CALL: {7, params.CallGas, 1},
- CALLCODE: {7, params.CallGas, 1},
- JUMPDEST: {0, params.JumpdestGas, 0},
- SUICIDE: {1, Zero, 0},
- RETURN: {2, Zero, 0},
- PUSH1: {0, GasFastestStep, 1},
- DUP1: {0, Zero, 1},
- }
|