Make tracer in block building block aware (#6135)

Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
pull/6148/head
Stefan Pingel 1 year ago committed by GitHub
parent 228424215c
commit f42f8c1122
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 39
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java
  2. 18
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java
  3. 4
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java
  4. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
  5. 25
      evm/src/main/java/org/hyperledger/besu/evm/tracing/StandardJsonTracer.java
  6. 2
      plugin-api/build.gradle
  7. 8
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/tracer/BlockAwareOperationTracer.java
  8. 6
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/PluginTransactionSelector.java

@ -24,6 +24,7 @@ import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.txselection.BlockTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.BlockTransactionSelector;
import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults; import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults;
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.AllAcceptingTransactionSelector;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
@ -56,6 +57,9 @@ import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.List; import java.util.List;
@ -183,13 +187,26 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
disposableWorldState.updater(), timestamp, bytes32)); disposableWorldState.updater(), timestamp, bytes32));
throwIfStopped(); throwIfStopped();
final PluginTransactionSelector pluginTransactionSelector =
protocolContext
.getTransactionSelectorFactory()
.map(PluginTransactionSelectorFactory::create)
.orElseGet(() -> AllAcceptingTransactionSelector.INSTANCE);
final BlockAwareOperationTracer operationTracer =
pluginTransactionSelector.getOperationTracer();
operationTracer.traceStartBlock(processableBlockHeader);
final TransactionSelectionResults transactionResults = final TransactionSelectionResults transactionResults =
selectTransactions( selectTransactions(
processableBlockHeader, processableBlockHeader,
disposableWorldState, disposableWorldState,
maybeTransactions, maybeTransactions,
miningBeneficiary, miningBeneficiary,
newProtocolSpec); newProtocolSpec,
pluginTransactionSelector);
transactionResults.logSelectionStats(); transactionResults.logSelectionStats();
@ -261,14 +278,13 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final Optional<List<Withdrawal>> withdrawals = final Optional<List<Withdrawal>> withdrawals =
withdrawalsCanBeProcessed ? maybeWithdrawals : Optional.empty(); withdrawalsCanBeProcessed ? maybeWithdrawals : Optional.empty();
final Block block = final BlockBody blockBody =
new Block( new BlockBody(
blockHeader, transactionResults.getSelectedTransactions(), ommers, withdrawals, maybeDeposits);
new BlockBody( final Block block = new Block(blockHeader, blockBody);
transactionResults.getSelectedTransactions(),
ommers, operationTracer.traceEndBlock(blockHeader, blockBody);
withdrawals,
maybeDeposits));
return new BlockCreationResult(block, transactionResults); return new BlockCreationResult(block, transactionResults);
} catch (final SecurityModuleException ex) { } catch (final SecurityModuleException ex) {
throw new IllegalStateException("Failed to create block signature", ex); throw new IllegalStateException("Failed to create block signature", ex);
@ -316,7 +332,8 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final MutableWorldState disposableWorldState, final MutableWorldState disposableWorldState,
final Optional<List<Transaction>> transactions, final Optional<List<Transaction>> transactions,
final Address miningBeneficiary, final Address miningBeneficiary,
final ProtocolSpec protocolSpec) final ProtocolSpec protocolSpec,
final PluginTransactionSelector pluginTransactionSelector)
throws RuntimeException { throws RuntimeException {
final MainnetTransactionProcessor transactionProcessor = protocolSpec.getTransactionProcessor(); final MainnetTransactionProcessor transactionProcessor = protocolSpec.getTransactionProcessor();
@ -343,7 +360,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
protocolSpec.getFeeMarket(), protocolSpec.getFeeMarket(),
protocolSpec.getGasCalculator(), protocolSpec.getGasCalculator(),
protocolSpec.getGasLimitCalculator(), protocolSpec.getGasLimitCalculator(),
protocolContext.getTransactionSelectorFactory()); pluginTransactionSelector);
if (transactions.isPresent()) { if (transactions.isPresent()) {
return selector.evaluateTransactions(transactions.get()); return selector.evaluateTransactions(transactions.get());

@ -18,7 +18,6 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.GasLimitCalculator;
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.AbstractTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.AbstractTransactionSelector;
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.AllAcceptingTransactionSelector;
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.BlobPriceTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.BlobPriceTransactionSelector;
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.BlockSizeTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.BlockSizeTransactionSelector;
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.MinPriorityFeePerGasTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.MinPriorityFeePerGasTransactionSelector;
@ -40,14 +39,12 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector; import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -87,7 +84,7 @@ public class BlockTransactionSelector {
new TransactionSelectionResults(); new TransactionSelectionResults();
private final List<AbstractTransactionSelector> transactionSelectors; private final List<AbstractTransactionSelector> transactionSelectors;
private final PluginTransactionSelector pluginTransactionSelector; private final PluginTransactionSelector pluginTransactionSelector;
private final OperationTracer pluginOperationTracer; private final BlockAwareOperationTracer pluginOperationTracer;
public BlockTransactionSelector( public BlockTransactionSelector(
final MiningParameters miningParameters, final MiningParameters miningParameters,
@ -103,7 +100,7 @@ public class BlockTransactionSelector {
final FeeMarket feeMarket, final FeeMarket feeMarket,
final GasCalculator gasCalculator, final GasCalculator gasCalculator,
final GasLimitCalculator gasLimitCalculator, final GasLimitCalculator gasLimitCalculator,
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) { final PluginTransactionSelector pluginTransactionSelector) {
this.transactionProcessor = transactionProcessor; this.transactionProcessor = transactionProcessor;
this.blockchain = blockchain; this.blockchain = blockchain;
this.worldState = worldState; this.worldState = worldState;
@ -120,11 +117,8 @@ public class BlockTransactionSelector {
miningBeneficiary, miningBeneficiary,
transactionPool); transactionPool);
transactionSelectors = createTransactionSelectors(blockSelectionContext); transactionSelectors = createTransactionSelectors(blockSelectionContext);
pluginTransactionSelector = this.pluginTransactionSelector = pluginTransactionSelector;
transactionSelectorFactory this.pluginOperationTracer = pluginTransactionSelector.getOperationTracer();
.map(PluginTransactionSelectorFactory::create)
.orElse(AllAcceptingTransactionSelector.INSTANCE);
pluginOperationTracer = pluginTransactionSelector.getOperationTracer();
} }
private List<AbstractTransactionSelector> createTransactionSelectors( private List<AbstractTransactionSelector> createTransactionSelectors(
@ -151,7 +145,9 @@ public class BlockTransactionSelector {
.setMessage("Transaction pool stats {}") .setMessage("Transaction pool stats {}")
.addArgument(blockSelectionContext.transactionPool().logStats()) .addArgument(blockSelectionContext.transactionPool().logStats())
.log(); .log();
blockSelectionContext.transactionPool().selectTransactions(this::evaluateTransaction); blockSelectionContext.transactionPool().selectTransactions(this::evaluateTransaction);
LOG.atTrace() LOG.atTrace()
.setMessage("Transaction selection result {}") .setMessage("Transaction selection result {}")
.addArgument(transactionSelectionResults::toTraceLog) .addArgument(transactionSelectionResults::toTraceLog)

@ -876,7 +876,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
getFeeMarket(), getFeeMarket(),
new LondonGasCalculator(), new LondonGasCalculator(),
GasLimitCalculator.constant(), GasLimitCalculator.constant(),
Optional.empty()); AllAcceptingTransactionSelector.INSTANCE);
return selector; return selector;
} }
@ -902,7 +902,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
getFeeMarket(), getFeeMarket(),
new LondonGasCalculator(), new LondonGasCalculator(),
GasLimitCalculator.constant(), GasLimitCalculator.constant(),
Optional.of(transactionSelectorFactory)); transactionSelectorFactory.create());
return selector; return selector;
} }

