public void spendGas(long gasValue, String cause) { gasLogger.info("[{}] Spent for cause: [ {} ], gas: [ {} ]", invokeHash, cause, gasValue); long afterSpend = invokeData.getGas().longValue() - gasValue - result.getGasUsed(); if (afterSpend < 0) throw new OutOfGasException(); result.spendGas(gasValue); }
public void fullTrace() { if (logger.isTraceEnabled() || listener != null) { StringBuilder stackData = new StringBuilder(); for (int i = 0; i < stack.size(); ++i) { stackData.append(" ").append(stack.get(i)); if (i < stack.size() - 1) stackData.append("\n"); } if (stackData.length() > 0) stackData.insert(0, "\n"); ContractDetails contractDetails = this.result.getRepository().getContractDetails(this.programAddress.getLast20Bytes()); StringBuilder storageData = new StringBuilder(); List<DataWord> storageKeys = new ArrayList<>(contractDetails.getStorage().keySet()); Collections.sort((List<DataWord>) storageKeys); for (DataWord key : storageKeys) { storageData .append(" ") .append(key) .append(" -> ") .append(contractDetails.getStorage().get(key)) .append("\n"); } if (storageData.length() > 0) storageData.insert(0, "\n"); StringBuilder memoryData = new StringBuilder(); StringBuilder oneLine = new StringBuilder(); for (int i = 0; memory != null && i < memory.limit(); ++i) { byte value = memory.get(i); oneLine.append(Utils.oneByteToHexString(value)).append(" "); if ((i + 1) % 16 == 0) { String tmp = String.format("[%4s]-[%4s]", Integer.toString(i - 15, 16), Integer.toString(i, 16)) .replace(" ", "0"); memoryData.append("").append(tmp).append(" "); memoryData.append(oneLine); if (i < memory.limit()) memoryData.append("\n"); oneLine.setLength(0); } } if (memoryData.length() > 0) memoryData.insert(0, "\n"); StringBuilder opsString = new StringBuilder(); for (int i = 0; i < ops.length; ++i) { String tmpString = Integer.toString(ops[i] & 0xFF, 16); tmpString = tmpString.length() == 1 ? "0" + tmpString : tmpString; if (i != pc) opsString.append(tmpString); else opsString.append(" >>").append(tmpString).append(""); } if (pc >= ops.length) opsString.append(" >>"); if (opsString.length() > 0) opsString.insert(0, "\n "); logger.trace(" -- OPS -- {}", opsString); logger.trace(" -- STACK -- {}", stackData); logger.trace(" -- MEMORY -- {}", memoryData); logger.trace(" -- STORAGE -- {}\n", storageData); logger.trace( "\n Spent Gas: [ {} ]/[ {} ]\n Left Gas: [ {} ]\n", result.getGasUsed(), invokeData.getGas().longValue(), getGas().longValue()); StringBuilder globalOutput = new StringBuilder("\n"); if (stackData.length() > 0) stackData.append("\n"); if (pc != 0) globalOutput.append("[Op: ").append(OpCode.code(lastOp).name()).append("]\n"); globalOutput.append(" -- OPS -- ").append(opsString).append("\n"); globalOutput.append(" -- STACK -- ").append(stackData).append("\n"); globalOutput.append(" -- MEMORY -- ").append(memoryData).append("\n"); globalOutput.append(" -- STORAGE -- ").append(storageData).append("\n"); if (result.getHReturn() != null) { globalOutput.append("\n HReturn: ").append(Hex.toHexString(result.getHReturn().array())); } // soffisticated assumption that msg.data != codedata // means we are calling the contract not creating it byte[] txData = invokeData.getDataCopy(DataWord.ZERO, getDataSize()); if (!Arrays.equals(txData, ops)) { globalOutput.append("\n msg.data: ").append(Hex.toHexString(txData)); } globalOutput.append("\n\n Spent Gas: ").append(result.getGasUsed()); if (listener != null) { listener.output(globalOutput.toString()); } } }
public DataWord getGas() { if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; long afterSpend = invokeData.getGas().longValue() - result.getGasUsed(); return new DataWord(afterSpend); }