public String memoryToString() { StringBuilder memoryData = new StringBuilder(); StringBuilder firstLine = new StringBuilder(); StringBuilder secondLine = new StringBuilder(); for (int i = 0; memory != null && i < memory.limit(); ++i) { byte value = memory.get(i); // Check if value is ASCII // (should be until 0x7e - but using 0x7f // to be compatible with cpp-ethereum) // See: https://github.com/ethereum/cpp-ethereum/issues/299 String character = ((byte) 0x20 <= value && value <= (byte) 0x7f) ? new String(new byte[] {value}) : "?"; firstLine.append(character).append(""); secondLine.append(Utils.oneByteToHexString(value)).append(" "); if ((i + 1) % 8 == 0) { String tmp = String.format("%4s", Integer.toString(i - 7, 16)).replace(" ", "0"); memoryData.append("").append(tmp).append(" "); memoryData.append(firstLine).append(" "); memoryData.append(secondLine); if (i + 1 < memory.limit()) memoryData.append("\n"); firstLine.setLength(0); secondLine.setLength(0); } } return memoryData.toString(); }
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()); } } }