Revert the revert of the tx selection commit (#5507)

* Revert "Revert "Add plugin API to select Transactions (#5396)" (#5499)"

This reverts commit a0c6052778.

* fix receipt root bug

Signed-off-by: Stefan <stefan.pingel@consensys.net>
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: Usman Saleem <usman@usmans.info>
Signed-off-by: Stefan Pingel <16143240+pinges@users.noreply.github.com>
Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
Co-authored-by: Usman Saleem <usman@usmans.info>
This commit is contained in:
Stefan Pingel
2023-06-02 15:06:03 +10:00
committed by GitHub
parent 186d38b81d
commit b97c9350b4
71 changed files with 671 additions and 177 deletions

View File

@@ -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;

View File

@@ -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));
besuPluginContext.addService(
TransactionSelectionService.class, new TransactionSelectionServiceImpl());
final Path pluginsPath = node.homeDirectory().resolve("plugins");
final File pluginsDirFile = pluginsPath.toFile();
if (!pluginsDirFile.isDirectory()) {
pluginsDirFile.mkdirs();
pluginsDirFile.deleteOnExit();
final Path pluginsPath;
final String pluginDir = System.getProperty("besu.plugins.dir");
if (pluginDir == null || pluginDir.isEmpty()) {
pluginsPath = node.homeDirectory().resolve("plugins");
final File pluginsDirFile = pluginsPath.toFile();
if (!pluginsDirFile.isDirectory()) {
pluginsDirFile.mkdirs();
pluginsDirFile.deleteOnExit();
}
System.setProperty("besu.plugins.dir", pluginsPath.toString());
} else {
pluginsPath = Path.of(pluginDir);
}
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();
}
}

View File

@@ -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);
}

View File

