mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-08 23:17:54 -05:00
Transaction Validation and Selection Plugin API update (#6020)
change Transaction Validation and Selection Plugin to make them more useful Signed-off-by: Stefan <stefan.pingel@consensys.net> Signed-off-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> Co-authored-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net>
This commit is contained in:
@@ -48,7 +48,7 @@ import org.hyperledger.besu.plugin.services.SecurityModuleService;
|
||||
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;
|
||||
@@ -185,7 +185,7 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
|
||||
|
||||
final int maxPeers = 25;
|
||||
|
||||
final Optional<TransactionSelectorFactory> transactionSelectorFactory =
|
||||
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory =
|
||||
getTransactionSelectorFactory(besuPluginContext);
|
||||
|
||||
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
|
||||
@@ -323,7 +323,7 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
|
||||
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);
|
||||
|
||||
@@ -177,7 +177,7 @@ import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
|
||||
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;
|
||||
@@ -2294,7 +2294,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
@@ -95,7 +95,7 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
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;
|
||||
@@ -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();
|
||||
|
||||
@@ -535,7 +535,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
* @return the besu controller builder
|
||||
*/
|
||||
public BesuControllerBuilder transactionSelectorFactory(
|
||||
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
|
||||
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
|
||||
this.transactionSelectorFactory = transactionSelectorFactory;
|
||||
return this;
|
||||
}
|
||||
@@ -1035,7 +1035,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
final WorldStateArchive worldStateArchive,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final ConsensusContextFactory consensusContextFactory,
|
||||
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
|
||||
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
|
||||
return ProtocolContext.init(
|
||||
blockchain,
|
||||
worldStateArchive,
|
||||
|
||||
@@ -62,7 +62,7 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
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;
|
||||
@@ -176,7 +176,7 @@ public class ConsensusScheduleBesuControllerBuilder extends BesuControllerBuilde
|
||||
final WorldStateArchive worldStateArchive,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final ConsensusContextFactory consensusContextFactory,
|
||||
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
|
||||
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
|
||||
return MigratingProtocolContext.init(
|
||||
blockchain,
|
||||
worldStateArchive,
|
||||
|
||||
@@ -60,7 +60,7 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
|
||||
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;
|
||||
@@ -190,7 +190,7 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
|
||||
final WorldStateArchive worldStateArchive,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final ConsensusContextFactory consensusContextFactory,
|
||||
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
|
||||
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
|
||||
final ProtocolContext protocolContext =
|
||||
super.createProtocolContext(
|
||||
blockchain,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
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;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class MigratingProtocolContext extends ProtocolContext {
|
||||
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;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ public class MigratingProtocolContext extends ProtocolContext {
|
||||
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);
|
||||
|
||||
@@ -77,6 +77,8 @@ public class JsonRpcErrorConverter {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter;
|
||||
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;
|
||||
@@ -33,6 +34,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -90,12 +92,29 @@ public class EthSendRawTransaction implements JsonRpcMethod {
|
||||
() ->
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class JsonRpcErrorResponse implements JsonRpcResponse {
|
||||
return Arrays.stream(RpcErrorType.values())
|
||||
.filter(e -> e.getCode() == code && message.startsWith(e.getMessage()))
|
||||
.findFirst()
|
||||
.get();
|
||||
.orElse(RpcErrorType.UNKNOWN);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
|
||||
@@ -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"),
|
||||
@@ -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;
|
||||
|
||||
@@ -38,10 +38,11 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
|
||||
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;
|
||||
@@ -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,
|
||||
@@ -101,7 +103,7 @@ public class 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;
|
||||
@@ -119,10 +121,11 @@ public class 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(
|
||||
@@ -223,7 +226,7 @@ public class BlockTransactionSelector {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return externalTransactionSelector.evaluateTransactionPreProcessing(pendingTransaction);
|
||||
return pluginTransactionSelector.evaluateTransactionPreProcessing(pendingTransaction);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,7 +251,7 @@ public class BlockTransactionSelector {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return externalTransactionSelector.evaluateTransactionPostProcessing(
|
||||
return pluginTransactionSelector.evaluateTransactionPostProcessing(
|
||||
pendingTransaction, processingResult);
|
||||
}
|
||||
|
||||
@@ -269,6 +272,7 @@ public class BlockTransactionSelector {
|
||||
blockSelectionContext.processableBlockHeader(),
|
||||
pendingTransaction.getTransaction(),
|
||||
blockSelectionContext.miningBeneficiary(),
|
||||
pluginOperationTracer,
|
||||
blockHashLookup,
|
||||
false,
|
||||
TransactionValidationParams.mining(),
|
||||
@@ -307,7 +311,7 @@ public class BlockTransactionSelector {
|
||||
|
||||
transactionSelectionResults.updateSelected(
|
||||
pendingTransaction.getTransaction(), receipt, gasUsedByTransaction, blobGasUsed);
|
||||
externalTransactionSelector.onTransactionSelected(pendingTransaction);
|
||||
pluginTransactionSelector.onTransactionSelected(pendingTransaction, processingResult);
|
||||
|
||||
return TransactionSelectionResult.SELECTED;
|
||||
}
|
||||
@@ -326,7 +330,7 @@ public class BlockTransactionSelector {
|
||||
final TransactionSelectionResult selectionResult) {
|
||||
transactionSelectionResults.updateNotSelected(
|
||||
pendingTransaction.getTransaction(), selectionResult);
|
||||
externalTransactionSelector.onTransactionNotSelected(pendingTransaction, selectionResult);
|
||||
pluginTransactionSelector.onTransactionNotSelected(pendingTransaction, selectionResult);
|
||||
return selectionResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ package org.hyperledger.besu.ethereum.blockcreation.txselection.selectors;
|
||||
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();
|
||||
|
||||
|
||||
@@ -71,8 +71,8 @@ import org.hyperledger.besu.evm.worldstate.WorldState;
|
||||
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
|
||||
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
|
||||
import org.hyperledger.besu.plugin.services.MetricsSystem;
|
||||
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 org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
|
||||
|
||||
import java.math.BigInteger;
|
||||
@@ -557,9 +557,9 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
final Transaction notSelectedInvalid = createTransaction(2, Wei.of(10), 21_000);
|
||||
ensureTransactionIsValid(notSelectedInvalid, 21_000, 0);
|
||||
|
||||
final TransactionSelectorFactory transactionSelectorFactory =
|
||||
final PluginTransactionSelectorFactory transactionSelectorFactory =
|
||||
() ->
|
||||
new TransactionSelector() {
|
||||
new PluginTransactionSelector() {
|
||||
@Override
|
||||
public TransactionSelectionResult evaluateTransactionPreProcessing(
|
||||
final PendingTransaction pendingTransaction) {
|
||||
@@ -621,9 +621,9 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
final Transaction selected3 = createTransaction(3, Wei.of(10), 21_000);
|
||||
ensureTransactionIsValid(selected3, maxGasUsedByTransaction, 0);
|
||||
|
||||
final TransactionSelectorFactory transactionSelectorFactory =
|
||||
final PluginTransactionSelectorFactory transactionSelectorFactory =
|
||||
() ->
|
||||
new TransactionSelector() {
|
||||
new PluginTransactionSelector() {
|
||||
@Override
|
||||
public TransactionSelectionResult evaluateTransactionPreProcessing(
|
||||
final PendingTransaction pendingTransaction) {
|
||||
@@ -666,18 +666,17 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
|
||||
@Test
|
||||
public void transactionSelectionPluginShouldBeNotifiedWhenTransactionSelectionCompletes() {
|
||||
final TransactionSelectorFactory transactionSelectorFactory =
|
||||
mock(TransactionSelectorFactory.class);
|
||||
TransactionSelector transactionSelector = spy(AllAcceptingTransactionSelector.INSTANCE);
|
||||
final PluginTransactionSelectorFactory transactionSelectorFactory =
|
||||
mock(PluginTransactionSelectorFactory.class);
|
||||
PluginTransactionSelector transactionSelector = spy(AllAcceptingTransactionSelector.INSTANCE);
|
||||
when(transactionSelectorFactory.create()).thenReturn(transactionSelector);
|
||||
|
||||
final Transaction transaction = createTransaction(0, Wei.of(10), 21_000);
|
||||
ensureTransactionIsValid(transaction, 21_000, 0);
|
||||
|
||||
final TransactionInvalidReason invalidReason =
|
||||
TransactionInvalidReason.PLUGIN_TX_VALIDATOR_INVALIDATED;
|
||||
final TransactionInvalidReason invalidReason = TransactionInvalidReason.PLUGIN_TX_VALIDATOR;
|
||||
final Transaction invalidTransaction = createTransaction(1, Wei.of(10), 21_000);
|
||||
ensureTransactionIsInvalid(invalidTransaction, invalidReason);
|
||||
ensureTransactionIsInvalid(invalidTransaction, TransactionInvalidReason.PLUGIN_TX_VALIDATOR);
|
||||
transactionPool.addRemoteTransactions(List.of(transaction, invalidTransaction));
|
||||
|
||||
createBlockSelectorWithTxSelPlugin(
|
||||
@@ -694,7 +693,8 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
ArgumentCaptor.forClass(PendingTransaction.class);
|
||||
|
||||
// selected transaction must be notified to the selector
|
||||
verify(transactionSelector).onTransactionSelected(argumentCaptor.capture());
|
||||
verify(transactionSelector)
|
||||
.onTransactionSelected(argumentCaptor.capture(), any(TransactionProcessingResult.class));
|
||||
PendingTransaction selected = argumentCaptor.getValue();
|
||||
assertThat(selected.getTransaction()).isEqualTo(transaction);
|
||||
|
||||
@@ -773,7 +773,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
final Address miningBeneficiary,
|
||||
final Wei blobGasPrice,
|
||||
final double minBlockOccupancyRatio,
|
||||
final TransactionSelectorFactory transactionSelectorFactory) {
|
||||
final PluginTransactionSelectorFactory transactionSelectorFactory) {
|
||||
final BlockTransactionSelector selector =
|
||||
new BlockTransactionSelector(
|
||||
transactionProcessor,
|
||||
@@ -854,7 +854,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
protected void ensureTransactionIsValid(
|
||||
final Transaction tx, final long gasUsedByTransaction, final long gasRemaining) {
|
||||
when(transactionProcessor.processTransaction(
|
||||
any(), any(), any(), eq(tx), any(), any(), anyBoolean(), any(), any()))
|
||||
any(), any(), any(), eq(tx), any(), any(), any(), anyBoolean(), any(), any()))
|
||||
.thenReturn(
|
||||
TransactionProcessingResult.successful(
|
||||
new ArrayList<>(),
|
||||
@@ -867,7 +867,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
protected void ensureTransactionIsInvalid(
|
||||
final Transaction tx, final TransactionInvalidReason invalidReason) {
|
||||
when(transactionProcessor.processTransaction(
|
||||
any(), any(), any(), eq(tx), any(), any(), anyBoolean(), any(), any()))
|
||||
any(), any(), any(), eq(tx), any(), any(), any(), anyBoolean(), any(), any()))
|
||||
.thenReturn(TransactionProcessingResult.invalid(ValidationResult.invalid(invalidReason)));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Synchronizer;
|
||||
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;
|
||||
|
||||
@@ -31,7 +31,7 @@ public class ProtocolContext {
|
||||
private final MutableBlockchain blockchain;
|
||||
private final WorldStateArchive worldStateArchive;
|
||||
private final ConsensusContext consensusContext;
|
||||
private final Optional<TransactionSelectorFactory> transactionSelectorFactory;
|
||||
private final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory;
|
||||
|
||||
private Optional<Synchronizer> synchronizer;
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ProtocolContext {
|
||||
final MutableBlockchain blockchain,
|
||||
final WorldStateArchive worldStateArchive,
|
||||
final ConsensusContext consensusContext,
|
||||
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
|
||||
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
|
||||
this.blockchain = blockchain;
|
||||
this.worldStateArchive = worldStateArchive;
|
||||
this.consensusContext = consensusContext;
|
||||
@@ -59,7 +59,7 @@ public class ProtocolContext {
|
||||
final WorldStateArchive worldStateArchive,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final ConsensusContextFactory consensusContextFactory,
|
||||
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
|
||||
final Optional<PluginTransactionSelectorFactory> transactionSelectorFactory) {
|
||||
return new ProtocolContext(
|
||||
blockchain,
|
||||
worldStateArchive,
|
||||
@@ -93,7 +93,7 @@ public class ProtocolContext {
|
||||
.map(klass::cast);
|
||||
}
|
||||
|
||||
public Optional<TransactionSelectorFactory> getTransactionSelectorFactory() {
|
||||
public Optional<PluginTransactionSelectorFactory> getTransactionSelectorFactory() {
|
||||
return transactionSelectorFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ public enum TransactionInvalidReason {
|
||||
INTERNAL_ERROR,
|
||||
TX_POOL_DISABLED,
|
||||
INVALID_BLOBS,
|
||||
PLUGIN_TX_VALIDATOR,
|
||||
// Private Transaction Invalid Reasons
|
||||
PRIVATE_TRANSACTION_INVALID,
|
||||
PRIVATE_TRANSACTION_FAILED,
|
||||
@@ -55,6 +56,5 @@ public enum TransactionInvalidReason {
|
||||
OFFCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST,
|
||||
PRIVATE_NONCE_TOO_HIGH,
|
||||
PRIVATE_VALUE_NOT_ZERO,
|
||||
PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE,
|
||||
PLUGIN_TX_VALIDATOR_INVALIDATED
|
||||
PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE
|
||||
}
|
||||
|
||||
@@ -476,11 +476,13 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
}
|
||||
|
||||
// Call the transaction validator plugin if one is available
|
||||
if (pluginTransactionValidator != null
|
||||
&& !pluginTransactionValidator.validateTransaction(transaction)) {
|
||||
return ValidationResultAndAccount.invalid(
|
||||
TransactionInvalidReason.PLUGIN_TX_VALIDATOR_INVALIDATED,
|
||||
"Plugin transaction vaildator returned false");
|
||||
if (pluginTransactionValidator != null) {
|
||||
final Optional<String> maybeError =
|
||||
pluginTransactionValidator.validateTransaction(transaction);
|
||||
if (maybeError.isPresent()) {
|
||||
return ValidationResultAndAccount.invalid(
|
||||
TransactionInvalidReason.PLUGIN_TX_VALIDATOR, maybeError.get());
|
||||
}
|
||||
}
|
||||
|
||||
try (final var worldState =
|
||||
|
||||
@@ -773,7 +773,7 @@ public abstract class AbstractTransactionPoolTest {
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void transactionNotRejectedByPluginShouldBeAdded(final boolean disableLocalTxs) {
|
||||
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
|
||||
getPluginTransactionValidatorFactoryReturning(true);
|
||||
getPluginTransactionValidatorFactoryReturning(null); // null -> not rejecting !!
|
||||
this.transactionPool =
|
||||
createTransactionPool(
|
||||
b -> b.disableLocalTransactions(disableLocalTxs), pluginTransactionValidatorFactory);
|
||||
@@ -787,7 +787,7 @@ public abstract class AbstractTransactionPoolTest {
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void transactionRejectedByPluginShouldNotBeAdded(final boolean disableLocalTxs) {
|
||||
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
|
||||
getPluginTransactionValidatorFactoryReturning(false);
|
||||
getPluginTransactionValidatorFactoryReturning("false");
|
||||
this.transactionPool =
|
||||
createTransactionPool(
|
||||
b -> b.disableLocalTransactions(disableLocalTxs), pluginTransactionValidatorFactory);
|
||||
@@ -795,13 +795,13 @@ public abstract class AbstractTransactionPoolTest {
|
||||
givenTransactionIsValid(transaction0);
|
||||
|
||||
addAndAssertTransactionViaApiInvalid(
|
||||
transaction0, TransactionInvalidReason.PLUGIN_TX_VALIDATOR_INVALIDATED);
|
||||
transaction0, TransactionInvalidReason.PLUGIN_TX_VALIDATOR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void remoteTransactionRejectedByPluginShouldNotBeAdded() {
|
||||
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
|
||||
getPluginTransactionValidatorFactoryReturning(false);
|
||||
getPluginTransactionValidatorFactoryReturning("false");
|
||||
this.transactionPool = createTransactionPool(b -> {}, pluginTransactionValidatorFactory);
|
||||
|
||||
givenTransactionIsValid(transaction0);
|
||||
@@ -1065,8 +1065,9 @@ public abstract class AbstractTransactionPoolTest {
|
||||
}
|
||||
|
||||
private static PluginTransactionValidatorFactory getPluginTransactionValidatorFactoryReturning(
|
||||
final boolean b) {
|
||||
final PluginTransactionValidator pluginTransactionValidator = transaction -> b;
|
||||
final String errorMessage) {
|
||||
final PluginTransactionValidator pluginTransactionValidator =
|
||||
transaction -> Optional.ofNullable(errorMessage);
|
||||
return () -> pluginTransactionValidator;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ Calculated : ${currentHash}
|
||||
tasks.register('checkAPIChanges', FileStateChecker) {
|
||||
description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
|
||||
files = sourceSets.main.allJava.files
|
||||
knownHash = 'Pfql+wKH6qarEvlb9TXZGVV/xwJuKWK5egKHt9uCpzE='
|
||||
knownHash = '5koUOxNHaYeuIFYH2PP/6RdMO1JvCm0ILdl/DyY297Y='
|
||||
}
|
||||
check.dependsOn('checkAPIChanges')
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.hyperledger.besu.plugin.services;
|
||||
|
||||
import org.hyperledger.besu.plugin.Unstable;
|
||||
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
|
||||
import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -29,12 +29,13 @@ public interface TransactionSelectionService extends BesuService {
|
||||
*
|
||||
* @return the transaction selector factory
|
||||
*/
|
||||
Optional<TransactionSelectorFactory> get();
|
||||
Optional<PluginTransactionSelectorFactory> get();
|
||||
|
||||
/**
|
||||
* Registers the transaction selector factory with the service
|
||||
*
|
||||
* @param transactionSelectorFactory transaction selector factory to be used
|
||||
*/
|
||||
void registerTransactionSelectorFactory(TransactionSelectorFactory transactionSelectorFactory);
|
||||
void registerTransactionSelectorFactory(
|
||||
PluginTransactionSelectorFactory transactionSelectorFactory);
|
||||
}
|
||||
|
||||
@@ -16,13 +16,25 @@
|
||||
package org.hyperledger.besu.plugin.services.txselection;
|
||||
|
||||
import org.hyperledger.besu.datatypes.PendingTransaction;
|
||||
import org.hyperledger.besu.evm.tracing.OperationTracer;
|
||||
import org.hyperledger.besu.plugin.Unstable;
|
||||
import org.hyperledger.besu.plugin.data.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
|
||||
|
||||
/** Interface for the transaction selector */
|
||||
@Unstable
|
||||
public interface TransactionSelector {
|
||||
public interface PluginTransactionSelector {
|
||||
|
||||
/**
|
||||
* Method that returns an OperationTracer that will be used when executing transactions that are
|
||||
* candidates to be added to a block.
|
||||
*
|
||||
* @return OperationTracer to be used to trace candidate transactions
|
||||
*/
|
||||
default OperationTracer getOperationTracer() {
|
||||
return OperationTracer.NO_TRACING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called to decide whether a transaction is added to a block. The result can also indicate
|
||||
* that no further transactions can be added to the block.
|
||||
@@ -48,8 +60,11 @@ public interface TransactionSelector {
|
||||
* Method called when a transaction is selected to be added to a block.
|
||||
*
|
||||
* @param pendingTransaction The transaction that has been selected.
|
||||
* @param processingResult The result of processing the selected transaction.
|
||||
*/
|
||||
default void onTransactionSelected(final PendingTransaction pendingTransaction) {}
|
||||
default void onTransactionSelected(
|
||||
final PendingTransaction pendingTransaction,
|
||||
final TransactionProcessingResult processingResult) {}
|
||||
/**
|
||||
* Method called when a transaction is not selected to be added to a block.
|
||||
*
|
||||
@@ -19,12 +19,12 @@ import org.hyperledger.besu.plugin.Unstable;
|
||||
|
||||
/** Interface for a factory that creates transaction selectors */
|
||||
@Unstable
|
||||
public interface TransactionSelectorFactory {
|
||||
public interface PluginTransactionSelectorFactory {
|
||||
|
||||
/**
|
||||
* Create a transaction selector
|
||||
*
|
||||
* @return the transaction selector
|
||||
*/
|
||||
TransactionSelector create();
|
||||
PluginTransactionSelector create();
|
||||
}
|
||||
@@ -18,7 +18,9 @@ package org.hyperledger.besu.plugin.services.txvalidator;
|
||||
import org.hyperledger.besu.datatypes.Transaction;
|
||||
import org.hyperledger.besu.plugin.Unstable;
|
||||
|
||||
/** Interface for the transaction validator */
|
||||
import java.util.Optional;
|
||||
|
||||
/** Interface for the transaction validator plugin */
|
||||
@Unstable
|
||||
public interface PluginTransactionValidator {
|
||||
|
||||
@@ -26,7 +28,8 @@ public interface PluginTransactionValidator {
|
||||
* Method called to decide whether a transaction can be added to the transaction pool.
|
||||
*
|
||||
* @param transaction candidate transaction
|
||||
* @return true if the transaction can be added, false otherwise
|
||||
* @return Optional.empty() if the transaction is valid, an Optional containing an error message,
|
||||
* if not
|
||||
*/
|
||||
boolean validateTransaction(final Transaction transaction);
|
||||
Optional<String> validateTransaction(final Transaction transaction);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user