Skip to content

Commit

Permalink
Transaction Validation and Selection Plugin API update (hyperledger#6020
Browse files Browse the repository at this point in the history
)

change Transaction Validation and Selection Plugin to make them more useful

Signed-off-by: Stefan <[email protected]>
Signed-off-by: Stefan Pingel <[email protected]>
Co-authored-by: Gabriel-Trintinalia <[email protected]>
  • Loading branch information
pinges and Gabriel-Trintinalia authored Oct 12, 2023
1 parent 4276a40 commit 1c293fe
Show file tree
Hide file tree
Showing 23 changed files with 136 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
import org.hyperledger.besu.plugin.services.StorageService;
import org.hyperledger.besu.plugin.services.TransactionSelectionService;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.BesuEventsImpl;
Expand Down Expand Up @@ -185,7 +185,7 @@ public void startNode(final BesuNode node) {

final int maxPeers = 25;

final Optional<TransactionSelectorFactory> transactionSelectorFactory =
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory =
getTransactionSelectorFactory(besuPluginContext);

final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
Expand Down Expand Up @@ -323,7 +323,7 @@ public String getConsoleContents() {
throw new RuntimeException("Console contents can only be captured in process execution");
}

private Optional<TransactionSelectorFactory> getTransactionSelectorFactory(
private Optional<PluginTransactionSelectorFactory> getTransactionSelectorFactory(
final BesuPluginContextImpl besuPluginContext) {
final Optional<TransactionSelectionService> txSelectionService =
besuPluginContext.getService(TransactionSelectionService.class);
Expand Down
4 changes: 2 additions & 2 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModule;
import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
Expand Down Expand Up @@ -2294,7 +2294,7 @@ public BesuControllerBuilder getControllerBuilder() {
}

@NotNull
private Optional<TransactionSelectorFactory> getTransactionSelectorFactory() {
private Optional<PluginTransactionSelectorFactory> getTransactionSelectorFactory() {
final Optional<TransactionSelectionService> txSelectionService =
besuPluginContext.getService(TransactionSelectionService.class);
return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;

import java.io.Closeable;
Expand Down Expand Up @@ -182,7 +182,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides

private NetworkingConfiguration networkingConfiguration;
private Boolean randomPeerPriority;
private Optional<TransactionSelectorFactory> transactionSelectorFactory = Optional.empty();
private Optional<PluginTransactionSelectorFactory> transactionSelectorFactory = Optional.empty();
/** the Dagger configured context that can provide dependencies */
protected Optional<BesuComponent> besuComponent = Optional.empty();

Expand Down Expand Up @@ -535,7 +535,7 @@ public BesuControllerBuilder randomPeerPriority(final Boolean randomPeerPriority
* @return the besu controller builder
*/
public BesuControllerBuilder transactionSelectorFactory(
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
this.transactionSelectorFactory = transactionSelectorFactory;
return this;
}
Expand Down Expand Up @@ -1035,7 +1035,7 @@ protected ProtocolContext createProtocolContext(
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
return ProtocolContext.init(
blockchain,
worldStateArchive,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;

import java.math.BigInteger;
import java.nio.file.Path;
Expand Down Expand Up @@ -176,7 +176,7 @@ protected ProtocolContext createProtocolContext(
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
return MigratingProtocolContext.init(
blockchain,
worldStateArchive,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;

import java.math.BigInteger;
import java.nio.file.Path;
Expand Down Expand Up @@ -190,7 +190,7 @@ protected ProtocolContext createProtocolContext(
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
final ProtocolContext protocolContext =
super.createProtocolContext(
blockchain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@
package org.hyperledger.besu.services;

import org.hyperledger.besu.plugin.services.TransactionSelectionService;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;

import java.util.Optional;

/** The Transaction Selection service implementation. */
public class TransactionSelectionServiceImpl implements TransactionSelectionService {

private Optional<TransactionSelectorFactory> factory = Optional.empty();
private Optional<PluginTransactionSelectorFactory> factory = Optional.empty();

@Override
public Optional<TransactionSelectorFactory> get() {
public Optional<PluginTransactionSelectorFactory> get() {
return factory;
}

@Override
public void registerTransactionSelectorFactory(
final TransactionSelectorFactory transactionSelectorFactory) {
final PluginTransactionSelectorFactory transactionSelectorFactory) {
factory = Optional.ofNullable(transactionSelectorFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;

import java.util.Optional;

Expand All @@ -41,7 +41,7 @@ public MigratingProtocolContext(
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ForksSchedule<ConsensusContext> consensusContextSchedule,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
super(blockchain, worldStateArchive, null, transactionSelectorFactory);
this.consensusContextSchedule = consensusContextSchedule;
}
Expand All @@ -61,7 +61,7 @@ public static ProtocolContext init(
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
final ConsensusContext consensusContext =
consensusContextFactory.create(blockchain, worldStateArchive, protocolSchedule);
final MigratingContext migratingContext = consensusContext.as(MigratingContext.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public static RpcErrorType convertTransactionInvalidReason(
return RpcErrorType.TOTAL_BLOB_GAS_TOO_HIGH;
case TX_POOL_DISABLED:
return RpcErrorType.TX_POOL_DISABLED;
case PLUGIN_TX_VALIDATOR:
return RpcErrorType.PLUGIN_TX_VALIDATOR;
default:
return RpcErrorType.INTERNAL_ERROR;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcRequestException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
Expand All @@ -33,6 +34,7 @@
import java.util.function.Supplier;

import com.google.common.base.Suppliers;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -90,12 +92,29 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
() ->
new JsonRpcSuccessResponse(
requestContext.getRequest().getId(), transaction.getHash().toString()),
errorReason ->
sendEmptyHashOnInvalidBlock
? new JsonRpcSuccessResponse(
requestContext.getRequest().getId(), Hash.EMPTY.toString())
: new JsonRpcErrorResponse(
requestContext.getRequest().getId(),
JsonRpcErrorConverter.convertTransactionInvalidReason(errorReason)));
errorReason -> getJsonRpcResponse(requestContext, errorReason, validationResult));
}

@NotNull
private JsonRpcResponse getJsonRpcResponse(
final JsonRpcRequestContext requestContext,
final TransactionInvalidReason errorReason,
final ValidationResult<TransactionInvalidReason> validationResult) {
if (sendEmptyHashOnInvalidBlock) {
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), Hash.EMPTY.toString());
} else {
if (errorReason == TransactionInvalidReason.PLUGIN_TX_VALIDATOR) {
final RpcErrorType rpcErrorType =
JsonRpcErrorConverter.convertTransactionInvalidReason(
validationResult.getInvalidReason());
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(),
new JsonRpcError(rpcErrorType.getCode(), validationResult.getErrorMessage(), null));
} else {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(),
JsonRpcErrorConverter.convertTransactionInvalidReason(errorReason));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private RpcErrorType findErrorType(final int code, final String message) {
return Arrays.stream(RpcErrorType.values())
.filter(e -> e.getCode() == code && message.startsWith(e.getMessage()))
.findFirst()
.get();
.orElse(RpcErrorType.UNKNOWN);
}

@SuppressWarnings({"unchecked", "rawtypes"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public enum RpcErrorType {
LOWER_NONCE_INVALID_TRANSACTION_EXISTS(
-32000, "An invalid transaction with a lower nonce exists"),
TOTAL_BLOB_GAS_TOO_HIGH(-32000, "Total blob gas too high"),
PLUGIN_TX_VALIDATOR(-32000, "Plugin has marked the transaction as invalid"),

// Execution engine failures
UNKNOWN_PAYLOAD(-32001, "Payload does not exist / is not available"),
Expand Down Expand Up @@ -210,7 +211,9 @@ public enum RpcErrorType {
// Retesteth Errors

BLOCK_RLP_IMPORT_ERROR(-32000, "Could not decode RLP for Block"),
BLOCK_IMPORT_ERROR(-32000, "Could not import Block");
BLOCK_IMPORT_ERROR(-32000, "Could not import Block"),

UNKNOWN(-32603, "Unknown internal error");

private final int code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
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.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;

import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -84,7 +85,8 @@ public class BlockTransactionSelector {
private final TransactionSelectionResults transactionSelectionResults =
new TransactionSelectionResults();
private final List<AbstractTransactionSelector> transactionSelectors;
private final TransactionSelector externalTransactionSelector;
private final PluginTransactionSelector pluginTransactionSelector;
private final OperationTracer pluginOperationTracer;

public BlockTransactionSelector(
final MainnetTransactionProcessor transactionProcessor,
Expand All @@ -101,7 +103,7 @@ public BlockTransactionSelector(
final FeeMarket feeMarket,
final GasCalculator gasCalculator,
final GasLimitCalculator gasLimitCalculator,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
this.transactionProcessor = transactionProcessor;
this.blockchain = blockchain;
this.worldState = worldState;
Expand All @@ -119,10 +121,11 @@ public BlockTransactionSelector(
miningBeneficiary,
transactionPool);
transactionSelectors = createTransactionSelectors(blockSelectionContext);
externalTransactionSelector =
pluginTransactionSelector =
transactionSelectorFactory
.map(TransactionSelectorFactory::create)
.map(PluginTransactionSelectorFactory::create)
.orElse(AllAcceptingTransactionSelector.INSTANCE);
pluginOperationTracer = pluginTransactionSelector.getOperationTracer();
}

private List<AbstractTransactionSelector> createTransactionSelectors(
Expand Down Expand Up @@ -223,7 +226,7 @@ private TransactionSelectionResult evaluatePreProcessing(
return result;
}
}
return externalTransactionSelector.evaluateTransactionPreProcessing(pendingTransaction);
return pluginTransactionSelector.evaluateTransactionPreProcessing(pendingTransaction);
}

/**
Expand All @@ -248,7 +251,7 @@ private TransactionSelectionResult evaluatePostProcessing(
return result;
}
}
return externalTransactionSelector.evaluateTransactionPostProcessing(
return pluginTransactionSelector.evaluateTransactionPostProcessing(
pendingTransaction, processingResult);
}

Expand All @@ -269,6 +272,7 @@ private TransactionProcessingResult processTransaction(
blockSelectionContext.processableBlockHeader(),
pendingTransaction.getTransaction(),
blockSelectionContext.miningBeneficiary(),
pluginOperationTracer,
blockHashLookup,
false,
TransactionValidationParams.mining(),
Expand Down Expand Up @@ -307,7 +311,7 @@ private TransactionSelectionResult handleTransactionSelected(

transactionSelectionResults.updateSelected(
pendingTransaction.getTransaction(), receipt, gasUsedByTransaction, blobGasUsed);
externalTransactionSelector.onTransactionSelected(pendingTransaction);
pluginTransactionSelector.onTransactionSelected(pendingTransaction, processingResult);

return TransactionSelectionResult.SELECTED;
}
Expand All @@ -326,7 +330,7 @@ private TransactionSelectionResult handleTransactionNotSelected(
final TransactionSelectionResult selectionResult) {
transactionSelectionResults.updateNotSelected(
pendingTransaction.getTransaction(), selectionResult);
externalTransactionSelector.onTransactionNotSelected(pendingTransaction, selectionResult);
pluginTransactionSelector.onTransactionNotSelected(pendingTransaction, selectionResult);
return selectionResult;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
import org.hyperledger.besu.datatypes.PendingTransaction;
import org.hyperledger.besu.plugin.data.TransactionProcessingResult;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector;

/** A TransactionSelector that unconditionally selects all transactions. */
public class AllAcceptingTransactionSelector implements TransactionSelector {
public class AllAcceptingTransactionSelector implements PluginTransactionSelector {
public static final AllAcceptingTransactionSelector INSTANCE =
new AllAcceptingTransactionSelector();

Expand Down
Loading

0 comments on commit 1c293fe

Please sign in to comment.