Add plugin API to select Transactions (#5396)

This API fulfils the basic requirements, but will probably be extended in the near future. 

Signed-off-by: Stefan <stefan.pingel@consensys.net>
Signed-off-by: Stefan Pingel <16143240+pinges@users.noreply.github.com>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
pull/5495/head
Stefan Pingel 2 years ago committed by GitHub
parent f121f12ead
commit 65bcc557e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java
  2. 39
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java
  3. 23
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java
  4. 29
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  5. 30
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  6. 10
      besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java
  7. 10
      besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java
  8. 37
      besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java
  9. 5
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  10. 3
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueDifficultyCalculatorTest.java
  11. 15
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/NodeCanProduceNextBlockTest.java
  12. 3
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java
  13. 2
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java
  14. 3
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueDifficultyValidationRuleTest.java
  15. 3
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRuleTest.java
  16. 18
      consensus/common/src/main/java/org/hyperledger/besu/consensus/common/MigratingProtocolContext.java
  17. 4
      consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingProtocolContextTest.java
  18. 5
      consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCoinbaseValidationRuleTest.java
  19. 11
      consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftCommitSealsValidationRuleTest.java
  20. 12
      consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftValidatorsValidationRuleTest.java
  21. 5
      consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/headervalidationrules/BftVanityDataValidationRuleTest.java
  22. 3
      consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContextBuilder.java
  23. 3
      consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java
  24. 5
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java
  25. 4
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/IbftProtocolScheduleTest.java
  26. 3
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java
  27. 3
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java
  28. 3
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java
  29. 5
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/validation/MessageValidatorTest.java
  30. 3
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java
  31. 3
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java
  32. 3
      consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java
  33. 4
      consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java
  34. 3
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftBlockHeaderValidationRulesetFactoryTest.java
  35. 3
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/QbftProtocolScheduleTest.java
  36. 16
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/headervalidationrules/QbftValidatorsValidationRuleTest.java
  37. 3
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java
  38. 3
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java
  39. 7
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java
  40. 3
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java
  41. 3
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java
  42. 2
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java
  43. 2
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthGetBlockByNumberLatestDesyncIntegrationTest.java
  44. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java
  45. 3
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java
  46. 87
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelector.java
  47. 17
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java
  48. 4
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java
  49. 21
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/ProtocolContext.java
  50. 4
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java
  51. 3
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java
  52. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java
  53. 7
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java
  54. 1
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java
  55. 4
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java
  56. 3
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java
  57. 3
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java
  58. 4
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java
  59. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java
  60. 6
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java
  61. 7
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsTestBase.java
  62. 3
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java
  63. 2
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java
  64. 2
      plugin-api/build.gradle
  65. 26
      plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java
  66. 40
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TransactionSelectionService.java
  67. 39
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelector.java
  68. 30
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/txselection/TransactionSelectorFactory.java

@ -386,7 +386,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
return LOCALHOST;
}
private NodeRequests nodeRequests() {
public NodeRequests nodeRequests() {
Optional<WebSocketService> websocketService = Optional.empty();
if (nodeRequests == null) {
final Web3jService web3jService;

@ -45,7 +45,9 @@ import org.hyperledger.besu.plugin.services.BesuEvents;
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
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.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
@ -54,6 +56,7 @@ import org.hyperledger.besu.services.PicoCLIOptionsImpl;
import org.hyperledger.besu.services.RpcEndpointServiceImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
import java.io.File;
import java.nio.file.Path;
@ -63,6 +66,7 @@ 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;
@ -91,14 +95,22 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
besuPluginContext.addService(StorageService.class, storageService);
besuPluginContext.addService(SecurityModuleService.class, securityModuleService);
besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine));
final Path pluginsPath = node.homeDirectory().resolve("plugins");
final File pluginsDirFile = pluginsPath.toFile();
if (!pluginsDirFile.isDirectory()) {
pluginsDirFile.mkdirs();
pluginsDirFile.deleteOnExit();
besuPluginContext.addService(
TransactionSelectionService.class, new TransactionSelectionServiceImpl());
final Path pluginsPath;
final String pluginDirEnv = System.getenv("besu.plugins.dir");
if (pluginDirEnv == null || pluginDirEnv.isEmpty()) {
pluginsPath = node.homeDirectory().resolve("plugins");
final File pluginsDirFile = pluginsPath.toFile();
if (!pluginsDirFile.isDirectory()) {
pluginsDirFile.mkdirs();
pluginsDirFile.deleteOnExit();
}
} else {
pluginsPath = Path.of(pluginDirEnv);
System.setProperty("besu.plugins.dir", pluginsPath.toString());
}
System.setProperty("besu.plugins.dir", pluginsPath.toString());
besuPluginContext.registerPlugins(pluginsPath);
commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0]));
@ -169,6 +181,9 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
final int maxPeers = 25;
final Optional<TransactionSelectorFactory> transactionSelectorFactory =
getTransactionSelectorFactory(besuPluginContext);
builder
.synchronizerConfiguration(new SynchronizerConfiguration.Builder().build())
.dataDirectory(node.homeDirectory())
@ -190,7 +205,8 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.lowerBoundPeers(maxPeers)
.maxRemotelyInitiatedPeers(15)
.networkConfiguration(node.getNetworkingConfiguration())
.randomPeerPriority(false);
.randomPeerPriority(false)
.transactionSelectorFactory(transactionSelectorFactory);
node.getGenesisConfig()
.map(GenesisConfigFile::fromConfig)
@ -299,4 +315,11 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
public String getConsoleContents() {
throw new RuntimeException("Console contents can only be captured in process execution");
}
private Optional<TransactionSelectorFactory> getTransactionSelectorFactory(
final BesuPluginContextImpl besuPluginContext) {
final Optional<TransactionSelectionService> txSelectionService =
besuPluginContext.getService(TransactionSelectionService.class);
return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty();
}
}

@ -107,10 +107,33 @@ public class BesuNodeFactory {
return create(config);
}
public BesuNode createMinerNodeWithExtraCliOptions(
final String name,
final UnaryOperator<BesuNodeConfigurationBuilder> configModifier,
final List<String> extraCliOptions)
throws IOException {
BesuNodeConfigurationBuilder builder =
new BesuNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcEnabled()
.webSocketEnabled()
.extraCLIOptions(extraCliOptions);
builder = configModifier.apply(builder);
final BesuNodeConfiguration config = builder.build();
return create(config);
}
public BesuNode createMinerNode(final String name) throws IOException {
return createMinerNode(name, UnaryOperator.identity());
}
public BesuNode createMinerNodeWithExtraCliOptions(
final String name, final List<String> extraCliOptions) throws IOException {
return createMinerNodeWithExtraCliOptions(name, UnaryOperator.identity(), extraCliOptions);
}
public BesuNode createMinerNodeWithRevertReasonEnabled(final String name) throws IOException {
return createMinerNode(name, BesuNodeConfigurationBuilder::revertReasonEnabled);
}

