gas.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. package vm
  17. import (
  18. "fmt"
  19. "math/big"
  20. "github.com/ethereum/go-ethereum/params"
  21. )
  22. var (
  23. GasQuickStep = big.NewInt(2)
  24. GasFastestStep = big.NewInt(3)
  25. GasFastStep = big.NewInt(5)
  26. GasMidStep = big.NewInt(8)
  27. GasSlowStep = big.NewInt(10)
  28. GasExtStep = big.NewInt(20)
  29. GasReturn = big.NewInt(0)
  30. GasStop = big.NewInt(0)
  31. GasContractByte = big.NewInt(200)
  32. n64 = big.NewInt(64)
  33. )
  34. // calcGas returns the actual gas cost of the call.
  35. //
  36. // The cost of gas was changed during the homestead price change HF. To allow for EIP150
  37. // to be implemented. The returned gas is gas - base * 63 / 64.
  38. func callGas(gasTable params.GasTable, availableGas, base, callCost *big.Int) *big.Int {
  39. if gasTable.CreateBySuicide != nil {
  40. availableGas = new(big.Int).Sub(availableGas, base)
  41. g := new(big.Int).Div(availableGas, n64)
  42. g.Sub(availableGas, g)
  43. if g.Cmp(callCost) < 0 {
  44. return g
  45. }
  46. }
  47. return callCost
  48. }
  49. // baseCheck checks for any stack error underflows
  50. func baseCheck(op OpCode, stack *Stack, gas *big.Int) error {
  51. // PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
  52. // PUSH is also allowed to calculate the same price for all PUSHes
  53. // DUP requirements are handled elsewhere (except for the stack limit check)
  54. if op >= PUSH1 && op <= PUSH32 {
  55. op = PUSH1
  56. }
  57. if op >= DUP1 && op <= DUP16 {
  58. op = DUP1
  59. }
  60. if r, ok := _baseCheck[op]; ok {
  61. err := stack.require(r.stackPop)
  62. if err != nil {
  63. return err
  64. }
  65. if r.stackPush > 0 && stack.len()-r.stackPop+r.stackPush > int(params.StackLimit.Int64()) {
  66. return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64())
  67. }
  68. gas.Add(gas, r.gas)
  69. }
  70. return nil
  71. }
  72. // casts a arbitrary number to the amount of words (sets of 32 bytes)
  73. func toWordSize(size *big.Int) *big.Int {
  74. tmp := new(big.Int)
  75. tmp.Add(size, u256(31))
  76. tmp.Div(tmp, u256(32))
  77. return tmp
  78. }
  79. type req struct {
  80. stackPop int
  81. gas *big.Int
  82. stackPush int
  83. }
  84. var _baseCheck = map[OpCode]req{
  85. // opcode | stack pop | gas price | stack push
  86. ADD: {2, GasFastestStep, 1},
  87. LT: {2, GasFastestStep, 1},
  88. GT: {2, GasFastestStep, 1},
  89. SLT: {2, GasFastestStep, 1},
  90. SGT: {2, GasFastestStep, 1},
  91. EQ: {2, GasFastestStep, 1},
  92. ISZERO: {1, GasFastestStep, 1},
  93. SUB: {2, GasFastestStep, 1},
  94. AND: {2, GasFastestStep, 1},
  95. OR: {2, GasFastestStep, 1},
  96. XOR: {2, GasFastestStep, 1},
  97. NOT: {1, GasFastestStep, 1},
  98. BYTE: {2, GasFastestStep, 1},
  99. CALLDATALOAD: {1, GasFastestStep, 1},
  100. CALLDATACOPY: {3, GasFastestStep, 1},
  101. MLOAD: {1, GasFastestStep, 1},
  102. MSTORE: {2, GasFastestStep, 0},
  103. MSTORE8: {2, GasFastestStep, 0},
  104. CODECOPY: {3, GasFastestStep, 0},
  105. MUL: {2, GasFastStep, 1},
  106. DIV: {2, GasFastStep, 1},
  107. SDIV: {2, GasFastStep, 1},
  108. MOD: {2, GasFastStep, 1},
  109. SMOD: {2, GasFastStep, 1},
  110. SIGNEXTEND: {2, GasFastStep, 1},
  111. ADDMOD: {3, GasMidStep, 1},
  112. MULMOD: {3, GasMidStep, 1},
  113. JUMP: {1, GasMidStep, 0},
  114. JUMPI: {2, GasSlowStep, 0},
  115. EXP: {2, GasSlowStep, 1},
  116. ADDRESS: {0, GasQuickStep, 1},
  117. ORIGIN: {0, GasQuickStep, 1},
  118. CALLER: {0, GasQuickStep, 1},
  119. CALLVALUE: {0, GasQuickStep, 1},
  120. CODESIZE: {0, GasQuickStep, 1},
  121. GASPRICE: {0, GasQuickStep, 1},
  122. COINBASE: {0, GasQuickStep, 1},
  123. TIMESTAMP: {0, GasQuickStep, 1},
  124. NUMBER: {0, GasQuickStep, 1},
  125. CALLDATASIZE: {0, GasQuickStep, 1},
  126. DIFFICULTY: {0, GasQuickStep, 1},
  127. GASLIMIT: {0, GasQuickStep, 1},
  128. POP: {1, GasQuickStep, 0},
  129. PC: {0, GasQuickStep, 1},
  130. MSIZE: {0, GasQuickStep, 1},
  131. GAS: {0, GasQuickStep, 1},
  132. BLOCKHASH: {1, GasExtStep, 1},
  133. BALANCE: {1, Zero, 1},
  134. EXTCODESIZE: {1, Zero, 1},
  135. EXTCODECOPY: {4, Zero, 0},
  136. SLOAD: {1, params.SloadGas, 1},
  137. SSTORE: {2, Zero, 0},
  138. SHA3: {2, params.Sha3Gas, 1},
  139. CREATE: {3, params.CreateGas, 1},
  140. // Zero is calculated in the gasSwitch
  141. CALL: {7, Zero, 1},
  142. CALLCODE: {7, Zero, 1},
  143. DELEGATECALL: {6, Zero, 1},
  144. SELFDESTRUCT: {1, Zero, 0},
  145. JUMPDEST: {0, params.JumpdestGas, 0},
  146. RETURN: {2, Zero, 0},
  147. PUSH1: {0, GasFastestStep, 1},
  148. DUP1: {0, Zero, 1},
  149. }