diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java index 71628c8896..2811a01135 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java @@ -69,24 +69,22 @@ public class TransactionTracer { final Hash blockHash, final Hash transactionHash, final DebugOperationTracer tracer) { - Optional transactionTrace = - blockReplay.beforeTransactionInBlock( - mutableWorldState, - blockHash, - transactionHash, - (transaction, header, blockchain, transactionProcessor, blobGasPrice) -> { - final TransactionProcessingResult result = - processTransaction( - header, - blockchain, - mutableWorldState.updater(), - transaction, - transactionProcessor, - tracer, - blobGasPrice); - return new TransactionTrace(transaction, result, tracer.getTraceFrames()); - }); - return transactionTrace; + return blockReplay.beforeTransactionInBlock( + mutableWorldState, + blockHash, + transactionHash, + (transaction, header, blockchain, transactionProcessor, blobGasPrice) -> { + final TransactionProcessingResult result = + processTransaction( + header, + blockchain, + mutableWorldState.updater(), + transaction, + transactionProcessor, + tracer, + blobGasPrice); + return new TransactionTrace(transaction, result, tracer.getTraceFrames()); + }); } public List traceTransactionToFile( @@ -139,7 +137,7 @@ public class TransactionTracer { stackedUpdater, transaction, transactionProcessor, - new StandardJsonTracer(out, showMemory, true, true), + new StandardJsonTracer(out, showMemory, true, true, false), blobGasPrice); out.println( summaryTrace( diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java index d41dd56093..0e2daf96eb 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java @@ -181,6 +181,14 @@ public class EvmToolCommand implements Runnable { negatable = true) final Boolean showReturnData = false; + @Option( + names = {"--trace.storage"}, + description = + "Show the updated storage slots for the current account. Default is to not show updated storage.", + scope = INHERIT, + negatable = true) + final Boolean showStorage = false; + @Option( names = {"--notime"}, description = "Don't include time data in summary output.", @@ -365,7 +373,7 @@ public class EvmToolCommand implements Runnable { final OperationTracer tracer = // You should have picked Mercy. lastLoop && showJsonResults - ? new StandardJsonTracer(out, showMemory, !hideStack, showReturnData) + ? new StandardJsonTracer(out, showMemory, !hideStack, showReturnData, showStorage) : OperationTracer.NO_TRACING; WorldUpdater updater = component.getWorldUpdater(); @@ -466,10 +474,10 @@ public class EvmToolCommand implements Runnable { " \"" + accountStorageEntry .getKey() - .map(UInt256::toHexString) + .map(UInt256::toQuantityHexString) .orElse("-") + "\": \"" - + accountStorageEntry.getValue().toHexString() + + accountStorageEntry.getValue().toQuantityHexString() + "\"") .toList())); out.println(" },"); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java index 2bc5f81530..a2d966f067 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java @@ -182,7 +182,8 @@ public class StateTestSubCommand implements Runnable { parentCommand.out, parentCommand.showMemory, !parentCommand.hideStack, - parentCommand.showReturnData) + parentCommand.showReturnData, + parentCommand.showStorage) : OperationTracer.NO_TRACING; final ObjectMapper objectMapper = JsonUtils.createObjectMapper(); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nSubCommand.java index ea2984c5c9..006a806e21 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nSubCommand.java @@ -254,7 +254,8 @@ public class T8nSubCommand implements Runnable { new PrintStream(traceDest), parentCommand.showMemory, !parentCommand.hideStack, - parentCommand.showReturnData); + parentCommand.showReturnData, + parentCommand.showStorage); outputStreams.put(jsonTracer, traceDest); return jsonTracer; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java b/evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java index 1734e7f673..e2c69f44d0 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java @@ -45,6 +45,7 @@ public class StandardJsonTracer implements OperationTracer { private final boolean showMemory; private final boolean showStack; private final boolean showReturnData; + private final boolean showStorage; private int pc; private int section; private List stack; @@ -52,6 +53,7 @@ public class StandardJsonTracer implements OperationTracer { private Bytes memory; private int memorySize; private int depth; + private String storageString; /** * Instantiates a new Standard json tracer. @@ -60,16 +62,19 @@ public class StandardJsonTracer implements OperationTracer { * @param showMemory show memory in trace lines * @param showStack show the stack in trace lines * @param showReturnData show return data in trace lines + * @param showStorage show the updated storage */ public StandardJsonTracer( final PrintWriter out, final boolean showMemory, final boolean showStack, - final boolean showReturnData) { + final boolean showReturnData, + final boolean showStorage) { this.out = out; this.showMemory = showMemory; this.showStack = showStack; this.showReturnData = showReturnData; + this.showStorage = showStorage; } /** @@ -79,13 +84,20 @@ public class StandardJsonTracer implements OperationTracer { * @param showMemory show memory in trace lines * @param showStack show the stack in trace lines * @param showReturnData show return data in trace lines + * @param showStorage show updated storage */ public StandardJsonTracer( final PrintStream out, final boolean showMemory, final boolean showStack, - final boolean showReturnData) { - this(new PrintWriter(out, true, StandardCharsets.UTF_8), showMemory, showStack, showReturnData); + final boolean showReturnData, + final boolean showStorage) { + this( + new PrintWriter(out, true, StandardCharsets.UTF_8), + showMemory, + showStack, + showReturnData, + showStorage); } /** @@ -130,6 +142,33 @@ public class StandardJsonTracer implements OperationTracer { memory = null; } depth = messageFrame.getMessageStackSize(); + + StringBuilder sb = new StringBuilder(); + if (showStorage) { + var updater = messageFrame.getWorldUpdater(); + var account = updater.getAccount(messageFrame.getRecipientAddress()); + if (account != null && !account.getUpdatedStorage().isEmpty()) { + boolean[] shownEntry = {false}; + sb.append(",\"storage\":{"); + account + .getUpdatedStorage() + .forEach( + (k, v) -> { + if (shownEntry[0]) { + sb.append(","); + } else { + shownEntry[0] = true; + } + sb.append("\"") + .append(k.toQuantityHexString()) + .append("\":\"") + .append(v.toQuantityHexString()) + .append("\""); + }); + sb.append("}"); + } + } + storageString = sb.toString(); } @Override @@ -155,7 +194,7 @@ public class StandardJsonTracer implements OperationTracer { if (showStack) { sb.append("\"stack\":[").append(commaJoiner.join(stack)).append("],"); } - if (showReturnData && returnData.size() > 0) { + if (showReturnData && !returnData.isEmpty()) { sb.append("\"returnData\":\"").append(returnData.toHexString()).append("\","); } sb.append("\"depth\":").append(depth).append(","); @@ -164,14 +203,14 @@ public class StandardJsonTracer implements OperationTracer { if (executeResult.getHaltReason() != null) { sb.append(",\"error\":\"") .append(executeResult.getHaltReason().getDescription()) - .append("\"}"); + .append("\""); } else if (messageFrame.getRevertReason().isPresent()) { sb.append(",\"error\":\"") .append(quoteEscape(messageFrame.getRevertReason().orElse(Bytes.EMPTY))) - .append("\"}"); - } else { - sb.append("}"); + .append("\""); } + + sb.append(storageString).append("}"); out.println(sb); } @@ -229,7 +268,7 @@ public class StandardJsonTracer implements OperationTracer { final long timeNs) { final StringBuilder sb = new StringBuilder(1024); sb.append("{"); - if (output.size() > 0) { + if (!output.isEmpty()) { sb.append("\"output\":\"").append(output.toShortHexString()).append("\","); } else { sb.append("\"output\":\"\","); diff --git a/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java b/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java index a65ab05d62..9ba9ebf96a 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java @@ -38,7 +38,7 @@ class StandardJsonTracerTest { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream out = new PrintStream(baos); var executor = EVMExecutor.istanbul(EvmConfiguration.DEFAULT); - StandardJsonTracer tracer = new StandardJsonTracer(out, true, true, true); + StandardJsonTracer tracer = new StandardJsonTracer(out, true, true, true, false); executor.tracer(tracer); executor.gas(10_000_000_000L); @@ -58,20 +58,56 @@ class StandardJsonTracerTest { // (g) if error is zero length or null it is not included. assertThat(baos) .hasToString( - "{\"pc\":0,\"op\":96,\"gas\":\"0x2540be400\",\"gasCost\":\"0x3\",\"memSize\":0,\"stack\":[],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":2,\"op\":128,\"gas\":\"0x2540be3fd\",\"gasCost\":\"0x3\",\"memSize\":0,\"stack\":[\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"DUP1\"}\n" - + "{\"pc\":3,\"op\":83,\"gas\":\"0x2540be3fa\",\"gasCost\":\"0xc\",\"memSize\":0,\"stack\":[\"0x40\",\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"MSTORE8\"}\n" - + "{\"pc\":4,\"op\":96,\"gas\":\"0x2540be3ee\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":6,\"op\":96,\"gas\":\"0x2540be3eb\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":8,\"op\":85,\"gas\":\"0x2540be3e8\",\"gasCost\":\"0x4e20\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"SSTORE\"}\n" - + "{\"pc\":9,\"op\":96,\"gas\":\"0x2540b95c8\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":11,\"op\":96,\"gas\":\"0x2540b95c5\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":13,\"op\":96,\"gas\":\"0x2540b95c2\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":15,\"op\":96,\"gas\":\"0x2540b95bf\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\",\"0x40\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":17,\"op\":96,\"gas\":\"0x2540b95bc\",\"gasCost\":\"0x3\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\",\"0x40\",\"0x0\"],\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":19,\"op\":90,\"gas\":\"0x2540b95b9\",\"gasCost\":\"0x2\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\",\"0x40\",\"0x0\",\"0x2\"],\"depth\":1,\"refund\":0,\"opName\":\"GAS\"}\n" - + "{\"pc\":20,\"op\":250,\"gas\":\"0x2540b95b7\",\"gasCost\":\"0x2bc\",\"memory\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x40\",\"0x0\",\"0x40\",\"0x0\",\"0x2\",\"0x2540b95b7\"],\"depth\":1,\"refund\":0,\"opName\":\"STATICCALL\"}\n" - + "{\"pc\":21,\"op\":96,\"gas\":\"0x2540b92a7\",\"gasCost\":\"0x3\",\"memory\":\"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x1\"],\"returnData\":\"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b\",\"depth\":1,\"refund\":0,\"opName\":\"PUSH1\"}\n" - + "{\"pc\":23,\"op\":243,\"gas\":\"0x2540b92a4\",\"gasCost\":\"0x0\",\"memory\":\"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000\",\"memSize\":96,\"stack\":[\"0x1\",\"0x40\"],\"returnData\":\"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b\",\"depth\":1,\"refund\":0,\"opName\":\"RETURN\"}\n"); + """ + {"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":2,"op":128,"gas":"0x2540be3fd","gasCost":"0x3","memSize":0,"stack":["0x40"],"depth":1,"refund":0,"opName":"DUP1"} + {"pc":3,"op":83,"gas":"0x2540be3fa","gasCost":"0xc","memSize":0,"stack":["0x40","0x40"],"depth":1,"refund":0,"opName":"MSTORE8"} + {"pc":4,"op":96,"gas":"0x2540be3ee","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":6,"op":96,"gas":"0x2540be3eb","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":8,"op":85,"gas":"0x2540be3e8","gasCost":"0x4e20","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x40"],"depth":1,"refund":0,"opName":"SSTORE"} + {"pc":9,"op":96,"gas":"0x2540b95c8","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":11,"op":96,"gas":"0x2540b95c5","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":13,"op":96,"gas":"0x2540b95c2","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":15,"op":96,"gas":"0x2540b95bf","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":17,"op":96,"gas":"0x2540b95bc","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0"],"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":19,"op":90,"gas":"0x2540b95b9","gasCost":"0x2","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0","0x2"],"depth":1,"refund":0,"opName":"GAS"} + {"pc":20,"op":250,"gas":"0x2540b95b7","gasCost":"0x2bc","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0","0x2","0x2540b95b7"],"depth":1,"refund":0,"opName":"STATICCALL"} + {"pc":21,"op":96,"gas":"0x2540b92a7","gasCost":"0x3","memory":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x1"],"returnData":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","depth":1,"refund":0,"opName":"PUSH1"} + {"pc":23,"op":243,"gas":"0x2540b92a4","gasCost":"0x0","memory":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x1","0x40"],"returnData":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","depth":1,"refund":0,"opName":"RETURN"} + """); + } + + @Test + void updatedStorageTestCase() { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(baos); + var executor = EVMExecutor.istanbul(EvmConfiguration.DEFAULT); + StandardJsonTracer tracer = new StandardJsonTracer(out, false, false, false, true); + executor.tracer(tracer); + executor.gas(10_000_000_000L); + + var codeBytes = Bytes.fromHexString("0x604080536040604055604060006040600060025afa6040f3"); + executor.execute(codeBytes, Bytes.EMPTY, Wei.ZERO, Address.ZERO); + + assertThat(baos) + .hasToString( + """ + {"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memSize":0,"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":2,"op":128,"gas":"0x2540be3fd","gasCost":"0x3","memSize":0,"depth":1,"refund":0,"opName":"DUP1"} + {"pc":3,"op":83,"gas":"0x2540be3fa","gasCost":"0xc","memSize":0,"depth":1,"refund":0,"opName":"MSTORE8"} + {"pc":4,"op":96,"gas":"0x2540be3ee","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":6,"op":96,"gas":"0x2540be3eb","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1"} + {"pc":8,"op":85,"gas":"0x2540be3e8","gasCost":"0x4e20","memSize":96,"depth":1,"refund":0,"opName":"SSTORE"} + {"pc":9,"op":96,"gas":"0x2540b95c8","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":11,"op":96,"gas":"0x2540b95c5","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":13,"op":96,"gas":"0x2540b95c2","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":15,"op":96,"gas":"0x2540b95bf","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":17,"op":96,"gas":"0x2540b95bc","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":19,"op":90,"gas":"0x2540b95b9","gasCost":"0x2","memSize":96,"depth":1,"refund":0,"opName":"GAS","storage":{"0x40":"0x40"}} + {"pc":20,"op":250,"gas":"0x2540b95b7","gasCost":"0x2bc","memSize":96,"depth":1,"refund":0,"opName":"STATICCALL","storage":{"0x40":"0x40"}} + {"pc":21,"op":96,"gas":"0x2540b92a7","gasCost":"0x3","memSize":96,"depth":1,"refund":0,"opName":"PUSH1","storage":{"0x40":"0x40"}} + {"pc":23,"op":243,"gas":"0x2540b92a4","gasCost":"0x0","memSize":96,"depth":1,"refund":0,"opName":"RETURN","storage":{"0x40":"0x40"}} + """); } } diff --git a/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java b/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java index 76934e041f..368dbffabd 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java @@ -122,6 +122,12 @@ public class EvmToyCommand implements Runnable { scope = ScopeType.INHERIT) final Boolean showReturnData = false; + @CommandLine.Option( + names = {"--trace.storage"}, + description = "When tracing, show the updated storage contents.", + scope = ScopeType.INHERIT) + final Boolean showStorage = false; + @CommandLine.Option( names = {"--repeat"}, description = "Number of times to repeat for benchmarking.") @@ -164,7 +170,8 @@ public class EvmToyCommand implements Runnable { final OperationTracer tracer = // You should have picked Mercy. lastLoop && showJsonResults - ? new StandardJsonTracer(System.out, showMemory, showStack, showReturnData) + ? new StandardJsonTracer( + System.out, showMemory, showStack, showReturnData, showStorage) : OperationTracer.NO_TRACING; MessageFrame initialMessageFrame =