From 9710a9adaac1f131c1e2e05f5aa53eba4fdc13bd Mon Sep 17 00:00:00 2001 From: ahamlat Date: Thu, 9 Nov 2023 16:07:56 +0100 Subject: [PATCH] Delete leftPad when capturing the stack before and after a frame execution (#6102) * Delete leftPad when capturing the stack before and after the execution * Still use leftPad when displaying the stack in the output (ex. for debug_traceTransaction) * Fix integration test * Use StringBuilder to left pad the hex representation of a 32 bytes Signed-off-by: Ameziane H --- .../api/jsonrpc/internal/results/StructLog.java | 17 ++++++++++++++++- .../vm/TraceTransactionIntegrationTest.java | 12 ++++-------- .../besu/ethereum/debug/TraceFrame.java | 13 ++++++------- .../besu/ethereum/vm/DebugOperationTracer.java | 13 +++++-------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/StructLog.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/StructLog.java index f6a873b597f..50ec093576d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/StructLog.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/StructLog.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; @JsonPropertyOrder({"pc", "op", "gas", "gasCost", "depth", "stack", "memory", "storage"}) @@ -38,6 +39,7 @@ public class StructLog { private final String[] stack; private final Object storage; private final String reason; + static final String bytes32ZeroString = Bytes32.ZERO.toUnprefixedHexString(); public StructLog(final TraceFrame traceFrame) { depth = traceFrame.getDepth() + 1; @@ -53,12 +55,25 @@ public StructLog(final TraceFrame traceFrame) { stack = traceFrame .getStack() - .map(a -> Arrays.stream(a).map(Bytes::toUnprefixedHexString).toArray(String[]::new)) + .map( + a -> + Arrays.stream(a) + .map(Bytes::toUnprefixedHexString) + .map(this::stringLeftPadTo64) + .toArray(String[]::new)) .orElse(null); + storage = traceFrame.getStorage().map(StructLog::formatStorage).orElse(null); reason = traceFrame.getRevertReason().map(Bytes::toShortHexString).orElse(null); } + private String stringLeftPadTo64(final String unPaddedHexString) { + StringBuilder sb = new StringBuilder(64); + sb.append(bytes32ZeroString, 0, 64 - unPaddedHexString.length()); + sb.append(unPaddedHexString); + return sb.toString(); + } + private static Map formatStorage(final Map storage) { final Map formattedStorage = new TreeMap<>(); storage.forEach( diff --git a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java index 37e6cdddced..972da935f35 100644 --- a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java @@ -206,8 +206,7 @@ public void shouldTraceContractCreation() { assertThat(frame.getGasCost()).isEqualTo(OptionalLong.of(3L)); assertThat(frame.getOpcode()).isEqualTo("PUSH1"); assertThat(frame.getPc()).isEqualTo(2); - assertStackContainsExactly( - frame, "0000000000000000000000000000000000000000000000000000000000000080"); + assertStackContainsExactly(frame, "0x80"); assertMemoryContainsExactly(frame); assertStorageContainsExactly(frame); @@ -217,10 +216,7 @@ public void shouldTraceContractCreation() { assertThat(frame.getGasCost()).isEqualTo(OptionalLong.of(12L)); assertThat(frame.getOpcode()).isEqualTo("MSTORE"); assertThat(frame.getPc()).isEqualTo(4); - assertStackContainsExactly( - frame, - "0000000000000000000000000000000000000000000000000000000000000080", - "0000000000000000000000000000000000000000000000000000000000000040"); + assertStackContainsExactly(frame, "80", "40"); assertMemoryContainsExactly( frame, "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -251,8 +247,8 @@ public void shouldTraceContractCreation() { private void assertStackContainsExactly( final TraceFrame frame, final String... stackEntriesAsHex) { assertThat(frame.getStack()).isPresent(); - final Bytes32[] stackEntries = - Stream.of(stackEntriesAsHex).map(Bytes32::fromHexString).toArray(Bytes32[]::new); + final Bytes[] stackEntries = + Stream.of(stackEntriesAsHex).map(Bytes::fromHexString).toArray(Bytes[]::new); assertThat(frame.getStack().get()).containsExactly(stackEntries); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/debug/TraceFrame.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/debug/TraceFrame.java index ed5a627d31d..33118bef8e5 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/debug/TraceFrame.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/debug/TraceFrame.java @@ -28,7 +28,6 @@ import com.google.common.base.MoreObjects; import org.apache.tuweni.bytes.Bytes; -import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; public class TraceFrame { @@ -44,7 +43,7 @@ public class TraceFrame { private final Wei value; private final Bytes inputData; private final Bytes outputData; - private final Optional stack; + private final Optional stack; private final Optional memory; private final Optional> storage; @@ -53,7 +52,7 @@ public class TraceFrame { private final Optional> maybeRefunds; private final Optional maybeCode; private final int stackItemsProduced; - private final Optional stackPostExecution; + private final Optional stackPostExecution; private long gasRemainingPostExecution; private final boolean virtualOperation; @@ -73,7 +72,7 @@ public TraceFrame( final Wei value, final Bytes inputData, final Bytes outputData, - final Optional stack, + final Optional stack, final Optional memory, final Optional> storage, final WorldUpdater worldUpdater, @@ -81,7 +80,7 @@ public TraceFrame( final Optional> maybeRefunds, final Optional maybeCode, final int stackItemsProduced, - final Optional stackPostExecution, + final Optional stackPostExecution, final boolean virtualOperation, final Optional maybeUpdatedMemory, final Optional maybeUpdatedStorage) { @@ -159,7 +158,7 @@ public Bytes getOutputData() { return outputData; } - public Optional getStack() { + public Optional getStack() { return stack; } @@ -206,7 +205,7 @@ public int getStackItemsProduced() { return stackItemsProduced; } - public Optional getStackPostExecution() { + public Optional getStackPostExecution() { return stackPostExecution; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracer.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracer.java index b1ef1bc0b1c..711f83e3d9a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracer.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracer.java @@ -14,8 +14,6 @@ */ package org.hyperledger.besu.ethereum.vm; -import static org.apache.tuweni.bytes.Bytes32.leftPad; - import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.debug.TraceFrame; @@ -36,7 +34,6 @@ import java.util.TreeMap; import org.apache.tuweni.bytes.Bytes; -import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; public class DebugOperationTracer implements OperationTracer { @@ -45,7 +42,7 @@ public class DebugOperationTracer implements OperationTracer { private List traceFrames = new ArrayList<>(); private TraceFrame lastFrame; - private Optional preExecutionStack; + private Optional preExecutionStack; private long gasRemaining; private Bytes inputData; private int pc; @@ -73,7 +70,7 @@ public void tracePostExecution(final MessageFrame frame, final OperationResult o final WorldUpdater worldUpdater = frame.getWorldUpdater(); final Bytes outputData = frame.getOutputData(); final Optional memory = captureMemory(frame); - final Optional stackPostExecution = captureStack(frame); + final Optional stackPostExecution = captureStack(frame); if (lastFrame != null) { lastFrame.setGasRemainingPostExecution(gasRemaining); @@ -218,15 +215,15 @@ private Optional captureMemory(final MessageFrame frame) { return Optional.of(memoryContents); } - private Optional captureStack(final MessageFrame frame) { + private Optional captureStack(final MessageFrame frame) { if (!options.isStackEnabled()) { return Optional.empty(); } - final Bytes32[] stackContents = new Bytes32[frame.stackSize()]; + final Bytes[] stackContents = new Bytes[frame.stackSize()]; for (int i = 0; i < stackContents.length; i++) { // Record stack contents in reverse - stackContents[i] = leftPad(frame.getStackItem(stackContents.length - i - 1)); + stackContents[i] = frame.getStackItem(stackContents.length - i - 1); } return Optional.of(stackContents); }