From a0ad521fa19f4c07afebce77f3a03b7826e51278 Mon Sep 17 00:00:00 2001 From: eugene-shevchenko Date: Thu, 9 Apr 2015 11:48:57 +0300 Subject: [PATCH] VM trace extending with 'result' and 'error' fields. --- .../ethereum/core/TransactionExecutor.java | 16 +++++++-- .../listener/CompositeEthereumListener.java | 4 +-- .../ethereum/listener/EthereumListener.java | 3 +- .../listener/EthereumListenerAdapter.java | 2 +- .../org/ethereum/vmtrace/ProgramTrace.java | 35 ++++++++++++++++++- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java index 235b9650..d4c50e6f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java @@ -13,6 +13,7 @@ import org.ethereum.vm.ProgramInvokeFactory; import org.ethereum.vm.ProgramResult; import org.ethereum.vm.VM; +import org.ethereum.vmtrace.ProgramTrace; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -200,9 +201,10 @@ public class TransactionExecutor { if (isContractCreation || code != EMPTY_BYTE_ARRAY) { // START TRACKING FOR REVERT CHANGES OPTION + Program program = null; Repository trackTx = track.startTracking(); trackTx.addBalance(receiverAddress, BigInteger.ZERO); // the contract created for anycase but SUICIDE call - + logger.info("Start tracking VM run"); try { @@ -217,12 +219,11 @@ public class TransactionExecutor { programInvokeFactory.createProgramInvoke(tx, currentBlock, trackTx, blockStore); VM vm = new VM(); - Program program = new Program(code, programInvoke); + program = new Program(code, programInvoke); if (CONFIG.playVM()) vm.play(program); - listener.onVMTraceCreated(txHash, program.getProgramTrace().getJsonString()); program.saveProgramTraceToFile(txHash); result = program.getResult(); @@ -238,6 +239,15 @@ public class TransactionExecutor { receipt.setCumulativeGas(tx.getGasLimit()); this.receipt = receipt; return; + } finally { + String traceAsJson = "{}"; + if (program != null) { + ProgramTrace trace = program.getProgramTrace(); + trace.setResult(result.getHReturn()); + trace.setError(result.getException()); + traceAsJson = trace.getJsonString(); + } + listener.onVMTraceCreated(txHash, traceAsJson); } trackTx.commit(); } else { diff --git a/ethereumj-core/src/main/java/org/ethereum/listener/CompositeEthereumListener.java b/ethereumj-core/src/main/java/org/ethereum/listener/CompositeEthereumListener.java index 91fa73b6..70709a6f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/listener/CompositeEthereumListener.java +++ b/ethereumj-core/src/main/java/org/ethereum/listener/CompositeEthereumListener.java @@ -84,9 +84,9 @@ public class CompositeEthereumListener implements EthereumListener { } @Override - public void onVMTraceCreated(String transactionHash, String traceAsJson) { + public void onVMTraceCreated(String transactionHash, String trace) { for (EthereumListener listener : listeners) { - listener.onVMTraceCreated(transactionHash, traceAsJson); + listener.onVMTraceCreated(transactionHash, trace); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/listener/EthereumListener.java b/ethereumj-core/src/main/java/org/ethereum/listener/EthereumListener.java index 55c50a58..841bfc5e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/listener/EthereumListener.java +++ b/ethereumj-core/src/main/java/org/ethereum/listener/EthereumListener.java @@ -6,6 +6,7 @@ import org.ethereum.core.TransactionReceipt; import org.ethereum.net.message.Message; import org.ethereum.net.p2p.HelloMessage; +import java.nio.ByteBuffer; import java.util.List; import java.util.Set; @@ -35,5 +36,5 @@ public interface EthereumListener { void onHandShakePeer(HelloMessage helloMessage); - void onVMTraceCreated(String transactionHash, String traceAsJson); + void onVMTraceCreated(String transactionHash, String trace); } diff --git a/ethereumj-core/src/main/java/org/ethereum/listener/EthereumListenerAdapter.java b/ethereumj-core/src/main/java/org/ethereum/listener/EthereumListenerAdapter.java index 87c6d5be..fd10cc20 100644 --- a/ethereumj-core/src/main/java/org/ethereum/listener/EthereumListenerAdapter.java +++ b/ethereumj-core/src/main/java/org/ethereum/listener/EthereumListenerAdapter.java @@ -60,7 +60,7 @@ public class EthereumListenerAdapter implements EthereumListener { } @Override - public void onVMTraceCreated(String transactionHash, String traceAsJson) { + public void onVMTraceCreated(String transactionHash, String trace) { } } diff --git a/ethereumj-core/src/main/java/org/ethereum/vmtrace/ProgramTrace.java b/ethereumj-core/src/main/java/org/ethereum/vmtrace/ProgramTrace.java index 75bcca17..2ee9eb98 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vmtrace/ProgramTrace.java +++ b/ethereumj-core/src/main/java/org/ethereum/vmtrace/ProgramTrace.java @@ -1,9 +1,22 @@ package org.ethereum.vmtrace; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.util.encoders.Hex; +import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; + +import static java.lang.String.format; /** * @author Roman Mandeleil @@ -11,13 +24,26 @@ import java.util.List; */ public class ProgramTrace { + private static final Logger LOGGER = LoggerFactory.getLogger("vmtrace"); + + @JsonIgnore private byte[] txHash; private List ops = new ArrayList<>(); + private String result; + private String error; public void setTxHash(byte[] txHash) { this.txHash = txHash; } + public void setResult(ByteBuffer result) { + this.result = Hex.toHexString(result.array()); + } + + public void setError(Exception error) { + this.error = (error == null) ? "" : format("%s: %s", error.getClass(), error.getMessage());; + } + public void addOp(Op op) { ops.add(op); } @@ -31,6 +57,13 @@ public class ProgramTrace { } public String getJsonString() { - return JSONArray.toJSONString(ops); + try { + return new ObjectMapper() + .enable(SerializationFeature.INDENT_OUTPUT) + .writeValueAsString(this); + } catch (JsonProcessingException e) { + LOGGER.error("JSON serialization error: ", e); + return "{}"; + } } }