Skip to content

Commit b1e3873

Browse files
committed
Added program arguments and parametrized some options
1 parent f8e5f01 commit b1e3873

File tree

8 files changed

+135
-30
lines changed

8 files changed

+135
-30
lines changed

README.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,35 @@ and jump where it is necessary in a quick and graphical way.
99

1010
# Usage
1111

12-
Right now, the debugger is very simple:
12+
Version 0.0.4 and earlier (this will be removed when 0.0.5 is released):
1313

1414
```
1515
edebugger-1.0-SNAPSHOT.jar <solidity source file> <node URL> <transaction hash>
1616
```
17-
For example:
17+
18+
Version 0.0.5 (current snapshot in master):
19+
20+
```
21+
edebugger-<VERSION>-SNAPSHOT.jar <OPTIONS>
22+
Options category 'mandatory':
23+
--node [-n] (a string; default: "")
24+
The node where the transaction was run. It must support debug_traceTransaction
25+
--source-file [-f] (a string; default: "")
26+
The source file of the contract the transaction is executed against
27+
--transaction-hash [-t] (a string; default: "")
28+
Transaction hash to debug
29+
30+
Options category 'optional':
31+
--d3-memory [-m] (a string; default: "537395200")
32+
D3 graph memory. If the graph is too large, you may want to increase this value (by multiplying it)
33+
--[no]only-trace [-o] (a boolean; default: "false")
34+
Exclude opcodes that are not executed in the transaction.
35+
This may help if the graph is too large and/or the opcodes not executed are not important
36+
```
37+
38+
Example:
1839
```
19-
java -jar edebugger-1.0-SNAPSHOT.jar ~/tests/Program.sol http://127.0.0.1:8545 0x0c971feb820d2bca26c3e7a0a27b5015694d9ec8ea0169935ff7168a63da3f6f
40+
java -jar edebugger-<VERSION>.jar -f ~/tests/Program.sol -n http://127.0.0.1:8545 -t 0x0c971feb820d2bca26c3e7a0a27b5015694d9ec8ea0169935ff7168a63da3f6f
2041
```
2142

2243
# Download
@@ -47,7 +68,7 @@ There are already tools that allow you to debug Ethereum transactions (Solidity)
4768

4869
For now there are many limitations since this is a very early release of the debugger
4970

50-
* The control flow graph is drawn from the static bytecode, so there can be nodes without edges, a symbolic execution would be needed. Maybe will be added in future releases
71+
* The control flow graph is drawn from the static bytecode, so there can be nodes without all edges, a symbolic execution would be needed. Maybe will be added in future releases
5172
* Transactions executed in the runtime bytecode are supported (for example, the constructor execution of a contract cannot be debugged right now)
5273
* You must provide a node URL that supports `debug_traceTransaction`, like Geth or Ganache, therefore, Infura is not supported
5374
* It only supports Solidity for now, but planning to make it more modular to support different languages (if the compiler gives source mappings)

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<apache.http.client.version>4.5.5</apache.http.client.version>
1515
<junit.version>4.12</junit.version>
1616
<velocity.version>1.7</velocity.version>
17+
<google.options.version>1.0.0</google.options.version>
1718
<mvn.assembly.plugin.version>3.1.0</mvn.assembly.plugin.version>
1819
<jar.cli>edebugger-${version}</jar.cli>
1920
</properties>
@@ -39,6 +40,11 @@
3940
<artifactId>velocity</artifactId>
4041
<version>${velocity.version}</version>
4142
</dependency>
43+
<dependency>
44+
<groupId>com.github.pcj</groupId>
45+
<artifactId>google-options</artifactId>
46+
<version>${google.options.version}</version>
47+
</dependency>
4248
<dependency>
4349
<groupId>junit</groupId>
4450
<artifactId>junit</artifactId>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package net.nandgr.debugger;
2+
3+
import com.google.devtools.common.options.Option;
4+
import com.google.devtools.common.options.OptionsBase;
5+
import com.google.devtools.common.options.OptionsParser;
6+
import java.io.File;
7+
import java.util.Collections;
8+
9+
public class Arguments extends OptionsBase {
10+
11+
@Option(
12+
name = "source-file",
13+
abbrev = 'f',
14+
help = "The source file of the contract the transaction is executed against",
15+
category = "mandatory",
16+
defaultValue = ""
17+
)
18+
public String sourceFile;
19+
20+
@Option(
21+
name = "node",
22+
abbrev = 'n',
23+
help = "The node where the transaction was run. It must support debug_traceTransaction",
24+
category = "mandatory",
25+
defaultValue = ""
26+
)
27+
public String nodeUrl;
28+
29+
@Option(
30+
name = "transaction-hash",
31+
abbrev = 't',
32+
help = "Transaction hash to debug",
33+
category = "mandatory",
34+
defaultValue = ""
35+
)
36+
public String transactionHash;
37+
38+
@Option(
39+
name = "d3-memory",
40+
abbrev = 'm',
41+
help = "D3 graph memory. If the graph is too large, you may want to increase this value (by multiplying it)",
42+
category = "optional",
43+
defaultValue = "537395200"
44+
)
45+
public String d3totalMemory;
46+
47+
@Option(
48+
name = "only-trace",
49+
abbrev = 'o',
50+
help = "Exclude opcodes that are not executed in the transaction when creating the graph. " +
51+
"This may help if the graph is too large and the opcodes not executed are not important",
52+
category = "optional",
53+
defaultValue = "false"
54+
)
55+
public boolean onlyTraceOpcodes;
56+
57+
public void validate(OptionsParser parser) {
58+
if (sourceFile.isEmpty() || nodeUrl.isEmpty() || transactionHash.isEmpty()) {
59+
String execName = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getName();
60+
System.out.println("Help: java -jar " + execName + " <OPTIONS>" + System.lineSeparator());
61+
System.out.println(parser.describeOptions(Collections.<String, String>emptyMap(), OptionsParser.HelpVerbosity.LONG));
62+
System.exit(0);
63+
}
64+
}
65+
}
Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,33 @@
11
package net.nandgr.debugger;
22

