Refactor and extend PluginTransactionPoolValidatorService (#6636)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
pull/6683/head
Fabio Di Fabio 9 months ago committed by GitHub
parent fe1b177ea8
commit 2b8d44ec77
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 20
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java
  3. 21
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  4. 15
      besu/src/main/java/org/hyperledger/besu/cli/options/TransactionPoolOptions.java
  5. 16
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  6. 35
      besu/src/main/java/org/hyperledger/besu/services/PluginTransactionValidatorServiceImpl.java
  7. 40
      besu/src/main/java/org/hyperledger/besu/services/TransactionPoolValidatorServiceImpl.java
  8. 6
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  9. 5
      besu/src/test/java/org/hyperledger/besu/cli/options/TransactionPoolOptionsTest.java
  10. 1
      besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java
  11. 3
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java
  12. 3
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java
  13. 3
      consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java
  14. 3
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java
  15. 3
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java
  16. 3
      consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java
  17. 3
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java
  18. 3
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java
  19. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcErrorConverter.java
  20. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSendRawTransaction.java
  21. 3
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java
  22. 6
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java
  23. 3
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java
  24. 3
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java
  25. 3
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java
  26. 3
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java
  27. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java
  28. 3
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/AbstractIsolationTests.java
  29. 25
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java
  30. 17
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolConfiguration.java
  31. 7
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java
  32. 1
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java
  33. 1
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java
  34. 57
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java
  35. 1
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java
  36. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java
  37. 1
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java
  38. 2
      plugin-api/build.gradle
  39. 17
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TransactionPoolValidatorService.java
  40. 12
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionPoolValidator.java
  41. 8
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionPoolValidatorFactory.java

@ -19,6 +19,7 @@
- Update commons-compress to 1.26.0 [#6648](https://github.com/hyperledger/besu/pull/6648)
- Add blob transaction support to `eth_call` [#6661](https://github.com/hyperledger/besu/pull/6661)
- Add blobs to `eth_feeHistory` [#6679](https://github.com/hyperledger/besu/pull/6679)
- Refactor and extend `TransactionPoolValidatorService` [#6636](https://github.com/hyperledger/besu/pull/6636)
### Bug fixes

@ -45,22 +45,21 @@ import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.plugin.services.BesuConfiguration;
import org.hyperledger.besu.plugin.services.BesuEvents;
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
import org.hyperledger.besu.plugin.services.PluginTransactionValidatorService;
import org.hyperledger.besu.plugin.services.RpcEndpointService;
import org.hyperledger.besu.plugin.services.SecurityModuleService;
import org.hyperledger.besu.plugin.services.StorageService;
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
import org.hyperledger.besu.plugin.services.TransactionSelectionService;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.PermissioningServiceImpl;
import org.hyperledger.besu.services.PicoCLIOptionsImpl;
import org.hyperledger.besu.services.PluginTransactionValidatorServiceImpl;
import org.hyperledger.besu.services.RpcEndpointServiceImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl;
import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
import java.io.File;
@ -71,7 +70,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@ -105,7 +103,7 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
besuPluginContext.addService(
TransactionSelectionService.class, transactionSelectionServiceImpl);
besuPluginContext.addService(
PluginTransactionValidatorService.class, new PluginTransactionValidatorServiceImpl());
TransactionPoolValidatorService.class, new TransactionPoolValidatorServiceImpl());
final Path pluginsPath;
final String pluginDir = System.getProperty("besu.plugins.dir");
if (pluginDir == null || pluginDir.isEmpty()) {
@ -205,8 +203,6 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
final int maxPeers = 25;
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
getPluginTransactionValidatorFactory(besuPluginContext);
builder
.synchronizerConfiguration(new SynchronizerConfiguration.Builder().build())
.dataDirectory(node.homeDirectory())
@ -228,8 +224,7 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.maxPeers(maxPeers)
.maxRemotelyInitiatedPeers(15)
.networkConfiguration(node.getNetworkingConfiguration())
.randomPeerPriority(false)
.pluginTransactionValidatorFactory(pluginTransactionValidatorFactory);
.randomPeerPriority(false);
node.getGenesisConfig()
.map(GenesisConfigFile::fromConfig)
@ -339,11 +334,4 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
public String getConsoleContents() {
throw new RuntimeException("Console contents can only be captured in process execution");
}
private PluginTransactionValidatorFactory getPluginTransactionValidatorFactory(
final BesuPluginContextImpl besuPluginContext) {
final Optional<PluginTransactionValidatorService> txValidatorService =
besuPluginContext.getService(PluginTransactionValidatorService.class);
return txValidatorService.map(PluginTransactionValidatorService::get).orElse(null);
}
}

@ -160,12 +160,12 @@ import org.hyperledger.besu.plugin.services.BlockchainService;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.PermissioningService;
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
import org.hyperledger.besu.plugin.services.PluginTransactionValidatorService;
import org.hyperledger.besu.plugin.services.PrivacyPluginService;
import org.hyperledger.besu.plugin.services.RpcEndpointService;
import org.hyperledger.besu.plugin.services.SecurityModuleService;
import org.hyperledger.besu.plugin.services.StorageService;
import org.hyperledger.besu.plugin.services.TraceService;
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
import org.hyperledger.besu.plugin.services.TransactionSelectionService;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.metrics.MetricCategory;
@ -174,19 +174,18 @@ import org.hyperledger.besu.plugin.services.securitymodule.SecurityModule;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.BlockchainServiceImpl;
import org.hyperledger.besu.services.PermissioningServiceImpl;
import org.hyperledger.besu.services.PicoCLIOptionsImpl;
import org.hyperledger.besu.services.PluginTransactionValidatorServiceImpl;
import org.hyperledger.besu.services.PrivacyPluginServiceImpl;
import org.hyperledger.besu.services.RpcEndpointServiceImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.services.TraceServiceImpl;
import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl;
import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin;
import org.hyperledger.besu.util.InvalidConfigurationException;
@ -370,7 +369,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
P2PDiscoveryOptionGroup p2PDiscoveryOptionGroup = new P2PDiscoveryOptionGroup();
private final TransactionSelectionServiceImpl transactionSelectionServiceImpl;
private final PluginTransactionValidatorServiceImpl transactionValidatorServiceImpl;
private final TransactionPoolValidatorServiceImpl transactionValidatorServiceImpl;
private final BlockchainServiceImpl blockchainServiceImpl;
static class P2PDiscoveryOptionGroup {
@ -956,7 +955,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
new PkiBlockCreationConfigurationProvider(),
new RpcEndpointServiceImpl(),
new TransactionSelectionServiceImpl(),
new PluginTransactionValidatorServiceImpl(),
new TransactionPoolValidatorServiceImpl(),
new BlockchainServiceImpl());
}
@ -998,7 +997,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider,
final RpcEndpointServiceImpl rpcEndpointServiceImpl,
final TransactionSelectionServiceImpl transactionSelectionServiceImpl,
final PluginTransactionValidatorServiceImpl transactionValidatorServiceImpl,
final TransactionPoolValidatorServiceImpl transactionValidatorServiceImpl,
final BlockchainServiceImpl blockchainServiceImpl) {
this.besuComponent = besuComponent;
this.logger = besuComponent.getBesuCommandLogger();
@ -1210,7 +1209,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuPluginContext.addService(
TransactionSelectionService.class, transactionSelectionServiceImpl);
besuPluginContext.addService(
PluginTransactionValidatorService.class, transactionValidatorServiceImpl);
TransactionPoolValidatorService.class, transactionValidatorServiceImpl);
besuPluginContext.addService(BlockchainService.class, blockchainServiceImpl);
// register built-in plugins
@ -1812,7 +1811,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.synchronizerConfiguration(buildSyncConfig())
.ethProtocolConfiguration(unstableEthProtocolOptions.toDomainObject())
.networkConfiguration(unstableNetworkingOptions.toDomainObject())
.pluginTransactionValidatorFactory(getPluginTransactionValidatorFactory())
.dataDirectory(dataDir())
.dataStorageConfiguration(getDataStorageConfiguration())
.miningParameters(getMiningParameters())
@ -1843,12 +1841,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.cacheLastBlocks(numberOfblocksToCache);
}
private PluginTransactionValidatorFactory getPluginTransactionValidatorFactory() {
final Optional<PluginTransactionValidatorService> txSValidatorService =
besuPluginContext.getService(PluginTransactionValidatorService.class);
return txSValidatorService.map(PluginTransactionValidatorService::get).orElse(null);
}
private JsonRpcConfiguration createEngineJsonRpcConfiguration(
final Integer engineListenPort, final List<String> allowCallsFrom) {
jsonRpcHttpOptions.checkDependencies(logger, commandLine);
@ -2115,6 +2107,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
private TransactionPoolConfiguration buildTransactionPoolConfiguration() {
transactionPoolOptions.setPluginTransactionValidatorService(transactionValidatorServiceImpl);
final var txPoolConf = transactionPoolOptions.toDomainObject();
final var txPoolConfBuilder =
ImmutableTransactionPoolConfiguration.builder()

@ -30,6 +30,7 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
import org.hyperledger.besu.util.number.Fraction;
import org.hyperledger.besu.util.number.Percentage;
@ -57,6 +58,8 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
private static final String TX_POOL_PRIORITY_SENDERS = "--tx-pool-priority-senders";
private static final String TX_POOL_MIN_GAS_PRICE = "--tx-pool-min-gas-price";
private TransactionPoolValidatorService transactionPoolValidatorService;
@CommandLine.Option(
names = {TX_POOL_IMPLEMENTATION},
paramLabel = "<Enum>",
@ -252,6 +255,16 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
return new TransactionPoolOptions();
}
/**
* Set the plugin txpool validator service
*
* @param transactionPoolValidatorService the plugin txpool validator service
*/
public void setPluginTransactionValidatorService(
final TransactionPoolValidatorService transactionPoolValidatorService) {
this.transactionPoolValidatorService = transactionPoolValidatorService;
}
/**
* Create Transaction Pool Options from Transaction Pool Configuration.
*
@ -277,6 +290,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
config.getTxPoolLimitByAccountPercentage();
options.sequencedOptions.txPoolMaxSize = config.getTxPoolMaxSize();
options.sequencedOptions.pendingTxRetentionPeriod = config.getPendingTxRetentionPeriod();
options.transactionPoolValidatorService = config.getTransactionPoolValidatorService();
options.unstableOptions.txMessageKeepAliveSeconds =
config.getUnstable().getTxMessageKeepAliveSeconds();
options.unstableOptions.eth65TrxAnnouncedBufferingPeriod =
@ -331,6 +345,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
.txPoolLimitByAccountPercentage(sequencedOptions.txPoolLimitByAccountPercentage)
.txPoolMaxSize(sequencedOptions.txPoolMaxSize)
.pendingTxRetentionPeriod(sequencedOptions.pendingTxRetentionPeriod)
.transactionPoolValidatorService(transactionPoolValidatorService)
.unstable(
ImmutableTransactionPoolConfiguration.Unstable.builder()
.txMessageKeepAliveSeconds(unstableOptions.txMessageKeepAliveSeconds)

@ -99,7 +99,6 @@ 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.storage.DataStorageFormat;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import java.io.Closeable;
import java.math.BigInteger;
@ -189,8 +188,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
/** the Dagger configured context that can provide dependencies */
protected Optional<BesuComponent> besuComponent = Optional.empty();
private PluginTransactionValidatorFactory pluginTransactionValidatorFactory;
private int numberOfBlocksToCache = 0;
/**
@ -532,18 +529,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
return this;
}
/**
* sets the pluginTransactionValidatorFactory
*
* @param pluginTransactionValidatorFactory factory that creates plugin transaction Validators
* @return the besu controller builder
*/
public BesuControllerBuilder pluginTransactionValidatorFactory(
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) {
this.pluginTransactionValidatorFactory = pluginTransactionValidatorFactory;
return this;
}
/**
* Build besu controller.
*
@ -697,7 +682,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
metricsSystem,
syncState,
transactionPoolConfiguration,
pluginTransactionValidatorFactory,
besuComponent.map(BesuComponent::getBlobCache).orElse(new BlobCache()),
miningParameters);

@ -1,35 +0,0 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.services;
import org.hyperledger.besu.plugin.services.PluginTransactionValidatorService;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
/** The Transaction Validation service implementation. */
public class PluginTransactionValidatorServiceImpl implements PluginTransactionValidatorService {
private PluginTransactionValidatorFactory factory;
@Override
public PluginTransactionValidatorFactory get() {
return factory;
}
@Override
public void registerTransactionValidatorFactory(
final PluginTransactionValidatorFactory transactionValidatorFactory) {
factory = transactionValidatorFactory;
}
}

@ -0,0 +1,40 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.services;
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidator;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidatorFactory;
import java.util.Optional;
/** The Transaction pool validator service implementation. */
public class TransactionPoolValidatorServiceImpl implements TransactionPoolValidatorService {
private Optional<PluginTransactionPoolValidatorFactory> factory = Optional.empty();
@Override
public PluginTransactionPoolValidator createTransactionValidator() {
return factory
.map(PluginTransactionPoolValidatorFactory::createTransactionValidator)
.orElse(PluginTransactionPoolValidator.VALIDATE_ALL);
}
@Override
public void registerPluginTransactionValidatorFactory(
final PluginTransactionPoolValidatorFactory pluginTransactionPoolValidatorFactory) {
factory = Optional.ofNullable(pluginTransactionPoolValidatorFactory);
}
}

@ -86,11 +86,11 @@ import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.BlockchainServiceImpl;
import org.hyperledger.besu.services.PermissioningServiceImpl;
import org.hyperledger.besu.services.PluginTransactionValidatorServiceImpl;
import org.hyperledger.besu.services.PrivacyPluginServiceImpl;
import org.hyperledger.besu.services.RpcEndpointServiceImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl;
import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
@ -297,8 +297,6 @@ public abstract class CommandTestAbstract {
when(mockControllerBuilder.maxPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxRemotelyInitiatedPeers(anyInt()))
.thenReturn(mockControllerBuilder);
when(mockControllerBuilder.pluginTransactionValidatorFactory(any()))
.thenReturn(mockControllerBuilder);
when(mockControllerBuilder.besuComponent(any(BesuComponent.class)))
.thenReturn(mockControllerBuilder);
when(mockControllerBuilder.cacheLastBlocks(any())).thenReturn(mockControllerBuilder);
@ -574,7 +572,7 @@ public abstract class CommandTestAbstract {
pkiBlockCreationConfigProvider,
rpcEndpointServiceImpl,
new TransactionSelectionServiceImpl(),
new PluginTransactionValidatorServiceImpl(),
new TransactionPoolValidatorServiceImpl(),
new BlockchainServiceImpl());
}

@ -370,4 +370,9 @@ public class TransactionPoolOptionsTest
protected TransactionPoolOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
return besuCommand.getTransactionPoolOptions();
}
@Override
protected String[] getNonOptionFields() {
return new String[] {"transactionPoolValidatorService"};
}
}

@ -167,7 +167,6 @@ public class BesuEventsImplTest {
new NoOpMetricsSystem(),
syncState,
txPoolConfig,
null,
new BlobCache(),
MiningParameters.newDefault());

@ -243,8 +243,7 @@ public class CliqueBlockCreatorTest {
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(metricsSystem),
conf,
null);
conf);
transactionPool.setEnabled();
return transactionPool;
}

