mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-08 21:38:15 -05:00
Change Qbft to use its own QbftBlockHeader type (#8244)
Signed-off-by: Jason Frame <jason.frame@consensys.net>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ dependencies {
|
||||
api project(':consensus:ibft')
|
||||
api project(':consensus:merge')
|
||||
api project(':consensus:qbft')
|
||||
api project(':consensus:qbft-core')
|
||||
api project(':crypto:algorithms')
|
||||
api project(':crypto:services')
|
||||
api project(':datatypes')
|
||||
|
||||
Reference in New Issue
Block a user