github.com/humaniq/go-ethereum@v1.6.8-0.20171225131628-061223a13848/core/vm/gas_table.go (about) 1 // Copyright 2017 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 "math/big" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/common/math" 24 "github.com/ethereum/go-ethereum/params" 25 ) 26 27 // memoryGasCosts calculates the quadratic gas for memory expansion. It does so 28 // only for the memory region that is expanded, not the total memory. 29 func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { 30 31 if newMemSize == 0 { 32 return 0, nil 33 } 34 // The maximum that will fit in a uint64 is max_word_count - 1 35 // anything above that will result in an overflow. 36 // Additionally, a newMemSize which results in a 37 // newMemSizeWords larger than 0x7ffffffff will cause the square operation 38 // to overflow. 39 // The constant 0xffffffffe0 is the highest number that can be used without 40 // overflowing the gas calculation 41 if newMemSize > 0xffffffffe0 { 42 return 0, errGasUintOverflow 43 } 44 45 newMemSizeWords := toWordSize(newMemSize) 46 newMemSize = newMemSizeWords * 32 47 48 if newMemSize > uint64(mem.Len()) { 49 square := newMemSizeWords * newMemSizeWords 50 linCoef := newMemSizeWords * params.MemoryGas 51 quadCoef := square / params.QuadCoeffDiv 52 newTotalFee := linCoef + quadCoef 53 54 fee := newTotalFee - mem.lastGasCost 55 mem.lastGasCost = newTotalFee 56 57 return fee, nil 58 } 59 return 0, nil 60 } 61 62 func constGasFunc(gas uint64) gasFunc { 63 return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 64 return gas, nil 65 } 66 } 67 68 func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 69 gas, err := memoryGasCost(mem, memorySize) 70 if err != nil { 71 return 0, err 72 } 73 74 var overflow bool 75 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 76 return 0, errGasUintOverflow 77 } 78 79 words, overflow := bigUint64(stack.Back(2)) 80 if overflow { 81 return 0, errGasUintOverflow 82 } 83 84 if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { 85 return 0, errGasUintOverflow 86 } 87 88 if gas, overflow = math.SafeAdd(gas, words); overflow { 89 return 0, errGasUintOverflow 90 } 91 return gas, nil 92 } 93 94 func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 95 gas, err := memoryGasCost(mem, memorySize) 96 if err != nil { 97 return 0, err 98 } 99 100 var overflow bool 101 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 102 return 0, errGasUintOverflow 103 } 104 105 words, overflow := bigUint64(stack.Back(2)) 106 if overflow { 107 return 0, errGasUintOverflow 108 } 109 110 if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { 111 return 0, errGasUintOverflow 112 } 113 114 if gas, overflow = math.SafeAdd(gas, words); overflow { 115 return 0, errGasUintOverflow 116 } 117 return gas, nil 118 } 119 120 func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 121 var ( 122 y, x = stack.Back(1), stack.Back(0) 123 val = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) 124 ) 125 // This checks for 3 scenario's and calculates gas accordingly 126 // 1. From a zero-value address to a non-zero value (NEW VALUE) 127 // 2. From a non-zero value address to a zero-value address (DELETE) 128 // 3. From a non-zero to a non-zero (CHANGE) 129 if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) { 130 // 0 => non 0 131 return params.SstoreSetGas, nil 132 } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) { 133 evm.StateDB.AddRefund(new(big.Int).SetUint64(params.SstoreRefundGas)) 134 135 return params.SstoreClearGas, nil 136 } else { 137 // non 0 => non 0 (or 0 => 0) 138 return params.SstoreResetGas, nil 139 } 140 } 141 142 func makeGasLog(n uint64) gasFunc { 143 return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 144 requestedSize, overflow := bigUint64(stack.Back(1)) 145 if overflow { 146 return 0, errGasUintOverflow 147 } 148 149 gas, err := memoryGasCost(mem, memorySize) 150 if err != nil { 151 return 0, err 152 } 153 154 if gas, overflow = math.SafeAdd(gas, params.LogGas); overflow { 155 return 0, errGasUintOverflow 156 } 157 if gas, overflow = math.SafeAdd(gas, n*params.LogTopicGas); overflow { 158 return 0, errGasUintOverflow 159 } 160 161 var memorySizeGas uint64 162 if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow { 163 return 0, errGasUintOverflow 164 } 165 if gas, overflow = math.SafeAdd(gas, memorySizeGas); overflow { 166 return 0, errGasUintOverflow 167 } 168 return gas, nil 169 } 170 } 171 172 func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 173 var overflow bool 174 gas, err := memoryGasCost(mem, memorySize) 175 if err != nil { 176 return 0, err 177 } 178 179 if gas, overflow = math.SafeAdd(gas, params.Sha3Gas); overflow { 180 return 0, errGasUintOverflow 181 } 182 183 wordGas, overflow := bigUint64(stack.Back(1)) 184 if overflow { 185 return 0, errGasUintOverflow 186 } 187 if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); overflow { 188 return 0, errGasUintOverflow 189 } 190 if gas, overflow = math.SafeAdd(gas, wordGas); overflow { 191 return 0, errGasUintOverflow 192 } 193 return gas, nil 194 } 195 196 func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 197 gas, err := memoryGasCost(mem, memorySize) 198 if err != nil { 199 return 0, err 200 } 201 202 var overflow bool 203 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 204 return 0, errGasUintOverflow 205 } 206 207 wordGas, overflow := bigUint64(stack.Back(2)) 208 if overflow { 209 return 0, errGasUintOverflow 210 } 211 if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow { 212 return 0, errGasUintOverflow 213 } 214 if gas, overflow = math.SafeAdd(gas, wordGas); overflow { 215 return 0, errGasUintOverflow 216 } 217 return gas, nil 218 } 219 220 func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 221 gas, err := memoryGasCost(mem, memorySize) 222 if err != nil { 223 return 0, err 224 } 225 226 var overflow bool 227 if gas, overflow = math.SafeAdd(gas, gt.ExtcodeCopy); overflow { 228 return 0, errGasUintOverflow 229 } 230 231 wordGas, overflow := bigUint64(stack.Back(3)) 232 if overflow { 233 return 0, errGasUintOverflow 234 } 235 236 if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow { 237 return 0, errGasUintOverflow 238 } 239 240 if gas, overflow = math.SafeAdd(gas, wordGas); overflow { 241 return 0, errGasUintOverflow 242 } 243 return gas, nil 244 } 245 246 func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 247 var overflow bool 248 gas, err := memoryGasCost(mem, memorySize) 249 if err != nil { 250 return 0, errGasUintOverflow 251 } 252 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 253 return 0, errGasUintOverflow 254 } 255 return gas, nil 256 } 257 258 func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 259 var overflow bool 260 gas, err := memoryGasCost(mem, memorySize) 261 if err != nil { 262 return 0, errGasUintOverflow 263 } 264 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 265 return 0, errGasUintOverflow 266 } 267 return gas, nil 268 } 269 270 func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 271 var overflow bool 272 gas, err := memoryGasCost(mem, memorySize) 273 if err != nil { 274 return 0, errGasUintOverflow 275 } 276 if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { 277 return 0, errGasUintOverflow 278 } 279 return gas, nil 280 } 281 282 func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 283 var overflow bool 284 gas, err := memoryGasCost(mem, memorySize) 285 if err != nil { 286 return 0, err 287 } 288 if gas, overflow = math.SafeAdd(gas, params.CreateGas); overflow { 289 return 0, errGasUintOverflow 290 } 291 return gas, nil 292 } 293 294 func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 295 return gt.Balance, nil 296 } 297 298 func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 299 return gt.ExtcodeSize, nil 300 } 301 302 func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 303 return gt.SLoad, nil 304 } 305 306 func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 307 expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) 308 309 var ( 310 gas = expByteLen * gt.ExpByte // no overflow check required. Max is 256 * ExpByte gas 311 overflow bool 312 ) 313 if gas, overflow = math.SafeAdd(gas, GasSlowStep); overflow { 314 return 0, errGasUintOverflow 315 } 316 return gas, nil 317 } 318 319 func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 320 var ( 321 gas = gt.Calls 322 transfersValue = stack.Back(2).Sign() != 0 323 address = common.BigToAddress(stack.Back(1)) 324 eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) 325 ) 326 if eip158 { 327 if transfersValue && evm.StateDB.Empty(address) { 328 gas += params.CallNewAccountGas 329 } 330 } else if !evm.StateDB.Exist(address) { 331 gas += params.CallNewAccountGas 332 } 333 if transfersValue { 334 gas += params.CallValueTransferGas 335 } 336 memoryGas, err := memoryGasCost(mem, memorySize) 337 if err != nil { 338 return 0, err 339 } 340 var overflow bool 341 if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { 342 return 0, errGasUintOverflow 343 } 344 345 evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) 346 if err != nil { 347 return 0, err 348 } 349 if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { 350 return 0, errGasUintOverflow 351 } 352 return gas, nil 353 } 354 355 func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 356 gas := gt.Calls 357 if stack.Back(2).Sign() != 0 { 358 gas += params.CallValueTransferGas 359 } 360 memoryGas, err := memoryGasCost(mem, memorySize) 361 if err != nil { 362 return 0, err 363 } 364 var overflow bool 365 if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { 366 return 0, errGasUintOverflow 367 } 368 369 evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) 370 if err != nil { 371 return 0, err 372 } 373 if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { 374 return 0, errGasUintOverflow 375 } 376 return gas, nil 377 } 378 379 func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 380 return memoryGasCost(mem, memorySize) 381 } 382 383 func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 384 return memoryGasCost(mem, memorySize) 385 } 386 387 func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 388 var gas uint64 389 // EIP150 homestead gas reprice fork: 390 if evm.ChainConfig().IsEIP150(evm.BlockNumber) { 391 gas = gt.Suicide 392 var ( 393 address = common.BigToAddress(stack.Back(0)) 394 eip158 = evm.ChainConfig().IsEIP158(evm.BlockNumber) 395 ) 396 397 if eip158 { 398 // if empty and transfers value 399 if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 { 400 gas += gt.CreateBySuicide 401 } 402 } else if !evm.StateDB.Exist(address) { 403 gas += gt.CreateBySuicide 404 } 405 } 406 407 if !evm.StateDB.HasSuicided(contract.Address()) { 408 evm.StateDB.AddRefund(new(big.Int).SetUint64(params.SuicideRefundGas)) 409 } 410 return gas, nil 411 } 412 413 func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 414 gas, err := memoryGasCost(mem, memorySize) 415 if err != nil { 416 return 0, err 417 } 418 var overflow bool 419 if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { 420 return 0, errGasUintOverflow 421 } 422 423 evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) 424 if err != nil { 425 return 0, err 426 } 427 if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { 428 return 0, errGasUintOverflow 429 } 430 return gas, nil 431 } 432 433 func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 434 gas, err := memoryGasCost(mem, memorySize) 435 if err != nil { 436 return 0, err 437 } 438 var overflow bool 439 if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { 440 return 0, errGasUintOverflow 441 } 442 443 evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) 444 if err != nil { 445 return 0, err 446 } 447 if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { 448 return 0, errGasUintOverflow 449 } 450 return gas, nil 451 } 452 453 func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 454 return GasFastestStep, nil 455 } 456 457 func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 458 return GasFastestStep, nil 459 } 460 461 func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 462 return GasFastestStep, nil 463 }