diff --git a/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java index f7db3639ae1..1e734f62312 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java @@ -125,7 +125,7 @@ void shouldRetrieveStateUpdatePostTracingForOneBlock() { verify(opTracer).traceStartTransaction(any(), eq(tx)); verify(opTracer) .traceEndTransaction( - any(), eq(tx), anyBoolean(), any(), any(), anyLong(), anyLong()); + any(), eq(tx), anyBoolean(), any(), any(), anyLong(), any(), anyLong()); }); verify(opTracer).traceEndBlock(tracedBlock.getHeader(), tracedBlock.getBody()); @@ -173,7 +173,14 @@ void shouldRetrieveStateUpdatePostTracingForAllBlocks() { verify(opTracer).traceStartTransaction(any(), eq(tx)); verify(opTracer) .traceEndTransaction( - any(), eq(tx), anyBoolean(), any(), any(), anyLong(), anyLong()); + any(), + eq(tx), + anyBoolean(), + any(), + any(), + anyLong(), + any(), + anyLong()); }); verify(opTracer).traceEndBlock(tracedBlock.getHeader(), tracedBlock.getBody()); @@ -222,6 +229,7 @@ void shouldReturnTheCorrectWorldViewForTxStartEnd() { assertThat(txStartEndTracer.txEndStatus).isTrue(); assertThat(txStartEndTracer.txEndOutput).isEqualTo(Bytes.fromHexString("0x")); assertThat(txStartEndTracer.txEndGasUsed).isEqualTo(24303); + assertThat(txStartEndTracer.txEndSelfDestructs).isEmpty(); assertThat(txStartEndTracer.txEndTimeNs).isNotNull(); assertThat(txStartEndTracer.txEndLogs).isNotEmpty(); @@ -263,6 +271,7 @@ private static class TxStartEndTracer implements BlockAwareOperationTracer { public Bytes txEndOutput; public List txEndLogs; public long txEndGasUsed; + public Set
txEndSelfDestructs; public Long txEndTimeNs; private final Set traceStartTxCalled = new HashSet<>(); @@ -287,6 +296,7 @@ public void traceEndTransaction( final Bytes output, final List logs, final long gasUsed, + final Set
selfDestructs, final long timeNs) { if (!traceEndTxCalled.add(transaction)) { fail("traceEndTransaction already called for tx " + transaction); @@ -297,6 +307,7 @@ public void traceEndTransaction( txEndOutput = output; txEndLogs = logs; txEndGasUsed = gasUsed; + txEndSelfDestructs = selfDestructs; txEndTimeNs = timeNs; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 0027c51b79d..51d300cbc46 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -59,6 +59,8 @@ public class MainnetTransactionProcessor { private static final Logger LOG = LoggerFactory.getLogger(MainnetTransactionProcessor.class); + private static final Set
EMPTY_ADDRESS_SET = Set.of(); + protected final GasCalculator gasCalculator; protected final TransactionValidatorFactory transactionValidatorFactory; @@ -451,15 +453,6 @@ public TransactionProcessingResult processTransaction( .log(); final long gasUsedByTransaction = transaction.getGasLimit() - initialFrame.getRemainingGas(); - operationTracer.traceEndTransaction( - worldUpdater, - transaction, - initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS, - initialFrame.getOutputData(), - initialFrame.getLogs(), - gasUsedByTransaction, - 0L); - // update the coinbase final var coinbase = worldState.getOrCreate(miningBeneficiary); final long usedGas = transaction.getGasLimit() - refundedGas; @@ -485,6 +478,16 @@ public TransactionProcessingResult processTransaction( coinbase.incrementBalance(coinbaseWeiDelta); + operationTracer.traceEndTransaction( + worldUpdater, + transaction, + initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS, + initialFrame.getOutputData(), + initialFrame.getLogs(), + gasUsedByTransaction, + initialFrame.getSelfDestructs(), + 0L); + initialFrame.getSelfDestructs().forEach(worldState::deleteAccount); if (clearEmptyAccounts) { @@ -516,13 +519,27 @@ public TransactionProcessingResult processTransaction( } } catch (final MerkleTrieException re) { operationTracer.traceEndTransaction( - worldState.updater(), transaction, false, Bytes.EMPTY, List.of(), 0, 0L); + worldState.updater(), + transaction, + false, + Bytes.EMPTY, + List.of(), + 0, + EMPTY_ADDRESS_SET, + 0L); // need to throw to trigger the heal throw re; } catch (final RuntimeException re) { operationTracer.traceEndTransaction( - worldState.updater(), transaction, false, Bytes.EMPTY, List.of(), 0, 0L); + worldState.updater(), + transaction, + false, + Bytes.EMPTY, + List.of(), + 0, + EMPTY_ADDRESS_SET, + 0L); LOG.error("Critical Exception Processing Transaction", re); return TransactionProcessingResult.invalid( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java index 77466587314..d541cbd99aa 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; @@ -216,6 +217,7 @@ public void traceEndTransaction( final Bytes output, final List logs, final long gasUsed, + final Set
selfDestructs, final long timeNs) { this.traceEndTxCalled = true; } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java index 6e48aaf82ca..ccabce833a6 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java @@ -69,6 +69,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; +import java.util.Set; import java.util.Spliterator; import java.util.Spliterators; import java.util.concurrent.TimeUnit; @@ -86,6 +87,8 @@ public class T8nExecutor { + private static final Set
EMPTY_ADDRESS_SET = Set.of(); + public record RejectedTransaction(int index, String error) {} protected static List extractTransactions( @@ -349,6 +352,7 @@ static T8nResult runTest( result.getOutput(), result.getLogs(), gasUsed - intrinsicGas, + EMPTY_ADDRESS_SET, timer.elapsed(TimeUnit.NANOSECONDS)); Bytes gasUsedInTransaction = Bytes.ofUnsignedLong(transactionGasUsed); receipts.add(receipt); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/tracing/OperationTracer.java b/evm/src/main/java/org/hyperledger/besu/evm/tracing/OperationTracer.java index 5bd6de591e5..34e28bbb32f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/tracing/OperationTracer.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/tracing/OperationTracer.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.evm.tracing; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; import org.hyperledger.besu.evm.frame.MessageFrame; @@ -23,6 +24,7 @@ import java.util.List; import java.util.Optional; +import java.util.Set; import org.apache.tuweni.bytes.Bytes; @@ -92,6 +94,7 @@ default void traceStartTransaction(final WorldView worldView, final Transaction * @param output the bytes output from the transaction * @param logs the logs emitted by this transaction * @param gasUsed the gas used by the entire transaction + * @param selfDestructs the set of addresses that self-destructed during the transaction * @param timeNs the time in nanoseconds it took to execute the transaction */ default void traceEndTransaction( @@ -101,6 +104,7 @@ default void traceEndTransaction( final Bytes output, final List logs, final long gasUsed, + final Set
selfDestructs, final long timeNs) {} /**