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

Class Class, % Method, % Line, %
ProgramResult 100% (1/1) 40.6% (13/32) 30.2% (26/86)


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; 21  22 import org.ethereum.core.Transaction; 23 import org.ethereum.vm.CallCreate; 24 import org.ethereum.vm.DataWord; 25 import org.ethereum.vm.GasCost; 26 import org.ethereum.vm.LogInfo; 27  28 import java.util.*; 29  30 import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; 31  32 /** 33  * @author Roman Mandeleil 34  * @since 07.06.2014 35  */ 36 public class ProgramResult { 37  38  private long gasUsed; 39  private byte[] hReturn = EMPTY_BYTE_ARRAY; 40  private Exception exception; 41  private boolean revert; 42  43  // Important: 44  // DataWord is used as a ByteArrayWrapper, because Java data Maps/Sets cannot distiguish duplicate 45  // keys if the key is of type byte[]. 46  private Map<DataWord, byte[]> codeChanges; 47  48  private Set<DataWord> deleteAccounts; 49  private List<InternalTransaction> internalTransactions; 50  private List<LogInfo> logInfoList; 51  private long futureRefund = 0; 52  53  /* 54  * for testing runs , 55  * call/create is not executed 56  * but dummy recorded 57  */ 58  private List<CallCreate> callCreateList; 59  60  public void clearUsedGas() { 61  gasUsed = 0; 62  } 63  64  public void spendGas(long gas) { 65  gasUsed = GasCost.add(gasUsed, gas); 66  } 67  68  public void setRevert() { 69  this.revert = true; 70  } 71  72  public boolean isRevert() { 73  return revert; 74  } 75  76  public void refundGas(long gas) { 77  gasUsed = GasCost.subtract(gasUsed, gas); 78  } 79  80  public void setHReturn(byte[] hReturn) { 81  this.hReturn = hReturn; 82  83  } 84  85  public byte[] getHReturn() { 86  return hReturn; 87  } 88  89  public Exception getException() { 90  return exception; 91  } 92  93  public long getGasUsed() { 94  return gasUsed; 95  } 96  97  public void setException(Exception exception) { 98  this.exception = exception; 99  } 100  101  102  public Set<DataWord> getDeleteAccounts() { 103  if (deleteAccounts == null) { 104  deleteAccounts = new HashSet<>(); 105  } 106  return deleteAccounts; 107  } 108  109  public Map<DataWord, byte[]> getCodeChanges() { 110  if (codeChanges == null) { 111  codeChanges = new HashMap<>(); 112  } 113  return codeChanges; 114  } 115  116  public void addCodeChange(DataWord addr, byte[] newCode) { 117  getCodeChanges().put(addr, newCode); 118  } 119  120  121  public void addDeleteAccount(DataWord address) { 122  getDeleteAccounts().add(address); 123  } 124  125  public void addDeleteAccounts(Set<DataWord> accounts) { 126  getDeleteAccounts().addAll(accounts); 127  } 128  129  public void clearFieldsOnException() { 130  if (deleteAccounts!=null) { 131  deleteAccounts.clear(); 132  } 133  if (logInfoList!=null) { 134  logInfoList.clear(); 135  } 136  if (codeChanges!=null) { 137  codeChanges.clear(); 138  } 139  resetFutureRefund(); 140  } 141  142  143  public List<LogInfo> getLogInfoList() { 144  if (logInfoList == null) { 145  logInfoList = new ArrayList<>(); 146  } 147  return logInfoList; 148  } 149  150  public void addLogInfo(LogInfo logInfo) { 151  getLogInfoList().add(logInfo); 152  } 153  154  public void addLogInfos(List<LogInfo> logInfos) { 155  getLogInfoList().addAll(logInfos); 156  } 157  158  public List<CallCreate> getCallCreateList() { 159  if (callCreateList == null) { 160  callCreateList = new ArrayList<>(); 161  } 162  return callCreateList; 163  } 164  165  public void addCallCreate(byte[] data, byte[] destination, long gasLimit, byte[] value) { 166  getCallCreateList().add(new CallCreate(data, destination, gasLimit, value)); 167  } 168  169  public List<InternalTransaction> getInternalTransactions() { 170  if (internalTransactions == null) { 171  internalTransactions = new ArrayList<>(); 172  } 173  return internalTransactions; 174  } 175  176  public InternalTransaction addInternalTransaction( 177  Transaction parentTransaction, 178  int deep, 179  byte[] nonce, 180  DataWord gasPrice, 181  DataWord gasLimit, 182  byte[] senderAddress, 183  byte[] receiveAddress, 184  byte[] value, 185  byte[] data, 186  String note 187  ) { 188  byte[] parentHash = parentTransaction.getHash().getBytes(); 189  byte[] originHash = parentHash; 190  if (parentTransaction instanceof InternalTransaction) { 191  originHash = ((InternalTransaction) parentTransaction).getOriginHash(); 192  } 193  InternalTransaction transaction = new InternalTransaction( 194  originHash, 195  parentHash, 196  deep, 197  getInternalTransactions().size(), 198  nonce, 199  gasPrice, 200  gasLimit, 201  senderAddress, 202  receiveAddress, 203  value, 204  data, 205  note 206  ); 207  getInternalTransactions().add(transaction); 208  return transaction; 209  } 210  211  public void addInternalTransactions(List<InternalTransaction> internalTransactions) { 212  getInternalTransactions().addAll(internalTransactions); 213  } 214  215  public void rejectInternalTransactions() { 216  for (InternalTransaction internalTx : getInternalTransactions()) { 217  internalTx.reject(); 218  } 219  } 220  221  public void rejectLogInfos() { 222  for (LogInfo logInfo : getLogInfoList()) { 223  logInfo.reject(); 224  } 225  } 226  227  public void addFutureRefund(long gasValue) { 228  futureRefund += gasValue; 229  } 230  231  public long getFutureRefund() { 232  return futureRefund; 233  } 234  235  public void resetFutureRefund() { 236  futureRefund = 0; 237  } 238  239  public void merge(ProgramResult another) { 240  addInternalTransactions(another.getInternalTransactions()); 241  if (another.getException() == null && !another.isRevert()) { 242  addDeleteAccounts(another.getDeleteAccounts()); 243  addLogInfos(another.getLogInfoList()); 244  addFutureRefund(another.getFutureRefund()); 245  } 246  } 247  248  public static ProgramResult empty() { 249  ProgramResult result = new ProgramResult(); 250  result.setHReturn(EMPTY_BYTE_ARRAY); 251  return result; 252  } 253 }