diff --git a/CHANGELOG.md b/CHANGELOG.md index d166031ce68..a74da30fd6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,8 +31,9 @@ - Log blob count when importing a block via Engine API [#6466](https://github.com/hyperledger/besu/pull/6466) - Introduce `--Xbonsai-limit-trie-logs-enabled` experimental feature which by default will only retain the latest 512 trie logs, saving about 3GB per week in database growth [#5390](https://github.com/hyperledger/besu/issues/5390) - Introduce `besu storage x-trie-log prune` experimental offline subcommand which will prune all redundant trie logs except the latest 512 [#6303](https://github.com/hyperledger/besu/pull/6303) +- Improve flat trace generation performance [#6472](https://github.com/hyperledger/besu/pull/6472) - SNAP and CHECKPOINT sync - early access flag removed so now simply SNAP and CHECKPOINT [#6405](https://github.com/hyperledger/besu/pull/6405) - - X_SNAP and X_CHECKPOINT are marked for deprecation and will be removed in 24.4.0 +- X_SNAP and X_CHECKPOINT are marked for deprecation and will be removed in 24.4.0 - Github Actions based build. - Introduce caching mechanism to optimize Keccak hash calculations for account storage slots during block processing [#6452](https://github.com/hyperledger/besu/pull/6452) - Added configuration options for `pragueTime` to genesis file for Prague fork development [#6473](https://github.com/hyperledger/besu/pull/6473) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/FlatTraceGenerator.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/FlatTraceGenerator.java index 3a7fa3951fb..ad39330fa53 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/FlatTraceGenerator.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/FlatTraceGenerator.java @@ -28,6 +28,8 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; +import org.hyperledger.besu.evm.operation.ReturnOperation; +import org.hyperledger.besu.evm.operation.RevertOperation; import java.util.ArrayDeque; import java.util.ArrayList; @@ -530,11 +532,19 @@ private static FlatTrace.Context handleCallDataLoad( private static boolean hasRevertInSubCall( final TransactionTrace transactionTrace, final TraceFrame callFrame) { - return transactionTrace.getTraceFrames().stream() - .filter(traceFrame -> !traceFrame.equals(callFrame)) - .takeWhile(traceFrame -> !traceFrame.getOpcode().equals("RETURN")) - .filter(traceFrame -> traceFrame.getOpcode().equals("REVERT")) - .anyMatch(traceFrame -> traceFrame.getDepth() == callFrame.getDepth()); + for (int i = 0; i < transactionTrace.getTraceFrames().size(); i++) { + if (i + 1 < transactionTrace.getTraceFrames().size()) { + final TraceFrame next = transactionTrace.getTraceFrames().get(i + 1); + if (next.getDepth() == callFrame.getDepth()) { + if (next.getOpcodeNumber() == RevertOperation.OPCODE) { + return true; + } else if (next.getOpcodeNumber() == ReturnOperation.OPCODE) { + return false; + } + } + } + } + return false; } private static String calculateCallingAddress(final FlatTrace.Context lastContext) { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByHashTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByHashTest.java index c6857bec332..75d7ae26a95 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByHashTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByHashTest.java @@ -91,6 +91,7 @@ public void shouldReturnCorrectResponse() { new TraceFrame( 12, Optional.of("NONE"), + Integer.MAX_VALUE, 45L, OptionalLong.of(56L), 0L, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByNumberTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByNumberTest.java index 9b23ab12e91..99e599ec110 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByNumberTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockByNumberTest.java @@ -77,6 +77,7 @@ public void shouldReturnCorrectResponse() { new TraceFrame( 12, Optional.of("NONE"), + Integer.MAX_VALUE, 45L, OptionalLong.of(56L), 0L, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockTest.java index 5da556182bc..f35f3d1a16a 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceBlockTest.java @@ -83,6 +83,7 @@ public void shouldReturnCorrectResponse() { new TraceFrame( 12, Optional.of("NONE"), + Integer.MAX_VALUE, 45L, OptionalLong.of(56L), 0L, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java index 580897abb8f..f57fd716c06 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java @@ -116,6 +116,7 @@ public void shouldTraceTheTransactionUsingTheTransactionTracer() { new TraceFrame( 12, Optional.of("NONE"), + Integer.MAX_VALUE, 45L, OptionalLong.of(56L), 0L, @@ -183,6 +184,7 @@ public void shouldNotTraceTheTransactionIfNotFound() { new TraceFrame( 12, Optional.of("NONE"), + Integer.MAX_VALUE, 45L, OptionalLong.of(56L), 0L, 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 33118bef8e5..cd6a9c3584f 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 @@ -34,6 +34,7 @@ public class TraceFrame { private final int pc; private final Optional opcode; + private final int opcodeNumber; private final long gasRemaining; private final OptionalLong gasCost; private final long gasRefund; @@ -63,6 +64,7 @@ public class TraceFrame { public TraceFrame( final int pc, final Optional opcode, + final int opcodeNumber, final long gasRemaining, final OptionalLong gasCost, final long gasRefund, @@ -86,6 +88,7 @@ public TraceFrame( final Optional maybeUpdatedStorage) { this.pc = pc; this.opcode = opcode; + this.opcodeNumber = opcodeNumber; this.gasRemaining = gasRemaining; this.gasCost = gasCost; this.gasRefund = gasRefund; @@ -118,6 +121,10 @@ public String getOpcode() { return opcode.orElse(""); } + public int getOpcodeNumber() { + return opcodeNumber; + } + public long getGasRemaining() { return gasRemaining; } 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 6644fbf5626..5156a7a0735 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 @@ -84,6 +84,7 @@ public void tracePreExecution(final MessageFrame frame) { public void tracePostExecution(final MessageFrame frame, final OperationResult operationResult) { final Operation currentOperation = frame.getCurrentOperation(); final String opcode = currentOperation.getName(); + final int opcodeNumber = (opcode != null) ? currentOperation.getOpcode() : Integer.MAX_VALUE; final WorldUpdater worldUpdater = frame.getWorldUpdater(); final Bytes outputData = frame.getOutputData(); final Optional memory = captureMemory(frame); @@ -103,6 +104,7 @@ public void tracePostExecution(final MessageFrame frame, final OperationResult o new TraceFrame( pc, Optional.of(opcode), + opcodeNumber, gasRemaining, thisGasCost == 0 ? OptionalLong.empty() : OptionalLong.of(thisGasCost), frame.getGasRefund(), @@ -136,6 +138,7 @@ public void tracePrecompileCall( new TraceFrame( frame.getPC(), Optional.empty(), + Integer.MAX_VALUE, frame.getRemainingGas(), OptionalLong.empty(), frame.getGasRefund(), @@ -182,6 +185,7 @@ public void traceAccountCreationResult( new TraceFrame( frame.getPC(), Optional.empty(), + Integer.MAX_VALUE, frame.getRemainingGas(), OptionalLong.empty(), frame.getGasRefund(), diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ReturnOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ReturnOperation.java index 56dbe9205cb..2e23e9b6df3 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ReturnOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ReturnOperation.java @@ -24,13 +24,16 @@ /** The Return operation. */ public class ReturnOperation extends AbstractOperation { + /** RETURN opcode number */ + public static final int OPCODE = 0xF3; + /** * Instantiates a new Return operation. * * @param gasCalculator the gas calculator */ public ReturnOperation(final GasCalculator gasCalculator) { - super(0xF3, "RETURN", 2, 0, gasCalculator); + super(OPCODE, "RETURN", 2, 0, gasCalculator); } @Override diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/RevertOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/RevertOperation.java index 8f08aac884f..6c681a5ce7f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/RevertOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/RevertOperation.java @@ -26,13 +26,16 @@ /** The Revert operation. */ public class RevertOperation extends AbstractOperation { + /** REVERT opcode number */ + public static final int OPCODE = 0xFD; + /** * Instantiates a new Revert operation. * * @param gasCalculator the gas calculator */ public RevertOperation(final GasCalculator gasCalculator) { - super(0xFD, "REVERT", 2, 0, gasCalculator); + super(OPCODE, "REVERT", 2, 0, gasCalculator); } @Override