@ -167,12 +167,14 @@ 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.TransactionSelectionService;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.metrics.MetricCategory;
import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModule;
import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.BlockchainServiceImpl;
@ -183,6 +185,7 @@ 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.TransactionSelectionServiceImpl;
import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin;
import org.hyperledger.besu.util.InvalidConfigurationException;
import org.hyperledger.besu.util.LogConfigurator;
@ -234,6 +237,7 @@ import io.vertx.core.json.DecodeException;
import io.vertx.core.metrics.MetricsOptions;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import picocli.AutoComplete;
import picocli.CommandLine;
@ -360,6 +364,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
@CommandLine.ArgGroup(validate = false, heading = "@|bold P2P Discovery Options|@%n")
P2PDiscoveryOptionGroup p2PDiscoveryOptionGroup = new P2PDiscoveryOptionGroup();
private final TransactionSelectionServiceImpl transactionSelectionServiceImpl;
static class P2PDiscoveryOptionGroup {
// Public IP stored to prevent having to research it each time we need it.
@ -1380,7 +1386,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
new PermissioningServiceImpl(),
new PrivacyPluginServiceImpl(),
new PkiBlockCreationConfigurationProvider(),
new RpcEndpointServiceImpl());
new RpcEndpointServiceImpl(),
new TransactionSelectionServiceImpl());
}
/**
@ -1400,6 +1407,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
* @param privacyPluginService instance of PrivacyPluginServiceImpl
* @param pkiBlockCreationConfigProvider instance of PkiBlockCreationConfigurationProvider
* @param rpcEndpointServiceImpl instance of RpcEndpointServiceImpl
* @param transactionSelectionServiceImpl instance of TransactionSelectionServiceImpl
*/
@VisibleForTesting
protected BesuCommand(
@ -1416,7 +1424,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final PermissioningServiceImpl permissioningService,
final PrivacyPluginServiceImpl privacyPluginService,
final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider,
final RpcEndpointServiceImpl rpcEndpointServiceImpl) {
final RpcEndpointServiceImpl rpcEndpointServiceImpl,
final TransactionSelectionServiceImpl transactionSelectionServiceImpl) {
this.besuComponent = besuComponent;
this.logger = besuComponent.getBesuCommandLogger();
this.rlpBlockImporter = rlpBlockImporter;
@ -1434,6 +1443,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuPluginContext.addService(BesuConfiguration.class, pluginCommonConfiguration);
this.pkiBlockCreationConfigProvider = pkiBlockCreationConfigProvider;
this.rpcEndpointServiceImpl = rpcEndpointServiceImpl;
this.transactionSelectionServiceImpl = transactionSelectionServiceImpl;
}
/**
@ -1614,6 +1624,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuPluginContext.addService(PermissioningService.class, permissioningService);
besuPluginContext.addService(PrivacyPluginService.class, privacyPluginService);
besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl);
besuPluginContext.addService(
TransactionSelectionService.class, transactionSelectionServiceImpl);
// register built-in plugins
rocksDBPlugin = new RocksDBPlugin();
@ -1715,6 +1727,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuController.getProtocolContext().getWorldStateArchive()),
besuController.getProtocolSchedule()));
besuPluginContext.addService(
TransactionSelectionService.class, new TransactionSelectionServiceImpl());
besuController.getAdditionalPluginServices().appendPluginServices(besuPluginContext);
besuPluginContext.startPlugins();
}
@ -2241,12 +2256,15 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
*/
public BesuControllerBuilder getControllerBuilder() {
final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName);
final Optional<TransactionSelectorFactory> transactionSelectorFactory =
getTransactionSelectorFactory();
return controllerBuilderFactory
.fromEthNetworkConfig(
updateNetworkConfig(network), genesisConfigOverrides, getDefaultSyncModeIfNotSet())
.synchronizerConfiguration(buildSyncConfig())
.ethProtocolConfiguration(unstableEthProtocolOptions.toDomainObject())
.networkConfiguration(unstableNetworkingOptions.toDomainObject())
.transactionSelectorFactory(transactionSelectorFactory)
.dataDirectory(dataDir())
.miningParameters(
new MiningParameters.Builder()
@ -2296,6 +2314,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.chainPruningConfiguration(unstableChainPruningOptions.toDomainObject());
}
@NotNull
private Optional<TransactionSelectorFactory> getTransactionSelectorFactory() {
final Optional<TransactionSelectionService> txSelectionService =
besuPluginContext.getService(TransactionSelectionService.class);
return txSelectionService.isPresent() ? txSelectionService.get().get() : Optional.empty();
}
private GraphQLConfiguration graphQLConfiguration() {
CommandLineUtils.checkOptionDependencies(

@ -94,6 +94,7 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import java.io.Closeable;
import java.math.BigInteger;
@ -179,6 +180,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
private NetworkingConfiguration networkingConfiguration;
private Boolean randomPeerPriority;
private Optional<TransactionSelectorFactory> transactionSelectorFactory = Optional.empty();
/** the Dagger configured context that can provide dependencies */
protected Optional<BesuComponent> besuComponent = Optional.empty();
@ -522,6 +524,18 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
return this;
}
/**
* sets the transactionSelectorFactory in the builder
*
* @param transactionSelectorFactory the optional transaction selector factory
* @return the besu controller builder
*/
public BesuControllerBuilder transactionSelectorFactory(
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
this.transactionSelectorFactory = transactionSelectorFactory;
return this;
}
/**
* Build besu controller.
*
@ -575,7 +589,11 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
final ProtocolContext protocolContext =
createProtocolContext(
blockchain, worldStateArchive, protocolSchedule, this::createConsensusContext);
blockchain,
worldStateArchive,
protocolSchedule,
this::createConsensusContext,
transactionSelectorFactory);
validateContext(protocolContext);
if (chainPrunerConfiguration.getChainPruningEnabled()) {
@ -991,15 +1009,21 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
* @param worldStateArchive the world state archive
* @param protocolSchedule the protocol schedule
* @param consensusContextFactory the consensus context factory
* @param transactionSelectorFactory optional transaction selector factory
* @return the protocol context
*/
protected ProtocolContext createProtocolContext(
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory) {
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
return ProtocolContext.init(
blockchain, worldStateArchive, protocolSchedule, consensusContextFactory);
blockchain,
worldStateArchive,
protocolSchedule,
consensusContextFactory,
transactionSelectorFactory);
}
private Optional<SnapProtocolManager> createSnapProtocolManager(

@ -62,6 +62,7 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import java.math.BigInteger;
import java.nio.file.Path;
@ -174,9 +175,14 @@ public class ConsensusScheduleBesuControllerBuilder extends BesuControllerBuilde
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory) {
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
return MigratingProtocolContext.init(
blockchain, worldStateArchive, protocolSchedule, consensusContextFactory);
blockchain,
worldStateArchive,
protocolSchedule,
consensusContextFactory,
transactionSelectorFactory);
}
@Override

@ -60,6 +60,7 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import java.math.BigInteger;
import java.nio.file.Path;
@ -188,10 +189,15 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory) {
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final ProtocolContext protocolContext =
super.createProtocolContext(
blockchain, worldStateArchive, protocolSchedule, consensusContextFactory);
blockchain,
worldStateArchive,
protocolSchedule,
consensusContextFactory,
transactionSelectorFactory);
transitionProtocolSchedule.setProtocolContext(protocolContext);
return protocolContext;
}

@ -0,0 +1,37 @@
/*
* 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.TransactionSelectionService;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import java.util.Optional;
/** The Transaction Selection service implementation. */
public class TransactionSelectionServiceImpl implements TransactionSelectionService {
private Optional<TransactionSelectorFactory> factory = Optional.empty();
@Override
public Optional<TransactionSelectorFactory> get() {
return factory;
}
@Override
public void registerTransactionSelectorFactory(
final TransactionSelectorFactory transactionSelectorFactory) {
factory = Optional.ofNullable(transactionSelectorFactory);
}
}