@ -355,6 +355,8 @@ public class MainnetTransactionProcessor {
contextVariablesBuilder.put(KEY_PRIVATE_METADATA_UPDATER, privateMetadataUpdater); contextVariablesBuilder.put(KEY_PRIVATE_METADATA_UPDATER, privateMetadataUpdater);
} }
operationTracer.traceStartTransaction(worldUpdater, transaction);
final MessageFrame.Builder commonMessageFrameBuilder = final MessageFrame.Builder commonMessageFrameBuilder =
MessageFrame.builder() MessageFrame.builder()
.maxStackSize(maxStackSize) .maxStackSize(maxStackSize)
@ -451,6 +453,15 @@ public class MainnetTransactionProcessor {
.log(); .log();
final long gasUsedByTransaction = transaction.getGasLimit() - initialFrame.getRemainingGas(); 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 // update the coinbase
final var coinbase = worldState.getOrCreate(miningBeneficiary); final var coinbase = worldState.getOrCreate(miningBeneficiary);
final long usedGas = transaction.getGasLimit() - refundedGas; final long usedGas = transaction.getGasLimit() - refundedGas;

@ -18,13 +18,9 @@ package org.hyperledger.besu.evm.tracing;
import static com.google.common.base.Strings.padStart; import static com.google.common.base.Strings.padStart;
import org.hyperledger.besu.datatypes.Transaction;
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.internal.Words;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.operation.Operation;
import org.hyperledger.besu.evm.worldstate.WorldView;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
@ -256,25 +252,4 @@ public class StandardJsonTracer implements OperationTracer {
final MessageFrame frame, final Optional<ExceptionalHaltReason> haltReason) { final MessageFrame frame, final Optional<ExceptionalHaltReason> haltReason) {
// precompile calls are not part of the standard trace // precompile calls are not part of the standard trace
} }
@Override
public void traceEndTransaction(
final WorldView _worldView,
final Transaction _tx,
final boolean _status,
final Bytes output,
final List<Log> _logs,
final long gasUsed,
final long timeNs) {
final StringBuilder sb = new StringBuilder(1024);
sb.append("{");
if (!output.isEmpty()) {
sb.append("\"output\":\"").append(output.toShortHexString()).append("\",");
} else {
sb.append("\"output\":\"\",");
}
sb.append("\"gasUsed\":\"").append(Words.longBytes(gasUsed).toShortHexString()).append("\",");
sb.append("\"time\":").append(timeNs).append("}");
out.println(sb);
}
} }