3+
import com.google.devtools.common.options.OptionsParser;
34
import net.nandgr.debugger.report.Report;
45
import net.nandgr.debugger.report.ReportException;
5-
import net.nandgr.debugger.solc.Solc;
66
import net.nandgr.debugger.transformers.ContractObject;
77
import net.nandgr.debugger.transformers.SolidityTransformer;
88
import net.nandgr.debugger.transformers.TransformException;
99
import net.nandgr.debugger.transformers.Transformer;
10-
import java.io.File;
1110
import java.util.List;
1211

1312
public class Main {
1413

15-
public static void main(String[] args){
14+
public static Arguments arguments;
1615

17-
if(args.length < 3) {
18-
String execName = new File(Main.class.getProtectionDomain()
19-
.getCodeSource()
20-
.getLocation()
21-
.getPath())
22-
.getName();
23-
System.out.println("Help: java -jar " + execName + " <solidity source file> <node URL> <transaction hash>");
24-
System.exit(0);
25-
}
16+
public static void main(String[] args){
2617

27-
String sourceCodeFile = args[0];
28-
String nodeUrl = args[1];
29-
String txHash = args[2];
30-
31-
if (!Solc.checkSolcInClasspath()) {
32-
System.out.println("solc was not found in classpath");
33-
System.exit(0);
34-
}
18+
parseArguments(args);
3519

3620
// for now only solidity is supported
37-
Transformer solidityTransformer = new SolidityTransformer(nodeUrl, txHash);
21+
Transformer solidityTransformer = new SolidityTransformer(arguments.nodeUrl, arguments.transactionHash);
3822
List<ContractObject> contracts = null;
3923
try {
40-
contracts = solidityTransformer.loadContracts(sourceCodeFile);
24+
contracts = solidityTransformer.loadContracts(arguments.sourceFile);
4125
} catch (TransformException e) {
4226
e.printStackTrace();
4327
System.exit(0);
4428
}
4529

46-
Report report = new Report(contracts, txHash);
30+
Report report = new Report(contracts, arguments.transactionHash);
4731
String reportName = null;
4832
try {
4933
reportName = report.createReport();
@@ -54,4 +38,11 @@ public static void main(String[] args){
5438
}
5539
System.out.println("Debug file created at: " + reportName);
5640
}
41+
42+
private static void parseArguments(String[] args) {
43+
OptionsParser optionsParser = OptionsParser.newOptionsParser(Arguments.class);
44+
optionsParser.parseAndExitUponError(args);
45+
arguments = optionsParser.getOptions(Arguments.class);
46+
arguments.validate(optionsParser);
47+
}
5748
}

src/main/java/net/nandgr/debugger/cfg/graphviz/GraphVizCreator.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.nandgr.debugger.cfg.graphviz;
22

3+
import net.nandgr.debugger.Main;
34
import net.nandgr.debugger.cfg.beans.BytecodeChunk;
45
import net.nandgr.debugger.cfg.beans.OpcodeSource;
56
import net.nandgr.debugger.node.response.json.DebugTraceTransactionLog;
@@ -26,21 +27,36 @@ public String buildStringGraph() {
2627
for (BytecodeChunk bytecodeChunk : chunks.values()) {
2728
String coloredNode = "";
2829
OpcodeSource firstOpcode = bytecodeChunk.getOpcodes().get(0);
30+
if (Main.arguments.onlyTraceOpcodes && !trace.containsKey(firstOpcode.getOffset())) {
31+
continue;
32+
}
2933
if (trace.containsKey(firstOpcode.getOffset())) {
3034
coloredNode = " fontcolor=\"red\" ";
3135
}
3236
sb.append(bytecodeChunk.getId()).append("[").append(coloredNode).append("label=").append(buildLabel(bytecodeChunk)).append("]").append(System.lineSeparator());
33-
if (bytecodeChunk.getBranchA() != null) {
37+
38+
if (checkIfAppendBranch(bytecodeChunk.getBranchA())) {
3439
sb.append(bytecodeChunk.getId()).append("->").append(bytecodeChunk.getBranchA().getId()).append("[color=\"#12cc12\"];").append(System.lineSeparator());
3540
}
36-
if (bytecodeChunk.getBranchB() != null) {
41+
if (checkIfAppendBranch(bytecodeChunk.getBranchB())) {
3742
sb.append(bytecodeChunk.getId()).append("->").append(bytecodeChunk.getBranchB().getId()).append("[color=\"#12cc12\"];").append(System.lineSeparator());
3843
}
3944
}
4045
sb.append("}");
4146
return sb.toString();
4247
}
4348

49+
private boolean checkIfAppendBranch(BytecodeChunk branch) {
50+
if (branch == null) {
51+
return false;
52+
}
53+
if (!Main.arguments.onlyTraceOpcodes) {
54+
return true;
55+
}
56+
OpcodeSource firstOpcode = branch.getOpcodes().get(0);
57+
return trace.containsKey(firstOpcode.getOffset());
58+
}
59+
4460
private String buildLabel(BytecodeChunk bytecodeChunk) {
4561
StringBuilder sb= new StringBuilder("< <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">").append(System.lineSeparator());
4662
for (OpcodeSource opcodeSource : bytecodeChunk.getOpcodes()) {

src/main/java/net/nandgr/debugger/report/Report.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.nandgr.debugger.report;
22

3+
import net.nandgr.debugger.Main;
34
import net.nandgr.debugger.transformers.ContractObject;
45
import org.apache.velocity.Template;
56
import org.apache.velocity.VelocityContext;
@@ -46,6 +47,7 @@ public String createReport() throws ReportException {
4647
VelocityContext velocityContext = new VelocityContext();
4748
velocityContext.put("contracts", contracts);
4849
velocityContext.put("txHash", txHash);
50+
velocityContext.put("d3memory", Main.arguments.d3totalMemory);
4951
StringWriter stringWriter = new StringWriter();
5052
template.merge(velocityContext, stringWriter);
5153
try {

src/main/java/net/nandgr/debugger/transformers/SolidityTransformer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public class SolidityTransformer implements Transformer {
3232
public SolidityTransformer(String nodeUrl, String txHash) {
3333
this.nodeUrl = nodeUrl;
3434
this.txHash = txHash;
35+
if (!Solc.checkSolcInClasspath()) {
36+
System.out.println("solc was not found in classpath");
37+
System.exit(0);
38+
}
3539
}
3640

3741
@Override

src/main/resources/template/graph_template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@
155155
`;
156156

157157
window["graphviz-$contract.contractName"] = d3.select("#graph-$contract.contractName").graphviz();
158-
window["graphviz-$contract.contractName"].totalMemory(537395200);
158+
window["graphviz-$contract.contractName"].totalMemory($d3memory);
159159
#end
160160

161161
function render(dotSrc, gViz, contractName) {

0 commit comments

Comments
 (0)