@ -230,8 +230,7 @@ public class CliqueMinerExecutorTest {
mock(TransactionBroadcaster.class),
cliqueEthContext,
new TransactionPoolMetrics(metricsSystem),
conf,
null);
conf);
transactionPool.setEnabled();
return transactionPool;

@ -368,8 +368,7 @@ public class TestContextBuilder {
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(metricsSystem),
poolConf,
null);
poolConf);
transactionPool.setEnabled();

@ -149,8 +149,7 @@ public class BftBlockCreatorTest {
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(metricsSystem),
poolConf,
null);
poolConf);
transactionPool.setEnabled();

@ -214,8 +214,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(metricsSystem),
poolConf,
null);
poolConf);
this.transactionPool.setEnabled();

@ -466,8 +466,7 @@ public class TestContextBuilder {
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(metricsSystem),
poolConf,
null);
poolConf);
transactionPool.setEnabled();

@ -120,8 +120,7 @@ public class EthGetFilterChangesIntegrationTest {
batchAddedListener,
ethContext,
new TransactionPoolMetrics(metricsSystem),
TransactionPoolConfiguration.DEFAULT,
null);
TransactionPoolConfiguration.DEFAULT);
transactionPool.setEnabled();
final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive());

@ -120,8 +120,7 @@ public class EthGetFilterChangesIntegrationTest {
batchAddedListener,
ethContext,
new TransactionPoolMetrics(metricsSystem),
TransactionPoolConfiguration.DEFAULT,
null);
TransactionPoolConfiguration.DEFAULT);
transactionPool.setEnabled();
final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive());

