github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/core/vm/gas.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "fmt" 21 "math/big" 22 23 "github.com/atheioschain/go-atheios/params" 24 ) 25 26 var ( 27 GasQuickStep = big.NewInt(2) 28 GasFastestStep = big.NewInt(3) 29 GasFastStep = big.NewInt(5) 30 GasMidStep = big.NewInt(8) 31 GasSlowStep = big.NewInt(10) 32 GasExtStep = big.NewInt(20) 33 34 GasReturn = big.NewInt(0) 35 GasStop = big.NewInt(0) 36 37 GasContractByte = big.NewInt(200) 38 39 n64 = big.NewInt(64) 40 ) 41 42 // calcGas returns the actual gas cost of the call. 43 // 44 // The cost of gas was changed during the homestead price change HF. To allow for EIP150 45 // to be implemented. The returned gas is gas - base * 63 / 64. 46 func callGas(gasTable params.GasTable, availableGas, base, callCost *big.Int) *big.Int { 47 if gasTable.CreateBySuicide != nil { 48 availableGas = new(big.Int).Sub(availableGas, base) 49 g := new(big.Int).Div(availableGas, n64) 50 g.Sub(availableGas, g) 51 52 if g.Cmp(callCost) < 0 { 53 return g 54 } 55 } 56 return callCost 57 } 58 59 // baseCheck checks for any stack error underflows 60 func baseCheck(op OpCode, stack *Stack, gas *big.Int) error { 61 // PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit 62 // PUSH is also allowed to calculate the same price for all PUSHes 63 // DUP requirements are handled elsewhere (except for the stack limit check) 64 if op >= PUSH1 && op <= PUSH32 { 65 op = PUSH1 66 } 67 if op >= DUP1 && op <= DUP16 { 68 op = DUP1 69 } 70 71 if r, ok := _baseCheck[op]; ok { 72 err := stack.require(r.stackPop) 73 if err != nil { 74 return err 75 } 76 77 if r.stackPush > 0 && stack.len()-r.stackPop+r.stackPush > int(params.StackLimit.Int64()) { 78 return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64()) 79 } 80 81 gas.Add(gas, r.gas) 82 } 83 return nil 84 } 85 86 // casts a arbitrary number to the amount of words (sets of 32 bytes) 87 func toWordSize(size *big.Int) *big.Int { 88 tmp := new(big.Int) 89 tmp.Add(size, u256(31)) 90 tmp.Div(tmp, u256(32)) 91 return tmp 92 } 93 94 type req struct { 95 stackPop int 96 gas *big.Int 97 stackPush int 98 } 99 100 var _baseCheck = map[OpCode]req{ 101 // opcode | stack pop | gas price | stack push 102 ADD: {2, GasFastestStep, 1}, 103 LT: {2, GasFastestStep, 1}, 104 GT: {2, GasFastestStep, 1}, 105 SLT: {2, GasFastestStep, 1}, 106 SGT: {2, GasFastestStep, 1}, 107 EQ: {2, GasFastestStep, 1}, 108 ISZERO: {1, GasFastestStep, 1}, 109 SUB: {2, GasFastestStep, 1}, 110 AND: {2, GasFastestStep, 1}, 111 OR: {2, GasFastestStep, 1}, 112 XOR: {2, GasFastestStep, 1}, 113 NOT: {1, GasFastestStep, 1}, 114 BYTE: {2, GasFastestStep, 1}, 115 CALLDATALOAD: {1, GasFastestStep, 1}, 116 CALLDATACOPY: {3, GasFastestStep, 1}, 117 MLOAD: {1, GasFastestStep, 1}, 118 MSTORE: {2, GasFastestStep, 0}, 119 MSTORE8: {2, GasFastestStep, 0}, 120 CODECOPY: {3, GasFastestStep, 0}, 121 MUL: {2, GasFastStep, 1}, 122 DIV: {2, GasFastStep, 1}, 123 SDIV: {2, GasFastStep, 1}, 124 MOD: {2, GasFastStep, 1}, 125 SMOD: {2, GasFastStep, 1}, 126 SIGNEXTEND: {2, GasFastStep, 1}, 127 ADDMOD: {3, GasMidStep, 1}, 128 MULMOD: {3, GasMidStep, 1}, 129 JUMP: {1, GasMidStep, 0}, 130 JUMPI: {2, GasSlowStep, 0}, 131 EXP: {2, GasSlowStep, 1}, 132 ADDRESS: {0, GasQuickStep, 1}, 133 ORIGIN: {0, GasQuickStep, 1}, 134 CALLER: {0, GasQuickStep, 1}, 135 CALLVALUE: {0, GasQuickStep, 1}, 136 CODESIZE: {0, GasQuickStep, 1}, 137 GASPRICE: {0, GasQuickStep, 1}, 138 COINBASE: {0, GasQuickStep, 1}, 139 TIMESTAMP: {0, GasQuickStep, 1}, 140 NUMBER: {0, GasQuickStep, 1}, 141 CALLDATASIZE: {0, GasQuickStep, 1}, 142 DIFFICULTY: {0, GasQuickStep, 1}, 143 GASLIMIT: {0, GasQuickStep, 1}, 144 POP: {1, GasQuickStep, 0}, 145 PC: {0, GasQuickStep, 1}, 146 MSIZE: {0, GasQuickStep, 1}, 147 GAS: {0, GasQuickStep, 1}, 148 BLOCKHASH: {1, GasExtStep, 1}, 149 BALANCE: {1, Zero, 1}, 150 EXTCODESIZE: {1, Zero, 1}, 151 EXTCODECOPY: {4, Zero, 0}, 152 SLOAD: {1, params.SloadGas, 1}, 153 SSTORE: {2, Zero, 0}, 154 SHA3: {2, params.Sha3Gas, 1}, 155 CREATE: {3, params.CreateGas, 1}, 156 // Zero is calculated in the gasSwitch 157 CALL: {7, Zero, 1}, 158 CALLCODE: {7, Zero, 1}, 159 DELEGATECALL: {6, Zero, 1}, 160 SELFDESTRUCT: {1, Zero, 0}, 161 JUMPDEST: {0, params.JumpdestGas, 0}, 162 RETURN: {2, Zero, 0}, 163 PUSH1: {0, GasFastestStep, 1}, 164 DUP1: {0, Zero, 1}, 165 }