Coverage Summary for Class: GasCost (org.ethereum.vm)

Class Method, % Line, %
GasCost 66.7% (6/9) 55% (22/40)
GasCost$InvalidGasException 0% (0/4) 0% (0/7)
Total 46.2% (6/13) 46.8% (22/47)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 RSK Labs Ltd. 4  * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>) 5  * 6  * This program is free software: you can redistribute it and/or modify 7  * it under the terms of the GNU Lesser General Public License as published by 8  * the Free Software Foundation, either version 3 of the License, or 9  * (at your option) any later version. 10  * 11  * This program is distributed in the hope that it will be useful, 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14  * GNU Lesser General Public License for more details. 15  * 16  * You should have received a copy of the GNU Lesser General Public License 17  * along with this program. If not, see <http://www.gnu.org/licenses/>. 18  */ 19  20  21 package org.ethereum.vm; 22  23 import org.ethereum.util.ByteUtil; 24  25 import java.math.BigInteger; 26  27 /** 28  * The fundamental network cost unit. Paid for exclusively by SBTC, which is converted 29  * freely to and from Gas as required. Gas does not exist outside of the internal RSK 30  * computation engine; its price is set by the Transaction and miners are free to 31  * ignore Transactions whose Gas price is too low. 32  * 33  * GasCost includes static methods to operate on longs which represent Gas. These methods 34  * should always be used when calculating gas. 35  */ 36 public class GasCost { 37  /* backwards compatibility, remove eventually */ 38  public static final long STEP = 1; 39  public static final long SSTORE = 300; 40  /* backwards compatibility, remove eventually */ 41  public static final long ZEROSTEP = 0; 42  public static final long QUICKSTEP = 2; 43  public static final long FASTESTSTEP = 3; 44  public static final long FASTSTEP = 5; 45  public static final long MIDSTEP = 8; 46  public static final long SLOWSTEP = 10; 47  public static final long EXTSTEP = 20; 48  49  public static final long GENESISGASLIMIT = 1000000; 50  public static final long MINGASLIMIT = 125000; 51  52  public static final long BALANCE = 400; 53  public static final long SHA3 = 30; 54  public static final long SHA3_WORD = 6; 55  public static final long SLOAD = 200; 56  public static final long STOP = 0; 57  public static final long SUICIDE = 5000; 58  public static final long CLEAR_SSTORE = 5000; 59  public static final long SET_SSTORE = 20000; 60  public static final long RESET_SSTORE = 5000; 61  public static final long REFUND_SSTORE = 15000; 62  public static final long CREATE = 32000; 63  64  public static final long JUMPDEST = 1; 65  public static final long CREATE_DATA_BYTE = 5; 66  public static final long CALL = 700; 67  public static final long STIPEND_CALL = 2300; // For transferring coins in CALL, this is always passed to child 68  public static final long VT_CALL = 9000; //value transfer call 69  public static final long NEW_ACCT_CALL = 25000; //new account call 70  public static final long MEMORY = 3; // TODO: Memory in V0 is more expensive than V1: This MUST be modified before release 71  public static final long MEMORY_V1 =3; 72  public static final long SUICIDE_REFUND = 24000; 73  public static final long QUAD_COEFF_DIV = 512; 74  public static final long CREATE_DATA = 200; // paid for each new byte of code 75  public static final long REPLACE_DATA = 50; // paid for each byte of code replaced 76  public static final long TX_NO_ZERO_DATA = 68; 77  public static final long TX_ZERO_DATA = 4; 78  public static final long TRANSACTION = 21000; 79  public static final long TRANSACTION_DEFAULT = 90000; //compatibility with ethereum (mmarquez) 80  public static final long TRANSACTION_CREATE_CONTRACT = 53000; 81  public static final long LOG_GAS = 375; 82  public static final long LOG_DATA_GAS = 8; 83  public static final long LOG_TOPIC_GAS = 375; 84  public static final long COPY_GAS = 3; 85  public static final long EXP_GAS = 10; 86  public static final long EXP_BYTE_GAS = 50; 87  public static final long IDENTITY = 15; 88  public static final long IDENTITY_WORD = 3; 89  public static final long RIPEMD160 = 600; 90  public static final long RIPEMD160_WORD = 120; 91  public static final long SHA256 = 60; 92  public static final long SHA256_WORD = 12; 93  public static final long EC_RECOVER = 3000; 94  public static final long EXT_CODE_SIZE = 700; 95  public static final long EXT_CODE_COPY = 700; 96  public static final long EXT_CODE_HASH = 400; 97  public static final long CODEREPLACE = 15000; 98  public static final long NEW_ACCT_SUICIDE = 25000; 99  public static final long RETURN = 0; 100  101  public static final long MAX_GAS = Long.MAX_VALUE; 102  103  /** 104  * An exception which is thrown be methods in GasCost when 105  * an operation overflows, has invalid inputs or wants to return 106  * an invalid gas value. 107  */ 108  public static class InvalidGasException extends IllegalArgumentException { 109  110  private InvalidGasException(long invalidValue) { 111  super(String.format("Got invalid gas value: %d", invalidValue)); 112  } 113  114  private InvalidGasException(byte[] bytes) { 115  super(String.format("Got invalid gas value as bytes array: %s", ByteUtil.toHexStringOrEmpty(bytes))); 116  } 117  118  private InvalidGasException(String str) { 119  super(String.format("Got invalid gas value, tried operation: %s", str)); 120  } 121  122  } 123  124  // Everything in this class should be static, do not initialize. 125  private GasCost() { } 126  127  /** 128  * Converts a byte array to gas. Byte arrays are signed two bit compliments. 129  * The byte array must have at most 8 values in it so as to fit in a long. 130  * Be careful so as not to send a negative byte array. 131  * @param bytes represents the number which will be converted to gas. 132  * @return the gas equivalent of the byte array. 133  * @throws InvalidGasException if the array has more than 8 values or 134  * is negative. 135  */ 136  public static long toGas(byte[] bytes) throws InvalidGasException { 137  if (bytes.length > 8) { 138  return Long.MAX_VALUE; 139  } 140  long result = ByteUtil.byteArrayToLong(bytes); 141  if (result < 0) { 142  throw new InvalidGasException(bytes); 143  } 144  return result; 145  } 146  147  /** 148  * Convert a BigInteger to gas. 149  * @throws InvalidGasException if the big integer is negative or is bigger than Long.MAX_VALUE. 150  */ 151  public static long toGas(BigInteger big) throws InvalidGasException { 152  if (big.compareTo(BigInteger.ZERO) < 0) { 153  throw new InvalidGasException(big.toByteArray()); 154  } 155  return toGas(big.toByteArray()); 156  } 157  158  /** 159  * Make sure the number is a valid gas value. 160  * @return: the number, if is positive or zero. 161  * @throws InvalidGasException if the number is negative. 162  */ 163  public static long toGas(long number) throws InvalidGasException { 164  if (number < 0) { 165  throw new InvalidGasException(number); 166  } 167  return number; 168  } 169  170  /** 171  * Adds two longs numbers representing gas, capping at Long.MAX_VALUE. 172  * @param x some gas. 173  * @param y another gas. 174  * @return the sum of the two numbers, capped. 175  * @throws InvalidGasException if any of the inputs is negative 176  */ 177  public static long add(long x, long y) throws InvalidGasException { 178  if (x < 0 || y < 0) { 179  throw new InvalidGasException(String.format("%d + %d", x, y)); 180  } 181  long result = x + y; 182  if (result < 0) { 183  return Long.MAX_VALUE; 184  } 185  return result; 186  } 187  188  /** 189  * Multply two longs representing gas, capping at Long.MAX_VALUE. 190  * @param x some gas. 191  * @param y another gas. 192  * @return the multiplication of the two numbers, capped. 193  * @throws InvalidGasException if any of the inputs is negative 194  */ 195  public static long multiply(long x, long y) throws InvalidGasException { 196  if (x < 0 || y < 0) { 197  throw new InvalidGasException(String.format("%d * %d", x, y)); 198  } 199  long result = x * y; 200  if (multiplicationOverflowed(x, y, result)) { 201  return Long.MAX_VALUE; 202  } 203  return result; 204  } 205  206  /** 207  * Subtracts two longs representing gas. 208  * @throws InvalidGasException if any of the inputs are negative or the 209  * result of the subtraction is negative. 210  */ 211  public static long subtract(long x, long y) throws InvalidGasException { 212  if (y < 0 || y > x) { 213  throw new InvalidGasException(String.format("%d - %d", x, y)); 214  } 215  return x - y; 216  } 217  218  /** 219  * Calculate the total gas cost given a baseline cost, the cost of an unit and how many units 220  * are passed. The operation is capped at Long.MAX_VALUE. 221  * @param baseCost a baseline cost. 222  * @param unitCost the cost of a single unit. 223  * @param units how many units. 224  * @return baseCost + unitCost * units, capped at Long.MAX_VALUE 225  * @throws InvalidGasException if any of the inputs are negative. 226  */ 227  public static long calculateTotal(long baseCost, long unitCost, long units) throws InvalidGasException { 228  if (baseCost < 0 || unitCost < 0 || units < 0) { 229  throw new InvalidGasException(String.format("%d + %d * %d", baseCost, unitCost, units)); 230  } 231  long mult = unitCost * units; 232  if (multiplicationOverflowed(unitCost, units, mult)) { 233  return Long.MAX_VALUE; 234  } 235  long result = baseCost + mult; 236  if (result < 0) { 237  return Long.MAX_VALUE; 238  } 239  return result; 240  } 241  242  /** 243  * Returns whether r is overflowed in `x * y = r` 244  * Both x and y must be positive. 245  */ 246  private static boolean multiplicationOverflowed(long x, long y, long result) { 247  // Heavily inspired on Math.multiplyExact 248  // https://github.com/frohoff/jdk8u-jdk/blob/master/src/share/classes/java/lang/Math.java#L882/ 249  // changed because a precondition states that both x and y must be positive. 250  if (((x | y) >>> 31 != 0)) { 251  // Some bits greater than 2^31 that might cause overflow 252  // Check the result using the divide operator 253  // and check for the special case of Long.MIN_VALUE * -1 254  return (y != 0) && (result/ y != x); 255  } 256  return false; 257  } 258 }