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.ProgramResult;
import org.ethereum.vm.VM; import org.ethereum.vm.VM;
import org.ethereum.vmtrace.ProgramTrace;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -200,6 +201,7 @@ public class TransactionExecutor {
if (isContractCreation || code != EMPTY_BYTE_ARRAY) { if (isContractCreation || code != EMPTY_BYTE_ARRAY) {
// START TRACKING FOR REVERT CHANGES OPTION // START TRACKING FOR REVERT CHANGES OPTION
Program program = null;
Repository trackTx = track.startTracking(); Repository trackTx = track.startTracking();
trackTx.addBalance(receiverAddress, BigInteger.ZERO); // the contract created for anycase but SUICIDE call trackTx.addBalance(receiverAddress, BigInteger.ZERO); // the contract created for anycase but SUICIDE call
@ -217,12 +219,11 @@ public class TransactionExecutor {
programInvokeFactory.createProgramInvoke(tx, currentBlock, trackTx, blockStore); programInvokeFactory.createProgramInvoke(tx, currentBlock, trackTx, blockStore);
VM vm = new VM(); VM vm = new VM();
Program program = new Program(code, programInvoke); program = new Program(code, programInvoke);
if (CONFIG.playVM()) if (CONFIG.playVM())
vm.play(program); vm.play(program);
listener.onVMTraceCreated(txHash, program.getProgramTrace().getJsonString());
program.saveProgramTraceToFile(txHash); program.saveProgramTraceToFile(txHash);
result = program.getResult(); result = program.getResult();
@ -238,6 +239,15 @@ public class TransactionExecutor {
receipt.setCumulativeGas(tx.getGasLimit()); receipt.setCumulativeGas(tx.getGasLimit());
this.receipt = receipt; this.receipt = receipt;
return; 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(); trackTx.commit();
} else { } else {

View File

@ -84,9 +84,9 @@ public class CompositeEthereumListener implements EthereumListener {
} }
@Override @Override
public void onVMTraceCreated(String transactionHash, String traceAsJson) { public void onVMTraceCreated(String transactionHash, String trace) {
for (EthereumListener listener : listeners) { 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.message.Message;
import org.ethereum.net.p2p.HelloMessage; import org.ethereum.net.p2p.HelloMessage;
import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -35,5 +36,5 @@ public interface EthereumListener {
void onHandShakePeer(HelloMessage helloMessage); 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 @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 op = new Op();
op.setPc(pc); op.setPc(pc);
op.setDeep(invokeData.getCallDeep());
op.setOp(ops[pc]); op.setOp(ops[pc]);
op.saveGas(getGas()); op.saveGas(getGas());

View File

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

View File

@ -1,9 +1,22 @@
package org.ethereum.vmtrace; 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.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.ArrayList;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import static java.lang.String.format;
/** /**
* @author Roman Mandeleil * @author Roman Mandeleil
@ -11,13 +24,26 @@ import java.util.List;
*/ */
public class ProgramTrace { public class ProgramTrace {
private static final Logger LOGGER = LoggerFactory.getLogger("vmtrace");
@JsonIgnore
private byte[] txHash; private byte[] txHash;
private List<Op> ops = new ArrayList<>(); private List<Op> ops = new ArrayList<>();
private String result;
private String error;
public void setTxHash(byte[] txHash) { public void setTxHash(byte[] txHash) {
this.txHash = 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) { public void addOp(Op op) {
ops.add(op); ops.add(op);
} }
@ -31,6 +57,13 @@ public class ProgramTrace {
} }
public String getJsonString() { 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 "{}";
}
} }
} }