diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index 29ce00b175f..e06aa8c9641 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -43,16 +43,19 @@ 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.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.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; @@ -97,7 +100,8 @@ private BesuPluginContextImpl buildPluginContext( besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine)); besuPluginContext.addService( TransactionSelectionService.class, new TransactionSelectionServiceImpl()); - + besuPluginContext.addService( + PluginTransactionValidatorService.class, new PluginTransactionValidatorServiceImpl()); final Path pluginsPath; final String pluginDir = System.getProperty("besu.plugins.dir"); if (pluginDir == null || pluginDir.isEmpty()) { @@ -184,6 +188,8 @@ public void startNode(final BesuNode node) { final Optional transactionSelectorFactory = getTransactionSelectorFactory(besuPluginContext); + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory = + getPluginTransactionValidatorFactory(besuPluginContext); builder .synchronizerConfiguration(new SynchronizerConfiguration.Builder().build()) .dataDirectory(node.homeDirectory()) @@ -206,7 +212,8 @@ public void startNode(final BesuNode node) { .maxRemotelyInitiatedPeers(15) .networkConfiguration(node.getNetworkingConfiguration()) .randomPeerPriority(false) - .transactionSelectorFactory(transactionSelectorFactory); + .transactionSelectorFactory(transactionSelectorFactory) + .pluginTransactionValidatorFactory(pluginTransactionValidatorFactory); node.getGenesisConfig() .map(GenesisConfigFile::fromConfig) @@ -322,4 +329,11 @@ private Optional getTransactionSelectorFactory( besuPluginContext.getService(TransactionSelectionService.class); return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty(); } + + private PluginTransactionValidatorFactory getPluginTransactionValidatorFactory( + final BesuPluginContextImpl besuPluginContext) { + final Optional txValidatorService = + besuPluginContext.getService(PluginTransactionValidatorService.class); + return txValidatorService.map(PluginTransactionValidatorService::get).orElse(null); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index e3cdaefe089..cb9a25fad8e 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -117,6 +117,7 @@ public BesuNode createMinerNodeWithExtraCliOptions( .name(name) .miningEnabled() .jsonRpcEnabled() + .jsonRpcTxPool() .webSocketEnabled() .extraCLIOptions(extraCliOptions); builder = configModifier.apply(builder); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 2538a1d7056..75c44198877 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -164,6 +164,7 @@ 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; @@ -177,11 +178,13 @@ 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.txvalidator.PluginTransactionValidatorFactory; 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; @@ -372,6 +375,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { P2PDiscoveryOptionGroup p2PDiscoveryOptionGroup = new P2PDiscoveryOptionGroup(); private final TransactionSelectionServiceImpl transactionSelectionServiceImpl; + private final PluginTransactionValidatorServiceImpl transactionValidatorServiceImpl; static class P2PDiscoveryOptionGroup { @@ -1355,7 +1359,8 @@ public BesuCommand( new PrivacyPluginServiceImpl(), new PkiBlockCreationConfigurationProvider(), new RpcEndpointServiceImpl(), - new TransactionSelectionServiceImpl()); + new TransactionSelectionServiceImpl(), + new PluginTransactionValidatorServiceImpl()); } /** @@ -1376,6 +1381,7 @@ public BesuCommand( * @param pkiBlockCreationConfigProvider instance of PkiBlockCreationConfigurationProvider * @param rpcEndpointServiceImpl instance of RpcEndpointServiceImpl * @param transactionSelectionServiceImpl instance of TransactionSelectionServiceImpl + * @param transactionValidatorServiceImpl instance of TransactionValidatorServiceImpl */ @VisibleForTesting protected BesuCommand( @@ -1393,7 +1399,8 @@ protected BesuCommand( final PrivacyPluginServiceImpl privacyPluginService, final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider, final RpcEndpointServiceImpl rpcEndpointServiceImpl, - final TransactionSelectionServiceImpl transactionSelectionServiceImpl) { + final TransactionSelectionServiceImpl transactionSelectionServiceImpl, + final PluginTransactionValidatorServiceImpl transactionValidatorServiceImpl) { this.besuComponent = besuComponent; this.logger = besuComponent.getBesuCommandLogger(); this.rlpBlockImporter = rlpBlockImporter; @@ -1412,6 +1419,7 @@ protected BesuCommand( this.pkiBlockCreationConfigProvider = pkiBlockCreationConfigProvider; this.rpcEndpointServiceImpl = rpcEndpointServiceImpl; this.transactionSelectionServiceImpl = transactionSelectionServiceImpl; + this.transactionValidatorServiceImpl = transactionValidatorServiceImpl; } /** @@ -1593,6 +1601,8 @@ private void preparePlugins() { besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl); besuPluginContext.addService( TransactionSelectionService.class, transactionSelectionServiceImpl); + besuPluginContext.addService( + PluginTransactionValidatorService.class, transactionValidatorServiceImpl); // register built-in plugins rocksDBPlugin = new RocksDBPlugin(); @@ -2193,7 +2203,7 @@ private void ensureAllNodesAreInAllowlist( final Collection enodeAddresses, final LocalPermissioningConfiguration permissioningConfiguration) { try { - PermissioningConfigurationValidator.areAllNodesAreInAllowlist( + PermissioningConfigurationValidator.areAllNodesInAllowlist( enodeAddresses, permissioningConfiguration); } catch (final Exception e) { throw new ParameterException(this.commandLine, e.getMessage()); @@ -2226,15 +2236,14 @@ public BesuController buildController() { */ public BesuControllerBuilder getControllerBuilder() { final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName); - final Optional transactionSelectorFactory = - getTransactionSelectorFactory(); return controllerBuilderFactory .fromEthNetworkConfig( updateNetworkConfig(network), genesisConfigOverrides, getDefaultSyncModeIfNotSet()) .synchronizerConfiguration(buildSyncConfig()) .ethProtocolConfiguration(unstableEthProtocolOptions.toDomainObject()) .networkConfiguration(unstableNetworkingOptions.toDomainObject()) - .transactionSelectorFactory(transactionSelectorFactory) + .transactionSelectorFactory(getTransactionSelectorFactory()) + .pluginTransactionValidatorFactory(getPluginTransactionValidatorFactory()) .dataDirectory(dataDir()) .miningParameters( new MiningParameters.Builder() @@ -2291,6 +2300,12 @@ private Optional getTransactionSelectorFactory() { return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty(); } + private PluginTransactionValidatorFactory getPluginTransactionValidatorFactory() { + final Optional txSValidatorService = + besuPluginContext.getService(PluginTransactionValidatorService.class); + return txSValidatorService.map(PluginTransactionValidatorService::get).orElse(null); + } + private GraphQLConfiguration graphQLConfiguration() { CommandLineUtils.checkOptionDependencies( diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index c5b9e8e8ebc..d023cdd76da 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -96,6 +96,7 @@ 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.txvalidator.PluginTransactionValidatorFactory; import java.io.Closeable; import java.math.BigInteger; @@ -185,6 +186,8 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides /** the Dagger configured context that can provide dependencies */ protected Optional besuComponent = Optional.empty(); + private PluginTransactionValidatorFactory pluginTransactionValidatorFactory; + /** * Provide a BesuComponent which can be used to get other dependencies * @@ -537,6 +540,18 @@ public BesuControllerBuilder transactionSelectorFactory( 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. * @@ -695,7 +710,8 @@ public BesuController build() { metricsSystem, syncState, miningParameters, - transactionPoolConfiguration); + transactionPoolConfiguration, + pluginTransactionValidatorFactory); final List peerValidators = createPeerValidators(protocolSchedule); diff --git a/besu/src/main/java/org/hyperledger/besu/services/PluginTransactionValidatorServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/PluginTransactionValidatorServiceImpl.java new file mode 100644 index 00000000000..171a31388c8 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/services/PluginTransactionValidatorServiceImpl.java @@ -0,0 +1,35 @@ +/* + * 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; + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/util/PermissioningConfigurationValidator.java b/besu/src/main/java/org/hyperledger/besu/util/PermissioningConfigurationValidator.java index f8e5c65dbc0..d1b4a107455 100644 --- a/besu/src/main/java/org/hyperledger/besu/util/PermissioningConfigurationValidator.java +++ b/besu/src/main/java/org/hyperledger/besu/util/PermissioningConfigurationValidator.java @@ -34,7 +34,7 @@ public class PermissioningConfigurationValidator { * @param permissioningConfiguration the permissioning configuration * @throws Exception In case of nodes are not in allow list */ - public static void areAllNodesAreInAllowlist( + public static void areAllNodesInAllowlist( final Collection nodeURIs, final LocalPermissioningConfiguration permissioningConfiguration) throws Exception { diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index d089ceaceb7..126052df0b9 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -76,6 +76,7 @@ import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier; import org.hyperledger.besu.services.BesuPluginContextImpl; 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; @@ -240,6 +241,8 @@ public void initMocks() throws Exception { when(mockControllerBuilder.maxRemotelyInitiatedPeers(anyInt())) .thenReturn(mockControllerBuilder); when(mockControllerBuilder.transactionSelectorFactory(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.pluginTransactionValidatorFactory(any())) + .thenReturn(mockControllerBuilder); when(mockControllerBuilder.besuComponent(any(BesuComponent.class))) .thenReturn(mockControllerBuilder); // doReturn used because of generic BesuController @@ -489,7 +492,8 @@ public static class TestBesuCommand extends BesuCommand { privacyPluginService, pkiBlockCreationConfigProvider, rpcEndpointServiceImpl, - new TransactionSelectionServiceImpl()); + new TransactionSelectionServiceImpl(), + new PluginTransactionValidatorServiceImpl()); } @Override diff --git a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java index 1057ae45a9d..8b6b10f5493 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java @@ -156,7 +156,8 @@ public void setUp() { new NoOpMetricsSystem(), syncState, new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), - txPoolConfig); + txPoolConfig, + null); serviceImpl = new BesuEventsImpl(blockchain, blockBroadcaster, transactionPool, syncState); } diff --git a/besu/src/test/java/org/hyperledger/besu/util/LocalPermissioningConfigurationValidatorTest.java b/besu/src/test/java/org/hyperledger/besu/util/LocalPermissioningConfigurationValidatorTest.java index f8dd890c21f..a5b3bb90d99 100644 --- a/besu/src/test/java/org/hyperledger/besu/util/LocalPermissioningConfigurationValidatorTest.java +++ b/besu/src/test/java/org/hyperledger/besu/util/LocalPermissioningConfigurationValidatorTest.java @@ -68,7 +68,7 @@ public void sepoliaWithNodesAllowlistOptionWhichDoesIncludeRopstenBootnodesMustN toml.toAbsolutePath().toString()); final List enodeURIs = ethNetworkConfig.getBootNodes(); - PermissioningConfigurationValidator.areAllNodesAreInAllowlist( + PermissioningConfigurationValidator.areAllNodesInAllowlist( enodeURIs, permissioningConfiguration); } @@ -92,7 +92,7 @@ public void nodesAllowlistOptionWhichDoesNotIncludeBootnodesMustError() throws E try { final List enodeURIs = ethNetworkConfig.getBootNodes(); - PermissioningConfigurationValidator.areAllNodesAreInAllowlist( + PermissioningConfigurationValidator.areAllNodesInAllowlist( enodeURIs, permissioningConfiguration); fail("expected exception because sepolia bootnodes are not in node-allowlist"); } catch (Exception e) { @@ -142,7 +142,7 @@ public void nodeAllowlistCheckShouldIgnoreDiscoveryPortParam() throws Exception // However, for the allowlist validation, we should ignore the discovery port and don't throw an // error try { - PermissioningConfigurationValidator.areAllNodesAreInAllowlist( + PermissioningConfigurationValidator.areAllNodesInAllowlist( Lists.newArrayList(enodeURL), permissioningConfiguration); } catch (Exception e) { fail( @@ -180,7 +180,7 @@ public void nodeAllowlistCheckShouldWorkWithHostnameIfDnsEnabled() throws Except // However, for the allowlist validation, we should ignore the discovery port and don't throw an // error try { - PermissioningConfigurationValidator.areAllNodesAreInAllowlist( + PermissioningConfigurationValidator.areAllNodesInAllowlist( Lists.newArrayList(enodeURL), permissioningConfiguration); } catch (Exception e) { fail( diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java index 604825bd71c..0b0210d4ef3 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java @@ -235,7 +235,8 @@ private TransactionPool createTransactionPool() { ethContext, mock(MiningParameters.class), new TransactionPoolMetrics(metricsSystem), - conf); + conf, + null); transactionPool.setEnabled(); return transactionPool; } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java index 90b3396211b..4a3bf5424d7 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java @@ -222,7 +222,8 @@ private TransactionPool createTransactionPool() { cliqueEthContext, mock(MiningParameters.class), new TransactionPoolMetrics(metricsSystem), - conf); + conf, + null); transactionPool.setEnabled(); return transactionPool; diff --git a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java index 13fb1d57cf8..42d68250821 100644 --- a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java +++ b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java @@ -357,7 +357,8 @@ private static ControllerAndState createControllerAndFinalState( ethContext, miningParams, new TransactionPoolMetrics(metricsSystem), - poolConf); + poolConf, + null); transactionPool.setEnabled(); diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java index a6668ad347e..1039b3579c1 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java @@ -145,7 +145,8 @@ public BlockHeaderValidator.Builder createBlockHeaderRuleset( ethContext, mock(MiningParameters.class), new TransactionPoolMetrics(metricsSystem), - poolConf); + poolConf, + null); transactionPool.setEnabled(); diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index d118a186af1..1948bced86b 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -222,7 +222,8 @@ public void setUp() { ethContext, miningParameters, new TransactionPoolMetrics(metricsSystem), - poolConf); + poolConf, + null); this.transactionPool.setEnabled(); diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java index eb4e6345207..ac824df6c0f 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java +++ b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java @@ -445,7 +445,8 @@ private static ControllerAndState createControllerAndFinalState( ethContext, miningParams, new TransactionPoolMetrics(metricsSystem), - poolConf); + poolConf, + null); transactionPool.setEnabled(); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java index 012c4bcc05b..bdb94af6e3d 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java @@ -119,7 +119,8 @@ public void setUp() { ethContext, new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), new TransactionPoolMetrics(metricsSystem), - TransactionPoolConfiguration.DEFAULT); + TransactionPoolConfiguration.DEFAULT, + null); transactionPool.setEnabled(); final BlockchainQueries blockchainQueries = new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive()); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java index d4d47d9356e..3ea2ee83633 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java @@ -119,7 +119,8 @@ public void setUp() { ethContext, new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), new TransactionPoolMetrics(metricsSystem), - TransactionPoolConfiguration.DEFAULT); + TransactionPoolConfiguration.DEFAULT, + null); transactionPool.setEnabled(); final BlockchainQueries blockchainQueries = new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive()); diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index ef208fc47e8..460e0809b41 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -381,7 +381,8 @@ private AbstractBlockCreator createBlockCreator( ethContext, mock(MiningParameters.class), new TransactionPoolMetrics(new NoOpMetricsSystem()), - poolConf); + poolConf, + null); transactionPool.setEnabled(); return new TestBlockCreator( diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java index 261c3d5f895..9b50bfadb8a 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java @@ -87,7 +87,8 @@ protected TransactionPool createTransactionPool() { ethContext, miningParameters, new TransactionPoolMetrics(metricsSystem), - poolConf); + poolConf, + null); transactionPool.setEnabled(); return transactionPool; } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java index 252f7f03655..0912c9d488a 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java @@ -91,7 +91,8 @@ protected TransactionPool createTransactionPool() { ethContext, miningParameters, new TransactionPoolMetrics(metricsSystem), - poolConf); + poolConf, + null); transactionPool.setEnabled(); return transactionPool; } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java index af9f5b690a6..07f5885f2b8 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java @@ -341,7 +341,8 @@ private TransactionPool createTransactionPool( ethContext, mock(MiningParameters.class), new TransactionPoolMetrics(metricsSystem), - poolConf); + poolConf, + null); transactionPool.setEnabled(); return transactionPool; diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java index 6edc39f333e..b3ab4ff0688 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutorTest.java @@ -119,7 +119,8 @@ private TransactionPool createTransactionPool(final MiningParameters miningParam ethContext, miningParameters, new TransactionPoolMetrics(new NoOpMetricsSystem()), - poolConf); + poolConf, + null); transactionPool.setEnabled(); return transactionPool; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java index 5b00d5fe521..3971b2f502b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java @@ -55,5 +55,6 @@ public enum TransactionInvalidReason { OFFCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST, PRIVATE_NONCE_TOO_HIGH, PRIVATE_VALUE_NOT_ZERO, - PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE + PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE, + PLUGIN_TX_VALIDATOR_INVALIDATED } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java index e787b766849..da12289afa8 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java @@ -162,7 +162,8 @@ public void createStorage() { ethContext, mock(MiningParameters.class), txPoolMetrics, - poolConfiguration); + poolConfiguration, + null); transactionPool.setEnabled(); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java index 9f5cc273b29..fd3d1a4c16a 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java @@ -42,6 +42,8 @@ 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; @@ -88,6 +90,7 @@ 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 pendingTransactionsSupplier; + private final PluginTransactionValidator pluginTransactionValidator; private volatile PendingTransactions pendingTransactions; private final ProtocolSchedule protocolSchedule; private final ProtocolContext protocolContext; @@ -110,7 +113,8 @@ public TransactionPool( final EthContext ethContext, final MiningParameters miningParameters, final TransactionPoolMetrics metrics, - final TransactionPoolConfiguration configuration) { + final TransactionPoolConfiguration configuration, + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) { this.pendingTransactionsSupplier = pendingTransactionsSupplier; this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; @@ -119,6 +123,10 @@ public TransactionPool( this.miningParameters = miningParameters; this.metrics = metrics; this.configuration = configuration; + this.pluginTransactionValidator = + pluginTransactionValidatorFactory == null + ? null + : pluginTransactionValidatorFactory.create(); initLogForReplay(); } @@ -409,7 +417,7 @@ private ValidationResultAndAccount validateTransaction( } if (isLocal - && strictReplayProtectionShouldBeEnforceLocally(chainHeadBlockHeader) + && strictReplayProtectionShouldBeEnforcedLocally(chainHeadBlockHeader) && transaction.getChainId().isEmpty()) { // Strict replay protection is enabled but the tx is not replay-protected return ValidationResultAndAccount.invalid( @@ -428,6 +436,14 @@ && strictReplayProtectionShouldBeEnforceLocally(chainHeadBlockHeader) "EIP-1559 transaction are not allowed yet"); } + // 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"); + } + try (final var worldState = protocolContext .getWorldStateArchive() @@ -477,7 +493,7 @@ && isMaxGasPriceBelowConfiguredMinGasPrice(transaction)) return null; } - private boolean strictReplayProtectionShouldBeEnforceLocally( + private boolean strictReplayProtectionShouldBeEnforcedLocally( final BlockHeader chainHeadBlockHeader) { return configuration.getStrictTransactionReplayProtectionEnabled() && protocolSchedule.getChainId().isPresent() diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java index 08d2aae5169..12cd2dc7e06 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java @@ -36,6 +36,7 @@ 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; @@ -54,7 +55,8 @@ public static TransactionPool createTransactionPool( final MetricsSystem metricsSystem, final SyncState syncState, final MiningParameters miningParameters, - final TransactionPoolConfiguration transactionPoolConfiguration) { + final TransactionPoolConfiguration transactionPoolConfiguration, + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) { final TransactionPoolMetrics metrics = new TransactionPoolMetrics(metricsSystem); @@ -76,7 +78,8 @@ public static TransactionPool createTransactionPool( transactionPoolConfiguration, transactionTracker, transactionsMessageSender, - newPooledTransactionHashesMessageSender); + newPooledTransactionHashesMessageSender, + pluginTransactionValidatorFactory); } static TransactionPool createTransactionPool( @@ -90,7 +93,8 @@ static TransactionPool createTransactionPool( final TransactionPoolConfiguration transactionPoolConfiguration, final PeerTransactionTracker transactionTracker, final TransactionsMessageSender transactionsMessageSender, - final NewPooledTransactionHashesMessageSender newPooledTransactionHashesMessageSender) { + final NewPooledTransactionHashesMessageSender newPooledTransactionHashesMessageSender, + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) { final TransactionPool transactionPool = new TransactionPool( @@ -111,7 +115,8 @@ static TransactionPool createTransactionPool( ethContext, miningParameters, metrics, - transactionPoolConfiguration); + transactionPoolConfiguration, + pluginTransactionValidatorFactory); final TransactionsMessageHandler transactionsMessageHandler = new TransactionsMessageHandler( diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java index d47581d2c88..60574c92152 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java @@ -1117,7 +1117,8 @@ public void transactionMessagesGoToTheCorrectExecutor() { metricsSystem, new SyncState(blockchain, ethManager.ethContext().getEthPeers()), new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), - TransactionPoolConfiguration.DEFAULT) + TransactionPoolConfiguration.DEFAULT, + null) .setEnabled(); // Send just a transaction message. diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java index aeb60471403..dc410937341 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java @@ -137,7 +137,8 @@ public void setupTest() { metricsSystem, syncState, new MiningParameters.Builder().minTransactionGasPrice(Wei.ONE).build(), - TransactionPoolConfiguration.DEFAULT); + TransactionPoolConfiguration.DEFAULT, + null); transactionPool.setEnabled(); ethProtocolManager = diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java index eaaff72a3e3..f66d7f41f94 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java @@ -68,6 +68,8 @@ import org.hyperledger.besu.evm.account.Account; 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 java.math.BigInteger; import java.util.Collections; @@ -76,6 +78,7 @@ import java.util.Set; import java.util.function.Consumer; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -173,6 +176,12 @@ protected TransactionPool createTransactionPool() { protected TransactionPool createTransactionPool( final Consumer configConsumer) { + return createTransactionPool(configConsumer, null); + } + + protected TransactionPool createTransactionPool( + final Consumer configConsumer, + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) { final ImmutableTransactionPoolConfiguration.Builder configBuilder = ImmutableTransactionPoolConfiguration.builder(); configConsumer.accept(configBuilder); @@ -187,7 +196,8 @@ protected TransactionPool createTransactionPool( ethContext, miningParameters, new TransactionPoolMetrics(metricsSystem), - config); + config, + pluginTransactionValidatorFactory); txPool.setEnabled(); return txPool; @@ -647,6 +657,59 @@ public void shouldRejectZeroGasPriceLocalTransactionWhenNotMining(final boolean assertTransactionViaApiInvalid(transaction, GAS_PRICE_TOO_LOW); } + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void transactionNotRejectedByPluginShouldBeAdded(final boolean disableLocalTxs) { + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory = + getPluginTransactionValidatorFactoryReturning(true); + this.transactionPool = + createTransactionPool( + b -> b.disableLocalTransactions(disableLocalTxs), pluginTransactionValidatorFactory); + + final Transaction transaction = createTransaction(0); + + givenTransactionIsValid(transaction); + + assertTransactionViaApiValid(transaction, disableLocalTxs); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void transactionRejectedByPluginShouldNotBeAdded(final boolean disableLocalTxs) { + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory = + getPluginTransactionValidatorFactoryReturning(false); + this.transactionPool = + createTransactionPool( + b -> b.disableLocalTransactions(disableLocalTxs), pluginTransactionValidatorFactory); + + final Transaction transaction = createTransaction(0); + + givenTransactionIsValid(transaction); + + assertTransactionViaApiInvalid( + transaction, TransactionInvalidReason.PLUGIN_TX_VALIDATOR_INVALIDATED); + } + + @Test + public void remoteTransactionRejectedByPluginShouldNotBeAdded() { + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory = + getPluginTransactionValidatorFactoryReturning(false); + this.transactionPool = createTransactionPool(b -> {}, pluginTransactionValidatorFactory); + + final Transaction transaction = createTransaction(0); + + givenTransactionIsValid(transaction); + + assertRemoteTransactionInvalid(transaction); + } + + @NotNull + private static PluginTransactionValidatorFactory getPluginTransactionValidatorFactoryReturning( + final boolean b) { + final PluginTransactionValidator pluginTransactionValidator = transaction -> b; + return () -> pluginTransactionValidator; + } + private void assertTransactionPending(final Transaction t) { assertThat(transactions.getTransactionByHash(t.getHash())).contains(t); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionsLayeredPendingTransactionsTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionsLayeredPendingTransactionsTest.java index a303a3bb704..3a6c9c8fbf2 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionsLayeredPendingTransactionsTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionsLayeredPendingTransactionsTest.java @@ -200,7 +200,8 @@ protected TransactionPool createTransactionPool( ethContext, miningParameters, new TransactionPoolMetrics(metricsSystem), - poolConfig); + poolConfig, + null); txPool.setEnabled(); return txPool; } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java index 02df9cb177f..6d3eb668f8f 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java @@ -164,7 +164,8 @@ public boolean isMessagePermitted(final EnodeURL destinationEnode, final int cod metricsSystem, syncState, new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), - TransactionPoolConfiguration.DEFAULT); + TransactionPoolConfiguration.DEFAULT, + null); final EthProtocolManager ethProtocolManager = new EthProtocolManager( diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java index fb56be15f8a..3da9bb9c66d 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java @@ -252,7 +252,8 @@ private void setupInitialSyncPhase(final boolean hasInitialSyncPhase) { .build(), peerTransactionTracker, transactionsMessageSender, - newPooledTransactionHashesMessageSender); + newPooledTransactionHashesMessageSender, + null); ethProtocolManager = new EthProtocolManager( @@ -358,7 +359,8 @@ private TransactionPool createTransactionPool( ImmutableTransactionPoolConfiguration.Unstable.builder() .txMessageKeepAliveSeconds(1) .build()) - .build()); + .build(), + null); txPool.setEnabled(); return txPool; diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java index 1f2af463a97..4d29bfd213e 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java @@ -240,7 +240,8 @@ private boolean buildContext( metricsSystem, syncState, new MiningParameters.Builder().minTransactionGasPrice(Wei.ZERO).build(), - transactionPoolConfiguration); + transactionPoolConfiguration, + null); if (LOG.isTraceEnabled()) { LOG.trace("Genesis Block {} ", genesisState.getBlock()); diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index a091f97c151..2aded925ce1 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -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 = 'BhqPyj1fT50NWuHTgzgCmW1ynAPj/2QiGWraq5OwgOQ=' + knownHash = 'yJgCLn/XmaOwyIlpSw/6gbsM5eNNQQs6hmpTMvkezqk=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/PluginTransactionValidatorService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/PluginTransactionValidatorService.java new file mode 100644 index 00000000000..993cbdafe1f --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/PluginTransactionValidatorService.java @@ -0,0 +1,39 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * 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.plugin.services; + +import org.hyperledger.besu.plugin.Unstable; +import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionValidatorFactory; + +/** Transaction validator for addition of transactions to the transaction pool */ +@Unstable +public interface PluginTransactionValidatorService extends BesuService { + + /** + * Returns the transaction validator factory + * + * @return the transaction validator factory + */ + PluginTransactionValidatorFactory get(); + + /** + * Registers the transaction validator factory with the service + * + * @param transactionValidatorFactory transaction validator factory to be used + */ + void registerTransactionValidatorFactory( + PluginTransactionValidatorFactory transactionValidatorFactory); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionValidator.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionValidator.java new file mode 100644 index 00000000000..60f04497199 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionValidator.java @@ -0,0 +1,32 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * 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.plugin.services.txvalidator; + +import org.hyperledger.besu.datatypes.Transaction; +import org.hyperledger.besu.plugin.Unstable; + +/** Interface for the transaction validator */ +@Unstable +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 + */ + boolean validateTransaction(final Transaction transaction); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionValidatorFactory.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionValidatorFactory.java new file mode 100644 index 00000000000..bfbf86bd1be --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionValidatorFactory.java @@ -0,0 +1,30 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * 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.plugin.services.txvalidator; + +import org.hyperledger.besu.plugin.Unstable; + +/** Interface for a factory that creates transaction validators */ +@Unstable +public interface PluginTransactionValidatorFactory { + + /** + * Create a transaction validator + * + * @return the transaction validator + */ + PluginTransactionValidator create(); +}