@ -75,7 +75,7 @@ public class JsonRpcErrorConverter {
return RpcErrorType.TOTAL_BLOB_GAS_TOO_HIGH;
case TX_POOL_DISABLED:
return RpcErrorType.TX_POOL_DISABLED;
case PLUGIN_TX_VALIDATOR:
case PLUGIN_TX_POOL_VALIDATOR:
return RpcErrorType.PLUGIN_TX_VALIDATOR;
case INVALID_BLOBS:
return RpcErrorType.INVALID_BLOBS;

@ -103,7 +103,7 @@ public class EthSendRawTransaction implements JsonRpcMethod {
if (sendEmptyHashOnInvalidBlock) {
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), Hash.EMPTY.toString());
} else {
if (errorReason == TransactionInvalidReason.PLUGIN_TX_VALIDATOR) {
if (errorReason == TransactionInvalidReason.PLUGIN_TX_POOL_VALIDATOR) {
final RpcErrorType rpcErrorType =
JsonRpcErrorConverter.convertTransactionInvalidReason(
validationResult.getInvalidReason());

@ -386,8 +386,7 @@ abstract class AbstractBlockCreatorTest {
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(new NoOpMetricsSystem()),
poolConf,
null);
poolConf);
transactionPool.setEnabled();
final MiningParameters miningParameters =

@ -732,9 +732,11 @@ public abstract class AbstractBlockTransactionSelectorTest {
final Transaction transaction = createTransaction(0, Wei.of(10), 21_000);
ensureTransactionIsValid(transaction, 21_000, 0);
final TransactionInvalidReason invalidReason = TransactionInvalidReason.PLUGIN_TX_VALIDATOR;
final TransactionInvalidReason invalidReason =
TransactionInvalidReason.PLUGIN_TX_POOL_VALIDATOR;
final Transaction invalidTransaction = createTransaction(1, Wei.of(10), 21_000);
ensureTransactionIsInvalid(invalidTransaction, TransactionInvalidReason.PLUGIN_TX_VALIDATOR);
ensureTransactionIsInvalid(
invalidTransaction, TransactionInvalidReason.PLUGIN_TX_POOL_VALIDATOR);
final BlockTransactionSelector selector =
createBlockSelectorAndSetupTxPool(

@ -90,8 +90,7 @@ public class LegacyFeeMarketBlockTransactionSelectorTest
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(metricsSystem),
poolConf,
null);
poolConf);
transactionPool.setEnabled();
return transactionPool;
}

@ -98,8 +98,7 @@ public class LondonFeeMarketBlockTransactionSelectorTest
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(metricsSystem),
poolConf,
null);
poolConf);
transactionPool.setEnabled();
return transactionPool;
}

