Coverage Summary for Class: ProgramInvokeImpl (org.ethereum.vm.program.invoke)

Class Class, % Method, % Line, %
ProgramInvokeImpl 100% (1/1) 33.3% (10/30) 34.8% (49/141)


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 package org.ethereum.vm.program.invoke; 21  22 import org.ethereum.core.Repository; 23 import org.ethereum.db.BlockStore; 24 import org.ethereum.vm.DataWord; 25 import org.ethereum.vm.program.Program; 26  27 import java.math.BigInteger; 28 import java.util.Arrays; 29 import java.util.Map; 30  31 /** 32  * @author Roman Mandeleil 33  * @since 03.06.2014 34  */ 35 public class ProgramInvokeImpl implements ProgramInvoke { 36  37  private BlockStore blockStore; 38  /** 39  * TRANSACTION env ** 40  */ 41  private final DataWord address; 42  private final DataWord origin; 43  private final DataWord caller; 44  private final DataWord balance; 45  private final DataWord gasPrice; 46  private final DataWord callValue; 47  private long gas; 48  49  byte[] msgData; 50  51  /** 52  * BLOCK env ** 53  */ 54  private final DataWord prevHash; 55  private final DataWord coinbase; 56  private final DataWord timestamp; 57  private final DataWord number; 58  private final DataWord difficulty; 59  private final DataWord gaslimit; 60  61  private final DataWord transactionIndex; 62  63  private Map<DataWord, DataWord> storage; 64  65  private final Repository repository; 66  private boolean byTransaction = true; 67  private boolean byTestingSuite = false; 68  private int callDeep = 0; 69  private boolean isStaticCall = false; 70  71  public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, DataWord balance, 72  DataWord gasPrice, 73  long gas, 74  DataWord callValue, byte[] msgData, 75  DataWord lastHash, DataWord coinbase, DataWord timestamp, DataWord number, DataWord transactionIndex, DataWord 76  difficulty, 77  DataWord gaslimit, Repository repository, int callDeep, BlockStore blockStore, 78  boolean isStaticCall, 79  boolean byTestingSuite) { 80  81  // Transaction env 82  this.address = address; 83  this.origin = origin; 84  this.caller = caller; 85  this.balance = balance; 86  this.gasPrice = gasPrice; 87  this.gas = gas; 88  this.callValue = callValue; 89  this.msgData = msgData; 90  91  // last Block env 92  this.prevHash = lastHash; 93  this.coinbase = coinbase; 94  this.timestamp = timestamp; 95  this.number = number; 96  this.transactionIndex = transactionIndex; 97  this.difficulty = difficulty; 98  this.gaslimit = gaslimit; 99  100  this.repository = repository; 101  this.byTransaction = false; 102  this.callDeep = callDeep; 103  this.blockStore = blockStore; 104  this.isStaticCall = isStaticCall; 105  this.byTestingSuite = byTestingSuite; 106  } 107  108  public ProgramInvokeImpl(byte[] address, byte[] origin, byte[] caller, byte[] balance, 109  byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData, 110  byte[] lastHash, byte[] coinbase, long timestamp, long number, int transactionIndex, byte[] difficulty, 111  byte[] gaslimit, 112  Repository repository, BlockStore blockStore, 113  boolean byTestingSuite) { 114  this(address, origin, caller, balance, gasPrice, gas, callValue, msgData, lastHash, coinbase, 115  timestamp, number, transactionIndex, difficulty, gaslimit, repository, blockStore); 116  117  this.byTestingSuite = byTestingSuite; 118  } 119  120  121  public ProgramInvokeImpl(byte[] address, byte[] origin, byte[] caller, byte[] balance, 122  byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData, 123  byte[] lastHash, byte[] coinbase, long timestamp, long number, int transactionIndex, byte[] difficulty, 124  byte[] gaslimit, 125  Repository repository, BlockStore blockStore) { 126  127  // Transaction env 128  this.address = DataWord.valueOf(address); 129  this.origin = DataWord.valueOf(origin); 130  this.caller = DataWord.valueOf(caller); 131  this.balance = DataWord.valueOf(balance); 132  this.gasPrice = DataWord.valueOf(gasPrice); 133  this.gas = Program.limitToMaxLong(DataWord.valueOf(gas)); 134  this.callValue = DataWord.valueOf(callValue); 135  this.msgData = msgData; 136  137  // last Block env 138  this.prevHash = DataWord.valueOf(lastHash); 139  this.coinbase = DataWord.valueOf(coinbase); 140  this.timestamp = DataWord.valueOf(timestamp); 141  this.number = DataWord.valueOf(number); 142  this.transactionIndex = DataWord.valueOf(transactionIndex); 143  this.difficulty = DataWord.valueOf(difficulty); 144  this.gaslimit = DataWord.valueOf(gaslimit); 145  146  this.repository = repository; 147  this.blockStore = blockStore; 148  } 149  150  /* ADDRESS op */ 151  public DataWord getOwnerAddress() { 152  return address; 153  } 154  155  /* BALANCE op */ 156  public DataWord getBalance() { 157  return balance; 158  } 159  160  /* ORIGIN op */ 161  public DataWord getOriginAddress() { 162  return origin; 163  } 164  165  /* CALLER op */ 166  public DataWord getCallerAddress() { 167  return caller; 168  } 169  170  /* GASPRICE op */ 171  public DataWord getMinGasPrice() { 172  return gasPrice; 173  } 174  175  /* GAS op */ 176  public long getGas() { 177  return gas; 178  } 179  180  /* CALLVALUE op */ 181  public DataWord getCallValue() { 182  return callValue; 183  } 184  185  /*****************/ 186  /*** msg data ***/ 187  /*****************/ 188  /* NOTE: In the protocol there is no restriction on the maximum message data, 189  * However msgData here is a byte[] and this can't hold more than 2^32-1 190  */ 191  private static BigInteger maxMsgData = BigInteger.valueOf(Integer.MAX_VALUE); 192  193  /* CALLDATALOAD op */ 194  public DataWord getDataValue(DataWord indexData) { 195  196  BigInteger tempIndex = indexData.value(); 197  int index = tempIndex.intValue(); // possible overflow is caught below 198  int size = 32; // maximum datavalue size 199  200  if (msgData == null || index >= msgData.length 201  || tempIndex.compareTo(maxMsgData) == 1) { 202  return DataWord.ZERO; 203  } 204  if (index + size > msgData.length) { 205  size = msgData.length - index; 206  } 207  208  byte[] data = new byte[32]; 209  System.arraycopy(msgData, index, data, 0, size); 210  return DataWord.valueOf(data); 211  } 212  213  /* CALLDATASIZE */ 214  public DataWord getDataSize() { 215  216  if (msgData == null || msgData.length == 0) { 217  return DataWord.ZERO; 218  } 219  int size = msgData.length; 220  return DataWord.valueOf(size); 221  } 222  223  /* CALLDATACOPY */ 224  public byte[] getDataCopy(DataWord offsetData, DataWord lengthData) { 225  226  int offset = offsetData.intValueSafe(); 227  int length = lengthData.intValueSafe(); 228  229  byte[] data = new byte[length]; 230  231  if (msgData == null) { 232  return data; 233  } 234  if (offset > msgData.length) { 235  return data; 236  } 237  if (offset + length > msgData.length) { 238  length = msgData.length - offset; 239  } 240  241  System.arraycopy(msgData, offset, data, 0, length); 242  243  return data; 244  } 245  246  247  /* PREVHASH op */ 248  public DataWord getPrevHash() { 249  return prevHash; 250  } 251  252  /* COINBASE op */ 253  public DataWord getCoinbase() { 254  return coinbase; 255  } 256  257  /* TIMESTAMP op */ 258  public DataWord getTimestamp() { 259  return timestamp; 260  } 261  262  /* NUMBER op */ 263  public DataWord getNumber() { 264  return number; 265  } 266  267  /* TXINDEX op */ 268  public DataWord getTransactionIndex() { 269  return transactionIndex; 270  } 271  272  /* DIFFICULTY op */ 273  public DataWord getDifficulty() { 274  return difficulty; 275  } 276  277  /* GASLIMIT op */ 278  public DataWord getGaslimit() { 279  return gaslimit; 280  } 281  282  /* Storage */ 283  public Map<DataWord, DataWord> getStorage() { 284  return storage; 285  } 286  287  public Repository getRepository() { 288  return repository; 289  } 290  291  @Override 292  public BlockStore getBlockStore() { 293  return blockStore; 294  } 295  296  @Override 297  public boolean byTransaction() { 298  return byTransaction; 299  } 300  301  @Override 302  public boolean isStaticCall() { 303  return isStaticCall; 304  } 305  306  @Override 307  public boolean byTestingSuite() { 308  return byTestingSuite; 309  } 310  311  @Override 312  public int getCallDeep() { 313  return this.callDeep; 314  } 315  316  @Override 317  public boolean equals(Object o) { 318  if (this == o) { 319  return true; 320  } 321  if (o == null || getClass() != o.getClass()) { 322  return false; 323  } 324  325  ProgramInvokeImpl that = (ProgramInvokeImpl) o; 326  327  if (byTestingSuite != that.byTestingSuite) { 328  return false; 329  } 330  if (byTransaction != that.byTransaction) { 331  return false; 332  } 333  if (address != null ? !address.equals(that.address) : that.address != null) { 334  return false; 335  } 336  if (balance != null ? !balance.equals(that.balance) : that.balance != null) { 337  return false; 338  } 339  if (callValue != null ? !callValue.equals(that.callValue) : that.callValue != null) { 340  return false; 341  } 342  if (caller != null ? !caller.equals(that.caller) : that.caller != null) { 343  return false; 344  } 345  if (coinbase != null ? !coinbase.equals(that.coinbase) : that.coinbase != null) { 346  return false; 347  } 348  if (difficulty != null ? !difficulty.equals(that.difficulty) : that.difficulty != null) { 349  return false; 350  } 351  if (gas!=that.gas) { 352  return false; 353  } 354  if (gasPrice != null ? !gasPrice.equals(that.gasPrice) : that.gasPrice != null) { 355  return false; 356  } 357  if (gaslimit != null ? !gaslimit.equals(that.gaslimit) : that.gaslimit != null) { 358  return false; 359  } 360  if (!Arrays.equals(msgData, that.msgData)) { 361  return false; 362  } 363  if (number != null ? !number.equals(that.number) : that.number != null) { 364  return false; 365  } 366  if (origin != null ? !origin.equals(that.origin) : that.origin != null) { 367  return false; 368  } 369  if (prevHash != null ? !prevHash.equals(that.prevHash) : that.prevHash != null) { 370  return false; 371  } 372  if (repository != null ? !repository.equals(that.repository) : that.repository != null) { 373  return false; 374  } 375  if (storage != null ? !storage.equals(that.storage) : that.storage != null) { 376  return false; 377  } 378  if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) { 379  return false; 380  } 381  382  return true; 383  } 384  385  @Override 386  public String toString() { 387  return "ProgramInvokeImpl{" + 388  "address=" + address + 389  ", origin=" + origin + 390  ", caller=" + caller + 391  ", balance=" + balance + 392  ", gas=" + gas + 393  ", gasPrice=" + gasPrice + 394  ", callValue=" + callValue + 395  ", msgData=" + Arrays.toString(msgData) + 396  ", prevHash=" + prevHash + 397  ", coinbase=" + coinbase + 398  ", timestamp=" + timestamp + 399  ", number=" + number + 400  ", difficulty=" + difficulty + 401  ", gaslimit=" + gaslimit + 402  ", storage=" + storage + 403  ", repository=" + repository + 404  ", byTransaction=" + byTransaction + 405  ", byTestingSuite=" + byTestingSuite + 406  ", callDeep=" + callDeep + 407  '}'; 408  } 409 }