@ -69,7 +69,7 @@ Calculated : ${currentHash}
tasks.register('checkAPIChanges', FileStateChecker) { tasks.register('checkAPIChanges', FileStateChecker) {
description = "Checks that the API for the Plugin-API project does not change without deliberate thought" description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
files = sourceSets.main.allJava.files files = sourceSets.main.allJava.files
knownHash = 'YYrWGQIwp1sgEmwx2DcfjiskFO8euGGKeWh7Lq1F+24=' knownHash = 'n4WfeMvltN4XWGtztd8ABjSU2TLiI3tk5yABivkgsFA='
} }
check.dependsOn('checkAPIChanges') check.dependsOn('checkAPIChanges')

@ -17,6 +17,7 @@ package org.hyperledger.besu.plugin.services.tracer;
import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.plugin.data.BlockBody; import org.hyperledger.besu.plugin.data.BlockBody;
import org.hyperledger.besu.plugin.data.BlockHeader; import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
/** /**
* An extended operation tracer that can trace the start and end of a block. * An extended operation tracer that can trace the start and end of a block.
@ -47,6 +48,13 @@ public interface BlockAwareOperationTracer extends OperationTracer {
*/ */
default void traceEndBlock(final BlockHeader blockHeader, final BlockBody blockBody) {} default void traceEndBlock(final BlockHeader blockHeader, final BlockBody blockBody) {}
/**
* When building a block this API is called at the start of the process
*
* @param processableBlockHeader the processable header
*/
default void traceStartBlock(final ProcessableBlockHeader processableBlockHeader) {}
@Override @Override
default boolean isExtendedTracing() { default boolean isExtendedTracing() {
return true; return true;

@ -16,10 +16,10 @@
package org.hyperledger.besu.plugin.services.txselection; package org.hyperledger.besu.plugin.services.txselection;
import org.hyperledger.besu.datatypes.PendingTransaction; import org.hyperledger.besu.datatypes.PendingTransaction;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.plugin.Unstable; import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.data.TransactionProcessingResult; import org.hyperledger.besu.plugin.data.TransactionProcessingResult;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
/** Interface for the transaction selector */ /** Interface for the transaction selector */
@Unstable @Unstable
@ -31,8 +31,8 @@ public interface PluginTransactionSelector {
* *
* @return OperationTracer to be used to trace candidate transactions * @return OperationTracer to be used to trace candidate transactions
*/ */
default OperationTracer getOperationTracer() { default BlockAwareOperationTracer getOperationTracer() {
return OperationTracer.NO_TRACING; return BlockAwareOperationTracer.NO_TRACING;
} }
/** /**

Loading…
Cancel
Save