@ -79,6 +79,7 @@ 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.TransactionSelectionServiceImpl;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
import java.io.ByteArrayOutputStream;
@ -237,6 +238,7 @@ public abstract class CommandTestAbstract {
when(mockControllerBuilder.lowerBoundPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxRemotelyInitiatedPeers(anyInt()))
.thenReturn(mockControllerBuilder);
when(mockControllerBuilder.transactionSelectorFactory(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.besuComponent(any(BesuComponent.class)))
.thenReturn(mockControllerBuilder);
// doReturn used because of generic BesuController
@ -484,7 +486,8 @@ public abstract class CommandTestAbstract {
new PermissioningServiceImpl(),
privacyPluginService,
pkiBlockCreationConfigProvider,
rpcEndpointServiceImpl);
rpcEndpointServiceImpl,
new TransactionSelectionServiceImpl());
}
@Override

@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.core.Util;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.BeforeEach;
@ -57,7 +58,7 @@ public class CliqueDifficultyCalculatorTest {
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext, Optional.empty());
blockHeaderBuilder = new BlockHeaderTestFixture();
}

@ -37,6 +37,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Util;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.BeforeEach;
@ -79,7 +80,7 @@ public class NodeCanProduceNextBlockTest {
final ValidatorProvider validatorProvider = mock(ValidatorProvider.class);
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty());
headerBuilder.number(1).parentHash(genesisBlock.getHash());
final Block block_1 = createEmptyBlock(proposerKeyPair);
@ -103,7 +104,7 @@ public class NodeCanProduceNextBlockTest {
final ValidatorProvider validatorProvider = mock(ValidatorProvider.class);
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty());
headerBuilder.number(1).parentHash(genesisBlock.getHash());
final Block block_1 = createEmptyBlock(proposerKeyPair);
@ -136,7 +137,7 @@ public class NodeCanProduceNextBlockTest {
final ValidatorProvider validatorProvider = mock(ValidatorProvider.class);
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty());
headerBuilder.parentHash(genesisBlock.getHash()).number(1);
final Block block_1 = createEmptyBlock(proposerKeyPair);
@ -165,7 +166,7 @@ public class NodeCanProduceNextBlockTest {
final ValidatorProvider validatorProvider = mock(ValidatorProvider.class);
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty());
headerBuilder.parentHash(genesisBlock.getHash()).number(1);
final Block block_1 = createEmptyBlock(proposerKeyPair);
@ -209,7 +210,7 @@ public class NodeCanProduceNextBlockTest {
final ValidatorProvider validatorProvider = mock(ValidatorProvider.class);
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty());
headerBuilder.parentHash(genesisBlock.getHash()).number(1);
final Block block_1 = createEmptyBlock(otherNodeKeyPair);
@ -237,7 +238,7 @@ public class NodeCanProduceNextBlockTest {
final ValidatorProvider validatorProvider = mock(ValidatorProvider.class);
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty());
headerBuilder.parentHash(Hash.ZERO).number(3);
final BlockHeader parentHeader =
@ -260,7 +261,7 @@ public class NodeCanProduceNextBlockTest {
final ValidatorProvider validatorProvider = mock(ValidatorProvider.class);
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(blockChain, null, cliqueContext, Optional.empty());
headerBuilder.parentHash(Hash.ZERO).number(3);
final BlockHeader parentHeader = headerBuilder.buildHeader();

@ -105,7 +105,8 @@ public class CliqueBlockCreatorTest {
final Block genesis =
GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule).getBlock();
blockchain = createInMemoryBlockchain(genesis);
protocolContext = new ProtocolContext(blockchain, stateArchive, cliqueContext);
protocolContext =
new ProtocolContext(blockchain, stateArchive, cliqueContext, Optional.empty());
epochManager = new EpochManager(10);
// Add a block above the genesis

@ -81,7 +81,7 @@ public class CliqueMinerExecutorTest {
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext, Optional.empty());
blockHeaderBuilder = new BlockHeaderTestFixture();
}

@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Util;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.BeforeEach;
@ -57,7 +58,7 @@ public class CliqueDifficultyValidationRuleTest {
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext, Optional.empty());
blockHeaderBuilder = new BlockHeaderTestFixture();
}

@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Util;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes;
@ -61,7 +62,7 @@ public class CliqueExtraDataValidationRuleTest {
when(validatorProvider.getValidatorsAfterBlock(any())).thenReturn(validatorList);
final CliqueContext cliqueContext = new CliqueContext(validatorProvider, null, blockInterface);
cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext);
cliqueProtocolContext = new ProtocolContext(null, null, cliqueContext, Optional.empty());
}
@Test