@ -338,8 +338,7 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(metricsSystem),
poolConf,
null);
poolConf);
transactionPool.setEnabled();
return transactionPool;

@ -117,8 +117,7 @@ public class PoWMinerExecutorTest {
mock(TransactionBroadcaster.class),
ethContext,
new TransactionPoolMetrics(new NoOpMetricsSystem()),
poolConf,
null);
poolConf);
transactionPool.setEnabled();
return transactionPool;

@ -49,7 +49,7 @@ public enum TransactionInvalidReason {
INTERNAL_ERROR,
TX_POOL_DISABLED,
INVALID_BLOBS,
PLUGIN_TX_VALIDATOR,
PLUGIN_TX_POOL_VALIDATOR,
EXECUTION_HALTED,
// Private Transaction Invalid Reasons
PRIVATE_TRANSACTION_INVALID,

@ -173,8 +173,7 @@ public abstract class AbstractIsolationTests {
mock(TransactionBroadcaster.class),
ethContext,
txPoolMetrics,
poolConfiguration,
null);
poolConfiguration);
transactionPool.setEnabled();
}

@ -42,8 +42,6 @@ import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.fluent.SimpleAccount;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidator;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import org.hyperledger.besu.util.Subscribers;
import java.io.BufferedReader;
@ -92,7 +90,6 @@ public class TransactionPool implements BlockAddedObserver {
private static final Logger LOG = LoggerFactory.getLogger(TransactionPool.class);
private static final Logger LOG_FOR_REPLAY = LoggerFactory.getLogger("LOG_FOR_REPLAY");
private final Supplier<PendingTransactions> pendingTransactionsSupplier;
private final PluginTransactionValidator pluginTransactionValidator;
private volatile PendingTransactions pendingTransactions;
private final ProtocolSchedule protocolSchedule;
private final ProtocolContext protocolContext;
@ -115,8 +112,7 @@ public class TransactionPool implements BlockAddedObserver {
final TransactionBroadcaster transactionBroadcaster,
final EthContext ethContext,
final TransactionPoolMetrics metrics,
final TransactionPoolConfiguration configuration,
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) {
final TransactionPoolConfiguration configuration) {
this.pendingTransactionsSupplier = pendingTransactionsSupplier;
this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext;
@ -124,10 +120,6 @@ public class TransactionPool implements BlockAddedObserver {
this.transactionBroadcaster = transactionBroadcaster;
this.metrics = metrics;
this.configuration = configuration;
this.pluginTransactionValidator =
pluginTransactionValidatorFactory == null
? null
: pluginTransactionValidatorFactory.create();
this.blockAddedEventOrderedProcessor =
ethContext.getScheduler().createOrderedProcessor(this::processBlockAddedEvent);
initLogForReplay();
@ -442,14 +434,15 @@ public class TransactionPool implements BlockAddedObserver {
TransactionInvalidReason.INVALID_BLOBS, "Blob transaction must have at least one blob");
}
// Call the transaction validator plugin if one is available
if (pluginTransactionValidator != null) {
final Optional<String> maybeError =
pluginTransactionValidator.validateTransaction(transaction);
if (maybeError.isPresent()) {
// Call the transaction validator plugin
final Optional<String> maybePluginInvalid =
configuration
.getTransactionPoolValidatorService()
.createTransactionValidator()
.validateTransaction(transaction, isLocal, hasPriority);
if (maybePluginInvalid.isPresent()) {
return ValidationResultAndAccount.invalid(
TransactionInvalidReason.PLUGIN_TX_VALIDATOR, maybeError.get());
}
TransactionInvalidReason.PLUGIN_TX_POOL_VALIDATOR, maybePluginInvalid.get());
}
try (final var worldState =

@ -16,6 +16,9 @@ package org.hyperledger.besu.ethereum.eth.transactions;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidator;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidatorFactory;
import org.hyperledger.besu.util.number.Fraction;
import org.hyperledger.besu.util.number.Percentage;
@ -154,6 +157,20 @@ public interface TransactionPoolConfiguration {
return DEFAULT_TX_POOL_MIN_GAS_PRICE;
}
@Value.Default
default TransactionPoolValidatorService getTransactionPoolValidatorService() {
return new TransactionPoolValidatorService() {
@Override
public PluginTransactionPoolValidator createTransactionValidator() {
return PluginTransactionPoolValidator.VALIDATE_ALL;
}
@Override
public void registerPluginTransactionValidatorFactory(
final PluginTransactionPoolValidatorFactory pluginTransactionPoolValidatorFactory) {}
};
}
@Value.Default
default Unstable getUnstable() {
return Unstable.DEFAULT;

@ -36,7 +36,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.plugin.services.BesuEvents;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import java.time.Clock;
import java.util.function.BiFunction;
@ -55,7 +54,6 @@ public class TransactionPoolFactory {
final MetricsSystem metricsSystem,
final SyncState syncState,
final TransactionPoolConfiguration transactionPoolConfiguration,
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory,
final BlobCache blobCache,
final MiningParameters miningParameters) {
@ -79,7 +77,6 @@ public class TransactionPoolFactory {
transactionTracker,
transactionsMessageSender,
newPooledTransactionHashesMessageSender,
pluginTransactionValidatorFactory,
blobCache,
miningParameters);
}
@ -95,7 +92,6 @@ public class TransactionPoolFactory {
final PeerTransactionTracker transactionTracker,
final TransactionsMessageSender transactionsMessageSender,
final NewPooledTransactionHashesMessageSender newPooledTransactionHashesMessageSender,
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory,
final BlobCache blobCache,
final MiningParameters miningParameters) {
@ -119,8 +115,7 @@ public class TransactionPoolFactory {
newPooledTransactionHashesMessageSender),
ethContext,
metrics,
transactionPoolConfiguration,
pluginTransactionValidatorFactory);
transactionPoolConfiguration);
final TransactionsMessageHandler transactionsMessageHandler =
new TransactionsMessageHandler(

@ -1118,7 +1118,6 @@ public final class EthProtocolManagerTest {
metricsSystem,
new SyncState(blockchain, ethManager.ethContext().getEthPeers()),
TransactionPoolConfiguration.DEFAULT,
null,
new BlobCache(),
MiningParameters.newDefault())
.setEnabled();

@ -138,7 +138,6 @@ public abstract class AbstractMessageTaskTest<T, R> {
metricsSystem,
syncState,
TransactionPoolConfiguration.DEFAULT,
null,
new BlobCache(),
MiningParameters.newDefault());
transactionPool.setEnabled();

@ -87,8 +87,9 @@ import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidator;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidator;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidatorFactory;
import org.hyperledger.besu.util.number.Percentage;
import java.math.BigInteger;
@ -256,14 +257,8 @@ public abstract class AbstractTransactionPoolTest {
return createTransactionPool(b -> b.minGasPrice(Wei.of(2)));
}
protected TransactionPool createTransactionPool(
final Consumer<ImmutableTransactionPoolConfiguration.Builder> configConsumer) {
return createTransactionPool(configConsumer, null);
}
private TransactionPool createTransactionPool(
final Consumer<ImmutableTransactionPoolConfiguration.Builder> configConsumer,
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) {
final Consumer<ImmutableTransactionPoolConfiguration.Builder> configConsumer) {
final ImmutableTransactionPoolConfiguration.Builder configBuilder =
ImmutableTransactionPoolConfiguration.builder();
configConsumer.accept(configBuilder);
@ -287,8 +282,7 @@ public abstract class AbstractTransactionPoolTest {
transactionBroadcaster,
ethContext,
new TransactionPoolMetrics(metricsSystem),
poolConfig,
pluginTransactionValidatorFactory);
poolConfig);
txPool.setEnabled();
return txPool;
}
@ -794,11 +788,13 @@ public abstract class AbstractTransactionPoolTest {
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void transactionNotRejectedByPluginShouldBeAdded(final boolean noLocalPriority) {
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
getPluginTransactionValidatorFactoryReturning(null); // null -> not rejecting !!
final TransactionPoolValidatorService transactionPoolValidatorService =
getTransactionPoolValidatorServiceReturning(null); // null -> not rejecting !!
this.transactionPool =
createTransactionPool(
b -> b.noLocalPriority(noLocalPriority), pluginTransactionValidatorFactory);
b ->
b.noLocalPriority(noLocalPriority)
.transactionPoolValidatorService(transactionPoolValidatorService));
givenTransactionIsValid(transaction0);
@ -808,23 +804,27 @@ public abstract class AbstractTransactionPoolTest {
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void transactionRejectedByPluginShouldNotBeAdded(final boolean noLocalPriority) {
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
getPluginTransactionValidatorFactoryReturning("false");
final TransactionPoolValidatorService transactionPoolValidatorService =
getTransactionPoolValidatorServiceReturning("false");
this.transactionPool =
createTransactionPool(
b -> b.noLocalPriority(noLocalPriority), pluginTransactionValidatorFactory);
b ->
b.noLocalPriority(noLocalPriority)
.transactionPoolValidatorService(transactionPoolValidatorService));
givenTransactionIsValid(transaction0);
addAndAssertTransactionViaApiInvalid(
transaction0, TransactionInvalidReason.PLUGIN_TX_VALIDATOR);
transaction0, TransactionInvalidReason.PLUGIN_TX_POOL_VALIDATOR);
}
@Test
public void remoteTransactionRejectedByPluginShouldNotBeAdded() {
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory =
getPluginTransactionValidatorFactoryReturning("false");
this.transactionPool = createTransactionPool(b -> {}, pluginTransactionValidatorFactory);
final TransactionPoolValidatorService transactionPoolValidatorService =
getTransactionPoolValidatorServiceReturning("false");
this.transactionPool =
createTransactionPool(
b -> b.transactionPoolValidatorService(transactionPoolValidatorService));
givenTransactionIsValid(transaction0);
@ -1270,11 +1270,18 @@ public abstract class AbstractTransactionPoolTest {
.containsExactlyInAnyOrder(transaction1, transaction2a, transaction3);
}
private static PluginTransactionValidatorFactory getPluginTransactionValidatorFactoryReturning(
private static TransactionPoolValidatorService getTransactionPoolValidatorServiceReturning(
final String errorMessage) {
final PluginTransactionValidator pluginTransactionValidator =
transaction -> Optional.ofNullable(errorMessage);
return () -> pluginTransactionValidator;
return new TransactionPoolValidatorService() {
@Override
public PluginTransactionPoolValidator createTransactionValidator() {
return (transaction, isLocal, hasPriority) -> Optional.ofNullable(errorMessage);
}
@Override
public void registerPluginTransactionValidatorFactory(
final PluginTransactionPoolValidatorFactory pluginTransactionPoolValidatorFactory) {}
};
}
@SuppressWarnings("unused")

@ -166,7 +166,6 @@ public class TestNode implements Closeable {
metricsSystem,
syncState,
TransactionPoolConfiguration.DEFAULT,
null,
new BlobCache(),
MiningParameters.newDefault());

@ -251,7 +251,6 @@ public class TransactionPoolFactoryTest {
peerTransactionTracker,
transactionsMessageSender,
newPooledTransactionHashesMessageSender,
null,
new BlobCache(),
MiningParameters.newDefault());
@ -360,7 +359,6 @@ public class TransactionPoolFactoryTest {
.txMessageKeepAliveSeconds(1)
.build())
.build(),
null,
new BlobCache(),
MiningParameters.newDefault());

@ -255,7 +255,6 @@ public class RetestethContext {
metricsSystem,
syncState,
transactionPoolConfiguration,
null,
new BlobCache(),
MiningParameters.newDefault());

@ -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 = 'Jv/pqyKOoZo3wlxRRwmzPuLIJjEqyV1i55wFyIUV90A='
knownHash = 'B/pzTaARYvd/T9WtAXtX6vFbxoK5u82GigByKD0YP6M='
}
check.dependsOn('checkAPIChanges')

@ -16,24 +16,25 @@
package org.hyperledger.besu.plugin.services;
import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidator;
import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidatorFactory;
/** Transaction validator for addition of transactions to the transaction pool */
@Unstable
public interface PluginTransactionValidatorService extends BesuService {
public interface TransactionPoolValidatorService extends BesuService {
/**
* Returns the transaction validator factory
* Returns the transaction validator to be used in the txpool
*
* @return the transaction validator factory
* @return the transaction validator
*/
PluginTransactionValidatorFactory get();
PluginTransactionPoolValidator createTransactionValidator();
/**
* Registers the transaction validator factory with the service
*
* @param transactionValidatorFactory transaction validator factory to be used
* @param pluginTransactionPoolValidatorFactory transaction validator factory to be used
*/
void registerTransactionValidatorFactory(
PluginTransactionValidatorFactory transactionValidatorFactory);
void registerPluginTransactionValidatorFactory(
PluginTransactionPoolValidatorFactory pluginTransactionPoolValidatorFactory);
}

@ -20,16 +20,22 @@ import org.hyperledger.besu.plugin.Unstable;
import java.util.Optional;
/** Interface for the transaction validator plugin */
/** Interface for the transaction validator plugin for txpool usage */
@Unstable
public interface PluginTransactionValidator {
public interface PluginTransactionPoolValidator {
/** Plugin transaction pool validator that unconditionally validates every transaction */
PluginTransactionPoolValidator VALIDATE_ALL =
(transaction, isLocal, hasPriority) -> Optional.empty();
/**
* Method called to decide whether a transaction can be added to the transaction pool.
*
* @param transaction candidate transaction
* @param isLocal if the transaction was sent to this node via API
* @param hasPriority if the transaction has priority
* @return Optional.empty() if the transaction is valid, an Optional containing an error message,
* if not
*/
Optional<String> validateTransaction(final Transaction transaction);
Optional<String> validateTransaction(
final Transaction transaction, final boolean isLocal, final boolean hasPriority);
}

@ -17,14 +17,14 @@ package org.hyperledger.besu.plugin.services.txvalidator;
import org.hyperledger.besu.plugin.Unstable;
/** Interface for a factory that creates transaction validators */
/** Interface for a factory that creates transaction validators for txpool usage */
@Unstable
public interface PluginTransactionValidatorFactory {
public interface PluginTransactionPoolValidatorFactory {
/**
* Create a transaction validator
* Create a transaction validator for txpool usage
*
* @return the transaction validator
*/
PluginTransactionValidator create();
PluginTransactionPoolValidator createTransactionValidator();
}
Loading…
Cancel
Save