@@ -168,12 +168,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;
@@ -184,6 +186,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;
@@ -235,6 +238,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;
@@ -361,6 +365,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.
@@ -1417,7 +1423,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
new PermissioningServiceImpl(),
new PrivacyPluginServiceImpl(),
new PkiBlockCreationConfigurationProvider(),
new RpcEndpointServiceImpl());
new RpcEndpointServiceImpl(),
new TransactionSelectionServiceImpl());
}
/**
@@ -1437,6 +1444,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(
@@ -1453,7 +1461,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;
@@ -1471,6 +1480,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuPluginContext.addService(BesuConfiguration.class, pluginCommonConfiguration);
this.pkiBlockCreationConfigProvider = pkiBlockCreationConfigProvider;
this.rpcEndpointServiceImpl = rpcEndpointServiceImpl;
this.transactionSelectionServiceImpl = transactionSelectionServiceImpl;
}
/**
@@ -1651,6 +1661,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();
@@ -2278,12 +2290,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()
@@ -2333,6 +2348,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(

View File

@@ -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(

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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();

View File

@@ -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));

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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(

View File

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

View File

@@ -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

View File

@@ -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());
}
}

View File

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

View File

@@ -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()))

View File

@@ -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);

View File

@@ -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()));

View File

@@ -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);

View File

@@ -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();

View File

@@ -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(

View File

@@ -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

View File

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

View File

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

View File

@@ -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();

View File

@@ -160,7 +160,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()))

View File

@@ -117,7 +117,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);

View File

@@ -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(

View File

@@ -98,7 +98,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(

View File

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

View File

@@ -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);

View File

@@ -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();

View File

@@ -112,7 +112,8 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
final MutableBlockchain blockchain = blockchainSetupUtil.getBlockchain();
ProtocolContext context =
new ProtocolContext(blockchain, blockchainSetupUtil.getWorldArchive(), null);
new ProtocolContext(
blockchain, blockchainSetupUtil.getWorldArchive(), null, Optional.empty());
final BlockchainQueries blockchainQueries =
new BlockchainQueries(
context.getBlockchain(),

View File

@@ -306,7 +306,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());

View File

@@ -18,12 +18,12 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.GasLimitCalculator;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.LogsWrapper;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
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.TransactionSelectionResult;
import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
@@ -34,14 +34,19 @@ import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
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.log.Log;
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.Function;
import java.util.function.Supplier;
@@ -221,8 +226,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(
@@ -239,7 +245,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;
@@ -254,6 +261,8 @@ public class BlockTransactionSelector {
this.feeMarket = feeMarket;
this.gasCalculator = gasCalculator;
this.gasLimitCalculator = gasLimitCalculator;
this.transactionSelector =
transactionSelectorFactory.map(TransactionSelectorFactory::create).orElse(null);
}
/*
@@ -270,14 +279,14 @@ public class BlockTransactionSelector {
pendingTransactions.selectTransactions(
pendingTransaction -> {
final var res = evaluateTransaction(pendingTransaction, false);
transactionSelectionResult.addSelectionResult(res);
transactionSelectionResults.addSelectionResult(res);
return res;
});
LOG.atTrace()
.setMessage("Transaction selection result {}")
.addArgument(transactionSelectionResult::toTraceLog)
.setMessage("Transaction selection result result {}")
.addArgument(transactionSelectionResults::toTraceLog)
.log();
return transactionSelectionResult;
return transactionSelectionResults;
}
/**
@@ -289,8 +298,8 @@ public class BlockTransactionSelector {
public TransactionSelectionResults evaluateTransactions(final List<Transaction> transactions) {
transactions.forEach(
transaction ->
transactionSelectionResult.addSelectionResult(evaluateTransaction(transaction, true)));
return transactionSelectionResult;
transactionSelectionResults.addSelectionResult(evaluateTransaction(transaction, true)));
return transactionSelectionResults;
}
/*
@@ -348,22 +357,55 @@ 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;
TransactionSelectionResult txSelectionResult = TransactionSelectionResult.SELECTED;
if (transactionSelector != null) {
txSelectionResult =
transactionSelector.selectTransaction(
transaction,
effectiveResult.getStatus() == TransactionProcessingResult.Status.SUCCESSFUL,
getLogs(effectiveResult.getLogs()),
cumulativeGasUsed);
}
if (txSelectionResult.equals(TransactionSelectionResult.SELECTED)) {
worldStateUpdater.commit();
final TransactionReceipt receipt =
transactionReceiptFactory.create(
transaction.getType(), effectiveResult, worldState, cumulativeGasUsed);
final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount());
transactionSelectionResults.update(transaction, receipt, gasUsedByTransaction, dataGasUsed);
LOG.atTrace()
.setMessage("Selected {} for block creation")
.addArgument(transaction::toTraceLog)
.log();
}
return txSelectionResult;
} else {
final boolean isIncorrectNonce = isIncorrectNonce(effectiveResult.getValidationResult());
if (!isIncorrectNonce || reportFutureNonceTransactionsAsInvalid) {
transactionSelectionResult.updateWithInvalidTransaction(
transactionSelectionResults.updateWithInvalidTransaction(
transaction, effectiveResult.getValidationResult());
}
return transactionSelectionResultForInvalidResult(
transaction, effectiveResult.getValidationResult());
}
return TransactionSelectionResult.SELECTED;
}
private List<org.hyperledger.besu.plugin.data.Log> getLogs(final List<Log> logs) {
return logs.stream().map(LogsWrapper::new).collect(Collectors.toList());
}
private boolean transactionDataPriceBelowMin(final Transaction transaction) {
@@ -430,28 +472,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);
}
@@ -461,20 +481,21 @@ 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 long gasAvailable = processableBlockHeader.getGasLimit();
final long gasUsed = transactionSelectionResult.getCumulativeGasUsed();
final long gasRemaining = gasAvailable - gasUsed;
final long gasUsed = transactionSelectionResults.getCumulativeGasUsed();
final long gasRemaining = gasAvailable - gasUsed;
final double occupancyRatio = (double) gasUsed / (double) gasAvailable;
LOG.trace(
"Min block occupancy ratio {}, gas used {}, available {}, remaining {}, used/available {}",
minBlockOccupancyRatio,
@@ -488,7 +509,8 @@ public class BlockTransactionSelector {
private boolean blockFull() {
final long gasAvailable = processableBlockHeader.getGasLimit();
final long gasUsed = transactionSelectionResult.getCumulativeGasUsed();
final long gasUsed = transactionSelectionResults.getCumulativeGasUsed();
final long gasRemaining = gasAvailable - gasUsed;
if (gasRemaining < gasCalculator.getMinimumTransactionCost()) {

View File

@@ -45,7 +45,6 @@ import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolCo
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.sorter.BaseFeePendingTransactionsSorter;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
@@ -57,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.TransactionSelectorFactory;
import org.hyperledger.besu.testutil.TestClock;
import java.math.BigInteger;
@@ -90,7 +91,6 @@ public abstract class AbstractBlockTransactionSelectorTest {
protected PendingTransactions pendingTransactions;
protected MutableWorldState worldState;
@Mock protected MainnetTransactionProcessor transactionProcessor;
@Mock protected MainnetTransactionValidator transactionValidator;
@Before
public void setup() {
@@ -286,7 +286,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 =
@@ -561,6 +562,74 @@ public abstract class AbstractBlockTransactionSelectorTest {
.isNotPresent();
}
@Test
public void transactionSelectionPluginShouldWork() {
final ProcessableBlockHeader blockHeader = createBlock(300);
final TransactionTestFixture txTestFixture = new TransactionTestFixture();
final Transaction selected =
txTestFixture
.nonce(1)
.gasLimit(1)
.createTransaction(SignatureAlgorithmFactory.getInstance().generateKeyPair());
ensureTransactionIsValid(selected, 2000, 10000);
final Transaction notSelectedTransient =
txTestFixture
.nonce(1)
.gasLimit(1)
.createTransaction(SignatureAlgorithmFactory.getInstance().generateKeyPair());
ensureTransactionIsValid(notSelectedTransient, 2000, 10000);
final Transaction notSelectedInvalid =
txTestFixture
.nonce(1)
.gasLimit(1)
.createTransaction(SignatureAlgorithmFactory.getInstance().generateKeyPair());
ensureTransactionIsValid(notSelectedInvalid, 2000, 10000);
final TransactionSelectorFactory transactionSelectorFactory =
(TransactionSelectorFactory)
() ->
(tx, s, logs, cg) -> {
if (tx.equals(notSelectedTransient))
return TransactionSelectionResult.invalidTransient("transient");
if (tx.equals(notSelectedInvalid))
return TransactionSelectionResult.invalid("invalid");
return TransactionSelectionResult.SELECTED;
};
final Address miningBeneficiary = AddressHelpers.ofValue(1);
final BlockTransactionSelector selector =
createBlockSelectorWithTxSelPlugin(
transactionProcessor,
blockHeader,
Wei.ZERO,
miningBeneficiary,
Wei.ZERO,
MIN_OCCUPANCY_80_PERCENT,
transactionSelectorFactory);
pendingTransactions.addRemoteTransaction(selected, Optional.empty());
pendingTransactions.addRemoteTransaction(notSelectedTransient, Optional.empty());
pendingTransactions.addRemoteTransaction(notSelectedInvalid, Optional.empty());
final BlockTransactionSelector.TransactionSelectionResults transactionSelectionResults =
selector.buildTransactionListForBlock();
Assertions.assertThat(pendingTransactions.getTransactionByHash(notSelectedTransient.getHash()))
.isPresent();
Assertions.assertThat(pendingTransactions.getTransactionByHash(notSelectedInvalid.getHash()))
.isNotPresent();
// Assertions.assertThat(pendingTransactions.getTransactionByHash(selected.getHash()))
// .isNotPresent(); // TODO check with Fabio what should happen with selected txs
Assertions.assertThat(transactionSelectionResults.getTransactions()).contains(selected);
Assertions.assertThat(transactionSelectionResults.getTransactions())
.doesNotContain(notSelectedTransient);
Assertions.assertThat(transactionSelectionResults.getTransactions())
.doesNotContain(notSelectedInvalid);
}
@Test
public void transactionWithIncorrectNonceRemainsInPoolAndNotSelected() {
final ProcessableBlockHeader blockHeader = createBlock(5000);
@@ -611,8 +680,39 @@ public abstract class AbstractBlockTransactionSelectorTest {
miningBeneficiary,
dataGasPrice,
getFeeMarket(),
getGasCalculator(),
GasLimitCalculator.constant());
new LondonGasCalculator(),
GasLimitCalculator.constant(),
Optional.empty());
return selector;
}
protected BlockTransactionSelector createBlockSelectorWithTxSelPlugin(
final MainnetTransactionProcessor transactionProcessor,
final ProcessableBlockHeader blockHeader,
final Wei minGasPrice,
final Address miningBeneficiary,
final Wei dataGasPrice,
final double minBlockOccupancyRatio,
final TransactionSelectorFactory transactionSelectorFactory) {
final BlockTransactionSelector selector =
new BlockTransactionSelector(
transactionProcessor,
blockchain,
worldState,
pendingTransactions,
blockHeader,
this::createReceipt,
minGasPrice,
minBlockOccupancyRatio,
this::isCancelled,
miningBeneficiary,
dataGasPrice,
getFeeMarket(),
new LondonGasCalculator(),
GasLimitCalculator.constant(),
Optional.of(transactionSelectorFactory));
return selector;
}

View File

@@ -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 =

View File

@@ -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;
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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.ethereum.core;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.evm.log.Log;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
public class LogsWrapper implements org.hyperledger.besu.plugin.data.Log {
final Log delegate;
public LogsWrapper(final Log delegate) {
this.delegate = delegate;
}
@Override
public Address getLogger() {
return delegate.getLogger();
}
@Override
public List<? extends Bytes32> getTopics() {
return delegate.getTopics();
}
@Override
public Bytes getData() {
return delegate.getData();
}
}

View File

@@ -14,7 +14,6 @@
*/
package org.hyperledger.besu.ethereum.core;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.mainnet.TransactionReceiptType;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
@@ -33,7 +32,6 @@ import java.util.stream.Collectors;
import com.google.common.base.MoreObjects;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
/**
* A transaction receipt, containing information pertaining a transaction execution.
@@ -370,27 +368,3 @@ public class TransactionReceipt implements org.hyperledger.besu.plugin.data.Tran
.toString();
}
}
class LogsWrapper implements org.hyperledger.besu.plugin.data.Log {
final Log delegate;
LogsWrapper(final Log delegate) {
this.delegate = delegate;
}
@Override
public Address getLogger() {
return delegate.getLogger();
}
@Override
public List<? extends Bytes32> getTopics() {
return delegate.getTopics();
}
@Override
public Bytes getData() {
return delegate.getData();
}
}

View File

@@ -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(

View File

@@ -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());
}

View File

@@ -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

View File

@@ -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;

View File

@@ -32,11 +32,11 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolReplacementHandler;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult;
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;

View File

@@ -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,

View File

@@ -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,

View File

@@ -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(

View File

@@ -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

View File

@@ -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);

View File

@@ -19,16 +19,16 @@ import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedRes
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.TransactionSelectionResult.BLOCK_FULL;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.CURRENT_TX_PRICE_BELOW_MIN;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.DATA_PRICE_BELOW_CURRENT_MIN;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.SELECTED;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult.TX_TOO_LARGE_FOR_REMAINING_GAS;
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.ethereum.transaction.TransactionInvalidReason.GAS_PRICE_BELOW_CURRENT_BASE_FEE;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_FULL;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.CURRENT_TX_PRICE_BELOW_MIN;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.DATA_PRICE_BELOW_CURRENT_MIN;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.TX_TOO_LARGE_FOR_REMAINING_GAS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
@@ -47,9 +47,9 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionDroppedL
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolReplacementHandler;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult;
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.ArrayList;
import java.util.List;
@@ -311,7 +311,7 @@ public class LayeredPendingTransactionsTest extends BaseTransactionPoolTest {
}
static Stream<TransactionSelectionResult> selectTransactionsUntilSelectorRequestsNoMore() {
return Stream.of(BLOCK_OCCUPANCY_ABOVE_THRESHOLD, BLOCK_FULL);
return Stream.of(BLOCK_OCCUPANCY_ABOVE_THRESHOLD, BLOCK_OCCUPANCY_ABOVE_THRESHOLD, BLOCK_FULL);
}
@Test

View File

@@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat;
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.ethereum.eth.transactions.TransactionSelectionResult.SELECTED;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
@@ -40,10 +40,10 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionAddedLis
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionDroppedListener;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionSelectionResult;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
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;

1
ethereum/evmtool/txs.rlp Normal file
View File

@@ -0,0 +1 @@
"0xf90620f860800a8307a12094000000000000000000000000000000000000010080801ca0f73b923883495dc2174285c8fa4176de3d45accfb11cc8034ea1dd09831a4ddfa01c6bccbcd655b4022bcc27de4b9d5cee9ce999cdb8459b0afec4f5054ea02243f860010a8307a12094000000000000000000000000000000000000010180801ba0bffca3f433f61c957d822af37f2b49c57700ff338588d51ea82dc9f720c91d9da0168bb65cc72d586384383f8ceef3a6a60e54b7f4aaa978a6dad271ced54b2ebff860020a8307a12094000000000000000000000000000000000000010280801ba03d9f110bcf0c44be552d4d0ec8387b705604f7d3bb3794dcef4004c38963103ea013bda734f3b5987b8c855f6aab046754506266ff32352ba0898c4eba4acaec8bf860030a8307a12094000000000000000000000000000000000000010380801ba0ecb276d2486664ea779813e599b6f07b7b0df746626d7fdddf60ea425efcb324a0739841682e79a8302dc2e146dfd1eecbdc611d386d42287bcdd94a39bf536020f860040a8307a12094000000000000000000000000000000000000010480801ba002866b5c5fa5dbfa3d88b71a49b82a779c2d508cda631893176782dbcd7435aaa003c380a9af9bfdb3503abcfd5037d3c66f39bb7a19011a3291712d22292c5236f860050a8307a12094000000000000000000000000000000000000010580801ca0c70d2e000e503933d0f1a9a923dc647924811a912adf77692ff7d8f6808d5617a04ad82c92b980580a4a67e4c405e83d560a14201c3fd4b3a42d34dcc19336479af860060a8307a12094000000000000000000000000000000000000010680801ca07f2527f8cbe14e021d270dd214a1820355c7af128001889f57b7f9bba46a6c5da03033308de0d39b9d1b47d28f81df39ceaff330349298c65deb836efe8bce273ff860070a8307a12094000000000000000000000000000000000000010780801ba0ecb720a8764f8967b95dc66e961c6261fceb392c0e90461d7d66113d3c8bbd12a02655e28b751cc2e03a835aa817d884b540765dba12968bc53f53737b4234ee21f860080a8307a12094000000000000000000000000000000000000010880801ba095a2e27c0b296679141c0ad61be112f689b134c04d1773814ddae67fefb2dfbda02955f126d57d8b9777f47c520ffe4285890ca2dd1189e67b3407d6369997e7ecf860090a8307a12094000000000000000000000000000000000000010980801ca02468a120d0ee8c57caac354f56842a1db10813169a328f9f852279668b573907a03971f4c2e6bc0aa666812712719199df6fe37c0e1e122131cdb47d6c0c77b371f8600a0a8307a12094000000000000000000000000000000000000010a80801ba0a3a2018ab0bc2695b94bb85d710f4d07132a94f8c3e0f385824da5fee11899a5a00d2dfe430ea5aaff3de8bbb9339e7485474c8e4e34636f787124a7a91e4d6d6af8600b0a8307a12094000000000000000000000000000000000000010b80801ba0b91968fdb3aecea26094ec30649daa4de81a875bcb1a123e732b8f3f112ce232a02ef8cd85969d8bcef5f4ee1f5d20783b8d9b7466726c15ebf911565825187665f8600c0a8307a12094000000000000000000000000000000000000010c80801ca0dd27e75aa990793205805c22265b04be8299b208fad4f37a7f652ecf32b67390a05aa8cda18521548ff8f95e88f49f309d05cab32de28a0942b8a7a824c50df459f8600d0a8307a12094000000000000000000000000000000000000010d80801ba0fad07ce7139dd4e00266194e6a51c048f74eaba3c0a1b03ece378a810abfaa63a04fec880dafaa5382797b4f88b16138b1f0c4e084817072c77ff9bf17ddd4ac26f8600e0a8307a12094000000000000000000000000000000000000010e80801ca0208b22ab245221bdc5cae6586d2ef019a2c37be41166e04b8abe354c41a8f5b6a032d5d6ef07731cd1684531c775c1727ef6ba75de18cda96d998aaa0c1db0bd68f8600f0a8307a12094000000000000000000000000000000000000010f80801ba0055225ffd3d8b2d19c32aa68cb46e7b52c1d99844fb8b7a53b922ea1649e9c5ba06ae2a1e3b9712354b706d0f4da6ea76ed2f8f75277a51a14a3e0ccf25b85c626"

View File

@@ -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() {

View File

@@ -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);

View File

@@ -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 = 'WC7tcTTrQg//+cIarm7NSabnxm6nY0lLkHWOH6+7Rmo='
knownHash = 'gfED3Pzd/+CSSrTtDo1X+lkc7qwffDqF98EZIDMCOIc='
}
check.dependsOn('checkAPIChanges')

View File

@@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.eth.transactions;
package org.hyperledger.besu.plugin.data;
import java.util.Objects;
import java.util.Optional;

View File

@@ -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);
}

View File

@@ -0,0 +1,44 @@
/*
* 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.Log;
import org.hyperledger.besu.plugin.data.Transaction;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import java.util.List;
/** 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 success true, if the transaction executed successfully
* @param logs the logs created by this transaction
* @param cumulativeGasUsed gas used by this and all previous transaction in the block
* @return TransactionSelectionResult that indicates whether to include the transaction
*/
TransactionSelectionResult selectTransaction(
final Transaction transaction,
final boolean success,
final List<Log> logs,
final long cumulativeGasUsed);
}

View File

@@ -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();
}