@ -20,6 +20,9 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import java.util.Optional;
/** The Migrating protocol context. */
public class MigratingProtocolContext extends ProtocolContext {
@ -32,12 +35,14 @@ public class MigratingProtocolContext extends ProtocolContext {
* @param blockchain the blockchain
* @param worldStateArchive the world state archive
* @param consensusContextSchedule the consensus context schedule
* @param transactionSelectorFactory the optional transaction selector factory
*/
public MigratingProtocolContext(
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ForksSchedule<ConsensusContext> consensusContextSchedule) {
super(blockchain, worldStateArchive, null);
final ForksSchedule<ConsensusContext> consensusContextSchedule,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
super(blockchain, worldStateArchive, null, transactionSelectorFactory);
this.consensusContextSchedule = consensusContextSchedule;
}
@ -48,18 +53,23 @@ public class MigratingProtocolContext extends ProtocolContext {
* @param worldStateArchive the world state archive
* @param protocolSchedule the protocol schedule
* @param consensusContextFactory the consensus context factory
* @param transactionSelectorFactory the optional transaction selector factory
* @return the protocol context
*/
public static ProtocolContext init(
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory) {
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
final ConsensusContext consensusContext =
consensusContextFactory.create(blockchain, worldStateArchive, protocolSchedule);
final MigratingContext migratingContext = consensusContext.as(MigratingContext.class);
return new MigratingProtocolContext(
blockchain, worldStateArchive, migratingContext.getConsensusContextSchedule());
blockchain,
worldStateArchive,
migratingContext.getConsensusContextSchedule(),
transactionSelectorFactory);
}
@Override

@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
import org.mockito.Mockito;
@ -43,7 +44,8 @@ public class MigratingProtocolContextTest {
final ForksSchedule<ConsensusContext> contextSchedule =
new ForksSchedule<>(List.of(new ForkSpec<>(0L, context1), new ForkSpec<>(10L, context2)));
final MigratingProtocolContext migratingProtocolContext =
new MigratingProtocolContext(blockchain, worldStateArchive, contextSchedule);
new MigratingProtocolContext(
blockchain, worldStateArchive, contextSchedule, Optional.empty());
assertThat(migratingProtocolContext.getConsensusContext(ConsensusContext.class))
.isSameAs(context1);

@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Util;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
import org.junit.Test;
@ -50,7 +51,7 @@ public class BftCoinbaseValidationRuleTest {
final List<Address> validators = Lists.newArrayList(proposerAddress);
final ProtocolContext context =
new ProtocolContext(null, null, setupContextWithValidators(validators));
new ProtocolContext(null, null, setupContextWithValidators(validators), Optional.empty());
final BftCoinbaseValidationRule coinbaseValidationRule = new BftCoinbaseValidationRule();
@ -70,7 +71,7 @@ public class BftCoinbaseValidationRuleTest {
final List<Address> validators = Lists.newArrayList(otherValidatorNodeAddress);
final ProtocolContext context =
new ProtocolContext(null, null, setupContextWithValidators(validators));
new ProtocolContext(null, null, setupContextWithValidators(validators), Optional.empty());
final BftCoinbaseValidationRule coinbaseValidationRule = new BftCoinbaseValidationRule();

@ -33,6 +33,7 @@ import org.hyperledger.besu.ethereum.core.Util;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@ -57,7 +58,7 @@ public class BftCommitSealsValidationRuleTest {
.collect(Collectors.toList());
final BftContext bftContext = setupContextWithValidators(committerAddresses);
final ProtocolContext context = new ProtocolContext(null, null, bftContext);
final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty());
when(bftContext.getBlockInterface().getCommitters(any())).thenReturn(committerAddresses);
assertThat(commitSealsValidationRule.validate(blockHeader, null, context)).isTrue();
@ -71,7 +72,7 @@ public class BftCommitSealsValidationRuleTest {
final List<Address> validators = singletonList(committerAddress);
final BftContext bftContext = setupContextWithValidators(validators);
final ProtocolContext context = new ProtocolContext(null, null, bftContext);
final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty());
when(bftContext.getBlockInterface().getCommitters(any())).thenReturn(emptyList());
assertThat(commitSealsValidationRule.validate(blockHeader, null, context)).isFalse();
@ -88,7 +89,7 @@ public class BftCommitSealsValidationRuleTest {
final NodeKey nonValidatorNodeKey = NodeKeyUtils.generate();
final BftContext bftContext = setupContextWithValidators(validators);
final ProtocolContext context = new ProtocolContext(null, null, bftContext);
final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty());
when(bftContext.getBlockInterface().getCommitters(any()))
.thenReturn(singletonList(Util.publicKeyToAddress(nonValidatorNodeKey.getPublicKey())));
@ -135,7 +136,7 @@ public class BftCommitSealsValidationRuleTest {
final List<Address> validators = singletonList(committerAddress);
final BftContext bftContext = setupContextWithValidators(validators);
final ProtocolContext context = new ProtocolContext(null, null, bftContext);
final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty());
when(bftContext.getBlockInterface().getCommitters(any()))
.thenReturn(List.of(committerAddress, committerAddress));
@ -154,7 +155,7 @@ public class BftCommitSealsValidationRuleTest {
Collections.sort(validators);
final BftContext bftContext = setupContextWithValidators(validators);
final ProtocolContext context = new ProtocolContext(null, null, bftContext);
final ProtocolContext context = new ProtocolContext(null, null, bftContext, Optional.empty());
when(bftContext.getBlockInterface().getCommitters(any()))
.thenReturn(validators.subList(0, committerCount));

@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
import org.junit.Test;
@ -44,7 +45,8 @@ public class BftValidatorsValidationRuleTest {
AddressHelpers.ofValue(1), AddressHelpers.ofValue(2), AddressHelpers.ofValue(3));
final ProtocolContext context =
new ProtocolContext(null, null, setupContextWithBftExtraData(validators, bftExtraData));
new ProtocolContext(
null, null, setupContextWithBftExtraData(validators, bftExtraData), Optional.empty());
when(bftExtraData.getValidators()).thenReturn(validators);
assertThat(validatorsValidationRule.validate(blockHeader, null, context)).isTrue();
@ -58,7 +60,8 @@ public class BftValidatorsValidationRuleTest {
AddressHelpers.ofValue(1), AddressHelpers.ofValue(2), AddressHelpers.ofValue(3));
final ProtocolContext context =
new ProtocolContext(null, null, setupContextWithBftExtraData(validators, bftExtraData));
new ProtocolContext(
null, null, setupContextWithBftExtraData(validators, bftExtraData), Optional.empty());
when(bftExtraData.getValidators()).thenReturn(Lists.reverse(validators));
assertThat(validatorsValidationRule.validate(blockHeader, null, context)).isFalse();
@ -76,7 +79,10 @@ public class BftValidatorsValidationRuleTest {
final ProtocolContext context =
new ProtocolContext(
null, null, setupContextWithBftExtraData(storedValidators, bftExtraData));
null,
null,
setupContextWithBftExtraData(storedValidators, bftExtraData),
Optional.empty());
when(bftExtraData.getValidators()).thenReturn(Lists.reverse(reportedValidators));
assertThat(validatorsValidationRule.validate(blockHeader, null, context)).isFalse();

@ -24,6 +24,8 @@ import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
@ -44,7 +46,8 @@ public class BftVanityDataValidationRuleTest {
new BftExtraData(Bytes.wrap(new byte[extraDataSize]), emptyList(), empty(), 0, emptyList());
final ProtocolContext context =
new ProtocolContext(null, null, setupContextWithBftExtraData(emptyList(), extraData));
new ProtocolContext(
null, null, setupContextWithBftExtraData(emptyList(), extraData), Optional.empty());
return validationRule.validate(blockHeader, null, context);
}
}

@ -328,7 +328,8 @@ public class TestContextBuilder {
new ProtocolContext(
blockChain,
worldStateArchive,
new BftContext(validatorProvider, epochManager, blockInterface));
new BftContext(validatorProvider, epochManager, blockInterface),
Optional.empty());
final GasPricePendingTransactionsSorter pendingTransactions =
new GasPricePendingTransactionsSorter(

@ -118,7 +118,8 @@ public class IbftRoundIntegrationTest {
new ProtocolContext(
blockChain,
worldStateArchive,
setupContextWithBftExtraDataEncoder(emptyList(), bftExtraDataEncoder));
setupContextWithBftExtraDataEncoder(emptyList(), bftExtraDataEncoder),
Optional.empty());
}
@Test

@ -48,7 +48,10 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
private ProtocolContext protocolContext(final Collection<Address> validators) {
return new ProtocolContext(
null, null, setupContextWithBftExtraDataEncoder(validators, new IbftExtraDataCodec()));
null,
null,
setupContextWithBftExtraDataEncoder(validators, new IbftExtraDataCodec()),
Optional.empty());
}
@Test

@ -47,6 +47,7 @@ import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
@ -119,6 +120,7 @@ public class IbftProtocolScheduleTest {
return new ProtocolContext(
null,
null,
setupContextWithBftExtraDataEncoder(BftContext.class, validators, bftExtraDataCodec));
setupContextWithBftExtraDataEncoder(BftContext.class, validators, bftExtraDataCodec),
Optional.empty());
}
}

@ -113,7 +113,8 @@ public class BftBlockCreatorTest {
new ProtocolContext(
blockchain,
createInMemoryWorldStateArchive(),
setupContextWithBftExtraDataEncoder(initialValidatorList, bftExtraDataEncoder));
setupContextWithBftExtraDataEncoder(initialValidatorList, bftExtraDataEncoder),
Optional.empty());
final GasPricePendingTransactionsSorter pendingTransactions =
new GasPricePendingTransactionsSorter(

@ -151,7 +151,8 @@ public class IbftBlockHeightManagerTest {
.thenReturn(futureRoundProposalMessageValidator);
when(messageValidatorFactory.createMessageValidator(any(), any())).thenReturn(messageValidator);
protocolContext = new ProtocolContext(null, null, setupContextWithValidators(validators));
protocolContext =
new ProtocolContext(null, null, setupContextWithValidators(validators), Optional.empty());
// Ensure the created IbftRound has the valid ConsensusRoundIdentifier;
when(roundFactory.createNewRound(any(), anyInt()))

@ -106,7 +106,8 @@ public class IbftRoundTest {
new ProtocolContext(
blockChain,
worldStateArchive,
setupContextWithBftExtraDataEncoder(emptyList(), new IbftExtraDataCodec()));
setupContextWithBftExtraDataEncoder(emptyList(), new IbftExtraDataCodec()),
Optional.empty());
when(messageValidator.validateProposal(any())).thenReturn(true);
when(messageValidator.validatePrepare(any())).thenReturn(true);

@ -95,7 +95,10 @@ public class MessageValidatorTest {
protocolContext =
new ProtocolContext(
mock(MutableBlockchain.class), mock(WorldStateArchive.class), mockBftCtx);
mock(MutableBlockchain.class),
mock(WorldStateArchive.class),
mockBftCtx,
Optional.empty());
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));

@ -183,7 +183,8 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
.when(protocolSchedule)
.getByBlockHeader(any(BlockHeader.class));
protocolContext = new ProtocolContext(blockchain, worldStateArchive, mergeContext);
protocolContext =
new ProtocolContext(blockchain, worldStateArchive, mergeContext, Optional.empty());
var mutable = worldStateArchive.getMutable();
genesisState.writeStateTo(mutable);
mutable.persist(null);

@ -45,6 +45,7 @@ import org.hyperledger.besu.util.LogConfigurator;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.junit.Before;
@ -69,7 +70,7 @@ public class MergeReorgTest implements MergeGenesisConfigHelper {
private final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock());
private final ProtocolContext protocolContext =
new ProtocolContext(blockchain, worldStateArchive, mergeContext);
new ProtocolContext(blockchain, worldStateArchive, mergeContext, Optional.empty());
private final Address coinbase = genesisAllocations(getPowGenesisConfigFile()).findFirst().get();
private final BlockHeaderTestFixture headerGenerator = new BlockHeaderTestFixture();

@ -456,7 +456,8 @@ public class TestContextBuilder {
new ProtocolContext(
blockChain,
worldStateArchive,
new QbftContext(validatorProvider, epochManager, blockInterface, Optional.empty()));
new QbftContext(validatorProvider, epochManager, blockInterface, Optional.empty()),
Optional.empty());
final GasPricePendingTransactionsSorter pendingTransactions =
new GasPricePendingTransactionsSorter(

@ -55,6 +55,7 @@ import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleExcepti
import org.hyperledger.besu.util.Subscribers;
import java.math.BigInteger;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
@ -121,7 +122,8 @@ public class QbftRoundIntegrationTest {
blockChain,
worldStateArchive,
setupContextWithBftExtraDataEncoder(
QbftContext.class, emptyList(), qbftExtraDataEncoder));
QbftContext.class, emptyList(), qbftExtraDataEncoder),
Optional.empty());
}
@Test

