Merge branch 'vm-trace-listener'

This commit is contained in:
eugene-shevchenko 2015-04-09 11:49:43 +03:00
commit 429d1025a2
7 changed files with 60 additions and 9 deletions

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -60,7 +60,7 @@ public class EthereumListenerAdapter implements EthereumListener {
}
@Override
public void onVMTraceCreated(String transactionHash, String traceAsJson) {
public void onVMTraceCreated(String transactionHash, String trace) {
}
}

View File

@ -825,7 +825,7 @@ public class Program {
Op op = new Op();
op.setPc(pc);
op.setDeep(invokeData.getCallDeep());
op.setOp(ops[pc]);
op.saveGas(getGas());

View File

@ -26,6 +26,7 @@ import java.util.Stack;
* 'op': 'CODECOPY'
* 'storage': {},
* 'gas': '99376',
* 'deep': 0,
* 'pc': '9',
* 'memory': '',
* 'stack': ['15', '15', '14', '0'],
@ -38,6 +39,7 @@ import java.util.Stack;
public class Op {
private byte op;
private int deep;
private int pc;
private DataWord gas;
private Map<String, String> storage;
@ -48,6 +50,10 @@ public class Op {
this.op = op;
}
public void setDeep(int deep) {
this.deep = deep;
}
public void setPc(int pc) {
this.pc = pc;
}
@ -87,6 +93,7 @@ public class Op {
Map<Object, Object> jsonData = new LinkedHashMap<>();
jsonData.put("op", OpCode.code(op).name());
jsonData.put("deep", Long.toString(deep));
jsonData.put("pc", Long.toString(pc));
jsonData.put("gas", gas.value().toString());
jsonData.put("stack", stack);

View File

@ -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<Op> 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 "{}";
}
}
}