github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/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/ethereum/go-ethereum/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  
    40  func baseCheck(op OpCode, stack *stack, gas *big.Int) error {
    41  	// PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
    42  	// PUSH is also allowed to calculate the same price for all PUSHes
    43  	// DUP requirements are handled elsewhere (except for the stack limit check)
    44  	if op >= PUSH1 && op <= PUSH32 {
    45  		op = PUSH1
    46  	}
    47  	if op >= DUP1 && op <= DUP16 {
    48  		op = DUP1
    49  	}
    50  
    51  	if r, ok := _baseCheck[op]; ok {
    52  		err := stack.require(r.stackPop)
    53  		if err != nil {
    54  			return err
    55  		}
    56  
    57  		if r.stackPush > 0 && stack.len()-r.stackPop+r.stackPush > int(params.StackLimit.Int64()) {
    58  			return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64())
    59  		}
    60  
    61  		gas.Add(gas, r.gas)
    62  	}
    63  	return nil
    64  }
    65  
    66  func toWordSize(size *big.Int) *big.Int {
    67  	tmp := new(big.Int)
    68  	tmp.Add(size, u256(31))
    69  	tmp.Div(tmp, u256(32))
    70  	return tmp
    71  }
    72  
    73  type req struct {
    74  	stackPop  int
    75  	gas       *big.Int
    76  	stackPush int
    77  }
    78  
    79  var _baseCheck = map[OpCode]req{
    80  	// opcode  |  stack pop | gas price | stack push
    81  	ADD:          {2, GasFastestStep, 1},
    82  	LT:           {2, GasFastestStep, 1},
    83  	GT:           {2, GasFastestStep, 1},
    84  	SLT:          {2, GasFastestStep, 1},
    85  	SGT:          {2, GasFastestStep, 1},
    86  	EQ:           {2, GasFastestStep, 1},
    87  	ISZERO:       {1, GasFastestStep, 1},
    88  	SUB:          {2, GasFastestStep, 1},
    89  	AND:          {2, GasFastestStep, 1},
    90  	OR:           {2, GasFastestStep, 1},
    91  	XOR:          {2, GasFastestStep, 1},
    92  	NOT:          {1, GasFastestStep, 1},
    93  	BYTE:         {2, GasFastestStep, 1},
    94  	CALLDATALOAD: {1, GasFastestStep, 1},
    95  	CALLDATACOPY: {3, GasFastestStep, 1},
    96  	MLOAD:        {1, GasFastestStep, 1},
    97  	MSTORE:       {2, GasFastestStep, 0},
    98  	MSTORE8:      {2, GasFastestStep, 0},
    99  	CODECOPY:     {3, GasFastestStep, 0},
   100  	MUL:          {2, GasFastStep, 1},
   101  	DIV:          {2, GasFastStep, 1},
   102  	SDIV:         {2, GasFastStep, 1},
   103  	MOD:          {2, GasFastStep, 1},
   104  	SMOD:         {2, GasFastStep, 1},
   105  	SIGNEXTEND:   {2, GasFastStep, 1},
   106  	ADDMOD:       {3, GasMidStep, 1},
   107  	MULMOD:       {3, GasMidStep, 1},
   108  	JUMP:         {1, GasMidStep, 0},
   109  	JUMPI:        {2, GasSlowStep, 0},
   110  	EXP:          {2, GasSlowStep, 1},
   111  	ADDRESS:      {0, GasQuickStep, 1},
   112  	ORIGIN:       {0, GasQuickStep, 1},
   113  	CALLER:       {0, GasQuickStep, 1},
   114  	CALLVALUE:    {0, GasQuickStep, 1},
   115  	CODESIZE:     {0, GasQuickStep, 1},
   116  	GASPRICE:     {0, GasQuickStep, 1},
   117  	COINBASE:     {0, GasQuickStep, 1},
   118  	TIMESTAMP:    {0, GasQuickStep, 1},
   119  	NUMBER:       {0, GasQuickStep, 1},
   120  	CALLDATASIZE: {0, GasQuickStep, 1},
   121  	DIFFICULTY:   {0, GasQuickStep, 1},
   122  	GASLIMIT:     {0, GasQuickStep, 1},
   123  	POP:          {1, GasQuickStep, 0},
   124  	PC:           {0, GasQuickStep, 1},
   125  	MSIZE:        {0, GasQuickStep, 1},
   126  	GAS:          {0, GasQuickStep, 1},
   127  	BLOCKHASH:    {1, GasExtStep, 1},
   128  	BALANCE:      {1, GasExtStep, 1},
   129  	EXTCODESIZE:  {1, GasExtStep, 1},
   130  	EXTCODECOPY:  {4, GasExtStep, 0},
   131  	SLOAD:        {1, params.SloadGas, 1},
   132  	SSTORE:       {2, Zero, 0},
   133  	SHA3:         {2, params.Sha3Gas, 1},
   134  	CREATE:       {3, params.CreateGas, 1},
   135  	CALL:         {7, params.CallGas, 1},
   136  	CALLCODE:     {7, params.CallGas, 1},
   137  	JUMPDEST:     {0, params.JumpdestGas, 0},
   138  	SUICIDE:      {1, Zero, 0},
   139  	RETURN:       {2, Zero, 0},
   140  	PUSH1:        {0, GasFastestStep, 1},
   141  	DUP1:         {0, Zero, 1},
   142  }