@ -45,7 +45,8 @@ public class QbftBlockHeaderValidationRulesetFactoryTest {
null,
null,
setupContextWithBftExtraDataEncoder(
QbftContext.class, validators, new QbftExtraDataCodec()));
QbftContext.class, validators, new QbftExtraDataCodec()),
Optional.empty());
}
@Test

@ -57,7 +57,8 @@ public class QbftProtocolScheduleTest {
null,
null,
setupContextWithBftExtraDataEncoder(
QbftContext.class, validators, new QbftExtraDataCodec()));
QbftContext.class, validators, new QbftExtraDataCodec()),
Optional.empty());
}
@Test

@ -46,7 +46,8 @@ public class QbftValidatorsValidationRuleTest {
new ProtocolContext(
null,
null,
setupContextWithBftExtraData(QbftContext.class, Collections.emptyList(), bftExtraData));
setupContextWithBftExtraData(QbftContext.class, Collections.emptyList(), bftExtraData),
Optional.empty());
when(bftExtraData.getValidators()).thenReturn(Collections.emptyList());
when(bftExtraData.getVote()).thenReturn(Optional.empty());
assertThat(qbftValidatorsValidationRule.validate(blockHeader, null, context)).isTrue();
@ -62,7 +63,10 @@ public class QbftValidatorsValidationRuleTest {
final ProtocolContext context =
new ProtocolContext(
null, null, setupContextWithBftExtraData(QbftContext.class, validators, bftExtraData));
null,
null,
setupContextWithBftExtraData(QbftContext.class, validators, bftExtraData),
Optional.empty());
when(bftExtraData.getValidators()).thenReturn(validators);
assertThat(qbftValidatorsValidationRule.validate(blockHeader, null, context)).isTrue();
}
@ -77,7 +81,10 @@ public class QbftValidatorsValidationRuleTest {
final ProtocolContext context =
new ProtocolContext(
null, null, setupContextWithBftExtraData(QbftContext.class, validators, bftExtraData));
null,
null,
setupContextWithBftExtraData(QbftContext.class, validators, bftExtraData),
Optional.empty());
when(bftExtraData.getValidators()).thenReturn(validators);
assertThat(qbftValidatorsValidationRule.validate(blockHeader, null, context)).isFalse();
}
@ -90,7 +97,8 @@ public class QbftValidatorsValidationRuleTest {
new ProtocolContext(
null,
null,
setupContextWithBftExtraData(QbftContext.class, Collections.emptyList(), bftExtraData));
setupContextWithBftExtraData(QbftContext.class, Collections.emptyList(), bftExtraData),
Optional.empty());
when(bftExtraData.getValidators()).thenReturn(Collections.emptyList());
when(bftExtraData.getVote()).thenReturn(Optional.of(mock(Vote.class)));
assertThat(qbftValidatorsValidationRule.validate(blockHeader, null, context)).isFalse();

@ -157,7 +157,8 @@ public class QbftBlockHeightManagerTest {
null,
null,
setupContextWithBftExtraDataEncoder(
QbftContext.class, validators, new QbftExtraDataCodec()));
QbftContext.class, validators, new QbftExtraDataCodec()),
Optional.empty());
// Ensure the created QbftRound has the valid ConsensusRoundIdentifier;
when(roundFactory.createNewRound(any(), anyInt()))

@ -114,7 +114,8 @@ public class QbftRoundTest {
blockChain,
worldStateArchive,
setupContextWithBftExtraDataEncoder(
QbftContext.class, emptyList(), new QbftExtraDataCodec()));
QbftContext.class, emptyList(), new QbftExtraDataCodec()),
Optional.empty());
when(messageValidator.validateProposal(any())).thenReturn(true);
when(messageValidator.validatePrepare(any())).thenReturn(true);

