mirror of
https://github.com/status-im/ethereumj-personal.git
synced 2025-01-09 19:35:53 +00:00
Merge branch 'vm-trace-listener'
This commit is contained in:
commit
429d1025a2
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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 "{}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user