Merge branch 'main' into zkbesu

# Conflicts:
#	gradle/verification-metadata.xml
This commit is contained in:
Fabio Di Fabio
2025-02-07 18:20:34 +01:00
110 changed files with 2147 additions and 573 deletions

View File

@@ -1,6 +1,24 @@
# Changelog
## Unreleased
### Breaking Changes
### Upcoming Breaking Changes
- `MetricSystem::createLabelledGauge` is deprecated and will be removed in a future release, replace it with `MetricSystem::createLabelledSuppliedGauge`
- k8s (KUBERNETES) Nat method is now deprecated and will be removed in a future release. Use docker or none instead.
- `--Xsnapsync-synchronizer-flat-db-healing-enabled` is deprecated, use `--Xbonsai-full-flat-db-enabled` instead.
- `--Xbonsai-limit-trie-logs-enabled` is deprecated, use `--bonsai-limit-trie-logs-enabled` instead.
- `--Xbonsai-trie-log-pruning-enabled` is deprecated, use `--bonsai-limit-trie-logs-enabled` instead.
- `--Xbonsai-trie-logs-pruning-window-size` is deprecated, use `--bonsai-trie-logs-pruning-window-size` instead.
- Sunsetting features - for more context on the reasoning behind the deprecation of these features, including alternative options, read [this blog post](https://www.lfdecentralizedtrust.org/blog/sunsetting-tessera-and-simplifying-hyperledger-besu)
- Tessera privacy
- Smart-contract-based (onchain) permissioning
- Proof of Work consensus
- Fast Sync
### Additions and Improvements
### Bug fixes
## 25.2.0
### Breaking Changes
- `rpc-gas-cap` default value has changed from 0 (unlimited) to 50M. If you require `rpc-gas-cap` greater than 50M, you'll need to set that explicitly. [#8251](https://github.com/hyperledger/besu/issues/8251)
### Upcoming Breaking Changes
@@ -28,6 +46,7 @@
### Bug fixes
- Fix the simulation of txs with a future nonce [#8215](https://github.com/hyperledger/besu/pull/8215)
- Bump to besu-native 1.1.2 for ubuntu 20.04 native support[#8264](https://github.com/hyperledger/besu/pull/8264)
## 25.1.0

View File

@@ -78,7 +78,7 @@ public class Account {
return new Account(eth, name, SIGNATURE_ALGORITHM.get().generateKeyPair());
}
static Account fromPrivateKey(
public static Account fromPrivateKey(
final EthTransactions eth, final String name, final String privateKey) {
return new Account(
eth,

View File

@@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.NodeConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
@@ -133,6 +134,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
private Optional<Integer> exitCode = Optional.empty();
private final boolean isStrictTxReplayProtectionEnabled;
private final Map<String, String> environment;
private final Optional<KeyValueStorageFactory> storageFactory;
public BesuNode(
final String name,
@@ -169,7 +171,8 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
final List<String> runCommand,
final Optional<KeyPair> keyPair,
final boolean isStrictTxReplayProtectionEnabled,
final Map<String, String> environment)
final Map<String, String> environment,
final Optional<KeyValueStorageFactory> maybeStorageFactory)
throws IOException {
this.homeDirectory = dataPath.orElseGet(BesuNode::createTmpDataDirectory);
this.isStrictTxReplayProtectionEnabled = isStrictTxReplayProtectionEnabled;
@@ -211,6 +214,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
this.secp256k1Native = secp256k1Native;
this.altbn128Native = altbn128Native;
this.runCommand = runCommand;
this.storageFactory = maybeStorageFactory;
plugins.forEach(
pluginName -> {
try {
@@ -836,4 +840,8 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
public ApiConfiguration getApiConfiguration() {
return apiConfiguration;
}
public Optional<KeyValueStorageFactory> getStorageFactory() {
return storageFactory;
}
}

View File

@@ -75,6 +75,7 @@ import org.hyperledger.besu.plugin.services.TransactionSelectionService;
import org.hyperledger.besu.plugin.services.TransactionSimulationService;
import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
import org.hyperledger.besu.plugin.services.mining.MiningService;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.plugin.services.transactionpool.TransactionPoolService;
import org.hyperledger.besu.services.BesuConfigurationImpl;
@@ -283,6 +284,7 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
}
@Module
@SuppressWarnings("CloseableProvides")
static class BesuNodeProviderModule {
private final BesuNode toProvide;
@@ -413,6 +415,13 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
return retval;
}
@Provides
KeyValueStorageFactory provideKeyValueStorageFactory() {
return toProvide
.getStorageFactory()
.orElse(new InMemoryStoragePlugin.InMemoryKeyValueStorageFactory("memory"));
}
@Provides
@Singleton
MetricCategoryRegistryImpl provideMetricCategoryRegistry() {
@@ -565,14 +574,16 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
@Provides
public KeyValueStorageProvider provideKeyValueStorageProvider(
final BesuConfiguration commonPluginConfiguration, final MetricsSystem metricsSystem) {
final BesuConfiguration commonPluginConfiguration,
final MetricsSystem metricsSystem,
final KeyValueStorageFactory keyValueStorageFactory) {
final StorageServiceImpl storageService = new StorageServiceImpl();
storageService.registerKeyValueStorage(
new InMemoryStoragePlugin.InMemoryKeyValueStorageFactory("memory"));
final KeyValueStorageFactory storageFactory = keyValueStorageFactory;
storageService.registerKeyValueStorage(storageFactory);
final KeyValueStorageProvider storageProvider =
new KeyValueStorageProviderBuilder()
.withStorageFactory(storageService.getByName("memory").get())
.withStorageFactory(storageFactory)
.withCommonConfiguration(commonPluginConfiguration)
.withMetricsSystem(metricsSystem)
.build();

View File

@@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
import java.nio.file.Path;
@@ -72,6 +73,7 @@ public class BesuNodeConfiguration {
private final Optional<KeyPair> keyPair;
private final boolean strictTxReplayProtectionEnabled;
private final Map<String, String> environment;
private final Optional<KeyValueStorageFactory> storageFactory;
BesuNodeConfiguration(
final String name,
@@ -108,7 +110,8 @@ public class BesuNodeConfiguration {
final List<String> runCommand,
final Optional<KeyPair> keyPair,
final boolean strictTxReplayProtectionEnabled,
final Map<String, String> environment) {
final Map<String, String> environment,
final Optional<KeyValueStorageFactory> storageFactory) {
this.name = name;
this.miningConfiguration = miningConfiguration;
this.transactionPoolConfiguration = transactionPoolConfiguration;
@@ -144,6 +147,7 @@ public class BesuNodeConfiguration {
this.keyPair = keyPair;
this.strictTxReplayProtectionEnabled = strictTxReplayProtectionEnabled;
this.environment = environment;
this.storageFactory = storageFactory;
}
public String getName() {
@@ -285,4 +289,8 @@ public class BesuNodeConfiguration {
public Map<String, String> getEnvironment() {
return environment;
}
public Optional<KeyValueStorageFactory> storageImplementation() {
return storageFactory;
}
}

View File

@@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
import java.io.File;
@@ -95,6 +96,7 @@ public class BesuNodeConfigurationBuilder {
private Optional<KeyPair> keyPair = Optional.empty();
private Boolean strictTxReplayProtectionEnabled = false;
private Map<String, String> environment = new HashMap<>();
private Optional<KeyValueStorageFactory> storageImplementation = Optional.empty();
public BesuNodeConfigurationBuilder() {
// Check connections more frequently during acceptance tests to cut down on
@@ -459,6 +461,12 @@ public class BesuNodeConfigurationBuilder {
return this;
}
public BesuNodeConfigurationBuilder storageImplementation(
final KeyValueStorageFactory storageFactory) {
this.storageImplementation = Optional.of(storageFactory);
return this;
}
public BesuNodeConfiguration build() {
return new BesuNodeConfiguration(
name,
@@ -495,6 +503,7 @@ public class BesuNodeConfigurationBuilder {
runCommand,
keyPair,
strictTxReplayProtectionEnabled,
environment);
environment,
storageImplementation);
}
}

View File

@@ -83,7 +83,8 @@ public class BesuNodeFactory {
config.getRunCommand(),
config.getKeyPair(),
config.isStrictTxReplayProtectionEnabled(),
config.getEnvironment());
config.getEnvironment(),
config.storageImplementation());
}
public BesuNode createMinerNode(

View File

@@ -52,6 +52,7 @@ dependencies {
testImplementation project(':privacy-contracts')
testImplementation project(':testutil')
testImplementation project(':util')
implementation project(':plugins:rocksdb')
testImplementation 'commons-io:commons-io'
testImplementation 'io.grpc:grpc-all'

View File

@@ -95,7 +95,7 @@ public class BftMiningSoakTest extends ParameterizedBftTestBase {
} catch (RuntimeException e) {
assertThat(e.getMessage())
.contains(
"Revert reason: 'Transaction processing could not be completed due to an exception'");
"Revert reason: 'Transaction processing could not be completed due to an exception (Invalid opcode: 0x5f)'");
}
// Should initially be set to 0

View File

@@ -14,7 +14,13 @@
*/
package org.hyperledger.besu.tests.acceptance.bootstrap;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions;
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNodeRunner;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
@@ -23,12 +29,14 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class ClusterThreadNodeRunnerAcceptanceTest extends AcceptanceTestBase {
private Node fullNode;
private Node miner;
private Cluster noDiscoveryCluster;
@BeforeEach
@@ -38,14 +46,37 @@ public class ClusterThreadNodeRunnerAcceptanceTest extends AcceptanceTestBase {
final BesuNodeRunner besuNodeRunner = new ThreadBesuNodeRunner();
noDiscoveryCluster = new Cluster(clusterConfiguration, net, besuNodeRunner);
final BesuNode noDiscoveryNode = besu.createNodeWithNoDiscovery("noDiscovery");
fullNode = besu.createArchiveNode("archive");
noDiscoveryCluster.start(noDiscoveryNode, fullNode);
miner =
besu.createMinerNode(
"miner",
(builder) -> {
KeyValueStorageFactory persistentStorageFactory =
new RocksDBKeyValueStorageFactory(
RocksDBCLIOptions.create()::toDomainObject,
List.of(KeyValueSegmentIdentifier.values()),
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
builder.storageImplementation(persistentStorageFactory);
return builder;
});
noDiscoveryCluster.start(noDiscoveryNode, miner);
}
@Test
public void shouldVerifySomething() {
// we don't care what verifies, just that it gets to the point something can verify
fullNode.verify(net.awaitPeerCount(0));
miner.verify(net.awaitPeerCount(0));
}
@Test
void shouldMineTransactionsEvenAfterRestart() {
final Account recipient = accounts.createAccount("account1");
miner.execute(accountTransactions.createTransfer(recipient, 2));
miner.verify(recipient.balanceEquals(2));
noDiscoveryCluster.stop();
noDiscoveryCluster.start(miner);
// Checking that state is retained after restart
miner.verify(recipient.balanceEquals(2));
}
@Override

View File

@@ -59,6 +59,7 @@ import org.slf4j.LoggerFactory;
public class MergeBesuControllerBuilder extends BesuControllerBuilder {
private final AtomicReference<SyncState> syncState = new AtomicReference<>();
private static final Logger LOG = LoggerFactory.getLogger(MergeBesuControllerBuilder.class);
private final PostMergeContext postMergeContext = new PostMergeContext();
/** Default constructor. */
public MergeBesuControllerBuilder() {}
@@ -198,7 +199,7 @@ public class MergeBesuControllerBuilder extends BesuControllerBuilder {
&& blockchain.getGenesisBlockHeader().getDifficulty().isZero();
final MergeContext mergeContext =
PostMergeContext.get()
postMergeContext
.setSyncState(syncState.get())
.setTerminalTotalDifficulty(
genesisConfigOptions
@@ -261,7 +262,16 @@ public class MergeBesuControllerBuilder extends BesuControllerBuilder {
@Override
public BesuController build() {
final BesuController controller = super.build();
PostMergeContext.get().setSyncState(controller.getSyncState());
postMergeContext.setSyncState(syncState.get());
return controller;
}
/**
* Gets post merge context.
*
* @return the post merge context
*/
public PostMergeContext getPostMergeContext() {
return postMergeContext;
}
}

View File

@@ -23,6 +23,7 @@ import org.hyperledger.besu.config.QbftFork;
import org.hyperledger.besu.consensus.common.BftValidatorOverrides;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.ForksSchedule;
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
import org.hyperledger.besu.consensus.common.bft.BftBlockInterface;
import org.hyperledger.besu.consensus.common.bft.BftContext;
import org.hyperledger.besu.consensus.common.bft.BftEventQueue;
@@ -46,13 +47,18 @@ import org.hyperledger.besu.consensus.common.validator.blockbased.BlockValidator
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.QbftForksSchedulesFactory;
import org.hyperledger.besu.consensus.qbft.QbftProtocolScheduleBuilder;
import org.hyperledger.besu.consensus.qbft.adaptor.BftEventHandlerAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.BlockUtil;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockCodecAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockCreatorFactoryAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockHashingAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockInterfaceAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockchainAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftExtraDataProviderAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftFinalStateImpl;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftProtocolScheduleAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorModeTransitionLoggerAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorProviderAdaptor;
import org.hyperledger.besu.consensus.qbft.blockcreation.QbftBlockCreatorFactory;
import org.hyperledger.besu.consensus.qbft.core.network.QbftGossip;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
@@ -62,16 +68,18 @@ import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftRoundFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
import org.hyperledger.besu.consensus.qbft.core.types.QbftEventHandler;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.consensus.qbft.core.types.QbftMinedBlockObserver;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory;
import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.consensus.qbft.jsonrpc.QbftJsonRpcMethods;
import org.hyperledger.besu.consensus.qbft.protocol.Istanbul100SubProtocol;
import org.hyperledger.besu.consensus.qbft.validator.ForkingValidatorProvider;
import org.hyperledger.besu.consensus.qbft.validator.TransactionValidatorProvider;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorContractController;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods;
@@ -209,9 +217,11 @@ public class QbftBesuControllerBuilder extends BesuControllerBuilder {
final ValidatorProvider validatorProvider =
protocolContext.getConsensusContext(BftContext.class).getValidatorProvider();
final QbftValidatorProvider qbftValidatorProvider =
new QbftValidatorProviderAdaptor(validatorProvider);
final QbftBlockInterface qbftBlockInterface = new QbftBlockInterfaceAdaptor(bftBlockInterface);
final QbftContext qbftContext = new QbftContext(validatorProvider, qbftBlockInterface);
final QbftContext qbftContext = new QbftContext(qbftValidatorProvider, qbftBlockInterface);
final ProtocolContext qbftProtocolContext =
new ProtocolContext(
blockchain,
@@ -267,27 +277,31 @@ public class QbftBesuControllerBuilder extends BesuControllerBuilder {
final MessageFactory messageFactory = new MessageFactory(nodeKey, blockEncoder);
QbftRoundFactory qbftRoundFactory =
new QbftRoundFactory(
finalState,
qbftProtocolContext,
qbftProtocolSchedule,
minedBlockObservers,
messageValidatorFactory,
messageFactory,
qbftExtraDataCodec,
new QbftExtraDataProviderAdaptor(qbftExtraDataCodec),
new QbftBlockHashingAdaptor(new BftBlockHashing(qbftExtraDataCodec)));
QbftBlockHeightManagerFactory qbftBlockHeightManagerFactory =
new QbftBlockHeightManagerFactory(
finalState,
new QbftRoundFactory(
finalState,
qbftProtocolContext,
qbftProtocolSchedule,
minedBlockObservers,
messageValidatorFactory,
messageFactory,
qbftExtraDataCodec,
new QbftExtraDataProviderAdaptor(qbftExtraDataCodec)),
qbftRoundFactory,
messageValidatorFactory,
messageFactory,
new ValidatorModeTransitionLogger(qbftForksSchedule));
new QbftValidatorModeTransitionLoggerAdaptor(
new ValidatorModeTransitionLogger(qbftForksSchedule)));
qbftBlockHeightManagerFactory.isEarlyRoundChangeEnabled(isEarlyRoundChangeEnabled);
final BftEventHandler qbftController =
final QbftEventHandler qbftController =
new QbftController(
blockchain,
new QbftBlockchainAdaptor(blockchain),
finalState,
qbftBlockHeightManagerFactory,
gossiper,
@@ -295,14 +309,15 @@ public class QbftBesuControllerBuilder extends BesuControllerBuilder {
futureMessageBuffer,
new EthSynchronizerUpdater(ethProtocolManager.ethContext().getEthPeers()),
blockEncoder);
final BftEventHandler bftEventHandler = new BftEventHandlerAdaptor(qbftController);
final EventMultiplexer eventMultiplexer = new EventMultiplexer(qbftController);
final EventMultiplexer eventMultiplexer = new EventMultiplexer(bftEventHandler);
final BftProcessor bftProcessor = new BftProcessor(bftEventQueue, eventMultiplexer);
final MiningCoordinator miningCoordinator =
new BftMiningCoordinator(
bftExecutors,
qbftController,
bftEventHandler,
bftProcessor,
blockCreatorFactory,
blockchain,

View File

@@ -147,7 +147,8 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
transitionMiningConfiguration,
syncState,
transitionBackwardsSyncContext,
ethProtocolManager.ethContext().getScheduler()));
ethProtocolManager.ethContext().getScheduler()),
mergeBesuControllerBuilder.getPostMergeContext());
initTransitionWatcher(protocolContext, composedCoordinator);
return composedCoordinator;
}
@@ -185,7 +186,7 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
new TransitionProtocolSchedule(
preMergeBesuControllerBuilder.createProtocolSchedule(),
mergeBesuControllerBuilder.createProtocolSchedule(),
PostMergeContext.get());
mergeBesuControllerBuilder.getPostMergeContext());
return transitionProtocolSchedule;
}
@@ -255,7 +256,7 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
private void initTransitionWatcher(
final ProtocolContext protocolContext, final TransitionCoordinator composedCoordinator) {
PostMergeContext postMergeContext = protocolContext.getConsensusContext(PostMergeContext.class);
PostMergeContext postMergeContext = mergeBesuControllerBuilder.getPostMergeContext();
postMergeContext.observeNewIsPostMergeState(
(isPoS, priorState, difficultyStoppedAt) -> {
if (isPoS) {
@@ -290,7 +291,7 @@ public class TransitionBesuControllerBuilder extends BesuControllerBuilder {
@Override
public BesuController build() {
final BesuController controller = super.build();
PostMergeContext.get().setSyncState(controller.getSyncState());
mergeBesuControllerBuilder.getPostMergeContext().setSyncState(controller.getSyncState());
return controller;
}

View File

@@ -54,6 +54,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class ForkIdsNetworkConfigTest {
private static final PostMergeContext postMergeContext = new PostMergeContext();
public static Collection<Object[]> parameters() {
return List.of(
@@ -63,18 +64,18 @@ public class ForkIdsNetworkConfigTest {
new ForkId(Bytes.ofUnsignedInt(0xfe3366e7L), 1735371L),
new ForkId(Bytes.ofUnsignedInt(0xb96cbd13L), 1677557088L),
new ForkId(Bytes.ofUnsignedInt(0xf7f9bc08L), 1706655072L),
new ForkId(Bytes.ofUnsignedInt(0x88cf81d9L), 1739980128L),
new ForkId(Bytes.ofUnsignedInt(0xbafd09c3L), 0L),
new ForkId(Bytes.ofUnsignedInt(0xbafd09c3L), 0L))
new ForkId(Bytes.ofUnsignedInt(0x88cf81d9L), 1741159776L),
new ForkId(Bytes.ofUnsignedInt(0xed88b5fdL), 0L),
new ForkId(Bytes.ofUnsignedInt(0xed88b5fdL), 0L))
},
new Object[] {
NetworkName.HOLESKY,
List.of(
new ForkId(Bytes.ofUnsignedInt(0xc61a6098L), 1696000704L),
new ForkId(Bytes.ofUnsignedInt(0xfd4f016bL), 1707305664L),
new ForkId(Bytes.ofUnsignedInt(0x9b192ad0L), 1739352768L),
new ForkId(Bytes.ofUnsignedInt(0xf818a0d6L), 0L),
new ForkId(Bytes.ofUnsignedInt(0xf818a0d6L), 0L))
new ForkId(Bytes.ofUnsignedInt(0x9b192ad0L), 1740434112L),
new ForkId(Bytes.ofUnsignedInt(0xdfbd9bedL), 0L),
new ForkId(Bytes.ofUnsignedInt(0xdfbd9bedL), 0L))
},
new Object[] {
NetworkName.MAINNET,
@@ -203,10 +204,10 @@ public class ForkIdsNetworkConfigTest {
public MilestoneStreamingTransitionProtocolSchedule(
final MilestoneStreamingProtocolSchedule preMergeProtocolSchedule,
final MilestoneStreamingProtocolSchedule postMergeProtocolSchedule) {
super(preMergeProtocolSchedule, postMergeProtocolSchedule, PostMergeContext.get());
super(preMergeProtocolSchedule, postMergeProtocolSchedule, postMergeContext);
transitionUtils =
new TransitionUtils<>(
preMergeProtocolSchedule, postMergeProtocolSchedule, PostMergeContext.get());
preMergeProtocolSchedule, postMergeProtocolSchedule, postMergeContext);
}
public Stream<Long> streamMilestoneBlocks() {

View File

@@ -15,7 +15,7 @@
"terminalTotalDifficulty": 0,
"shanghaiTime": 1696000704,
"cancunTime": 1707305664,
"pragueTime": 1739352768,
"pragueTime": 1740434112,
"blobSchedule": {
"cancun": {
"target": 3,

View File

@@ -15,7 +15,7 @@
"terminalTotalDifficulty": 17000000000000000,
"shanghaiTime": 1677557088,
"cancunTime": 1706655072,
"pragueTime": 1739980128,
"pragueTime": 1741159776,
"blobSchedule": {
"cancun": {
"target": 3,

View File

@@ -17,12 +17,12 @@ package org.hyperledger.besu.consensus.common.bft;
import org.hyperledger.besu.config.BftConfigOptions;
import org.hyperledger.besu.consensus.common.ForksSchedule;
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import java.time.Clock;
import java.util.Optional;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -81,10 +81,10 @@ public class BlockTimer {
* Starts a timer for the supplied round cancelling any previously active block timer
*
* @param round The round identifier which this timer is tracking
* @param chainHeadHeader The header of the chain head
* @param headerTimestamp The timestamp from the of the chain head header
*/
public synchronized void startTimer(
final ConsensusRoundIdentifier round, final BlockHeader chainHeadHeader) {
final ConsensusRoundIdentifier round, final Supplier<Long> headerTimestamp) {
cancelTimer();
final long expiryTime;
@@ -104,7 +104,7 @@ public class BlockTimer {
final int currentBlockPeriodSeconds =
forksSchedule.getFork(round.getSequenceNumber()).getValue().getBlockPeriodSeconds();
final long minimumTimeBetweenBlocksMillis = currentBlockPeriodSeconds * 1000L;
expiryTime = chainHeadHeader.getTimestamp() * 1_000 + minimumTimeBetweenBlocksMillis;
expiryTime = headerTimestamp.get() * 1_000 + minimumTimeBetweenBlocksMillis;
}
setBlockTimes(round);
@@ -115,14 +115,14 @@ public class BlockTimer {
/**
* Checks if the empty block timer is expired
*
* @param chainHeadHeader The header of the chain head
* @param headerTimestamp Function to get the chain head timestamp
* @param currentTimeInMillis The current time
* @return a boolean value
*/
public synchronized boolean checkEmptyBlockExpired(
final BlockHeader chainHeadHeader, final long currentTimeInMillis) {
final Supplier<Long> headerTimestamp, final long currentTimeInMillis) {
final long emptyBlockPeriodExpiryTime =
(chainHeadHeader.getTimestamp() + emptyBlockPeriodSeconds) * 1000;
(headerTimestamp.get() + emptyBlockPeriodSeconds) * 1000;
if (currentTimeInMillis > emptyBlockPeriodExpiryTime) {
LOG.debug("Empty Block expired");
@@ -136,15 +136,15 @@ public class BlockTimer {
* Resets the empty block timer
*
* @param roundIdentifier The current round identifier
* @param chainHeadHeader The header of the chain head
* @param headerTimestamp Function to get timestamp from the header of the chain head
* @param currentTimeInMillis The current time
*/
public void resetTimerForEmptyBlock(
final ConsensusRoundIdentifier roundIdentifier,
final BlockHeader chainHeadHeader,
final Supplier<Long> headerTimestamp,
final long currentTimeInMillis) {
final long emptyBlockPeriodExpiryTime =
(chainHeadHeader.getTimestamp() + emptyBlockPeriodSeconds) * 1000;
(headerTimestamp.get() + emptyBlockPeriodSeconds) * 1000;
final long nextBlockPeriodExpiryTime = currentTimeInMillis + blockPeriodSeconds * 1000;
startTimer(roundIdentifier, Math.min(emptyBlockPeriodExpiryTime, nextBlockPeriodExpiryTime));

View File

@@ -102,7 +102,7 @@ public class BlockTimerTest {
bftExecutors.scheduleTask(any(Runnable.class), anyLong(), any()))
.thenReturn(mockedFuture);
timer.startTimer(round, header);
timer.startTimer(round, header::getTimestamp);
verify(bftExecutors)
.scheduleTask(any(Runnable.class), eq(EXPECTED_DELAY), eq(TimeUnit.MILLISECONDS));
}
@@ -136,7 +136,7 @@ public class BlockTimerTest {
final BftEventQueue eventQueue = new BftEventQueue(1000);
final BlockTimer timer = new BlockTimer(eventQueue, mockForksSchedule, bftExecutors, mockClock);
timer.startTimer(round, header);
timer.startTimer(round, header::getTimestamp);
// Verify that the event will not be added to the queue immediately
assertThat(eventQueue.isEmpty()).isTrue();
@@ -182,7 +182,7 @@ public class BlockTimerTest {
final ConsensusRoundIdentifier round =
new ConsensusRoundIdentifier(0xFEDBCA9876543210L, 0x12345678);
timer.startTimer(round, header);
timer.startTimer(round, header::getTimestamp);
verify(bftExecutors, never()).scheduleTask(any(Runnable.class), anyLong(), any());
final ArgumentCaptor<BftEvent> bftEventCaptor = ArgumentCaptor.forClass(BftEvent.class);
@@ -218,7 +218,7 @@ public class BlockTimerTest {
final ConsensusRoundIdentifier round =
new ConsensusRoundIdentifier(0xFEDBCA9876543210L, 0x12345678);
timer.startTimer(round, header);
timer.startTimer(round, header::getTimestamp);
verify(bftExecutors, never()).scheduleTask(any(Runnable.class), anyLong(), any());
final ArgumentCaptor<BftEvent> bftEventCaptor = ArgumentCaptor.forClass(BftEvent.class);
@@ -258,9 +258,9 @@ public class BlockTimerTest {
Mockito.<ScheduledFuture<?>>when(
bftExecutors.scheduleTask(any(Runnable.class), anyLong(), eq(TimeUnit.MILLISECONDS)))
.thenReturn(mockedFuture);
timer.startTimer(round, header);
timer.startTimer(round, header::getTimestamp);
verify(mockedFuture, times(0)).cancel(false);
timer.startTimer(round, header);
timer.startTimer(round, header::getTimestamp);
verify(mockedFuture, times(1)).cancel(false);
}
@@ -292,7 +292,7 @@ public class BlockTimerTest {
Mockito.<ScheduledFuture<?>>when(
bftExecutors.scheduleTask(any(Runnable.class), anyLong(), eq(TimeUnit.MILLISECONDS)))
.thenReturn(mockedFuture);
timer.startTimer(round, header);
timer.startTimer(round, header::getTimestamp);
when(mockedFuture.isDone()).thenReturn(false);
assertThat(timer.isRunning()).isTrue();
when(mockedFuture.isDone()).thenReturn(true);
@@ -322,7 +322,7 @@ public class BlockTimerTest {
MINIMAL_TIME_BETWEEN_EMPTY_BLOCKS_SECONDS)));
final BlockTimer timer = new BlockTimer(mockQueue, mockForksSchedule, bftExecutors, mockClock);
timer.startTimer(round, header);
timer.startTimer(round, header::getTimestamp);
assertThat(timer.getBlockPeriodSeconds()).isEqualTo(MINIMAL_TIME_BETWEEN_BLOCKS_SECONDS);
assertThat(timer.getEmptyBlockPeriodSeconds())

View File

@@ -117,7 +117,7 @@ public class IbftBlockHeightManager implements BaseIbftBlockHeightManager {
currentRound = roundFactory.createNewRound(parentHeader, 0);
if (finalState.isLocalNodeProposerForRound(currentRound.getRoundIdentifier())) {
blockTimer.startTimer(currentRound.getRoundIdentifier(), parentHeader);
blockTimer.startTimer(currentRound.getRoundIdentifier(), parentHeader::getTimestamp);
}
}

View File

@@ -28,7 +28,6 @@ import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.EvictingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +39,6 @@ public class PostMergeContext implements MergeContext {
/** The Max blocks in progress. */
static final int MAX_BLOCKS_IN_PROGRESS = 12;
private static final AtomicReference<PostMergeContext> singleton = new AtomicReference<>();
private final AtomicReference<SyncState> syncState;
private final AtomicReference<Difficulty> terminalTotalDifficulty;
// initial postMerge state is indeterminate until it is set:
@@ -62,8 +60,7 @@ public class PostMergeContext implements MergeContext {
private boolean isPostMergeAtGenesis;
/** Instantiates a new Post merge context. */
@VisibleForTesting
PostMergeContext() {
public PostMergeContext() {
this(Difficulty.ZERO);
}
@@ -72,24 +69,11 @@ public class PostMergeContext implements MergeContext {
*
* @param difficulty the difficulty
*/
@VisibleForTesting
PostMergeContext(final Difficulty difficulty) {
private PostMergeContext(final Difficulty difficulty) {
this.terminalTotalDifficulty = new AtomicReference<>(difficulty);
this.syncState = new AtomicReference<>();
}
/**
* Get post merge context.
*
* @return the post merge context
*/
public static PostMergeContext get() {
if (singleton.get() == null) {
singleton.compareAndSet(null, new PostMergeContext());
}
return singleton.get();
}
@Override
public <C extends ConsensusContext> C as(final Class<C> klass) {
return klass.cast(this);

View File

@@ -14,21 +14,16 @@
*/
package org.hyperledger.besu.consensus.merge;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.datatypes.HardforkId;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.PermissionTransactionFilter;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.math.BigInteger;
import java.util.Optional;
@@ -60,41 +55,6 @@ public class TransitionProtocolSchedule implements ProtocolSchedule {
new TransitionUtils<>(preMergeProtocolSchedule, postMergeProtocolSchedule, mergeContext);
}
/**
* Create a Proof-of-Stake protocol schedule from a config object
*
* @param genesisConfigOptions {@link GenesisConfigOptions} containing the config options for the
* milestone starting points
* @param miningConfiguration the mining parameters
* @param badBlockManager the cache to use to keep invalid blocks
* @param isParallelTxProcessingEnabled indicates whether parallel transaction is enabled.
* @return an initialised TransitionProtocolSchedule using post-merge defaults
*/
public static TransitionProtocolSchedule fromConfig(
final GenesisConfigOptions genesisConfigOptions,
final MiningConfiguration miningConfiguration,
final BadBlockManager badBlockManager,
final boolean isParallelTxProcessingEnabled,
final MetricsSystem metricsSystem) {
ProtocolSchedule preMergeProtocolSchedule =
MainnetProtocolSchedule.fromConfig(
genesisConfigOptions,
miningConfiguration,
badBlockManager,
isParallelTxProcessingEnabled,
metricsSystem);
ProtocolSchedule postMergeProtocolSchedule =
MergeProtocolSchedule.create(
genesisConfigOptions,
false,
miningConfiguration,
badBlockManager,
isParallelTxProcessingEnabled,
metricsSystem);
return new TransitionProtocolSchedule(
preMergeProtocolSchedule, postMergeProtocolSchedule, PostMergeContext.get());
}
/**
* Gets pre merge schedule.
*

View File

@@ -47,10 +47,13 @@ public class TransitionCoordinator extends TransitionUtils<MiningCoordinator>
*
* @param miningCoordinator the mining coordinator
* @param mergeCoordinator the merge coordinator
* @param postMergeContext the post merge context
*/
public TransitionCoordinator(
final MiningCoordinator miningCoordinator, final MiningCoordinator mergeCoordinator) {
super(miningCoordinator, mergeCoordinator, PostMergeContext.get());
final MiningCoordinator miningCoordinator,
final MiningCoordinator mergeCoordinator,
final PostMergeContext postMergeContext) {
super(miningCoordinator, mergeCoordinator, postMergeContext);
this.miningCoordinator = miningCoordinator;
this.mergeCoordinator = (MergeMiningCoordinator) mergeCoordinator;
}

View File

@@ -67,7 +67,7 @@ public class MergeReorgTest implements MergeGenesisConfigHelper {
private MergeCoordinator coordinator;
private final MergeContext mergeContext = PostMergeContext.get();
private final MergeContext mergeContext = new PostMergeContext();
private final ProtocolSchedule mockProtocolSchedule = getMergeProtocolSchedule();
private final GenesisState genesisState =
GenesisState.fromConfig(getPowGenesisConfig(), mockProtocolSchedule);

View File

@@ -19,13 +19,17 @@ import org.hyperledger.besu.consensus.common.bft.BftBlockInterface;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockHashingAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockInterfaceAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftExtraDataProviderAdaptor;
import org.hyperledger.besu.consensus.qbft.core.payload.CommitPayload;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
import org.hyperledger.besu.consensus.qbft.core.types.QbftHashMode;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.cryptoservices.NodeKey;
@@ -42,10 +46,14 @@ public class IntegrationTestHelpers {
final QbftBlock commitBlock =
createCommitBlockFromProposalBlock(block, roundId.getRoundNumber());
final QbftBlockHashing blockHashing =
new QbftBlockHashingAdaptor(new BftBlockHashing(qbftExtraDataEncoder));
final QbftExtraDataProvider extraDataProvider =
new QbftExtraDataProviderAdaptor(qbftExtraDataEncoder);
final SECPSignature commitSeal =
nodeKey.sign(
new BftBlockHashing(qbftExtraDataEncoder)
.calculateDataHashForCommittedSeal(commitBlock.getHeader()));
blockHashing.calculateDataHashForCommittedSeal(
commitBlock.getHeader(), extraDataProvider.getExtraData(commitBlock.getHeader())));
final MessageFactory messageFactory = new MessageFactory(nodeKey, blockEncoder);

View File

@@ -22,14 +22,20 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.EventMultiplexer;
import org.hyperledger.besu.consensus.common.bft.blockcreation.ProposerSelector;
import org.hyperledger.besu.consensus.common.bft.inttest.NodeParams;
import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.qbft.adaptor.BlockUtil;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockHeaderAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockchainAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorProviderAdaptor;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockchain;
import org.hyperledger.besu.consensus.qbft.core.types.QbftEventHandler;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@@ -57,7 +63,7 @@ public class TestContext {
private final Map<Address, ValidatorPeer> remotePeers;
private final MutableBlockchain blockchain;
private final BftExecutors bftExecutors;
private final BftEventHandler controller;
private final QbftEventHandler controller;
private final QbftFinalState finalState;
private final EventMultiplexer eventMultiplexer;
private final MessageFactory messageFactory;
@@ -70,7 +76,7 @@ public class TestContext {
final Map<Address, ValidatorPeer> remotePeers,
final MutableBlockchain blockchain,
final BftExecutors bftExecutors,
final BftEventHandler controller,
final QbftEventHandler controller,
final QbftFinalState finalState,
final EventMultiplexer eventMultiplexer,
final MessageFactory messageFactory,
@@ -96,11 +102,11 @@ public class TestContext {
controller.start();
}
public MutableBlockchain getBlockchain() {
return blockchain;
public QbftBlockchain getBlockchain() {
return new QbftBlockchainAdaptor(blockchain);
}
public BftEventHandler getController() {
public QbftEventHandler getController() {
return controller;
}
@@ -129,25 +135,30 @@ public class TestContext {
public QbftBlock createBlockForProposalFromChainHead(
final long timestamp, final Address proposer) {
// this implies that EVERY block will have this node as the proposer :/
return createBlockForProposal(blockchain.getChainHeadHeader(), timestamp, proposer, 0);
return createBlockForProposal(
new QbftBlockHeaderAdaptor(blockchain.getChainHeadHeader()), timestamp, proposer, 0);
}
public QbftBlock createBlockForProposalFromChainHead(
final long timestamp, final Address proposer, final int roundNumber) {
// this implies that EVERY block will have this node as the proposer :/
return createBlockForProposal(
blockchain.getChainHeadHeader(), timestamp, proposer, roundNumber);
new QbftBlockHeaderAdaptor(blockchain.getChainHeadHeader()),
timestamp,
proposer,
roundNumber);
}
public QbftBlock createBlockForProposal(
final BlockHeader parent,
final QbftBlockHeader parent,
final long timestamp,
final Address proposer,
final int roundNumber) {
final QbftBlock block =
finalState.getBlockCreatorFactory().create(roundNumber).createBlock(timestamp, parent);
final BlockHeaderBuilder headerBuilder = BlockHeaderBuilder.fromHeader(block.getHeader());
final BlockHeaderBuilder headerBuilder =
BlockHeaderBuilder.fromHeader(BlockUtil.toBesuBlockHeader(block.getHeader()));
headerBuilder
.coinbase(proposer)
.blockHeaderFunctions(BftBlockHeaderFunctions.forCommittedSeal(bftExtraDataCodec));
@@ -158,7 +169,7 @@ public class TestContext {
}
public QbftBlock createBlockForProposal(
final BlockHeader parent, final long timestamp, final Address proposer) {
final QbftBlockHeader parent, final long timestamp, final Address proposer) {
return createBlockForProposal(parent, timestamp, proposer, 0);
}
@@ -192,12 +203,16 @@ public class TestContext {
return blockchain.getChainHeadBlockNumber();
}
public ValidatorProvider getValidatorProvider() {
return validatorProvider;
public QbftValidatorProvider getValidatorProvider() {
return new QbftValidatorProviderAdaptor(validatorProvider);
}
public void appendBlock(final QbftBlock signedCurrentHeightBlock) {
blockchain.appendBlock(
BlockUtil.toBesuBlock(signedCurrentHeightBlock), Collections.emptyList());
}
public QbftBlockHeader getBlockHeader(final int blockNumber) {
return new QbftBlockHeaderAdaptor(blockchain.getBlockHeader(blockNumber).get());
}
}

View File

@@ -32,6 +32,7 @@ import org.hyperledger.besu.config.StubGenesisConfigOptions;
import org.hyperledger.besu.consensus.common.BftValidatorOverrides;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.ForksSchedule;
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions;
import org.hyperledger.besu.consensus.common.bft.BftBlockInterface;
import org.hyperledger.besu.consensus.common.bft.BftContext;
@@ -54,7 +55,6 @@ import org.hyperledger.besu.consensus.common.bft.inttest.NodeParams;
import org.hyperledger.besu.consensus.common.bft.inttest.StubValidatorMulticaster;
import org.hyperledger.besu.consensus.common.bft.inttest.StubbedSynchronizerUpdater;
import org.hyperledger.besu.consensus.common.bft.inttest.TestTransitions;
import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler;
import org.hyperledger.besu.consensus.common.bft.statemachine.FutureMessageBuffer;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.common.validator.blockbased.BlockValidatorProvider;
@@ -62,12 +62,17 @@ import org.hyperledger.besu.consensus.qbft.MutableQbftConfigOptions;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.QbftForksSchedulesFactory;
import org.hyperledger.besu.consensus.qbft.QbftProtocolScheduleBuilder;
import org.hyperledger.besu.consensus.qbft.adaptor.BftEventHandlerAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockCodecAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockCreatorFactoryAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockHashingAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockInterfaceAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockchainAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftExtraDataProviderAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftFinalStateImpl;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftProtocolScheduleAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorModeTransitionLoggerAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorProviderAdaptor;
import org.hyperledger.besu.consensus.qbft.blockcreation.QbftBlockCreatorFactory;
import org.hyperledger.besu.consensus.qbft.core.network.QbftGossip;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
@@ -75,16 +80,19 @@ import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftBlockHeightMana
import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftController;
import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftRoundFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
import org.hyperledger.besu.consensus.qbft.core.types.QbftEventHandler;
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.consensus.qbft.core.types.QbftMinedBlockObserver;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory;
import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.consensus.qbft.validator.ForkingValidatorProvider;
import org.hyperledger.besu.consensus.qbft.validator.TransactionValidatorProvider;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorContractController;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.cryptoservices.NodeKey;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
@@ -148,7 +156,7 @@ public class TestContextBuilder {
"UnusedVariable") // false positive https://github.com/google/error-prone/issues/2713
private record ControllerAndState(
BftExecutors bftExecutors,
BftEventHandler eventHandler,
QbftEventHandler eventHandler,
QbftFinalState finalState,
EventMultiplexer eventMultiplexer,
MessageFactory messageFactory,
@@ -470,6 +478,8 @@ public class TestContextBuilder {
final ValidatorProvider validatorProvider =
new ForkingValidatorProvider(
blockChain, forksSchedule, blockValidatorProvider, transactionValidatorProvider);
final QbftValidatorProvider qbftValidatorProvider =
new QbftValidatorProviderAdaptor(validatorProvider);
final ProtocolContext bftProtocolContext =
new ProtocolContext(
@@ -481,7 +491,7 @@ public class TestContextBuilder {
new ProtocolContext(
blockChain,
worldStateArchive,
new QbftContext(validatorProvider, qbftBlockInterface),
new QbftContext(qbftValidatorProvider, qbftBlockInterface),
new BadBlockManager());
final TransactionPoolConfiguration poolConf =
@@ -555,10 +565,15 @@ public class TestContextBuilder {
blockChain.getChainHeadBlockNumber());
final QbftExtraDataProvider qbftExtraDataProvider =
new QbftExtraDataProviderAdaptor(BFT_EXTRA_DATA_ENCODER);
final QbftBlockHashing blockHashing =
new QbftBlockHashingAdaptor(new BftBlockHashing(BFT_EXTRA_DATA_ENCODER));
final QbftValidatorModeTransitionLoggerAdaptor validatorModeTransitionLogger =
new QbftValidatorModeTransitionLoggerAdaptor(
new ValidatorModeTransitionLogger(forksSchedule));
final QbftController qbftController =
new QbftController(
blockChain,
new QbftBlockchainAdaptor(blockChain),
finalState,
new QbftBlockHeightManagerFactory(
finalState,
@@ -570,17 +585,19 @@ public class TestContextBuilder {
messageValidatorFactory,
messageFactory,
BFT_EXTRA_DATA_ENCODER,
qbftExtraDataProvider),
qbftExtraDataProvider,
blockHashing),
messageValidatorFactory,
messageFactory,
new ValidatorModeTransitionLogger(forksSchedule)),
validatorModeTransitionLogger),
gossiper,
duplicateMessageTracker,
futureMessageBuffer,
synchronizerUpdater,
blockEncoder);
final EventMultiplexer eventMultiplexer = new EventMultiplexer(qbftController);
final EventMultiplexer eventMultiplexer =
new EventMultiplexer(new BftEventHandlerAdaptor(qbftController));
//////////////////////////// END QBFT BesuController ////////////////////////////
return new ControllerAndState(

View File

@@ -19,7 +19,6 @@ import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHe
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare;
@@ -28,6 +27,7 @@ import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers;
import org.hyperledger.besu.consensus.qbft.core.support.TestContext;
import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftNewChainHead;
import java.time.Clock;
import java.time.Instant;
@@ -94,7 +94,7 @@ public class FutureHeightTest {
assertThat(context.getCurrentChainHeight()).isEqualTo(1);
context
.getController()
.handleNewBlockEvent(new NewChainHead(signedCurrentHeightBlock.getHeader()));
.handleNewBlockEvent(new QbftNewChainHead(signedCurrentHeightBlock.getHeader()));
final Prepare expectedPrepareMessage =
localNodeMessageFactory.createPrepare(futureHeightRoundId, futureHeightBlock.getHash());
@@ -132,7 +132,7 @@ public class FutureHeightTest {
assertThat(context.getCurrentChainHeight()).isEqualTo(1);
context
.getController()
.handleNewBlockEvent(new NewChainHead(signedCurrentHeightBlock.getHeader()));
.handleNewBlockEvent(new QbftNewChainHead(signedCurrentHeightBlock.getHeader()));
// Inject prepares and commits from all peers for the 'previous' round (i.e. the height
// from before the block arrived).
@@ -156,7 +156,7 @@ public class FutureHeightTest {
context
.getController()
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
.handleNewBlockEvent(new QbftNewChainHead(context.getBlockchain().getChainHeadHeader()));
// Should only require 1 more prepare to close it out
peers.getNonProposing(1).injectPrepare(roundId, currentHeightBlock.getHash());
@@ -201,7 +201,7 @@ public class FutureHeightTest {
assertThat(context.getCurrentChainHeight()).isEqualTo(1);
context
.getController()
.handleNewBlockEvent(new NewChainHead(signedCurrentHeightBlock.getHeader()));
.handleNewBlockEvent(new QbftNewChainHead(signedCurrentHeightBlock.getHeader()));
peers.verifyNoMessagesReceived();
peers.getProposer().injectProposal(nextHeightRoundId, nextHeightBlock);
@@ -221,7 +221,7 @@ public class FutureHeightTest {
assertThat(context.getCurrentChainHeight()).isEqualTo(2);
context
.getController()
.handleNewBlockEvent(new NewChainHead(signedNextHeightBlock.getHeader()));
.handleNewBlockEvent(new QbftNewChainHead(signedNextHeightBlock.getHeader()));
final Prepare expectedFuturePrepareMessage =
localNodeMessageFactory.createPrepare(futureHeightRoundId, futureHeightBlock.getHash());

View File

@@ -17,7 +17,6 @@ package org.hyperledger.besu.consensus.qbft.core.test;
import static java.util.Collections.emptyList;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit;
@@ -30,6 +29,7 @@ import org.hyperledger.besu.consensus.qbft.core.support.TestContext;
import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder;
import org.hyperledger.besu.consensus.qbft.core.support.ValidatorPeer;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftNewChainHead;
import org.hyperledger.besu.cryptoservices.NodeKeyUtils;
import java.time.Clock;
@@ -170,7 +170,7 @@ public class GossipTest {
context.appendBlock(signedCurrentHeightBlock);
context
.getController()
.handleNewBlockEvent(new NewChainHead(signedCurrentHeightBlock.getHeader()));
.handleNewBlockEvent(new QbftNewChainHead(signedCurrentHeightBlock.getHeader()));
peers.verifyMessagesReceivedNonProposing(futurePrepare);
}

View File

@@ -19,7 +19,6 @@ import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHe
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare;
@@ -29,6 +28,7 @@ import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers;
import org.hyperledger.besu.consensus.qbft.core.support.TestContext;
import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftNewChainHead;
import java.time.Clock;
import java.time.Instant;
@@ -138,7 +138,7 @@ public class LocalNodeIsProposerTest {
context
.getController()
.handleNewBlockEvent(new NewChainHead(expectedProposedBlock.getHeader()));
.handleNewBlockEvent(new QbftNewChainHead(expectedProposedBlock.getHeader()));
peers.verifyNoMessagesReceived();
}

View File

@@ -20,10 +20,10 @@ import org.hyperledger.besu.config.BftFork;
import org.hyperledger.besu.config.JsonUtil;
import org.hyperledger.besu.config.QbftFork;
import org.hyperledger.besu.consensus.common.bft.BftEventQueue;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.qbft.core.support.TestContext;
import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftNewChainHead;
import org.hyperledger.besu.testutil.TestClock;
import java.time.Instant;
@@ -63,13 +63,13 @@ public class TransitionsTest {
context
.getController()
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
.handleNewBlockEvent(new QbftNewChainHead(context.getBlockchain().getChainHeadHeader()));
clock.stepMillis(20_000);
context.getEventMultiplexer().handleBftEvent(bftEventQueue.poll(1, TimeUnit.SECONDS));
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader blockHeader1 = context.getBlockchain().getBlockHeader(1).get();
final BlockHeader blockHeader2 = context.getBlockchain().getBlockHeader(2).get();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader blockHeader1 = context.getBlockHeader(1);
final QbftBlockHeader blockHeader2 = context.getBlockHeader(2);
assertThat(blockHeader1.getTimestamp()).isEqualTo(genesisBlock.getTimestamp() + 10);
assertThat(blockHeader2.getTimestamp()).isEqualTo(blockHeader1.getTimestamp() + 20);

View File

@@ -23,18 +23,20 @@ import org.hyperledger.besu.config.QbftFork;
import org.hyperledger.besu.config.QbftFork.VALIDATOR_SELECTION_MODE;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.common.bft.inttest.NodeParams;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftExtraDataProviderAdaptor;
import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers;
import org.hyperledger.besu.consensus.qbft.core.support.TestContext;
import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder;
import org.hyperledger.besu.consensus.qbft.core.support.ValidatorPeer;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
import org.hyperledger.besu.consensus.qbft.core.types.QbftNewChainHead;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
import org.hyperledger.besu.cryptoservices.NodeKeyUtils;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.testutil.TestClock;
import java.time.Instant;
@@ -66,7 +68,8 @@ public class ValidatorContractTest {
private TestClock clock;
private final QbftExtraDataCodec extraDataCodec = new QbftExtraDataCodec();
private final QbftExtraDataProvider extraDataProvider =
new QbftExtraDataProviderAdaptor(new QbftExtraDataCodec());
@BeforeEach
public void setup() {
@@ -87,9 +90,9 @@ public class ValidatorContractTest {
createNewBlockAsProposer(context, 1);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).containsExactly(NODE_ADDRESS);
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
}
@@ -109,9 +112,9 @@ public class ValidatorContractTest {
createNewBlockAsProposer(context, 1);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).containsExactly(NODE_ADDRESS);
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
}
@@ -133,9 +136,9 @@ public class ValidatorContractTest {
createNewBlockAsProposer(context, 1);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).containsExactly(NODE_ADDRESS);
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
}
@@ -160,9 +163,9 @@ public class ValidatorContractTest {
context, 1,
266L); // 10s ahead of genesis timestamp in genesis_validator_contract_shanghai.json
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).containsExactly(NODE_ADDRESS);
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
}
@@ -184,9 +187,9 @@ public class ValidatorContractTest {
createNewBlockAsProposer(context, 1);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).containsExactly(NODE_ADDRESS);
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
}
@@ -211,9 +214,9 @@ public class ValidatorContractTest {
context, 1,
266L); // 10s ahead of genesis timestamp in genesis_validator_contract_shanghai.json
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).containsExactly(NODE_ADDRESS);
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
}
@@ -244,17 +247,18 @@ public class ValidatorContractTest {
remotePeerProposesNewBlock(context, 1L);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).isEqualTo(block0Addresses);
assertThat(extraDataCodec.decode(genesisBlock).getValidators()).containsExactly(NODE_ADDRESS);
assertThat(extraDataProvider.getExtraData(genesisBlock).getValidators())
.containsExactly(NODE_ADDRESS);
// contract block extra data cannot contain validators or vote
assertThat(validatorProvider.getValidatorsForBlock(block1)).isEqualTo(block1Addresses);
assertThat(extraDataCodec.decode(block1).getValidators()).isEmpty();
assertThat(extraDataCodec.decode(block1).getVote()).isEmpty();
assertThat(extraDataProvider.getExtraData(block1).getValidators()).isEmpty();
assertThat(extraDataProvider.getExtraData(block1).getVote()).isEmpty();
}
@Test
@@ -282,19 +286,19 @@ public class ValidatorContractTest {
remotePeerProposesNewBlock(context, 1L);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
// contract block extra data cannot contain validators or vote
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).isEqualTo(block0Addresses);
assertThat(extraDataCodec.decode(genesisBlock).getValidators()).isEmpty();
assertThat(extraDataCodec.decode(genesisBlock).getVote()).isEmpty();
assertThat(extraDataProvider.getExtraData(genesisBlock).getValidators()).isEmpty();
assertThat(extraDataProvider.getExtraData(genesisBlock).getVote()).isEmpty();
// contract block extra data cannot contain validators or vote
assertThat(validatorProvider.getValidatorsForBlock(block1)).isEqualTo(block1Addresses);
assertThat(extraDataCodec.decode(block1).getValidators()).isEmpty();
assertThat(extraDataCodec.decode(block1).getVote()).isEmpty();
assertThat(extraDataProvider.getExtraData(block1).getValidators()).isEmpty();
assertThat(extraDataProvider.getExtraData(block1).getVote()).isEmpty();
}
@Test
@@ -325,24 +329,24 @@ public class ValidatorContractTest {
clock.step(TestContextBuilder.BLOCK_TIMER_SEC, SECONDS);
remotePeerProposesNewBlock(context, 2L);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final BlockHeader block2 = context.getBlockchain().getBlockHeader(2).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
final QbftBlockHeader block2 = context.getBlockHeader(2);
// contract block extra data cannot contain validators or vote
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).isEqualTo(block0Addresses);
assertThat(extraDataCodec.decode(genesisBlock).getValidators()).isEmpty();
assertThat(extraDataCodec.decode(genesisBlock).getVote()).isEmpty();
assertThat(extraDataProvider.getExtraData(genesisBlock).getValidators()).isEmpty();
assertThat(extraDataProvider.getExtraData(genesisBlock).getVote()).isEmpty();
// uses overridden validators
assertThat(validatorProvider.getValidatorsForBlock(block1)).isEqualTo(block1Addresses);
assertThat(extraDataCodec.decode(block1).getValidators())
assertThat(extraDataProvider.getExtraData(block1).getValidators())
.containsExactly(NODE_2_ADDRESS, NODE_ADDRESS);
// uses cached validators
assertThat(validatorProvider.getValidatorsForBlock(block2)).isEqualTo(block1Addresses);
assertThat(extraDataCodec.decode(block2).getValidators())
assertThat(extraDataProvider.getExtraData(block2).getValidators())
.containsExactly(NODE_2_ADDRESS, NODE_ADDRESS);
}
@@ -381,28 +385,29 @@ public class ValidatorContractTest {
clock.step(TestContextBuilder.BLOCK_TIMER_SEC, SECONDS);
remotePeerProposesNewBlock(context, 3L);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final BlockHeader block2 = context.getBlockchain().getBlockHeader(2).get();
final BlockHeader block3 = context.getBlockchain().getBlockHeader(3).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
final QbftBlockHeader block2 = context.getBlockHeader(2);
final QbftBlockHeader block3 = context.getBlockHeader(3);
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).isEqualTo(block0Addresses);
assertThat(extraDataCodec.decode(genesisBlock).getValidators()).containsExactly(NODE_ADDRESS);
assertThat(extraDataProvider.getExtraData(genesisBlock).getValidators())
.containsExactly(NODE_ADDRESS);
// contract block extra data cannot contain validators or vote
assertThat(validatorProvider.getValidatorsForBlock(block1)).isEqualTo(block1Addresses);
assertThat(extraDataCodec.decode(block1).getValidators()).isEmpty();
assertThat(extraDataCodec.decode(block1).getVote()).isEmpty();
assertThat(extraDataProvider.getExtraData(block1).getValidators()).isEmpty();
assertThat(extraDataProvider.getExtraData(block1).getVote()).isEmpty();
// uses overridden validators
assertThat(validatorProvider.getValidatorsForBlock(block2)).isEqualTo(block1Addresses);
assertThat(extraDataCodec.decode(block2).getValidators())
assertThat(extraDataProvider.getExtraData(block2).getValidators())
.containsExactly(NODE_2_ADDRESS, NODE_ADDRESS);
// uses cached validators
assertThat(validatorProvider.getValidatorsForBlock(block3)).isEqualTo(block1Addresses);
assertThat(extraDataCodec.decode(block3).getValidators())
assertThat(extraDataProvider.getExtraData(block3).getValidators())
.containsExactly(NODE_2_ADDRESS, NODE_ADDRESS);
}
@@ -438,23 +443,24 @@ public class ValidatorContractTest {
clock.step(TestContextBuilder.BLOCK_TIMER_SEC, SECONDS);
remotePeerProposesNewBlock(context, 2L);
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
final BlockHeader block2 = context.getBlockchain().getBlockHeader(2).get();
final QbftValidatorProvider validatorProvider = context.getValidatorProvider();
final QbftBlockHeader genesisBlock = context.getBlockHeader(0);
final QbftBlockHeader block1 = context.getBlockHeader(1);
final QbftBlockHeader block2 = context.getBlockHeader(2);
// contract block extra data cannot contain validators or vote
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).isEqualTo(block0Addresses);
assertThat(extraDataCodec.decode(genesisBlock).getValidators()).isEmpty();
assertThat(extraDataCodec.decode(genesisBlock).getVote()).isEmpty();
assertThat(extraDataProvider.getExtraData(genesisBlock).getValidators()).isEmpty();
assertThat(extraDataProvider.getExtraData(genesisBlock).getVote()).isEmpty();
assertThat(validatorProvider.getValidatorsForBlock(block1)).isEqualTo(block1Addresses);
assertThat(extraDataCodec.decode(block1).getValidators()).containsExactly(NODE_2_ADDRESS);
assertThat(extraDataProvider.getExtraData(block1).getValidators())
.containsExactly(NODE_2_ADDRESS);
// contract block extra data cannot contain validators or vote
assertThat(validatorProvider.getValidatorsForBlock(block2)).isEqualTo(block2Addresses);
assertThat(extraDataCodec.decode(block2).getValidators()).isEmpty();
assertThat(extraDataCodec.decode(block2).getVote()).isEmpty();
assertThat(extraDataProvider.getExtraData(block2).getValidators()).isEmpty();
assertThat(extraDataProvider.getExtraData(block2).getVote()).isEmpty();
}
private void createNewBlockAsProposer(final TestContext context, final long blockNumber) {
@@ -472,7 +478,7 @@ public class ValidatorContractTest {
assertThat(context.getCurrentChainHeight()).isEqualTo(blockNumber);
context
.getController()
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
.handleNewBlockEvent(new QbftNewChainHead(context.getBlockchain().getChainHeadHeader()));
}
private void createNewBlockAsProposerFixedTime(
@@ -490,7 +496,7 @@ public class ValidatorContractTest {
assertThat(context.getCurrentChainHeight()).isEqualTo(blockNumber);
context
.getController()
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
.handleNewBlockEvent(new QbftNewChainHead(context.getBlockchain().getChainHeadHeader()));
}
private void remotePeerProposesNewBlock(final TestContext context, final long blockNumber) {
@@ -507,7 +513,7 @@ public class ValidatorContractTest {
context
.getController()
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
.handleNewBlockEvent(new QbftNewChainHead(context.getBlockchain().getChainHeadHeader()));
}
private QbftFork createContractFork(final long block, final Address contractAddress) {

View File

@@ -30,6 +30,7 @@ import org.hyperledger.besu.consensus.common.bft.RoundTimer;
import org.hyperledger.besu.consensus.common.bft.inttest.StubValidatorMulticaster;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockHeaderAdaptor;
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockInterfaceAdaptor;
import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
@@ -38,6 +39,8 @@ import org.hyperledger.besu.consensus.qbft.core.statemachine.RoundState;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockImporter;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
@@ -97,9 +100,10 @@ public class QbftRoundIntegrationTest {
private MessageFactory throwingMessageFactory;
private QbftMessageTransmitter transmitter;
@Mock private StubValidatorMulticaster multicaster;
@Mock private BlockHeader parentHeader;
@Mock private QbftBlockHeader parentHeader;
@Mock private QbftBlockCodec blockEncoder;
@Mock private QbftExtraDataProvider qbftExtraDataProvider;
@Mock private QbftBlockHashing blockHashing;
private QbftBlock proposedBlock;
@@ -129,8 +133,9 @@ public class QbftRoundIntegrationTest {
headerTestFixture.number(1);
final BlockHeader header = headerTestFixture.buildHeader();
final Block block = new Block(header, new BlockBody(emptyList(), emptyList()));
final QbftBlockHeader qbftBlockHeader = new QbftBlockHeaderAdaptor(header);
proposedBlock = new QbftBlockAdaptor(block);
when(qbftExtraDataProvider.getExtraData(header)).thenReturn(proposedExtraData);
when(qbftExtraDataProvider.getExtraData(qbftBlockHeader)).thenReturn(proposedExtraData);
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
@@ -163,6 +168,7 @@ public class QbftRoundIntegrationTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
round.handleProposalMessage(
@@ -203,6 +209,7 @@ public class QbftRoundIntegrationTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
// inject a block first, then a prepare on it.

View File

@@ -14,14 +14,43 @@
*/
package org.hyperledger.besu.consensus.qbft.core.statemachine;
import org.hyperledger.besu.consensus.common.bft.statemachine.BaseBlockHeightManager;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
/** The interface Base qbft block height manager. */
public interface BaseQbftBlockHeightManager extends BaseBlockHeightManager {
public interface BaseQbftBlockHeightManager {
/**
* Handle block timer expiry.
*
* @param roundIdentifier the round identifier
*/
void handleBlockTimerExpiry(ConsensusRoundIdentifier roundIdentifier);
/**
* Round expired.
*
* @param expire the expiry
*/
void roundExpired(RoundExpiry expire);
/**
* Gets chain height.
*
* @return the chain height
*/
long getChainHeight();
/**
* Gets parent block header.
*
* @return the parent block header
*/
QbftBlockHeader getParentBlockHeader();
/**
* Handle proposal payload.

View File

@@ -20,19 +20,19 @@ import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
/** The type NoOp block height manager. */
public class NoOpBlockHeightManager implements BaseQbftBlockHeightManager {
private final BlockHeader parentHeader;
private final QbftBlockHeader parentHeader;
/**
* Instantiates a new NoOp block height manager.
*
* @param parentHeader the parent header
*/
public NoOpBlockHeightManager(final BlockHeader parentHeader) {
public NoOpBlockHeightManager(final QbftBlockHeader parentHeader) {
this.parentHeader = parentHeader;
}
@@ -60,7 +60,7 @@ public class NoOpBlockHeightManager implements BaseQbftBlockHeightManager {
}
@Override
public BlockHeader getParentBlockHeader() {
public QbftBlockHeader getParentBlockHeader() {
return parentHeader;
}
}

View File

@@ -25,11 +25,11 @@ import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.consensus.qbft.core.validation.FutureRoundProposalMessageValidator;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import java.time.Clock;
@@ -57,7 +57,7 @@ public class QbftBlockHeightManager implements BaseQbftBlockHeightManager {
private final QbftRoundFactory roundFactory;
private final RoundChangeManager roundChangeManager;
private final BlockHeader parentHeader;
private final QbftBlockHeader parentHeader;
private final QbftMessageTransmitter transmitter;
private final MessageFactory messageFactory;
private final Map<Integer, RoundState> futureRoundStateBuffer = Maps.newHashMap();
@@ -82,7 +82,7 @@ public class QbftBlockHeightManager implements BaseQbftBlockHeightManager {
* @param messageFactory the message factory
*/
public QbftBlockHeightManager(
final BlockHeader parentHeader,
final QbftBlockHeader parentHeader,
final QbftFinalState finalState,
final RoundChangeManager roundChangeManager,
final QbftRoundFactory qbftRoundFactory,
@@ -113,7 +113,7 @@ public class QbftBlockHeightManager implements BaseQbftBlockHeightManager {
final ConsensusRoundIdentifier roundIdentifier =
new ConsensusRoundIdentifier(nextBlockHeight, 0);
finalState.getBlockTimer().startTimer(roundIdentifier, parentHeader);
finalState.getBlockTimer().startTimer(roundIdentifier, parentHeader::getTimestamp);
}
/**
@@ -130,7 +130,7 @@ public class QbftBlockHeightManager implements BaseQbftBlockHeightManager {
* @param isEarlyRoundChangeEnabled enable round change when f+1 RC messages are received
*/
public QbftBlockHeightManager(
final BlockHeader parentHeader,
final QbftBlockHeader parentHeader,
final QbftFinalState finalState,
final RoundChangeManager roundChangeManager,
final QbftRoundFactory qbftRoundFactory,
@@ -199,7 +199,9 @@ public class QbftBlockHeightManager implements BaseQbftBlockHeightManager {
// handle the block times period
final long currentTimeInMillis = finalState.getClock().millis();
boolean emptyBlockExpired =
finalState.getBlockTimer().checkEmptyBlockExpired(parentHeader, currentTimeInMillis);
finalState
.getBlockTimer()
.checkEmptyBlockExpired(parentHeader::getTimestamp, currentTimeInMillis);
if (emptyBlockExpired) {
LOG.trace(
"Block has no transactions and this node is a proposer so it will send a proposal: "
@@ -211,7 +213,8 @@ public class QbftBlockHeightManager implements BaseQbftBlockHeightManager {
+ roundIdentifier);
finalState
.getBlockTimer()
.resetTimerForEmptyBlock(roundIdentifier, parentHeader, currentTimeInMillis);
.resetTimerForEmptyBlock(
roundIdentifier, parentHeader::getTimestamp, currentTimeInMillis);
finalState.getRoundTimer().cancelTimer();
currentRound = Optional.empty();
}
@@ -452,7 +455,7 @@ public class QbftBlockHeightManager implements BaseQbftBlockHeightManager {
}
@Override
public BlockHeader getParentBlockHeader() {
public QbftBlockHeader getParentBlockHeader() {
return parentHeader;
}

View File

@@ -16,10 +16,10 @@ package org.hyperledger.besu.consensus.qbft.core.statemachine;
import org.hyperledger.besu.consensus.common.bft.BftHelpers;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorModeTransitionLogger;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory;
import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +33,7 @@ public class QbftBlockHeightManagerFactory {
private final QbftFinalState finalState;
private final MessageValidatorFactory messageValidatorFactory;
private final MessageFactory messageFactory;
private final ValidatorModeTransitionLogger validatorModeTransitionLogger;
private final QbftValidatorModeTransitionLogger validatorModeTransitionLogger;
private boolean isEarlyRoundChangeEnabled = false;
/**
@@ -50,7 +50,7 @@ public class QbftBlockHeightManagerFactory {
final QbftRoundFactory roundFactory,
final MessageValidatorFactory messageValidatorFactory,
final MessageFactory messageFactory,
final ValidatorModeTransitionLogger validatorModeTransitionLogger) {
final QbftValidatorModeTransitionLogger validatorModeTransitionLogger) {
this.roundFactory = roundFactory;
this.finalState = finalState;
this.messageValidatorFactory = messageValidatorFactory;
@@ -64,7 +64,7 @@ public class QbftBlockHeightManagerFactory {
* @param parentHeader the parent header
* @return the base qbft block height manager
*/
public BaseQbftBlockHeightManager create(final BlockHeader parentHeader) {
public BaseQbftBlockHeightManager create(final QbftBlockHeader parentHeader) {
validatorModeTransitionLogger.logTransitionChange(parentHeader);
if (finalState.isLocalNodeValidator()) {
@@ -85,11 +85,13 @@ public class QbftBlockHeightManagerFactory {
this.isEarlyRoundChangeEnabled = isEarlyRoundChangeEnabled;
}
private BaseQbftBlockHeightManager createNoOpBlockHeightManager(final BlockHeader parentHeader) {
private BaseQbftBlockHeightManager createNoOpBlockHeightManager(
final QbftBlockHeader parentHeader) {
return new NoOpBlockHeightManager(parentHeader);
}
private BaseQbftBlockHeightManager createFullBlockHeightManager(final BlockHeader parentHeader) {
private BaseQbftBlockHeightManager createFullBlockHeightManager(
final QbftBlockHeader parentHeader) {
QbftBlockHeightManager qbftBlockHeightManager;
RoundChangeManager roundChangeManager;

View File

@@ -20,11 +20,9 @@ import org.hyperledger.besu.consensus.common.bft.MessageTracker;
import org.hyperledger.besu.consensus.common.bft.SynchronizerUpdater;
import org.hyperledger.besu.consensus.common.bft.events.BftReceivedMessageEvent;
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry;
import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage;
import org.hyperledger.besu.consensus.common.bft.payload.Authored;
import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler;
import org.hyperledger.besu.consensus.common.bft.statemachine.FutureMessageBuffer;
import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData;
import org.hyperledger.besu.consensus.qbft.core.messagedata.PrepareMessageData;
@@ -32,9 +30,11 @@ import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData;
import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1;
import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockchain;
import org.hyperledger.besu.consensus.qbft.core.types.QbftEventHandler;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftNewChainHead;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
@@ -45,10 +45,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** The Qbft controller. */
public class QbftController implements BftEventHandler {
public class QbftController implements QbftEventHandler {
private static final Logger LOG = LoggerFactory.getLogger(QbftController.class);
private final Blockchain blockchain;
private final QbftBlockchain blockchain;
private final QbftFinalState finalState;
private final FutureMessageBuffer futureMessageBuffer;
private final Gossiper gossiper;
@@ -72,7 +72,7 @@ public class QbftController implements BftEventHandler {
* @param blockEncoder the block encoder
*/
public QbftController(
final Blockchain blockchain,
final QbftBlockchain blockchain,
final QbftFinalState finalState,
final QbftBlockHeightManagerFactory qbftBlockHeightManagerFactory,
final Gossiper gossiper,
@@ -131,7 +131,7 @@ public class QbftController implements BftEventHandler {
}
}
private void createNewHeightManager(final BlockHeader parentHeader) {
private void createNewHeightManager(final QbftBlockHeader parentHeader) {
currentHeightManager = qbftBlockHeightManagerFactory.create(parentHeader);
}
@@ -187,9 +187,9 @@ public class QbftController implements BftEventHandler {
}
@Override
public void handleNewBlockEvent(final NewChainHead newChainHead) {
final BlockHeader newBlockHeader = newChainHead.getNewChainHeadHeader();
final BlockHeader currentMiningParent = getCurrentHeightManager().getParentBlockHeader();
public void handleNewBlockEvent(final QbftNewChainHead newChainHead) {
final QbftBlockHeader newBlockHeader = newChainHead.newChainHeadHeader();
final QbftBlockHeader currentMiningParent = getCurrentHeightManager().getParentBlockHeader();
LOG.debug(
"New chain head detected (block number={})," + " currently mining on top of {}.",
newBlockHeader.getNumber(),
@@ -251,7 +251,7 @@ public class QbftController implements BftEventHandler {
}
}
private void startNewHeightManager(final BlockHeader parentHeader) {
private void startNewHeightManager(final QbftBlockHeader parentHeader) {
createNewHeightManager(parentHeader);
final long newChainHeight = getCurrentHeightManager().getChainHeight();
futureMessageBuffer.retrieveMessagesForHeight(newChainHeight).forEach(this::handleMessage);

View File

@@ -16,7 +16,6 @@ package org.hyperledger.besu.consensus.qbft.core.statemachine;
import static java.util.Collections.emptyList;
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
@@ -31,6 +30,8 @@ import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockImporter;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
@@ -42,7 +43,6 @@ import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.cryptoservices.NodeKey;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers;
@@ -81,7 +81,8 @@ public class QbftRound {
/** The Bft extra data provider */
protected final QbftExtraDataProvider qbftExtraDataProvider;
private final BlockHeader parentHeader;
private final QbftBlockHashing blockHashing;
private final QbftBlockHeader parentHeader;
/**
* Instantiates a new Qbft round.
@@ -97,6 +98,7 @@ public class QbftRound {
* @param roundTimer the round timer
* @param bftExtraDataCodec the bft extra data codec
* @param qbftExtraDataProvider the qbft extra data provider
* @param blockHashing the block hashing
* @param parentHeader the parent header
*/
public QbftRound(
@@ -111,7 +113,8 @@ public class QbftRound {
final RoundTimer roundTimer,
final BftExtraDataCodec bftExtraDataCodec,
final QbftExtraDataProvider qbftExtraDataProvider,
final BlockHeader parentHeader) {
final QbftBlockHashing blockHashing,
final QbftBlockHeader parentHeader) {
this.roundState = roundState;
this.blockCreator = blockCreator;
this.protocolContext = protocolContext;
@@ -122,6 +125,7 @@ public class QbftRound {
this.transmitter = transmitter;
this.bftExtraDataCodec = bftExtraDataCodec;
this.qbftExtraDataProvider = qbftExtraDataProvider;
this.blockHashing = blockHashing;
this.parentHeader = parentHeader;
roundTimer.startTimer(getRoundIdentifier());
}
@@ -166,7 +170,7 @@ public class QbftRound {
"Sending proposal from PreparedCertificate. round={}", roundState.getRoundIdentifier());
QbftBlock preparedBlock = bestPreparedCertificate.get().getBlock();
final QbftBlockInterface bftBlockInterface =
protocolContext.getConsensusContext(QbftContext.class).getBlockInterface();
protocolContext.getConsensusContext(QbftContext.class).blockInterface();
blockToPublish =
bftBlockInterface.replaceRoundInBlock(
preparedBlock,
@@ -391,17 +395,16 @@ public class QbftRound {
private SECPSignature createCommitSeal(final QbftBlock block) {
final QbftBlock commitBlock = createCommitBlock(block);
final BlockHeader proposedHeader = commitBlock.getHeader();
final QbftBlockHeader proposedHeader = commitBlock.getHeader();
final BftExtraData extraData = qbftExtraDataProvider.getExtraData(proposedHeader);
final Hash commitHash =
new BftBlockHashing(bftExtraDataCodec)
.calculateDataHashForCommittedSeal(proposedHeader, extraData);
blockHashing.calculateDataHashForCommittedSeal(proposedHeader, extraData);
return nodeKey.sign(commitHash);
}
private QbftBlock createCommitBlock(final QbftBlock block) {
final QbftBlockInterface bftBlockInterface =
protocolContext.getConsensusContext(QbftContext.class).getBlockInterface();
protocolContext.getConsensusContext(QbftContext.class).blockInterface();
return bftBlockInterface.replaceRoundInBlock(
block, getRoundIdentifier().getRoundNumber(), QbftHashMode.COMMITTED_SEAL);
}

View File

@@ -20,13 +20,14 @@ import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreatorFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.consensus.qbft.core.types.QbftMinedBlockObserver;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.util.Subscribers;
/** The Qbft round factory. */
@@ -41,6 +42,7 @@ public class QbftRoundFactory {
private final MessageFactory messageFactory;
private final BftExtraDataCodec bftExtraDataCodec;
private final QbftExtraDataProvider qbftExtraDataProvider;
private final QbftBlockHashing blockHashing;
/**
* Instantiates a new Qbft round factory.
@@ -53,6 +55,7 @@ public class QbftRoundFactory {
* @param messageFactory the message factory
* @param bftExtraDataCodec the bft extra data codec
* @param qbftExtraDataProvider the bft extra data codec
* @param blockHashing the block hashing
*/
public QbftRoundFactory(
final QbftFinalState finalState,
@@ -62,7 +65,8 @@ public class QbftRoundFactory {
final MessageValidatorFactory messageValidatorFactory,
final MessageFactory messageFactory,
final BftExtraDataCodec bftExtraDataCodec,
final QbftExtraDataProvider qbftExtraDataProvider) {
final QbftExtraDataProvider qbftExtraDataProvider,
final QbftBlockHashing blockHashing) {
this.finalState = finalState;
this.blockCreatorFactory = finalState.getBlockCreatorFactory();
this.protocolContext = protocolContext;
@@ -72,6 +76,7 @@ public class QbftRoundFactory {
this.messageFactory = messageFactory;
this.bftExtraDataCodec = bftExtraDataCodec;
this.qbftExtraDataProvider = qbftExtraDataProvider;
this.blockHashing = blockHashing;
}
/**
@@ -81,7 +86,7 @@ public class QbftRoundFactory {
* @param round the round
* @return the qbft round
*/
public QbftRound createNewRound(final BlockHeader parentHeader, final int round) {
public QbftRound createNewRound(final QbftBlockHeader parentHeader, final int round) {
long nextBlockHeight = parentHeader.getNumber() + 1;
final ConsensusRoundIdentifier roundIdentifier =
new ConsensusRoundIdentifier(nextBlockHeight, round);
@@ -103,7 +108,7 @@ public class QbftRoundFactory {
* @return the qbft round
*/
public QbftRound createNewRoundWithState(
final BlockHeader parentHeader, final RoundState roundState) {
final QbftBlockHeader parentHeader, final RoundState roundState) {
final QbftBlockCreator blockCreator =
blockCreatorFactory.create(roundState.getRoundIdentifier().getRoundNumber());
@@ -123,6 +128,7 @@ public class QbftRoundFactory {
finalState.getRoundTimer(),
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
}
}

View File

@@ -15,7 +15,6 @@
package org.hyperledger.besu.consensus.qbft.core.types;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
/** Represents a block in the context of the QBFT consensus mechanism. */
public interface QbftBlock {
@@ -25,7 +24,7 @@ public interface QbftBlock {
*
* @return the block header.
*/
BlockHeader getHeader();
QbftBlockHeader getHeader();
/**
* Whether the block is considered empty, generally this means that the block has no transactions.

View File

@@ -15,7 +15,6 @@
package org.hyperledger.besu.consensus.qbft.core.types;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import java.util.Collection;
@@ -29,7 +28,7 @@ public interface QbftBlockCreator {
* @param parentHeader the parent header
* @return the block
*/
QbftBlock createBlock(long headerTimeStampSeconds, BlockHeader parentHeader);
QbftBlock createBlock(long headerTimeStampSeconds, QbftBlockHeader parentHeader);
/**
* Create sealed block.

View File

@@ -0,0 +1,34 @@
/*
* Copyright contributors to 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.consensus.qbft.core.types;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.datatypes.Hash;
/** Provides hashing for QBFT block headers. */
public interface QbftBlockHashing {
/**
* Constructs a hash of the block header suitable for signing as a committed seal. The extra data
* in the hash uses an empty list for the committed seals.
*
* @param header The header for which a proposer seal is to be calculated (with or without extra
* data)
* @param extraData The extra data block which is to be inserted to the header once seal is
* calculated
* @return the hash of the header including the validator and proposer seal in the extra data
*/
Hash calculateDataHashForCommittedSeal(QbftBlockHeader header, BftExtraData extraData);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright contributors to 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.consensus.qbft.core.types;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
/** Represents a block header in the context of the QBFT consensus mechanism. */
public interface QbftBlockHeader {
/**
* Returns the block number of the block.
*
* @return the block number.
*/
long getNumber();
/**
* Returns the timestamp of the block.
*
* @return the timestamp.
*/
long getTimestamp();
/**
* Returns the coinbase of the block.
*
* @return the coinbase.
*/
Address getCoinbase();
/**
* Returns the hash of the block.
*
* @return the hash.
*/
Hash getHash();
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright contributors to 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.consensus.qbft.core.types;
/** Minimal QBFT interface for reading data from the blockchain. */
public interface QbftBlockchain {
/**
* Returns the chain head header.
*
* @return the header.
*/
QbftBlockHeader getChainHeadHeader();
/**
* Returns the chain head block number.
*
* @return the block number.
*/
long getChainHeadBlockNumber();
}

View File

@@ -14,33 +14,25 @@
*/
package org.hyperledger.besu.consensus.qbft.core.types;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.ethereum.ConsensusContext;
/** Holds the QBFT specific mutable state. */
public class QbftContext implements ConsensusContext {
private final ValidatorProvider validatorProvider;
private final QbftBlockInterface blockInterface;
/**
* Instantiates a new Bft context.
*
* @param validatorProvider the validator provider
* @param blockInterface the block interface
*/
public QbftContext(
final ValidatorProvider validatorProvider, final QbftBlockInterface blockInterface) {
this.validatorProvider = validatorProvider;
this.blockInterface = blockInterface;
}
/**
* Holds the QBFT specific mutable state.
*
* @param validatorProvider the validator provider
* @param blockInterface the block interface
*/
public record QbftContext(
QbftValidatorProvider validatorProvider, QbftBlockInterface blockInterface)
implements ConsensusContext {
/**
* Gets validator provider.
*
* @return the validator provider
*/
public ValidatorProvider getValidatorProvider() {
@Override
public QbftValidatorProvider validatorProvider() {
return validatorProvider;
}
@@ -49,7 +41,8 @@ public class QbftContext implements ConsensusContext {
*
* @return the block interface
*/
public QbftBlockInterface getBlockInterface() {
@Override
public QbftBlockInterface blockInterface() {
return blockInterface;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright contributors to 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.consensus.qbft.core.types;
import org.hyperledger.besu.consensus.common.bft.events.BftReceivedMessageEvent;
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry;
/** The interface QBFT event handler. */
public interface QbftEventHandler {
/** Start. */
void start();
/**
* Handle errorMessage event.
*
* @param msg the msg
*/
void handleMessageEvent(BftReceivedMessageEvent msg);
/**
* Handle new block event.
*
* @param newChainHead the new chain head
*/
void handleNewBlockEvent(QbftNewChainHead newChainHead);
/**
* Handle block timer expiry.
*
* @param blockTimerExpiry the block timer expiry
*/
void handleBlockTimerExpiry(BlockTimerExpiry blockTimerExpiry);
/**
* Handle round expiry.
*
* @param roundExpiry the round expiry
*/
void handleRoundExpiry(RoundExpiry roundExpiry);
}

View File

@@ -15,7 +15,6 @@
package org.hyperledger.besu.consensus.qbft.core.types;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.ethereum.core.BlockHeader;
/** Provides the extra data for a block. */
public interface QbftExtraDataProvider {
@@ -26,5 +25,5 @@ public interface QbftExtraDataProvider {
* @param header the block header to retrieve the extra data from
* @return the extra data
*/
BftExtraData getExtraData(BlockHeader header);
BftExtraData getExtraData(QbftBlockHeader header);
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright contributors to 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.consensus.qbft.core.types;
import org.hyperledger.besu.consensus.common.bft.events.BftEvent;
import org.hyperledger.besu.consensus.common.bft.events.BftEvents;
/**
* Event indicating that new chain head has been received
*
* @param newChainHeadHeader the new chain head header
*/
public record QbftNewChainHead(QbftBlockHeader newChainHeadHeader) implements BftEvent {
@Override
public BftEvents.Type getType() {
return BftEvents.Type.NEW_CHAIN_HEAD;
}
/**
* Gets new chain head header.
*
* @return the new chain head header
*/
@Override
public QbftBlockHeader newChainHeadHeader() {
return newChainHeadHeader;
}
}

View File

@@ -14,8 +14,6 @@
*/
package org.hyperledger.besu.consensus.qbft.core.types;
import org.hyperledger.besu.ethereum.core.BlockHeader;
/**
* Provides the ability to select the appropriate QbftProtocolSpec containing the validation and
* import for the supplied block header.
@@ -28,5 +26,5 @@ public interface QbftProtocolSchedule {
* @param header The block header to select the appropriate QbftProtocolSpec for
* @return The QbftProtocolSpec for the supplied block header
*/
QbftProtocolSpec getByBlockHeader(BlockHeader header);
QbftProtocolSpec getByBlockHeader(QbftBlockHeader header);
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright contributors to 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.consensus.qbft.core.types;
/** Provides logging for QBFT transition changes */
public interface QbftValidatorModeTransitionLogger {
/**
* Logs the transition change
*
* @param parentHeader the parent header
*/
void logTransitionChange(QbftBlockHeader parentHeader);
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright ConsenSys AG.
*
* 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.consensus.qbft.core.types;
import org.hyperledger.besu.consensus.common.validator.VoteProvider;
import org.hyperledger.besu.cryptoservices.NodeKey;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.Util;
import java.util.Collection;
import java.util.Optional;
/** The interface Validator provider. */
public interface QbftValidatorProvider {
/**
* Gets validators at head.
*
* @return the validators at head
*/
Collection<Address> getValidatorsAtHead();
/**
* Gets validators after block.
*
* @param header the header
* @return the validators after block
*/
Collection<Address> getValidatorsAfterBlock(QbftBlockHeader header);
/**
* Gets validators for block.
*
* @param header the header
* @return the validators for block
*/
Collection<Address> getValidatorsForBlock(QbftBlockHeader header);
/**
* Gets vote provider at head.
*
* @return the vote provider at head
*/
Optional<VoteProvider> getVoteProviderAtHead();
/**
* Gets vote provider after block.
*
* @param header the header
* @return the vote provider after block
*/
/*
* ForkingValidatorProvider has a specific implementation but we don't want the client code to
* know it's using a ForkingValidatorProvider. ForkingValidatorProvider's voteProvider can be
* different per block. Other ValidatorProviders yield the same voteProvider at every block.
*/
default Optional<VoteProvider> getVoteProviderAfterBlock(final QbftBlockHeader header) {
return getVoteProviderAtHead();
}
/**
* Determines if this node is a validator
*
* @param nodekey our node key
* @return true if this node is a validator
*/
default boolean nodeIsValidator(final NodeKey nodekey) {
return this.getValidatorsAtHead().contains(Util.publicKeyToAddress(nodekey.getPublicKey()));
}
}

View File

@@ -16,14 +16,14 @@ package org.hyperledger.besu.consensus.qbft.core.validation;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
/** The Future round proposal message validator. */
public class FutureRoundProposalMessageValidator {
private final MessageValidatorFactory messageValidatorFactory;
private final long chainHeight;
private final BlockHeader parentHeader;
private final QbftBlockHeader parentHeader;
/**
* Instantiates a new Future round proposal message validator.
@@ -35,7 +35,7 @@ public class FutureRoundProposalMessageValidator {
public FutureRoundProposalMessageValidator(
final MessageValidatorFactory messageValidatorFactory,
final long chainHeight,
final BlockHeader parentHeader) {
final QbftBlockHeader parentHeader) {
this.messageValidatorFactory = messageValidatorFactory;
this.chainHeight = chainHeight;
this.parentHeader = parentHeader;

View File

@@ -17,13 +17,13 @@ package org.hyperledger.besu.consensus.qbft.core.validation;
import org.hyperledger.besu.consensus.common.bft.BftHelpers;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.blockcreation.ProposerSelector;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator.SubsequentMessageValidator;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import java.util.Collection;
@@ -58,10 +58,10 @@ public class MessageValidatorFactory {
* @return the list of validators
*/
public static Collection<Address> getValidatorsAfterBlock(
final ProtocolContext protocolContext, final BlockHeader parentHeader) {
final ProtocolContext protocolContext, final QbftBlockHeader parentHeader) {
return protocolContext
.getConsensusContext(QbftContext.class)
.getValidatorProvider()
.validatorProvider()
.getValidatorsAfterBlock(parentHeader);
}
@@ -73,10 +73,10 @@ public class MessageValidatorFactory {
* @return the list of validators
*/
public static Collection<Address> getValidatorsForBlock(
final ProtocolContext protocolContext, final BlockHeader parentHeader) {
final ProtocolContext protocolContext, final QbftBlockHeader parentHeader) {
return protocolContext
.getConsensusContext(QbftContext.class)
.getValidatorProvider()
.validatorProvider()
.getValidatorsForBlock(parentHeader);
}
@@ -88,7 +88,7 @@ public class MessageValidatorFactory {
* @return the round change message validator
*/
public RoundChangeMessageValidator createRoundChangeMessageValidator(
final long chainHeight, final BlockHeader parentHeader) {
final long chainHeight, final QbftBlockHeader parentHeader) {
final Collection<Address> validatorsForHeight =
getValidatorsAfterBlock(protocolContext, parentHeader);
@@ -112,7 +112,7 @@ public class MessageValidatorFactory {
* @return the message validator
*/
public MessageValidator createMessageValidator(
final ConsensusRoundIdentifier roundIdentifier, final BlockHeader parentHeader) {
final ConsensusRoundIdentifier roundIdentifier, final QbftBlockHeader parentHeader) {
final Collection<Address> validatorsForHeight =
getValidatorsAfterBlock(protocolContext, parentHeader);
@@ -126,7 +126,7 @@ public class MessageValidatorFactory {
proposerSelector.selectProposerForRound(roundIdentifier));
final QbftBlockInterface blockInterface =
protocolContext.getConsensusContext(QbftContext.class).getBlockInterface();
protocolContext.getConsensusContext(QbftContext.class).blockInterface();
return new MessageValidator(
block ->
new SubsequentMessageValidator(
@@ -142,7 +142,7 @@ public class MessageValidatorFactory {
* @return the future round proposal message validator
*/
public FutureRoundProposalMessageValidator createFutureRoundProposalMessageValidator(
final long chainHeight, final BlockHeader parentHeader) {
final long chainHeight, final QbftBlockHeader parentHeader) {
return new FutureRoundProposalMessageValidator(this, chainHeight, parentHeader);
}
}

View File

@@ -144,7 +144,7 @@ public class ProposalValidator {
// Need to check that if we substitute the LatestPrepareCert round number into the supplied
// block that we get the SAME hash as PreparedCert.
final QbftBlockInterface bftBlockInterface =
protocolContext.getConsensusContext(QbftContext.class).getBlockInterface();
protocolContext.getConsensusContext(QbftContext.class).blockInterface();
final QbftBlock currentBlockWithOldRound =
bftBlockInterface.replaceRoundInBlock(
proposal.getBlock(), metadata.getPreparedRound(), QbftHashMode.COMMITTED_SEAL);

View File

@@ -15,15 +15,15 @@
package org.hyperledger.besu.consensus.qbft.core;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.validation.QbftBlockHeaderTestFixture;
public class QbftBlockTestFixture {
private BlockHeader blockHeader = new BlockDataGenerator().header();
private QbftBlockHeader blockHeader = new QbftBlockHeaderTestFixture().buildHeader();
private boolean isEmpty = true;
public QbftBlockTestFixture blockHeader(final BlockHeader blockHeader) {
public QbftBlockTestFixture blockHeader(final QbftBlockHeader blockHeader) {
this.blockHeader = blockHeader;
return this;
}
@@ -40,7 +40,7 @@ public class QbftBlockTestFixture {
class TestQbftBlock implements QbftBlock {
@Override
public BlockHeader getHeader() {
public QbftBlockHeader getHeader() {
return blockHeader;
}

View File

@@ -19,9 +19,9 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
import org.hyperledger.besu.datatypes.Address;
import java.util.Collection;
@@ -35,11 +35,11 @@ public class QbftContextBuilder {
final Collection<Address> validators,
final QbftBlockInterface bftBlockInterface) {
final T bftContext = mock(contextClazz, withSettings().strictness(Strictness.LENIENT));
final ValidatorProvider mockValidatorProvider =
mock(ValidatorProvider.class, withSettings().strictness(Strictness.LENIENT));
when(bftContext.getValidatorProvider()).thenReturn(mockValidatorProvider);
final QbftValidatorProvider mockValidatorProvider =
mock(QbftValidatorProvider.class, withSettings().strictness(Strictness.LENIENT));
when(bftContext.validatorProvider()).thenReturn(mockValidatorProvider);
when(mockValidatorProvider.getValidatorsAfterBlock(any())).thenReturn(validators);
when(bftContext.getBlockInterface()).thenReturn(bftBlockInterface);
when(bftContext.blockInterface()).thenReturn(bftBlockInterface);
when(bftContext.as(any())).thenReturn(bftContext);
return bftContext;

View File

@@ -37,7 +37,6 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry;
import org.hyperledger.besu.consensus.common.bft.network.ValidatorMulticaster;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.qbft.core.QbftBlockTestFixture;
import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit;
@@ -49,6 +48,8 @@ import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockImporter;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
@@ -56,9 +57,11 @@ import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSpec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
import org.hyperledger.besu.consensus.qbft.core.validation.FutureRoundProposalMessageValidator;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory;
import org.hyperledger.besu.consensus.qbft.core.validation.QbftBlockHeaderTestFixture;
import org.hyperledger.besu.consensus.qbft.core.validation.RoundChangeMessageValidator;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.cryptoservices.NodeKey;
@@ -66,8 +69,6 @@ import org.hyperledger.besu.cryptoservices.NodeKeyUtils;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Util;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
import org.hyperledger.besu.util.Subscribers;
@@ -95,7 +96,7 @@ import org.mockito.quality.Strictness;
public class QbftBlockHeightManagerTest {
private final NodeKey nodeKey = NodeKeyUtils.generate();
private final BlockHeaderTestFixture headerTestFixture = new BlockHeaderTestFixture();
private final QbftBlockHeaderTestFixture headerTestFixture = new QbftBlockHeaderTestFixture();
private MessageFactory messageFactory;
@Mock private QbftFinalState finalState;
@@ -111,14 +112,15 @@ public class QbftBlockHeightManagerTest {
@Mock private ValidatorMulticaster validatorMulticaster;
@Mock private ProtocolContext protocolContext;
@Mock private QbftProtocolSchedule protocolSchedule;
@Mock private BlockHeader parentHeader;
@Mock private QbftBlockHeader parentHeader;
@Mock private BftExtraDataCodec bftExtraDataCodec;
@Mock private QbftBlockCodec blockEncoder;
@Mock private QbftExtraDataProvider qbftExtraDataProvider;
@Mock private QbftBlockInterface blockInterface;
@Mock private ValidatorProvider validatorProvider;
@Mock private QbftValidatorProvider validatorProvider;
@Mock private QbftProtocolSpec protocolSpec;
@Mock private QbftBlockImporter blockImporter;
@Mock private QbftBlockHashing blockHashing;
@Captor private ArgumentCaptor<MessageData> sentMessageArgCaptor;
@@ -176,6 +178,7 @@ public class QbftBlockHeightManagerTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
});
@@ -195,6 +198,7 @@ public class QbftBlockHeightManagerTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
});
@@ -406,6 +410,7 @@ public class QbftBlockHeightManagerTest {
when(finalState.getQuorum()).thenReturn(1);
when(blockInterface.replaceRoundInBlock(eq(createdBlock), eq(2), any()))
.thenReturn(createdBlock);
when(blockHashing.calculateDataHashForCommittedSeal(any(), any())).thenReturn(Hash.ZERO);
when(blockCreator.createSealedBlock(any(), any(), anyInt(), any())).thenReturn(createdBlock);
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
@@ -456,6 +461,7 @@ public class QbftBlockHeightManagerTest {
when(blockTimer.checkEmptyBlockExpired(any(), eq(0L))).thenReturn(true);
when(blockInterface.replaceRoundInBlock(eq(createdBlock), eq(0), any()))
.thenReturn(createdBlock);
when(blockHashing.calculateDataHashForCommittedSeal(any(), any())).thenReturn(Hash.ZERO);
when(blockCreator.createSealedBlock(any(), any(), anyInt(), any())).thenReturn(createdBlock);
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);

View File

@@ -30,7 +30,6 @@ import org.hyperledger.besu.consensus.common.bft.EthSynchronizerUpdater;
import org.hyperledger.besu.consensus.common.bft.MessageTracker;
import org.hyperledger.besu.consensus.common.bft.events.BftReceivedMessageEvent;
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry;
import org.hyperledger.besu.consensus.common.bft.statemachine.FutureMessageBuffer;
import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData;
@@ -44,11 +43,12 @@ import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.qbft.core.network.QbftGossip;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockchain;
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
import org.hyperledger.besu.consensus.qbft.core.types.QbftNewChainHead;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.DefaultMessage;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message;
@@ -67,11 +67,11 @@ import org.mockito.quality.Strictness;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class QbftControllerTest {
@Mock private Blockchain blockChain;
@Mock private QbftBlockchain blockChain;
@Mock private QbftFinalState qbftFinalState;
@Mock private QbftBlockHeightManagerFactory blockHeightManagerFactory;
@Mock private BlockHeader chainHeadBlockHeader;
@Mock private BlockHeader nextBlock;
@Mock private QbftBlockHeader chainHeadBlockHeader;
@Mock private QbftBlockHeader nextBlock;
@Mock private BaseQbftBlockHeightManager blockHeightManager;
@Mock private Proposal proposal;
@@ -187,7 +187,7 @@ public class QbftControllerTest {
constructQbftController();
qbftController.start();
final NewChainHead newChainHead = new NewChainHead(nextBlock);
final QbftNewChainHead newChainHead = new QbftNewChainHead(nextBlock);
qbftController.handleNewBlockEvent(newChainHead);
verify(blockHeightManagerFactory).create(nextBlock);
@@ -210,11 +210,11 @@ public class QbftControllerTest {
long chainHeadHeight = 4;
when(nextBlock.getNumber()).thenReturn(chainHeadHeight);
when(nextBlock.getHash()).thenReturn(Hash.ZERO);
final NewChainHead sameHeightBlock = new NewChainHead(nextBlock);
final QbftNewChainHead sameHeightBlock = new QbftNewChainHead(nextBlock);
qbftController.handleNewBlockEvent(sameHeightBlock);
when(nextBlock.getNumber()).thenReturn(chainHeadHeight - 1);
final NewChainHead priorBlock = new NewChainHead(nextBlock);
final QbftNewChainHead priorBlock = new QbftNewChainHead(nextBlock);
qbftController.handleNewBlockEvent(priorBlock);
verify(blockHeightManagerFactory, times(2)).create(any()); // 2 blocks created
}

View File

@@ -42,6 +42,8 @@ import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockImporter;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
@@ -51,15 +53,15 @@ import org.hyperledger.besu.consensus.qbft.core.types.QbftMinedBlockObserver;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSpec;
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator;
import org.hyperledger.besu.consensus.qbft.core.validation.QbftBlockHeaderTestFixture;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.cryptoservices.NodeKey;
import org.hyperledger.besu.cryptoservices.NodeKeyUtils;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers;
@@ -102,11 +104,12 @@ public class QbftRoundTest {
@Mock private RoundTimer roundTimer;
@Mock private QbftProtocolSpec protocolSpec;
@Mock private QbftBlockImporter blockImporter;
@Mock private org.hyperledger.besu.ethereum.core.BlockHeader parentHeader;
@Mock private QbftBlockHeader parentHeader;
@Mock private BftExtraDataCodec bftExtraDataCodec;
@Mock private QbftBlockInterface blockInteface;
@Mock private QbftBlockCodec blockEncoder;
@Mock private QbftExtraDataProvider qbftExtraDataProvider;
@Mock private QbftBlockHashing blockHashing;
@Captor private ArgumentCaptor<QbftBlock> blockCaptor;
@@ -132,7 +135,7 @@ public class QbftRoundTest {
when(messageValidator.validatePrepare(any())).thenReturn(true);
when(messageValidator.validateCommit(any())).thenReturn(true);
final BlockHeader header = new BlockHeaderTestFixture().number(1).buildHeader();
final QbftBlockHeader header = new QbftBlockHeaderTestFixture().number(1).buildHeader();
proposedBlock = new QbftBlockTestFixture().blockHeader(header).build();
@@ -168,6 +171,7 @@ public class QbftRoundTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
verify(roundTimer, times(1)).startTimer(roundIdentifier);
}
@@ -188,6 +192,7 @@ public class QbftRoundTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
when(blockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any()))
@@ -202,7 +207,7 @@ public class QbftRoundTest {
@Test
public void aProposalWithAnewBlockIsSentUponReceptionOfARoundChangeWithNoCertificate() {
final BlockHeader header = new BlockHeaderTestFixture().number(0).buildHeader();
final QbftBlockHeader header = new QbftBlockHeaderTestFixture().number(0).buildHeader();
final QbftBlock commitBlock = new QbftBlockTestFixture().blockHeader(header).build();
when(blockInteface.replaceRoundInBlock(proposedBlock, 0, QbftHashMode.COMMITTED_SEAL))
@@ -222,6 +227,7 @@ public class QbftRoundTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
round.startRoundWith(new RoundChangeArtifacts(emptyList(), Optional.empty()), 15);
@@ -234,11 +240,11 @@ public class QbftRoundTest {
public void aProposalMessageWithTheSameBlockIsSentUponReceptionOfARoundChangeWithCertificate() {
final QbftBlock publishBlock =
new QbftBlockTestFixture()
.blockHeader(new BlockHeaderTestFixture().number(0).buildHeader())
.blockHeader(new QbftBlockHeaderTestFixture().number(0).buildHeader())
.build();
final QbftBlock commitBlock =
new QbftBlockTestFixture()
.blockHeader(new BlockHeaderTestFixture().number(0).buildHeader())
.blockHeader(new QbftBlockHeaderTestFixture().number(0).buildHeader())
.build();
when(blockInteface.replaceRoundInBlock(proposedBlock, 0, QbftHashMode.COMMITTED_SEAL))
.thenReturn(publishBlock);
@@ -260,6 +266,7 @@ public class QbftRoundTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
final SignedData<PreparePayload> preparedPayload =
@@ -294,7 +301,7 @@ public class QbftRoundTest {
public void creatingNewBlockFromEmptyPreparedCertificateUpdatesInternalState() {
final QbftBlock commitBlock =
new QbftBlockTestFixture()
.blockHeader(new BlockHeaderTestFixture().number(0).buildHeader())
.blockHeader(new QbftBlockHeaderTestFixture().number(0).buildHeader())
.build();
when(blockInteface.replaceRoundInBlock(proposedBlock, 0, QbftHashMode.COMMITTED_SEAL))
.thenReturn(commitBlock);
@@ -313,6 +320,7 @@ public class QbftRoundTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
final RoundChange roundChange =
@@ -356,12 +364,14 @@ public class QbftRoundTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
when(blockInteface.replaceRoundInBlock(proposedBlock, 0, QbftHashMode.COMMITTED_SEAL))
.thenReturn(proposedBlock);
when(blockCreator.createSealedBlock(eq(qbftExtraDataProvider), eq(proposedBlock), eq(0), any()))
.thenReturn(proposedBlock);
when(blockHashing.calculateDataHashForCommittedSeal(any(), any())).thenReturn(Hash.ZERO);
round.handleCommitMessage(
messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal));
@@ -390,12 +400,14 @@ public class QbftRoundTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
when(blockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any()))
.thenReturn(proposedBlock);
when(blockCreator.createSealedBlock(eq(qbftExtraDataProvider), eq(proposedBlock), eq(0), any()))
.thenReturn(proposedBlock);
when(blockHashing.calculateDataHashForCommittedSeal(any(), any())).thenReturn(Hash.ZERO);
round.handleCommitMessage(
messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal));
@@ -428,6 +440,7 @@ public class QbftRoundTest {
roundTimer,
bftExtraDataCodec,
qbftExtraDataProvider,
blockHashing,
parentHeader);
when(blockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any()))

View File

@@ -27,12 +27,11 @@ import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal;
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockValidator;
import org.hyperledger.besu.cryptoservices.NodeKey;
import org.hyperledger.besu.cryptoservices.NodeKeyUtils;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Util;
import java.util.Optional;
@@ -68,8 +67,8 @@ public class ProposalPayloadValidatorTest {
public void validationPassesWhenProposerAndRoundMatchAndBlockIsValid() {
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(expectedProposer, roundIdentifier, blockValidator);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final Proposal proposal =
messageFactory.createProposal(roundIdentifier, block, emptyList(), emptyList());
@@ -85,8 +84,8 @@ public class ProposalPayloadValidatorTest {
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(expectedProposer, roundIdentifier, blockValidator);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final Proposal proposal =
messageFactory.createProposal(roundIdentifier, block, emptyList(), emptyList());
@@ -104,8 +103,8 @@ public class ProposalPayloadValidatorTest {
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(expectedProposer, roundIdentifier, blockValidator);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final Proposal proposal =
messageFactory.createProposal(roundIdentifier, block, emptyList(), emptyList());
@@ -120,8 +119,8 @@ public class ProposalPayloadValidatorTest {
public void validationFailsWhenExpectedProposerDoesNotMatchPayloadsAuthor() {
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(Address.fromHexString("0x1"), roundIdentifier, blockValidator);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final Proposal proposal =
messageFactory.createProposal(roundIdentifier, block, emptyList(), emptyList());
@@ -135,8 +134,8 @@ public class ProposalPayloadValidatorTest {
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(expectedProposer, roundIdentifier, blockValidator);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final Proposal proposal =
messageFactory.createProposal(
@@ -154,8 +153,8 @@ public class ProposalPayloadValidatorTest {
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(expectedProposer, roundIdentifier, blockValidator);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final Proposal proposal =
messageFactory.createProposal(
@@ -172,8 +171,10 @@ public class ProposalPayloadValidatorTest {
public void validationFailsForBlockWithIncorrectHeight() {
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(expectedProposer, roundIdentifier, blockValidator);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber() + 1).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture()
.number(roundIdentifier.getSequenceNumber() + 1)
.buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final Proposal proposal =
messageFactory.createProposal(roundIdentifier, block, emptyList(), emptyList());

View File

@@ -27,7 +27,6 @@ import org.hyperledger.besu.consensus.common.bft.BftHelpers;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.qbft.core.QbftBlockTestFixture;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare;
import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal;
@@ -37,16 +36,16 @@ import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata;
import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockValidator;
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
import org.hyperledger.besu.consensus.qbft.core.types.QbftHashMode;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSpec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import java.util.HashMap;
import java.util.List;
@@ -89,7 +88,7 @@ public class ProposalValidatorTest {
@Mock private QbftProtocolSpec protocolSpec;
@Mock private QbftBlockCodec blockEncoder;
@Mock private QbftBlockInterface blockInterface;
@Mock private ValidatorProvider validatorProvider;
@Mock private QbftValidatorProvider validatorProvider;
@Mock private ProtocolContext protocolContext;
private QbftNodeList validators;
@@ -115,8 +114,8 @@ public class ProposalValidatorTest {
private RoundSpecificItems createRoundSpecificItems(final int roundNumber) {
final ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier(1, roundNumber);
final BlockHeader blockHeader =
new BlockHeaderTestFixture()
final QbftBlockHeader blockHeader =
new QbftBlockHeaderTestFixture()
.number(roundIdentifier.getSequenceNumber())
.coinbase(validators.getNodeAddresses().getFirst())
.buildHeader();

View File

@@ -0,0 +1,71 @@
/*
* Copyright contributors to 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.consensus.qbft.core.validation;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
public class QbftBlockHeaderTestFixture {
private long number = 0;
private long timestamp = 0;
private Hash hash = Hash.EMPTY;
private Address coinbase = Address.ZERO;
public QbftBlockHeaderTestFixture number(final long number) {
this.number = number;
return this;
}
public QbftBlockHeaderTestFixture timestamp(final long timestamp) {
this.timestamp = timestamp;
return this;
}
public QbftBlockHeaderTestFixture hash(final Hash hash) {
this.hash = hash;
return this;
}
public QbftBlockHeaderTestFixture coinbase(final Address coinbase) {
this.coinbase = coinbase;
return this;
}
public QbftBlockHeader buildHeader() {
return new QbftBlockHeader() {
@Override
public long getNumber() {
return number;
}
@Override
public long getTimestamp() {
return timestamp;
}
@Override
public Hash getHash() {
return hash;
}
@Override
public Address getCoinbase() {
return coinbase;
}
};
}
}

View File

@@ -34,14 +34,13 @@ import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockValidator;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockValidator.ValidationResult;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSpec;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -109,8 +108,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
createPreparedCertificate(
@@ -134,8 +133,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
createPreparedCertificate(
@@ -161,8 +160,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
createPreparedCertificate(
@@ -202,8 +201,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
createPreparedCertificate(
@@ -229,8 +228,8 @@ public class RoundChangeMessageValidatorTest {
final QbftNode nonValidator = QbftNode.create(blockEncoder);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
createPreparedCertificate(
@@ -254,8 +253,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
new PreparedCertificate(
@@ -287,8 +286,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
new PreparedCertificate(
@@ -322,8 +321,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
new PreparedCertificate(
@@ -357,8 +356,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final PreparedCertificate prepCert =
createPreparedCertificate(
@@ -387,8 +386,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final RoundChangePayload payload = new RoundChangePayload(targetRound, Optional.empty());
@@ -415,8 +414,8 @@ public class RoundChangeMessageValidatorTest {
validators.getNodeAddresses(),
protocolSchedule);
final BlockHeader header =
new BlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlockHeader header =
new QbftBlockHeaderTestFixture().number(roundIdentifier.getSequenceNumber()).buildHeader();
final QbftBlock block = new QbftBlockTestFixture().blockHeader(header).build();
final RoundChangePayload payload =

View File

@@ -0,0 +1,65 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.common.bft.events.BftReceivedMessageEvent;
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry;
import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler;
import org.hyperledger.besu.consensus.qbft.core.types.QbftEventHandler;
import org.hyperledger.besu.consensus.qbft.core.types.QbftNewChainHead;
import org.hyperledger.besu.ethereum.core.BlockHeader;
/** Adaptor class to allow a {@link QbftEventHandler} to be used as a {@link BftEventHandler}. */
public class BftEventHandlerAdaptor implements BftEventHandler {
private final QbftEventHandler qbftEventHandler;
/**
* Create a new instance of the adaptor.
*
* @param qbftEventHandler The {@link QbftEventHandler} to adapt.
*/
public BftEventHandlerAdaptor(final QbftEventHandler qbftEventHandler) {
this.qbftEventHandler = qbftEventHandler;
}
@Override
public void start() {
qbftEventHandler.start();
}
@Override
public void handleMessageEvent(final BftReceivedMessageEvent msg) {
qbftEventHandler.handleMessageEvent(msg);
}
@Override
public void handleNewBlockEvent(final NewChainHead newChainHead) {
BlockHeader besuNewChainHeadHeader = newChainHead.getNewChainHeadHeader();
var qbftChainHead = new QbftNewChainHead(new QbftBlockHeaderAdaptor(besuNewChainHeadHeader));
qbftEventHandler.handleNewBlockEvent(qbftChainHead);
}
@Override
public void handleBlockTimerExpiry(final BlockTimerExpiry blockTimerExpiry) {
qbftEventHandler.handleBlockTimerExpiry(blockTimerExpiry);
}
@Override
public void handleRoundExpiry(final RoundExpiry roundExpiry) {
qbftEventHandler.handleRoundExpiry(roundExpiry);
}
}

View File

@@ -15,7 +15,9 @@
package org.hyperledger.besu.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
/** Utility class to convert between Besu and QBFT blocks. */
public class BlockUtil {
@@ -36,4 +38,18 @@ public class BlockUtil {
throw new IllegalArgumentException("Unsupported block type");
}
}
/**
* Convert a QBFT block header to a Besu block header.
*
* @param header the QBFT block header
* @return the Besu block header
*/
public static BlockHeader toBesuBlockHeader(final QbftBlockHeader header) {
if (header instanceof QbftBlockHeaderAdaptor) {
return ((QbftBlockHeaderAdaptor) header).getBesuBlockHeader();
} else {
throw new IllegalArgumentException("Unsupported block header type");
}
}
}

View File

@@ -15,35 +15,36 @@
package org.hyperledger.besu.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import java.util.Objects;
/** Adaptor class to allow a {@link Block} to be used as a {@link QbftBlock}. */
public class QbftBlockAdaptor implements QbftBlock {
private final BlockHeader header;
private final Block block;
private final Block besuBlock;
private final QbftBlockHeader qbftBlockHeader;
/**
* Constructs a QbftBlock from a Besu Block.
*
* @param block the Besu Block
* @param besuBlock the Besu Block
*/
public QbftBlockAdaptor(final Block block) {
this.block = block;
this.header = block.getHeader();
public QbftBlockAdaptor(final Block besuBlock) {
this.besuBlock = besuBlock;
this.qbftBlockHeader = new QbftBlockHeaderAdaptor(besuBlock.getHeader());
}
@Override
public BlockHeader getHeader() {
return header;
public QbftBlockHeader getHeader() {
return qbftBlockHeader;
}
@Override
public boolean isEmpty() {
return block.getBody().getTransactions().isEmpty();
return besuBlock.getHeader().getTransactionsRoot().equals(Hash.EMPTY_TRIE_HASH);
}
/**
@@ -53,17 +54,18 @@ public class QbftBlockAdaptor implements QbftBlock {
* @return the Besu Block
*/
public Block getBesuBlock() {
return block;
return besuBlock;
}
@Override
public boolean equals(final Object o) {
if (!(o instanceof QbftBlockAdaptor qbftBlock)) return false;
return Objects.equals(header, qbftBlock.header) && Objects.equals(block, qbftBlock.block);
return Objects.equals(besuBlock, qbftBlock.besuBlock)
&& Objects.equals(qbftBlockHeader, qbftBlock.qbftBlockHeader);
}
@Override
public int hashCode() {
return Objects.hash(header, block);
return Objects.hash(besuBlock, qbftBlockHeader);
}
}

View File

@@ -19,6 +19,7 @@ import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCreator;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.blockcreation.BlockCreator;
@@ -47,8 +48,11 @@ public class QbftBlockCreatorAdaptor implements QbftBlockCreator {
}
@Override
public QbftBlock createBlock(final long headerTimeStampSeconds, final BlockHeader parentHeader) {
var blockResult = besuBlockCreator.createBlock(headerTimeStampSeconds, parentHeader);
public QbftBlock createBlock(
final long headerTimeStampSeconds, final QbftBlockHeader parentHeader) {
var blockResult =
besuBlockCreator.createBlock(
headerTimeStampSeconds, BlockUtil.toBesuBlockHeader(parentHeader));
return new QbftBlockAdaptor(blockResult.getBlock());
}
@@ -59,8 +63,8 @@ public class QbftBlockCreatorAdaptor implements QbftBlockCreator {
final int roundNumber,
final Collection<SECPSignature> commitSeals) {
final Block besuBlock = BlockUtil.toBesuBlock(block);
final BlockHeader initialBesuHeader = besuBlock.getHeader();
final BftExtraData initialExtraData = bftQbftExtraDataProvider.getExtraData(initialBesuHeader);
final QbftBlockHeader initialHeader = block.getHeader();
final BftExtraData initialExtraData = bftQbftExtraDataProvider.getExtraData(initialHeader);
final BftExtraData sealedExtraData =
new BftExtraData(
@@ -71,7 +75,7 @@ public class QbftBlockCreatorAdaptor implements QbftBlockCreator {
initialExtraData.getValidators());
final BlockHeader sealedHeader =
BlockHeaderBuilder.fromHeader(initialBesuHeader)
BlockHeaderBuilder.fromHeader(BlockUtil.toBesuBlockHeader(initialHeader))
.extraData(bftExtraDataCodec.encode(sealedExtraData))
.blockHeaderFunctions(BftBlockHeaderFunctions.forOnchainBlock(bftExtraDataCodec))
.buildBlockHeader();

View File

@@ -0,0 +1,42 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.datatypes.Hash;
/** Adaptor to allow a {linkBftBlockHashing} to be used as a {@link QbftBlockHashing}. */
public class QbftBlockHashingAdaptor implements QbftBlockHashing {
private final BftBlockHashing bftBlockHashing;
/**
* Construct a new Qbft BlockHasher
*
* @param bftBlockHashing the BFT BlockHashing
*/
public QbftBlockHashingAdaptor(final BftBlockHashing bftBlockHashing) {
this.bftBlockHashing = bftBlockHashing;
}
@Override
public Hash calculateDataHashForCommittedSeal(
final QbftBlockHeader header, final BftExtraData extraData) {
return bftBlockHashing.calculateDataHashForCommittedSeal(
BlockUtil.toBesuBlockHeader(header), extraData);
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import java.util.Objects;
/** Adaptor class to allow a {@link BlockHeader} to be used as a {@link QbftBlockHeader}. */
public class QbftBlockHeaderAdaptor implements QbftBlockHeader {
private final BlockHeader blockHeader;
/**
* Construct a new QbftBlockHeader
*
* @param blockHeader the Besu block header
*/
public QbftBlockHeaderAdaptor(final BlockHeader blockHeader) {
this.blockHeader = blockHeader;
}
@Override
public long getNumber() {
return blockHeader.getNumber();
}
@Override
public long getTimestamp() {
return blockHeader.getTimestamp();
}
@Override
public Address getCoinbase() {
return blockHeader.getCoinbase();
}
@Override
public Hash getHash() {
return blockHeader.getHash();
}
/**
* Returns the Besu block header.
*
* @return the Besu block header.
*/
public BlockHeader getBesuBlockHeader() {
return blockHeader;
}
@Override
public boolean equals(final Object o) {
if (!(o instanceof QbftBlockHeaderAdaptor that)) return false;
return Objects.equals(blockHeader, that.blockHeader);
}
@Override
public int hashCode() {
return Objects.hashCode(blockHeader);
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockchain;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
/** Adaptor class to allow a {@link Blockchain} to be used as a {@link QbftBlockchain}. */
public class QbftBlockchainAdaptor implements QbftBlockchain {
private final Blockchain blockchain;
/**
* Create a new instance of the adaptor.
*
* @param blockchain The {@link Blockchain} to adapt.
*/
public QbftBlockchainAdaptor(final Blockchain blockchain) {
this.blockchain = blockchain;
}
@Override
public QbftBlockHeader getChainHeadHeader() {
BlockHeader chainHeadHeader = blockchain.getChainHeadHeader();
return new QbftBlockHeaderAdaptor(chainHeadHeader);
}
@Override
public long getChainHeadBlockNumber() {
return blockchain.getChainHeadBlockNumber();
}
}

View File

@@ -16,8 +16,8 @@ package org.hyperledger.besu.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
import org.hyperledger.besu.ethereum.core.BlockHeader;
/**
* Adaptor class to allow a {@link BftExtraDataCodec} to be used as a {@link QbftExtraDataProvider}.
@@ -35,7 +35,7 @@ public class QbftExtraDataProviderAdaptor implements QbftExtraDataProvider {
}
@Override
public BftExtraData getExtraData(final BlockHeader header) {
return bftExtraDataCodec.decode(header);
public BftExtraData getExtraData(final QbftBlockHeader header) {
return bftExtraDataCodec.decode(BlockUtil.toBesuBlockHeader(header));
}
}

View File

@@ -14,10 +14,10 @@
*/
package org.hyperledger.besu.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSpec;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
@@ -42,8 +42,9 @@ public class QbftProtocolScheduleAdaptor implements QbftProtocolSchedule {
}
@Override
public QbftProtocolSpec getByBlockHeader(final BlockHeader header) {
final ProtocolSpec protocolSpec = besuProtocolSchedule.getByBlockHeader(header);
public QbftProtocolSpec getByBlockHeader(final QbftBlockHeader header) {
final ProtocolSpec protocolSpec =
besuProtocolSchedule.getByBlockHeader(BlockUtil.toBesuBlockHeader(header));
return new QbftProtocolSpecAdaptor(protocolSpec, context);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorModeTransitionLogger;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger;
/**
* Adaptor class to allow the {@link ValidatorModeTransitionLogger} to be used as a {@link
* QbftValidatorModeTransitionLogger}.
*/
public class QbftValidatorModeTransitionLoggerAdaptor implements QbftValidatorModeTransitionLogger {
private final ValidatorModeTransitionLogger validatorModeTransitionLogger;
/**
* Create a new instance of the adaptor.
*
* @param validatorModeTransitionLogger the {@link ValidatorModeTransitionLogger} to adapt.
*/
public QbftValidatorModeTransitionLoggerAdaptor(
final ValidatorModeTransitionLogger validatorModeTransitionLogger) {
this.validatorModeTransitionLogger = validatorModeTransitionLogger;
}
@Override
public void logTransitionChange(final QbftBlockHeader parentHeader) {
validatorModeTransitionLogger.logTransitionChange(BlockUtil.toBesuBlockHeader(parentHeader));
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.common.validator.VoteProvider;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
import org.hyperledger.besu.datatypes.Address;
import java.util.Collection;
import java.util.Optional;
/**
* Adaptor class to allow the {@link ValidatorProvider} to be used as a {@link
* QbftValidatorProvider}.
*/
public class QbftValidatorProviderAdaptor implements QbftValidatorProvider {
private final ValidatorProvider validatorProvider;
/**
* Create a new instance of the adaptor.
*
* @param validatorProvider the {@link ValidatorProvider} to adapt.
*/
public QbftValidatorProviderAdaptor(final ValidatorProvider validatorProvider) {
this.validatorProvider = validatorProvider;
}
@Override
public Collection<Address> getValidatorsAtHead() {
return validatorProvider.getValidatorsAtHead();
}
@Override
public Collection<Address> getValidatorsAfterBlock(final QbftBlockHeader header) {
return validatorProvider.getValidatorsAfterBlock(BlockUtil.toBesuBlockHeader(header));
}
@Override
public Collection<Address> getValidatorsForBlock(final QbftBlockHeader header) {
return validatorProvider.getValidatorsForBlock(BlockUtil.toBesuBlockHeader(header));
}
@Override
public Optional<VoteProvider> getVoteProviderAtHead() {
return validatorProvider.getVoteProviderAtHead();
}
}

View File

@@ -12,7 +12,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.qbft.core.validator;
package org.hyperledger.besu.consensus.qbft.validator;
import org.hyperledger.besu.config.QbftConfigOptions;
import org.hyperledger.besu.consensus.common.ForkSpec;

View File

@@ -0,0 +1,87 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.bft.events.BftReceivedMessageEvent;
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
import org.hyperledger.besu.consensus.common.bft.events.NewChainHead;
import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry;
import org.hyperledger.besu.consensus.qbft.core.types.QbftEventHandler;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class BftEventHandlerAdaptorTest {
@Mock private QbftEventHandler qbftEventHandler;
@Mock private BftReceivedMessageEvent bftReceivedMessageEvent;
@Mock private BlockTimerExpiry blockTimerExpiry;
@Mock private RoundExpiry roundExpiry;
@Mock private NewChainHead newChainHead;
private BftEventHandlerAdaptor handler;
@BeforeEach
void start() {
handler = new BftEventHandlerAdaptor(qbftEventHandler);
}
@Test
void startDelegatesToQbftEventHandler() {
handler.start();
verify(qbftEventHandler).start();
}
@Test
void handleMessageEventDelegatesToQbftEventHandler() {
handler.handleMessageEvent(bftReceivedMessageEvent);
verify(qbftEventHandler).handleMessageEvent(bftReceivedMessageEvent);
}
@Test
void handleBlockTimerExpiryDelegatesToQbftEventHandler() {
handler.handleBlockTimerExpiry(blockTimerExpiry);
verify(qbftEventHandler).handleBlockTimerExpiry(blockTimerExpiry);
}
@Test
void handleRoundExpiryDelegatesToQbftEventHandler() {
handler.handleRoundExpiry(roundExpiry);
verify(qbftEventHandler).handleRoundExpiry(roundExpiry);
}
@Test
void handleNewBlockEventDelegatesToQbftEventHandler() {
BlockHeader header = new BlockHeaderTestFixture().buildHeader();
when(newChainHead.getNewChainHeadHeader()).thenReturn(header);
handler.handleNewBlockEvent(newChainHead);
verify(qbftEventHandler)
.handleNewBlockEvent(
argThat(
argument ->
((QbftBlockHeaderAdaptor) argument.newChainHeadHeader())
.getBesuBlockHeader()
.equals(header)));
}
}

View File

@@ -22,6 +22,7 @@ import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.common.bft.Vote;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.datatypes.Address;
@@ -44,14 +45,16 @@ import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class QbftBlockCreatorAdaptorTest {
@Mock private BlockCreator blockCreator;
@Mock private BlockHeader parentHeader;
@Mock private Block besuBlock;
@Mock private QbftExtraDataProvider qbftExtraDataProvider;
private final QbftExtraDataCodec qbftExtraDataCodec = new QbftExtraDataCodec();
@Test
void createsBlockUsingBesuBlockCreator() {
when(blockCreator.createBlock(10, parentHeader))
BlockHeader besuParentHeader = new BlockHeaderTestFixture().buildHeader();
QbftBlockHeader parentHeader = new QbftBlockHeaderAdaptor(besuParentHeader);
when(blockCreator.createBlock(10, besuParentHeader))
.thenReturn(new BlockCreator.BlockCreationResult(besuBlock, null, null));
QbftBlockCreatorAdaptor qbftBlockCreator =
@@ -73,13 +76,15 @@ class QbftBlockCreatorAdaptorTest {
Block besuBlock = new Block(header, BlockBody.empty());
QbftBlock block = new QbftBlockAdaptor(besuBlock);
SECPSignature seal = new SECPSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1);
when(qbftExtraDataProvider.getExtraData(header)).thenReturn(bftExtraData);
when(qbftExtraDataProvider.getExtraData(new QbftBlockHeaderAdaptor(header)))
.thenReturn(bftExtraData);
QbftBlockCreatorAdaptor qbftBlockCreator =
new QbftBlockCreatorAdaptor(blockCreator, qbftExtraDataCodec);
QbftBlock sealedBlock =
qbftBlockCreator.createSealedBlock(qbftExtraDataProvider, block, 1, List.of(seal));
BftExtraData sealedExtraData = qbftExtraDataCodec.decode(sealedBlock.getHeader());
BftExtraData sealedExtraData =
qbftExtraDataCodec.decode(BlockUtil.toBesuBlockHeader(sealedBlock.getHeader()));
assertThat(sealedExtraData.getVanityData()).isEqualTo(Bytes.wrap(new byte[32]));
assertThat(sealedExtraData.getVote()).contains(Vote.authVote(Address.ZERO));
assertThat(sealedExtraData.getValidators()).isEqualTo(List.of(Address.ZERO));

View File

@@ -0,0 +1,54 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import static java.util.Collections.emptyList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class QbftBlockHashingAdaptorTest {
@Mock private BftBlockHashing bftBlockHashing;
@Test
void calculatesHashForCommittedSeal() {
BlockHeader header = new BlockHeaderTestFixture().buildHeader();
QbftBlockHeader qbftBlockHeader = new QbftBlockHeaderAdaptor(header);
final BftExtraData bftExtraData =
new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), Optional.empty(), 0, emptyList());
when(bftBlockHashing.calculateDataHashForCommittedSeal(header, bftExtraData))
.thenReturn(Hash.EMPTY);
QbftBlockHashingAdaptor qbftBlockHashingAdaptor = new QbftBlockHashingAdaptor(bftBlockHashing);
Hash hash =
qbftBlockHashingAdaptor.calculateDataHashForCommittedSeal(qbftBlockHeader, bftExtraData);
assertThat(hash).isEqualTo(Hash.EMPTY);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.junit.jupiter.api.Test;
class QbftBlockHeaderAdaptorTest {
@Test
void adaptsBesuBlockHeader() {
BlockHeader header =
new BlockHeaderTestFixture()
.number(1)
.timestamp(1000L)
.coinbase(Address.ZERO)
.buildHeader();
QbftBlockHeader qbftBlockHeader = new QbftBlockHeaderAdaptor(header);
assertThat(qbftBlockHeader.getNumber()).isEqualTo(1);
assertThat(qbftBlockHeader.getTimestamp()).isEqualTo(1000L);
assertThat(qbftBlockHeader.getHash()).isEqualTo(header.getHash());
assertThat(qbftBlockHeader.getCoinbase()).isEqualTo(Address.ZERO);
}
}

View File

@@ -53,7 +53,8 @@ class QbftBlockInterfaceAdaptorTest {
QbftBlockInterface qbftBlockInterface = new QbftBlockInterfaceAdaptor(bftBlockInterface);
QbftBlock updatedBlock =
qbftBlockInterface.replaceRoundInBlock(block, 1, QbftHashMode.COMMITTED_SEAL);
BftExtraData extraData = qbftExtraDataCodec.decode(updatedBlock.getHeader());
BftExtraData extraData =
qbftExtraDataCodec.decode(BlockUtil.toBesuBlockHeader(updatedBlock.getHeader()));
assertThat(extraData.getRound()).isEqualTo(1);
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class QbftBlockchainAdaptorTest {
@Mock private Blockchain blockchain;
@Test
void returnsChainHeadBlockNumber() {
when(blockchain.getChainHeadBlockNumber()).thenReturn(1L);
long chainHeadBlockNumber = new QbftBlockchainAdaptor(blockchain).getChainHeadBlockNumber();
assertThat(chainHeadBlockNumber).isEqualTo(1L);
verify(blockchain).getChainHeadBlockNumber();
}
}

View File

@@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
@@ -35,12 +36,13 @@ class QbftExtraDataProviderAdaptorTest {
final BftExtraData bftExtraData =
new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), Optional.empty(), 0, emptyList());
final Bytes encoded = qbftExtraDataCodec.encode(bftExtraData);
final BlockHeader header =
final BlockHeader besuHeader =
new BlockHeaderTestFixture().number(1).extraData(encoded).buildHeader();
final QbftBlockHeader qbftHeader = new QbftBlockHeaderAdaptor(besuHeader);
final QbftExtraDataProviderAdaptor qbftExtraDataProvider =
new QbftExtraDataProviderAdaptor(new QbftExtraDataCodec());
final BftExtraData retrievedExtraData = qbftExtraDataProvider.getExtraData(header);
final BftExtraData retrievedExtraData = qbftExtraDataProvider.getExtraData(qbftHeader);
assertThat(retrievedExtraData).isEqualToComparingFieldByField(bftExtraData);
}
}

View File

@@ -17,10 +17,12 @@ package org.hyperledger.besu.consensus.qbft.adaptor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSpec;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
@@ -34,15 +36,17 @@ class QbftProtocolScheduleAdaptorTest {
@Mock private ProtocolSchedule besuProtocolSchedule;
@Mock private ProtocolSpec besuProtocolSpec;
@Mock private ProtocolContext besuProtocolContext;
@Mock private BlockHeader blockHeader;
@Test
void createsAProtocolSpecUsingBesuProtocolSpec() {
when(besuProtocolSchedule.getByBlockHeader(blockHeader)).thenReturn(besuProtocolSpec);
final BlockHeader besuHeader = new BlockHeaderTestFixture().number(1).buildHeader();
final QbftBlockHeader qbftHeader = new QbftBlockHeaderAdaptor(besuHeader);
when(besuProtocolSchedule.getByBlockHeader(besuHeader)).thenReturn(besuProtocolSpec);
final QbftProtocolSchedule qbftProtocolSchedule =
new QbftProtocolScheduleAdaptor(besuProtocolSchedule, besuProtocolContext);
final QbftProtocolSpec protocolSpec = qbftProtocolSchedule.getByBlockHeader(blockHeader);
final QbftProtocolSpec protocolSpec = qbftProtocolSchedule.getByBlockHeader(qbftHeader);
assertThat(protocolSpec).hasFieldOrPropertyWithValue("besuProtocolSpec", besuProtocolSpec);
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import static org.mockito.Mockito.verify;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class QbftValidatorModeTransitionLoggerAdaptorTest {
@Mock private ValidatorModeTransitionLogger logger;
@Test
void logTransitionChangeDelegatesToLogger() {
BlockHeader header = new BlockHeaderTestFixture().buildHeader();
QbftBlockHeaderAdaptor qbftHeader = new QbftBlockHeaderAdaptor(header);
var adaptor = new QbftValidatorModeTransitionLoggerAdaptor(logger);
adaptor.logTransitionChange(qbftHeader);
verify(logger).logTransitionChange(header);
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright contributors to 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.consensus.qbft.adaptor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
import org.hyperledger.besu.consensus.common.validator.VoteProvider;
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHeader;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class QbftValidatorProviderAdaptorTest {
@Mock private ValidatorProvider validatorProvider;
@Mock private VoteProvider voteProvider;
@Test
void returnsValidatorsAtHead() {
List<Address> validatorsAtHead =
List.of(Address.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"));
when(validatorProvider.getValidatorsAtHead()).thenReturn(validatorsAtHead);
QbftValidatorProviderAdaptor qbftValidatorProviderAdaptor =
new QbftValidatorProviderAdaptor(validatorProvider);
assertThat(qbftValidatorProviderAdaptor.getValidatorsAtHead()).isEqualTo(validatorsAtHead);
}
@Test
void returnsValidatorsAfterBlock() {
BlockHeader header = new BlockHeaderTestFixture().buildHeader();
QbftBlockHeader qbftBlockHeader = new QbftBlockHeaderAdaptor(header);
List<Address> validatorsAfterBlock =
List.of(Address.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"));
when(validatorProvider.getValidatorsAfterBlock(header)).thenReturn(validatorsAfterBlock);
QbftValidatorProviderAdaptor qbftValidatorProviderAdaptor =
new QbftValidatorProviderAdaptor(validatorProvider);
assertThat(qbftValidatorProviderAdaptor.getValidatorsAfterBlock(qbftBlockHeader))
.isEqualTo(validatorsAfterBlock);
}
@Test
void returnsValidatorsForBlock() {
BlockHeader header = new BlockHeaderTestFixture().buildHeader();
QbftBlockHeader qbftBlockHeader = new QbftBlockHeaderAdaptor(header);
List<Address> validatorsForBlock =
List.of(Address.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"));
when(validatorProvider.getValidatorsForBlock(header)).thenReturn(validatorsForBlock);
QbftValidatorProviderAdaptor qbftValidatorProviderAdaptor =
new QbftValidatorProviderAdaptor(validatorProvider);
assertThat(qbftValidatorProviderAdaptor.getValidatorsForBlock(qbftBlockHeader))
.isEqualTo(validatorsForBlock);
}
@Test
void returnsVoteProviderAtHead() {
when(validatorProvider.getVoteProviderAtHead()).thenReturn(Optional.of(voteProvider));
QbftValidatorProviderAdaptor qbftValidatorProviderAdaptor =
new QbftValidatorProviderAdaptor(validatorProvider);
assertThat(qbftValidatorProviderAdaptor.getVoteProviderAtHead()).contains(voteProvider);
}
}

View File

@@ -25,7 +25,6 @@ import org.hyperledger.besu.config.QbftConfigOptions;
import org.hyperledger.besu.consensus.common.ForkSpec;
import org.hyperledger.besu.consensus.common.ForksSchedule;
import org.hyperledger.besu.consensus.qbft.MutableQbftConfigOptions;
import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;

View File

@@ -170,11 +170,6 @@ public abstract class AbstractEngineForkchoiceUpdated extends ExecutionEngineJso
.log();
return maybeError.get();
}
ValidationResult<RpcErrorType> forkValidationResult =
validateForkSupported(payloadAttributes.getTimestamp());
if (!forkValidationResult.isValid()) {
return new JsonRpcErrorResponse(requestId, forkValidationResult);
}
}
final BlockHeader newHead = maybeNewHead.get();

View File

@@ -153,6 +153,12 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
e);
}
final ValidationResult<RpcErrorType> forkValidationResult =
validateForkSupported(blockParam.getTimestamp());
if (!forkValidationResult.isValid()) {
return new JsonRpcErrorResponse(reqId, forkValidationResult);
}
final ValidationResult<RpcErrorType> parameterValidationResult =
validateParameters(
blockParam,
@@ -163,12 +169,6 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
return new JsonRpcErrorResponse(reqId, parameterValidationResult);
}
final ValidationResult<RpcErrorType> forkValidationResult =
validateForkSupported(blockParam.getTimestamp());
if (!forkValidationResult.isValid()) {
return new JsonRpcErrorResponse(reqId, forkValidationResult);
}
final Optional<List<VersionedHash>> maybeVersionedHashes;
try {
maybeVersionedHashes = extractVersionedHashes(maybeVersionedHashParam);

View File

@@ -59,6 +59,12 @@ public class EngineForkchoiceUpdatedV2 extends AbstractEngineForkchoiceUpdated {
return Optional.of(new JsonRpcErrorResponse(requestId, getInvalidPayloadAttributesError()));
}
ValidationResult<RpcErrorType> forkValidationResult =
validateForkSupported(payloadAttributes.getTimestamp());
if (!forkValidationResult.isValid()) {
return Optional.of(new JsonRpcErrorResponse(requestId, forkValidationResult));
}
return Optional.empty();
}

View File

@@ -81,6 +81,7 @@ public class EngineForkchoiceUpdatedV3 extends AbstractEngineForkchoiceUpdated {
@Override
protected Optional<JsonRpcErrorResponse> isPayloadAttributesValid(
final Object requestId, final EnginePayloadAttributesParameter payloadAttributes) {
if (payloadAttributes.getParentBeaconBlockRoot() == null) {
LOG.error(
"Parent beacon block root hash not present in payload attributes after cancun hardfork");
@@ -91,8 +92,10 @@ public class EngineForkchoiceUpdatedV3 extends AbstractEngineForkchoiceUpdated {
return Optional.of(new JsonRpcErrorResponse(requestId, getInvalidPayloadAttributesError()));
}
if (cancunMilestone.isEmpty() || payloadAttributes.getTimestamp() < cancunMilestone.get()) {
return Optional.of(new JsonRpcErrorResponse(requestId, RpcErrorType.UNSUPPORTED_FORK));
ValidationResult<RpcErrorType> forkValidationResult =
validateForkSupported(payloadAttributes.getTimestamp());
if (!forkValidationResult.isValid()) {
return Optional.of(new JsonRpcErrorResponse(requestId, forkValidationResult));
}
return Optional.empty();

View File

@@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine;
import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.CANCUN;
import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.PRAGUE;
import org.hyperledger.besu.consensus.merge.PayloadWrapper;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
@@ -68,6 +69,11 @@ public class EngineGetPayloadV3 extends AbstractEngineGetPayload {
@Override
protected ValidationResult<RpcErrorType> validateForkSupported(final long blockTimestamp) {
return ForkSupportHelper.validateForkSupported(CANCUN, cancunMilestone, blockTimestamp);
return ForkSupportHelper.validateForkSupported(
CANCUN,
cancunMilestone,
PRAGUE,
protocolSchedule.flatMap(s -> s.milestoneFor(PRAGUE)),
blockTimestamp);
}
}

View File

@@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine;
import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.CANCUN;
import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.PRAGUE;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.ethereum.ProtocolContext;
@@ -89,6 +90,11 @@ public class EngineNewPayloadV3 extends AbstractEngineNewPayload {
@Override
protected ValidationResult<RpcErrorType> validateForkSupported(final long blockTimestamp) {
return ForkSupportHelper.validateForkSupported(CANCUN, cancunMilestone, blockTimestamp);
return ForkSupportHelper.validateForkSupported(
CANCUN,
cancunMilestone,
PRAGUE,
protocolSchedule.flatMap(s -> s.milestoneFor(PRAGUE)),
blockTimestamp);
}
}

View File

@@ -21,22 +21,54 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import java.util.Optional;
public class ForkSupportHelper {
public static ValidationResult<RpcErrorType> validateForkSupported(
final HardforkId firstSupportedHardforkId,
final Optional<Long> maybeForkMilestone,
final Optional<Long> maybeFirstSupportedForkMilestone,
final long blockTimestamp) {
if (maybeForkMilestone.isEmpty()) {
if (maybeFirstSupportedForkMilestone.isEmpty()) {
return ValidationResult.invalid(
RpcErrorType.UNSUPPORTED_FORK,
"Configuration error, no schedule for " + firstSupportedHardforkId.name() + " fork set");
}
if (Long.compareUnsigned(blockTimestamp, maybeForkMilestone.get()) < 0) {
if (Long.compareUnsigned(blockTimestamp, maybeFirstSupportedForkMilestone.get()) < 0) {
return ValidationResult.invalid(
RpcErrorType.UNSUPPORTED_FORK,
firstSupportedHardforkId.name()
+ " configured to start at timestamp: "
+ maybeForkMilestone.get());
+ maybeFirstSupportedForkMilestone.get());
}
return ValidationResult.valid();
}
public static ValidationResult<RpcErrorType> validateForkSupported(
final HardforkId firstSupportedHardforkId,
final Optional<Long> maybeFirstSupportedForkMilestone,
final HardforkId firstUnsupportedHardforkId,
final Optional<Long> maybeFirstUnsupportedMilestone,
final long blockTimestamp) {
var result =
validateForkSupported(
firstSupportedHardforkId, maybeFirstSupportedForkMilestone, blockTimestamp);
if (!result.isValid()) {
return result;
}
if (maybeFirstUnsupportedMilestone.isPresent()
&& Long.compareUnsigned(blockTimestamp, maybeFirstUnsupportedMilestone.get()) >= 0) {
return ValidationResult.invalid(
RpcErrorType.UNSUPPORTED_FORK,
"block timestamp "
+ blockTimestamp
+ " is after the first unsupported milestone: "
+ firstUnsupportedHardforkId.name()
+ " at timestamp "
+ maybeFirstUnsupportedMilestone.get());
}
return ValidationResult.valid();

View File

@@ -0,0 +1,70 @@
/*
* Copyright contributors to 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.ethereum.api.jsonrpc.internal.results;
import org.hyperledger.besu.datatypes.CodeDelegation;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.tuweni.units.bigints.UInt256;
@JsonPropertyOrder({"chainId", "address", "nonce", "yParity", "r", "s"})
public class CodeDelegationResult {
private final String chainId;
private final String address;
private final String nonce;
private final String yParity;
private final String r;
private final String s;
public CodeDelegationResult(final CodeDelegation codeDelegation) {
chainId = Quantity.create(UInt256.valueOf(codeDelegation.chainId()));
address = codeDelegation.address().toHexString();
nonce = Quantity.create(codeDelegation.nonce());
yParity = Quantity.create(codeDelegation.v());
r = Quantity.create(codeDelegation.r());
s = Quantity.create(codeDelegation.s());
}
@JsonProperty("chainId")
public String chainId() {
return chainId;
}
@JsonProperty("address")
public String address() {
return address;
}
@JsonProperty("nonce")
public String nonce() {
return nonce;
}
@JsonProperty("yParity")
public String yParity() {
return yParity;
}
@JsonProperty("r")
public String r() {
return r;
}
@JsonProperty("s")
public String s() {
return s;
}
}

View File

@@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.core.Transaction;
import java.util.List;
import java.util.Optional;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -94,7 +95,7 @@ public class TransactionCompleteResult implements TransactionResult {
private final List<VersionedHash> versionedHashes;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final List<CodeDelegation> authorizationList;
private final List<CodeDelegationResult> authorizationList;
public TransactionCompleteResult(final TransactionWithMetadata tx) {
final Transaction transaction = tx.getTransaction();
@@ -140,7 +141,11 @@ public class TransactionCompleteResult implements TransactionResult {
this.r = Quantity.create(transaction.getR());
this.s = Quantity.create(transaction.getS());
this.versionedHashes = transaction.getVersionedHashes().orElse(null);
this.authorizationList = transaction.getCodeDelegationList().orElse(null);
final Optional<List<CodeDelegation>> codeDelegationList = transaction.getCodeDelegationList();
this.authorizationList =
codeDelegationList
.map(cds -> cds.stream().map(CodeDelegationResult::new).toList())
.orElse(null);
}
@JsonGetter(value = "accessList")
@@ -256,7 +261,7 @@ public class TransactionCompleteResult implements TransactionResult {
}
@JsonGetter(value = "authorizationList")
public List<CodeDelegation> getAuthorizationList() {
public List<CodeDelegationResult> getAuthorizationList() {
return authorizationList;
}
}

View File

@@ -50,8 +50,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class EthGetTransactionByHashTest {
// EIP-7702 Set Code Transaction
private static final String VALID_TRANSACTION =
"0xf86d0485174876e800830222e0945aae326516b4f8fe08074b7e972e40a713048d62880de0b6b3a7640000801ba05d4e7998757264daab67df2ce6f7e7a0ae36910778a406ca73898c9899a32b9ea0674700d5c3d1d27f2e6b4469957dfd1a1c49bf92383d80717afc84eb05695d5b";
"0xb8c404f8c1018080078307a12094a94f5374fce5edbc8e2a8697c15331677e6ebf0b8080c0f85cf85a809400000000000000000000000000000000000010008080a0dbcff17ff6c249f13b334fa86bcbaa1afd9f566ca9b06e4ea5fab9bdde9a9202a05c34c9d8af5b20e4a425fc1daf2d9d484576857eaf1629145b4686bac733868e01a0d61673cd58ffa5fc605c3215aa4647fa3afbea1d1f577e08402442992526d980a0063068ca818025c7b8493d0623cb70ef3a2ba4b3e2ae0af1146d1c9b065c0aff";
@Mock private BlockchainQueries blockchainQueries;
private EthGetTransactionByHash method;

View File

@@ -20,6 +20,7 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.Executi
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.SYNCING;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.VALID;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineTestSupport.fromErrorResp;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
@@ -43,7 +44,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngin
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EnginePayloadStatusResult;
@@ -429,14 +429,6 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
.get();
}
protected JsonRpcError fromErrorResp(final JsonRpcResponse resp) {
assertThat(resp.getType()).isEqualTo(RpcResponseType.ERROR);
return Optional.of(resp)
.map(JsonRpcErrorResponse.class::cast)
.map(JsonRpcErrorResponse::getError)
.get();
}
protected BlockHeader createBlockHeader(final Optional<List<Withdrawal>> maybeWithdrawals) {
return createBlockHeaderFixture(maybeWithdrawals).buildHeader();
}

View File

@@ -44,9 +44,9 @@ public class AbstractScheduledApiTest {
protected final ScheduledProtocolSpec.Hardfork cancunHardfork =
new ScheduledProtocolSpec.Hardfork("Cancun", 30);
protected final ScheduledProtocolSpec.Hardfork pragueHardfork =
new ScheduledProtocolSpec.Hardfork("Prague", 40);
new ScheduledProtocolSpec.Hardfork("Prague", 50);
protected final ScheduledProtocolSpec.Hardfork experimentalHardfork =
new ScheduledProtocolSpec.Hardfork("ExperimentalEips", 50);
new ScheduledProtocolSpec.Hardfork("ExperimentalEips", 70);
@Mock protected DefaultProtocolSchedule protocolSchedule;

View File

@@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineTestSupport.fromErrorResp;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -32,7 +33,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
@@ -256,12 +256,4 @@ public class EngineGetBlobsV1Test {
list.forEach(obj -> blobAndProofV1s.add((BlobAndProofV1) obj));
return blobAndProofV1s;
}
private RpcErrorType fromErrorResp(final JsonRpcResponse resp) {
assertThat(resp.getType()).isEqualTo(RpcResponseType.ERROR);
return Optional.of(resp)
.map(JsonRpcErrorResponse.class::cast)
.map(JsonRpcErrorResponse::getErrorType)
.get();
}
}

View File

@@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineTestSupport.fromErrorResp;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INVALID_RANGE_REQUEST_TOO_LARGE;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -29,10 +30,8 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EngineGetPayloadBodiesResultV1;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@@ -259,12 +258,4 @@ public class EngineGetPayloadBodiesByHashV1Test {
.map(EngineGetPayloadBodiesResultV1.class::cast)
.get();
}
private RpcErrorType fromErrorResp(final JsonRpcResponse resp) {
assertThat(resp.getType()).isEqualTo(RpcResponseType.ERROR);
return Optional.of(resp)
.map(JsonRpcErrorResponse.class::cast)
.map(JsonRpcErrorResponse::getErrorType)
.get();
}
}

Some files were not shown because too many files have changed in this diff Show More