@ -86,7 +86,8 @@ public class ProposalPayloadValidatorTest {
new ProtocolContext(
blockChain,
worldStateArchive,
setupContextWithBftExtraDataEncoder(QbftContext.class, emptyList(), bftExtraDataCodec));
setupContextWithBftExtraDataEncoder(QbftContext.class, emptyList(), bftExtraDataCodec),
Optional.empty());
}
@Test
@ -239,7 +240,7 @@ public class ProposalPayloadValidatorTest {
setupContextWithBftExtraDataEncoder(QbftContext.class, emptyList(), pkiQbftExtraDataCodec);
final Bytes cms = Bytes.fromHexStringLenient("0x1");
final ProtocolContext protocolContext =
new ProtocolContext(blockChain, worldStateArchive, qbftContext);
new ProtocolContext(blockChain, worldStateArchive, qbftContext, Optional.empty());
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(
@ -274,7 +275,7 @@ public class ProposalPayloadValidatorTest {
setupContextWithBftExtraDataEncoder(QbftContext.class, emptyList(), pkiQbftExtraDataCodec);
final Bytes cms = Bytes.fromHexStringLenient("0x1");
final ProtocolContext protocolContext =
new ProtocolContext(blockChain, worldStateArchive, qbftContext);
new ProtocolContext(blockChain, worldStateArchive, qbftContext, Optional.empty());
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(

@ -97,7 +97,8 @@ public class ProposalValidatorTest {
blockChain,
worldStateArchive,
setupContextWithBftExtraDataEncoder(
QbftContext.class, emptyList(), bftExtraDataEncoder));
QbftContext.class, emptyList(), bftExtraDataEncoder),
Optional.empty());
// typically tests require the blockValidation to be successful
when(blockValidator.validateAndProcessBlock(

@ -81,7 +81,8 @@ public class RoundChangeMessageValidatorTest {
blockChain,
worldStateArchive,
setupContextWithBftExtraDataEncoder(
QbftContext.class, emptyList(), bftExtraDataEncoder));
QbftContext.class, emptyList(), bftExtraDataEncoder),
Optional.empty());
}
@Test

@ -76,7 +76,7 @@ public class JsonRpcTestMethodsFactory {
this.blockchain = createInMemoryBlockchain(importer.getGenesisBlock());
this.stateArchive = createInMemoryWorldStateArchive();
this.importer.getGenesisState().writeStateTo(stateArchive.getMutable());
this.context = new ProtocolContext(blockchain, stateArchive, null);
this.context = new ProtocolContext(blockchain, stateArchive, null, Optional.empty());
final ProtocolSchedule protocolSchedule = importer.getProtocolSchedule();
this.synchronizer = mock(Synchronizer.class);

@ -67,7 +67,7 @@ public class EthGetBlockByNumberLatestDesyncIntegrationTest {
InMemoryKeyValueStorageProvider.createInMemoryBlockchain(importer.getGenesisBlock());
WorldStateArchive state = InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive();
importer.getGenesisState().writeStateTo(state.getMutable());
ProtocolContext context = new ProtocolContext(chain, state, null);
ProtocolContext context = new ProtocolContext(chain, state, null, Optional.empty());
for (final Block block : importer.getBlocks()) {
final ProtocolSchedule protocolSchedule = importer.getProtocolSchedule();

@ -156,7 +156,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
final MutableBlockchain blockchain =
InMemoryKeyValueStorageProvider.createInMemoryBlockchain(GENESIS_BLOCK);
context = new ProtocolContext(blockchain, stateArchive, null);
context = new ProtocolContext(blockchain, stateArchive, null, Optional.empty());
final BlockchainQueries blockchainQueries =
new BlockchainQueries(
context.getBlockchain(),

@ -304,7 +304,8 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
dataGasPrice,
protocolSpec.getFeeMarket(),
protocolSpec.getGasCalculator(),
protocolSpec.getGasLimitCalculator());
protocolSpec.getGasLimitCalculator(),
protocolContext.getTransactionSelectorFactory());
if (transactions.isPresent()) {
return selector.evaluateTransactions(transactions.get());

@ -23,7 +23,6 @@ import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult;
import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
@ -35,13 +34,17 @@ import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelector;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@ -71,6 +74,7 @@ import org.slf4j.LoggerFactory;
* not cleared between executions of buildTransactionListForBlock().
*/
public class BlockTransactionSelector {
public static class TransactionValidationResult {
private final Transaction transaction;
private final ValidationResult<TransactionInvalidReason> validationResult;
@ -218,8 +222,9 @@ public class BlockTransactionSelector {
private final FeeMarket feeMarket;
private final GasCalculator gasCalculator;
private final GasLimitCalculator gasLimitCalculator;
private final TransactionSelector transactionSelector;
private final TransactionSelectionResults transactionSelectionResult =
private final TransactionSelectionResults transactionSelectionResults =
new TransactionSelectionResults();
public BlockTransactionSelector(
@ -236,7 +241,8 @@ public class BlockTransactionSelector {
final Wei dataGasPrice,
final FeeMarket feeMarket,
final GasCalculator gasCalculator,
final GasLimitCalculator gasLimitCalculator) {
final GasLimitCalculator gasLimitCalculator,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
this.transactionProcessor = transactionProcessor;
this.blockchain = blockchain;
this.worldState = worldState;
@ -251,6 +257,10 @@ public class BlockTransactionSelector {
this.feeMarket = feeMarket;
this.gasCalculator = gasCalculator;
this.gasLimitCalculator = gasLimitCalculator;
this.transactionSelector =
transactionSelectorFactory.isPresent()
? transactionSelectorFactory.get().create()
: new TransactionSelector() {};
}
/*
@ -268,9 +278,9 @@ public class BlockTransactionSelector {
pendingTransaction -> evaluateTransaction(pendingTransaction, false));
LOG.atTrace()
.setMessage("Transaction selection result result {}")
.addArgument(transactionSelectionResult::toTraceLog)
.addArgument(transactionSelectionResults::toTraceLog)
.log();
return transactionSelectionResult;
return transactionSelectionResults;
}
/**
@ -281,7 +291,7 @@ public class BlockTransactionSelector {
*/
public TransactionSelectionResults evaluateTransactions(final List<Transaction> transactions) {
transactions.forEach(transaction -> evaluateTransaction(transaction, true));
return transactionSelectionResult;
return transactionSelectionResults;
}
/*
@ -336,22 +346,43 @@ public class BlockTransactionSelector {
dataGasPrice);
if (!effectiveResult.isInvalid()) {
worldStateUpdater.commit();
LOG.atTrace()
.setMessage("Selected {} for block creation")
.addArgument(transaction::toTraceLog)
.log();
updateTransactionResultTracking(transaction, effectiveResult);
final long gasUsedByTransaction =
transaction.getGasLimit() - effectiveResult.getGasRemaining();
final long cumulativeGasUsed =
transactionSelectionResults.getCumulativeGasUsed() + gasUsedByTransaction;
final TransactionReceipt receipt =
transactionReceiptFactory.create(
transaction.getType(), effectiveResult, worldState, cumulativeGasUsed);
final TransactionSelectionResult transactionSelectionResult =
transactionSelector.selectTransaction(transaction, receipt);
if (transactionSelectionResult == TransactionSelectionResult.CONTINUE) {
final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount());
transactionSelectionResults.update(transaction, receipt, gasUsedByTransaction, dataGasUsed);
worldStateUpdater.commit();
LOG.atTrace()
.setMessage("Selected {} for block creation")
.addArgument(transaction::toTraceLog)
.log();
}
return transactionSelectionResult;
} else {
final boolean isIncorrectNonce = isIncorrectNonce(effectiveResult.getValidationResult());
if (!isIncorrectNonce || reportFutureNonceTransactionsAsInvalid) {
transactionSelectionResult.updateWithInvalidTransaction(
transactionSelectionResults.updateWithInvalidTransaction(
transaction, effectiveResult.getValidationResult());
}
return transactionSelectionResultForInvalidResult(
transaction, effectiveResult.getValidationResult());
}
return TransactionSelectionResult.CONTINUE;
}
private boolean transactionDataPriceBelowMin(final Transaction transaction) {
@ -418,28 +449,6 @@ public class BlockTransactionSelector {
|| invalidReason.equals(TransactionInvalidReason.NONCE_TOO_HIGH);
}
/*
Responsible for updating the state maintained between transaction validation (i.e. receipts,
cumulative gas, world state root hash.).
*/
private void updateTransactionResultTracking(
final Transaction transaction, final TransactionProcessingResult result) {
final long gasUsedByTransaction = transaction.getGasLimit() - result.getGasRemaining();
final long cumulativeGasUsed =
transactionSelectionResult.getCumulativeGasUsed() + gasUsedByTransaction;
final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount());
transactionSelectionResult.update(
transaction,
transactionReceiptFactory.create(
transaction.getType(), result, worldState, cumulativeGasUsed),
gasUsedByTransaction,
dataGasUsed);
}
private boolean isIncorrectNonce(final ValidationResult<TransactionInvalidReason> result) {
return result.getInvalidReason().equals(TransactionInvalidReason.NONCE_TOO_HIGH);
}
@ -449,17 +458,17 @@ public class BlockTransactionSelector {
if (dataGasUsed
> gasLimitCalculator.currentDataGasLimit()
- transactionSelectionResult.getCumulativeDataGasUsed()) {
- transactionSelectionResults.getCumulativeDataGasUsed()) {
return true;
}
return transaction.getGasLimit() + dataGasUsed
> processableBlockHeader.getGasLimit() - transactionSelectionResult.getCumulativeGasUsed();
> processableBlockHeader.getGasLimit() - transactionSelectionResults.getCumulativeGasUsed();
}
private boolean blockOccupancyAboveThreshold() {
final double gasAvailable = processableBlockHeader.getGasLimit();
final double gasUsed = transactionSelectionResult.getCumulativeGasUsed();
final double gasUsed = transactionSelectionResults.getCumulativeGasUsed();
final double occupancyRatio = gasUsed / gasAvailable;
LOG.trace(
"Min block occupancy ratio {}, gas used {}, available {}, used/available {}",

@ -56,8 +56,10 @@ import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.worldstate.WorldState;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelector;
import org.hyperledger.besu.testutil.TestClock;
import java.math.BigInteger;
@ -80,6 +82,15 @@ import org.mockito.junit.MockitoJUnitRunner;
public abstract class AbstractBlockTransactionSelectorTest {
protected static final KeyPair keyPair =
SignatureAlgorithmFactory.getInstance().generateKeyPair();
public static final TransactionSelector DO_NOTHING_TRANSACTION_SELECTOR =
new TransactionSelector() {
@Override
public TransactionSelectionResult selectTransaction(
final org.hyperledger.besu.plugin.data.Transaction transaction,
final org.hyperledger.besu.plugin.data.TransactionReceipt receipt) {
return TransactionSelectionResult.CONTINUE;
}
};
protected final MetricsSystem metricsSystem = new NoOpMetricsSystem();
protected final Blockchain blockchain = new ReferenceTestBlockchain();
@ -262,7 +273,8 @@ public abstract class AbstractBlockTransactionSelectorTest {
Wei.ZERO,
FeeMarket.london(0L),
new LondonGasCalculator(),
GasLimitCalculator.constant());
GasLimitCalculator.constant(),
Optional.empty());
// this should fill up all the block space
final Transaction fillingLegacyTx =
@ -467,7 +479,8 @@ public abstract class AbstractBlockTransactionSelectorTest {
dataGasPrice,
getFeeMarket(),
new LondonGasCalculator(),
GasLimitCalculator.constant());
GasLimitCalculator.constant(),
Optional.empty());
return selector;
}

@ -54,7 +54,7 @@ public class BlockMinerTest {
new Block(
headerBuilder.buildHeader(), new BlockBody(Lists.newArrayList(), Lists.newArrayList()));
final ProtocolContext protocolContext = new ProtocolContext(null, null, null);
final ProtocolContext protocolContext = new ProtocolContext(null, null, null, Optional.empty());
final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class);
final Function<BlockHeader, PoWBlockCreator> blockCreatorSupplier =
@ -95,7 +95,7 @@ public class BlockMinerTest {
new Block(
headerBuilder.buildHeader(), new BlockBody(Lists.newArrayList(), Lists.newArrayList()));
final ProtocolContext protocolContext = new ProtocolContext(null, null, null);
final ProtocolContext protocolContext = new ProtocolContext(null, null, null, Optional.empty());
final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class);
final Function<BlockHeader, PoWBlockCreator> blockCreatorSupplier =

@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.txselection.TransactionSelectorFactory;
import java.util.Optional;
@ -30,6 +31,7 @@ public class ProtocolContext {
private final MutableBlockchain blockchain;
private final WorldStateArchive worldStateArchive;
private final ConsensusContext consensusContext;
private final Optional<TransactionSelectorFactory> transactionSelectorFactory;
private Optional<Synchronizer> synchronizer;
@ -37,21 +39,32 @@ public class ProtocolContext {
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ConsensusContext consensusContext) {
this(blockchain, worldStateArchive, consensusContext, Optional.empty());
}
public ProtocolContext(
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ConsensusContext consensusContext,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
this.blockchain = blockchain;
this.worldStateArchive = worldStateArchive;
this.consensusContext = consensusContext;
this.synchronizer = Optional.empty();
this.transactionSelectorFactory = transactionSelectorFactory;
}
public static ProtocolContext init(
final MutableBlockchain blockchain,
final WorldStateArchive worldStateArchive,
final ProtocolSchedule protocolSchedule,
final ConsensusContextFactory consensusContextFactory) {
final ConsensusContextFactory consensusContextFactory,
final Optional<TransactionSelectorFactory> transactionSelectorFactory) {
return new ProtocolContext(
blockchain,
worldStateArchive,
consensusContextFactory.create(blockchain, worldStateArchive, protocolSchedule));
consensusContextFactory.create(blockchain, worldStateArchive, protocolSchedule),
transactionSelectorFactory);
}
public Optional<Synchronizer> getSynchronizer() {
@ -79,4 +92,8 @@ public class ProtocolContext {
.filter(c -> klass.isAssignableFrom(c.getClass()))
.map(klass::cast);
}
public Optional<TransactionSelectorFactory> getTransactionSelectorFactory() {
return transactionSelectorFactory;
}
}

@ -48,6 +48,7 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
@ -151,7 +152,8 @@ public class BlockchainSetupUtil {
public <C extends ConsensusContext> C as(final Class<C> klass) {
return null;
}
});
},
Optional.empty());
}
private static BlockchainSetupUtil create(

@ -34,6 +34,7 @@ import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
import java.math.BigInteger;
import java.util.Optional;
import java.util.function.Function;
public class ExecutionContextTestFixture {
@ -61,7 +62,7 @@ public class ExecutionContextTestFixture {
0);
this.stateArchive = createInMemoryWorldStateArchive();
this.protocolSchedule = protocolSchedule;
this.protocolContext = new ProtocolContext(blockchain, stateArchive, null);
this.protocolContext = new ProtocolContext(blockchain, stateArchive, null, Optional.empty());
genesisState.writeStateTo(stateArchive.getMutable());
}

@ -143,7 +143,7 @@ public abstract class AbstractIsolationTests {
null);
var ws = archive.getMutable();
genesisState.writeStateTo(ws);
protocolContext = new ProtocolContext(blockchain, archive, null);
protocolContext = new ProtocolContext(blockchain, archive, null, Optional.empty());
}
// storage provider which uses a temporary directory based rocksdb

@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import java.util.Collection;
import java.util.List;
@ -85,12 +86,6 @@ public interface PendingTransactions {
boolean isLocalSender(Address sender);
enum TransactionSelectionResult {
DELETE_TRANSACTION_AND_CONTINUE,
CONTINUE,
COMPLETE_OPERATION
}
@FunctionalInterface
interface TransactionSelector {
TransactionSelectionResult evaluateTransaction(Transaction transaction);

@ -36,6 +36,7 @@ import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.AccountState;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;

@ -65,6 +65,7 @@ import org.hyperledger.besu.testutil.TestClock;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
@ -104,7 +105,8 @@ public abstract class AbstractBlockPropagationManagerTest {
new ProtocolContext(
blockchain,
tempProtocolContext.getWorldStateArchive(),
tempProtocolContext.getConsensusContext(ConsensusContext.class));
tempProtocolContext.getConsensusContext(ConsensusContext.class),
Optional.empty());
ethProtocolManager =
EthProtocolManagerTestUtil.create(
protocolSchedule,

@ -40,6 +40,7 @@ import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.junit.After;
@ -80,7 +81,7 @@ public class FullSyncTargetManagerTest {
final ProtocolSchedule protocolSchedule = ProtocolScheduleFixture.MAINNET;
final ProtocolContext protocolContext =
new ProtocolContext(localBlockchain, localWorldState, null);
new ProtocolContext(localBlockchain, localWorldState, null, Optional.empty());
ethProtocolManager =
EthProtocolManagerTestUtil.create(
protocolSchedule,

@ -45,6 +45,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@ -160,7 +161,7 @@ public class DetermineCommonAncestorTaskParameterizedTest {
final EthContext ethContext = ethProtocolManager.ethContext();
final ProtocolContext protocolContext =
new ProtocolContext(localBlockchain, worldStateArchive, null);
new ProtocolContext(localBlockchain, worldStateArchive, null, Optional.empty());
final EthTask<BlockHeader> task =
DetermineCommonAncestorTask.create(

@ -54,6 +54,7 @@ import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.util.ExceptionUtils;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
@ -86,7 +87,8 @@ public class DetermineCommonAncestorTaskTest {
mock(TransactionPool.class),
EthProtocolConfiguration.defaultConfig());
ethContext = ethProtocolManager.ethContext();
protocolContext = new ProtocolContext(localBlockchain, worldStateArchive, null);
protocolContext =
new ProtocolContext(localBlockchain, worldStateArchive, null, Optional.empty());
}
@Test

@ -123,7 +123,7 @@ public class TestNode implements Closeable {
final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive();
genesisState.writeStateTo(worldStateArchive.getMutable());
final ProtocolContext protocolContext =
new ProtocolContext(blockchain, worldStateArchive, null);
new ProtocolContext(blockchain, worldStateArchive, null, Optional.empty());
final SyncState syncState = mock(SyncState.class);
final SynchronizerConfiguration syncConfig = mock(SynchronizerConfiguration.class);

@ -15,15 +15,15 @@
package org.hyperledger.besu.ethereum.eth.transactions.layered;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.COMPLETE_OPERATION;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.CONTINUE;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ADDED;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ALREADY_KNOWN;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.REJECTED_UNDERPRICED_REPLACEMENT;
import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.DROPPED;
import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.REPLACED;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.COMPLETE_OPERATION;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.CONTINUE;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;

@ -15,11 +15,11 @@
package org.hyperledger.besu.ethereum.eth.transactions.sorter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.CONTINUE;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ADDED;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ALREADY_KNOWN;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.REJECTED_UNDERPRICED_REPLACEMENT;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.CONTINUE;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.DELETE_TRANSACTION_AND_CONTINUE;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
@ -43,6 +43,7 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.metrics.StubMetricsSystem;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.testutil.TestClock;
import java.time.Clock;
@ -314,7 +315,7 @@ public abstract class AbstractPendingTransactionsTestBase {
transactions.selectTransactions(
transaction -> {
parsedTransactions.add(transaction);
return PendingTransactions.TransactionSelectionResult.COMPLETE_OPERATION;
return TransactionSelectionResult.COMPLETE_OPERATION;
});
assertThat(parsedTransactions.size()).isEqualTo(1);

@ -106,7 +106,8 @@ public class BlockchainReferenceTestCaseSpec {
this.worldStateArchive = buildWorldStateArchive(accounts);
this.blockchain = buildBlockchain(genesisBlockHeader);
this.sealEngine = sealEngine;
this.protocolContext = new ProtocolContext(this.blockchain, this.worldStateArchive, null);
this.protocolContext =
new ProtocolContext(this.blockchain, this.worldStateArchive, null, Optional.empty());
}
public String getNetwork() {

@ -168,7 +168,7 @@ public class RetestethContext {
genesisState.writeStateTo(worldState);
blockchain = createInMemoryBlockchain(genesisState.getBlock());
protocolContext = new ProtocolContext(blockchain, worldStateArchive, null);
protocolContext = new ProtocolContext(blockchain, worldStateArchive, null, Optional.empty());
blockchainQueries = new BlockchainQueries(blockchain, worldStateArchive, ethScheduler);

@ -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 = '3/qsZ9+jA10YbctpPtQ5Rn7cvYHwKRWBv6jXa+7WQMY='
knownHash = 'p757auCgPIb5l/MEk8XPpJOkvEabVmkWUqEcq+NRtS4='
}
check.dependsOn('checkAPIChanges')

@ -0,0 +1,26 @@
/*
* 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.data;
/** Enum for the transaction selection result */
public enum TransactionSelectionResult {
/** remove transaction from pool and continue block building */
DELETE_TRANSACTION_AND_CONTINUE,
/** continue block building */
CONTINUE,
/** stop block building */
COMPLETE_OPERATION
}

@ -0,0 +1,40 @@
/*
* 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.txselection.TransactionSelectorFactory;
import java.util.Optional;
/** Transaction selection service interface */
@Unstable
public interface TransactionSelectionService extends BesuService {
/**
* Returns the (Optional) transaction selector factory
*
* @return the transaction selector factory
*/
Optional<TransactionSelectorFactory> get();
/**
* Registers the transaction selector factory with the service
*
* @param transactionSelectorFactory transaction selector factory to be used
*/
void registerTransactionSelectorFactory(TransactionSelectorFactory transactionSelectorFactory);
}

@ -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.txselection;
import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.data.Transaction;
import org.hyperledger.besu.plugin.data.TransactionReceipt;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
/** Interface for the transaction selector */
@Unstable
public interface TransactionSelector {
/**
* Method called to decide whether a transaction is added to a block. The method can also indicate
* that no further transactions can be added to the block.
*
* @param transaction candidate transaction
* @param receipt receipt for the candidate transaction
* @return TransactionSelectionResult that indicates whether to include the transaction
*/
default TransactionSelectionResult selectTransaction(
final Transaction transaction, final TransactionReceipt receipt) {
return TransactionSelectionResult.CONTINUE;
}
}

@ -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.txselection;
import org.hyperledger.besu.plugin.Unstable;
/** Interface for a factory that creates transaction selectors */
@Unstable
public interface TransactionSelectorFactory {
/**
* Create a transaction selector
*
* @return the transaction selector
*/
TransactionSelector create();
}
Loading…
Cancel
Save