Skip to content

Commit a021fea

Browse files
authored
Change Qbft to use its own QbftBlockHeader type (#8244)
Signed-off-by: Jason Frame <[email protected]>
1 parent e835cd0 commit a021fea

File tree

69 files changed

+1572
-345
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1572
-345
lines changed

acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public void shouldBeStableDuringLongTest(
9595
} catch (RuntimeException e) {
9696
assertThat(e.getMessage())
9797
.contains(
98-
"Revert reason: 'Transaction processing could not be completed due to an exception'");
98+
"Revert reason: 'Transaction processing could not be completed due to an exception (Invalid opcode: 0x5f)'");
9999
}
100100

101101
// Should initially be set to 0

besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java

+31-16
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.hyperledger.besu.consensus.common.BftValidatorOverrides;
2424
import org.hyperledger.besu.consensus.common.EpochManager;
2525
import org.hyperledger.besu.consensus.common.ForksSchedule;
26+
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
2627
import org.hyperledger.besu.consensus.common.bft.BftBlockInterface;
2728
import org.hyperledger.besu.consensus.common.bft.BftContext;
2829
import org.hyperledger.besu.consensus.common.bft.BftEventQueue;
@@ -46,13 +47,18 @@
4647
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
4748
import org.hyperledger.besu.consensus.qbft.QbftForksSchedulesFactory;
4849
import org.hyperledger.besu.consensus.qbft.QbftProtocolScheduleBuilder;
50+
import org.hyperledger.besu.consensus.qbft.adaptor.BftEventHandlerAdaptor;
4951
import org.hyperledger.besu.consensus.qbft.adaptor.BlockUtil;
5052
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockCodecAdaptor;
5153
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockCreatorFactoryAdaptor;
54+
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockHashingAdaptor;
5255
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockInterfaceAdaptor;
56+
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockchainAdaptor;
5357
import org.hyperledger.besu.consensus.qbft.adaptor.QbftExtraDataProviderAdaptor;
5458
import org.hyperledger.besu.consensus.qbft.adaptor.QbftFinalStateImpl;
5559
import org.hyperledger.besu.consensus.qbft.adaptor.QbftProtocolScheduleAdaptor;
60+
import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorModeTransitionLoggerAdaptor;
61+
import org.hyperledger.besu.consensus.qbft.adaptor.QbftValidatorProviderAdaptor;
5662
import org.hyperledger.besu.consensus.qbft.blockcreation.QbftBlockCreatorFactory;
5763
import org.hyperledger.besu.consensus.qbft.core.network.QbftGossip;
5864
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
@@ -62,16 +68,18 @@
6268
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
6369
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
6470
import org.hyperledger.besu.consensus.qbft.core.types.QbftContext;
71+
import org.hyperledger.besu.consensus.qbft.core.types.QbftEventHandler;
6572
import org.hyperledger.besu.consensus.qbft.core.types.QbftFinalState;
6673
import org.hyperledger.besu.consensus.qbft.core.types.QbftMinedBlockObserver;
6774
import org.hyperledger.besu.consensus.qbft.core.types.QbftProtocolSchedule;
75+
import org.hyperledger.besu.consensus.qbft.core.types.QbftValidatorProvider;
6876
import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory;
69-
import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger;
7077
import org.hyperledger.besu.consensus.qbft.jsonrpc.QbftJsonRpcMethods;
7178
import org.hyperledger.besu.consensus.qbft.protocol.Istanbul100SubProtocol;
7279
import org.hyperledger.besu.consensus.qbft.validator.ForkingValidatorProvider;
7380
import org.hyperledger.besu.consensus.qbft.validator.TransactionValidatorProvider;
7481
import org.hyperledger.besu.consensus.qbft.validator.ValidatorContractController;
82+
import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger;
7583
import org.hyperledger.besu.datatypes.Address;
7684
import org.hyperledger.besu.ethereum.ProtocolContext;
7785
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods;
@@ -209,9 +217,11 @@ protected MiningCoordinator createMiningCoordinator(
209217

210218
final ValidatorProvider validatorProvider =
211219
protocolContext.getConsensusContext(BftContext.class).getValidatorProvider();
220+
final QbftValidatorProvider qbftValidatorProvider =
221+
new QbftValidatorProviderAdaptor(validatorProvider);
212222

213223
final QbftBlockInterface qbftBlockInterface = new QbftBlockInterfaceAdaptor(bftBlockInterface);
214-
final QbftContext qbftContext = new QbftContext(validatorProvider, qbftBlockInterface);
224+
final QbftContext qbftContext = new QbftContext(qbftValidatorProvider, qbftBlockInterface);
215225
final ProtocolContext qbftProtocolContext =
216226
new ProtocolContext(
217227
blockchain,
@@ -267,42 +277,47 @@ protected MiningCoordinator createMiningCoordinator(
267277

268278
final MessageFactory messageFactory = new MessageFactory(nodeKey, blockEncoder);
269279

280+
QbftRoundFactory qbftRoundFactory =
281+
new QbftRoundFactory(
282+
finalState,
283+
qbftProtocolContext,
284+
qbftProtocolSchedule,
285+
minedBlockObservers,
286+
messageValidatorFactory,
287+
messageFactory,
288+
qbftExtraDataCodec,
289+
new QbftExtraDataProviderAdaptor(qbftExtraDataCodec),
290+
new QbftBlockHashingAdaptor(new BftBlockHashing(qbftExtraDataCodec)));
270291
QbftBlockHeightManagerFactory qbftBlockHeightManagerFactory =
271292
new QbftBlockHeightManagerFactory(
272293
finalState,
273-
new QbftRoundFactory(
274-
finalState,
275-
qbftProtocolContext,
276-
qbftProtocolSchedule,
277-
minedBlockObservers,
278-
messageValidatorFactory,
279-
messageFactory,
280-
qbftExtraDataCodec,
281-
new QbftExtraDataProviderAdaptor(qbftExtraDataCodec)),
294+
qbftRoundFactory,
282295
messageValidatorFactory,
283296
messageFactory,
284-
new ValidatorModeTransitionLogger(qbftForksSchedule));
297+
new QbftValidatorModeTransitionLoggerAdaptor(
298+
new ValidatorModeTransitionLogger(qbftForksSchedule)));
285299

286300
qbftBlockHeightManagerFactory.isEarlyRoundChangeEnabled(isEarlyRoundChangeEnabled);
287301

288-
final BftEventHandler qbftController =
302+
final QbftEventHandler qbftController =
289303
new QbftController(
290-
blockchain,
304+
new QbftBlockchainAdaptor(blockchain),
291305
finalState,
292306
qbftBlockHeightManagerFactory,
293307
gossiper,
294308
duplicateMessageTracker,
295309
futureMessageBuffer,
296310
new EthSynchronizerUpdater(ethProtocolManager.ethContext().getEthPeers()),
297311
blockEncoder);
312+
final BftEventHandler bftEventHandler = new BftEventHandlerAdaptor(qbftController);
298313

299-
final EventMultiplexer eventMultiplexer = new EventMultiplexer(qbftController);
314+
final EventMultiplexer eventMultiplexer = new EventMultiplexer(bftEventHandler);
300315
final BftProcessor bftProcessor = new BftProcessor(bftEventQueue, eventMultiplexer);
301316

302317
final MiningCoordinator miningCoordinator =
303318
new BftMiningCoordinator(
304319
bftExecutors,
305-
qbftController,
320+
bftEventHandler,
306321
bftProcessor,
307322
blockCreatorFactory,
308323
blockchain,

consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/BlockTimer.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
import org.hyperledger.besu.config.BftConfigOptions;
1818
import org.hyperledger.besu.consensus.common.ForksSchedule;
1919
import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry;
20-
import org.hyperledger.besu.ethereum.core.BlockHeader;
2120

2221
import java.time.Clock;
2322
import java.util.Optional;
2423
import java.util.concurrent.ScheduledFuture;
2524
import java.util.concurrent.TimeUnit;
25+
import java.util.function.Supplier;
2626

2727
import org.slf4j.Logger;
2828
import org.slf4j.LoggerFactory;
@@ -81,10 +81,10 @@ public synchronized boolean isRunning() {
8181
* Starts a timer for the supplied round cancelling any previously active block timer
8282
*
8383
* @param round The round identifier which this timer is tracking
84-
* @param chainHeadHeader The header of the chain head
84+
* @param headerTimestamp The timestamp from the of the chain head header
8585
*/
8686
public synchronized void startTimer(
87-
final ConsensusRoundIdentifier round, final BlockHeader chainHeadHeader) {
87+
final ConsensusRoundIdentifier round, final Supplier<Long> headerTimestamp) {
8888
cancelTimer();
8989

9090
final long expiryTime;
@@ -104,7 +104,7 @@ public synchronized void startTimer(
104104
final int currentBlockPeriodSeconds =
105105
forksSchedule.getFork(round.getSequenceNumber()).getValue().getBlockPeriodSeconds();
106106
final long minimumTimeBetweenBlocksMillis = currentBlockPeriodSeconds * 1000L;
107-
expiryTime = chainHeadHeader.getTimestamp() * 1_000 + minimumTimeBetweenBlocksMillis;
107+
expiryTime = headerTimestamp.get() * 1_000 + minimumTimeBetweenBlocksMillis;
108108
}
109109

110110
setBlockTimes(round);
@@ -115,14 +115,14 @@ public synchronized void startTimer(
115115
/**
116116
* Checks if the empty block timer is expired
117117
*
118-
* @param chainHeadHeader The header of the chain head
118+
* @param headerTimestamp Function to get the chain head timestamp
119119
* @param currentTimeInMillis The current time
120120
* @return a boolean value
121121
*/
122122
public synchronized boolean checkEmptyBlockExpired(
123-
final BlockHeader chainHeadHeader, final long currentTimeInMillis) {
123+
final Supplier<Long> headerTimestamp, final long currentTimeInMillis) {
124124
final long emptyBlockPeriodExpiryTime =
125-
(chainHeadHeader.getTimestamp() + emptyBlockPeriodSeconds) * 1000;
125+
(headerTimestamp.get() + emptyBlockPeriodSeconds) * 1000;
126126

127127
if (currentTimeInMillis > emptyBlockPeriodExpiryTime) {
128128
LOG.debug("Empty Block expired");
@@ -136,15 +136,15 @@ public synchronized boolean checkEmptyBlockExpired(
136136
* Resets the empty block timer
137137
*
138138
* @param roundIdentifier The current round identifier
139-
* @param chainHeadHeader The header of the chain head
139+
* @param headerTimestamp Function to get timestamp from the header of the chain head
140140
* @param currentTimeInMillis The current time
141141
*/
142142
public void resetTimerForEmptyBlock(
143143
final ConsensusRoundIdentifier roundIdentifier,
144-
final BlockHeader chainHeadHeader,
144+
final Supplier<Long> headerTimestamp,
145145
final long currentTimeInMillis) {
146146
final long emptyBlockPeriodExpiryTime =
147-
(chainHeadHeader.getTimestamp() + emptyBlockPeriodSeconds) * 1000;
147+
(headerTimestamp.get() + emptyBlockPeriodSeconds) * 1000;
148148
final long nextBlockPeriodExpiryTime = currentTimeInMillis + blockPeriodSeconds * 1000;
149149

150150
startTimer(roundIdentifier, Math.min(emptyBlockPeriodExpiryTime, nextBlockPeriodExpiryTime));

consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/BlockTimerTest.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public void startTimerSchedulesCorrectlyWhenExpiryIsInTheFuture() {
102102
bftExecutors.scheduleTask(any(Runnable.class), anyLong(), any()))
103103
.thenReturn(mockedFuture);
104104

105-
timer.startTimer(round, header);
105+
timer.startTimer(round, header::getTimestamp);
106106
verify(bftExecutors)
107107
.scheduleTask(any(Runnable.class), eq(EXPECTED_DELAY), eq(TimeUnit.MILLISECONDS));
108108
}
@@ -136,7 +136,7 @@ public void aBlockTimerExpiryEventIsAddedToTheQueueOnExpiry() throws Interrupted
136136

137137
final BftEventQueue eventQueue = new BftEventQueue(1000);
138138
final BlockTimer timer = new BlockTimer(eventQueue, mockForksSchedule, bftExecutors, mockClock);
139-
timer.startTimer(round, header);
139+
timer.startTimer(round, header::getTimestamp);
140140

141141
// Verify that the event will not be added to the queue immediately
142142
assertThat(eventQueue.isEmpty()).isTrue();
@@ -182,7 +182,7 @@ public void eventIsImmediatelyAddedToTheQueueIfAbsoluteExpiryIsEqualToNow() {
182182
final ConsensusRoundIdentifier round =
183183
new ConsensusRoundIdentifier(0xFEDBCA9876543210L, 0x12345678);
184184

185-
timer.startTimer(round, header);
185+
timer.startTimer(round, header::getTimestamp);
186186
verify(bftExecutors, never()).scheduleTask(any(Runnable.class), anyLong(), any());
187187

188188
final ArgumentCaptor<BftEvent> bftEventCaptor = ArgumentCaptor.forClass(BftEvent.class);
@@ -218,7 +218,7 @@ public void eventIsImmediatelyAddedToTheQueueIfAbsoluteExpiryIsInThePast() {
218218
final ConsensusRoundIdentifier round =
219219
new ConsensusRoundIdentifier(0xFEDBCA9876543210L, 0x12345678);
220220

221-
timer.startTimer(round, header);
221+
timer.startTimer(round, header::getTimestamp);
222222
verify(bftExecutors, never()).scheduleTask(any(Runnable.class), anyLong(), any());
223223

224224
final ArgumentCaptor<BftEvent> bftEventCaptor = ArgumentCaptor.forClass(BftEvent.class);
@@ -258,9 +258,9 @@ public void startTimerCancelsExistingTimer() {
258258
Mockito.<ScheduledFuture<?>>when(
259259
bftExecutors.scheduleTask(any(Runnable.class), anyLong(), eq(TimeUnit.MILLISECONDS)))
260260
.thenReturn(mockedFuture);
261-
timer.startTimer(round, header);
261+
timer.startTimer(round, header::getTimestamp);
262262
verify(mockedFuture, times(0)).cancel(false);
263-
timer.startTimer(round, header);
263+
timer.startTimer(round, header::getTimestamp);
264264
verify(mockedFuture, times(1)).cancel(false);
265265
}
266266

@@ -292,7 +292,7 @@ public void runningFollowsTheStateOfTheTimer() {
292292
Mockito.<ScheduledFuture<?>>when(
293293
bftExecutors.scheduleTask(any(Runnable.class), anyLong(), eq(TimeUnit.MILLISECONDS)))
294294
.thenReturn(mockedFuture);
295-
timer.startTimer(round, header);
295+
timer.startTimer(round, header::getTimestamp);
296296
when(mockedFuture.isDone()).thenReturn(false);
297297
assertThat(timer.isRunning()).isTrue();
298298
when(mockedFuture.isDone()).thenReturn(true);
@@ -322,7 +322,7 @@ public void checkBlockTimerEmptyAndNonEmptyPeriodSecods() {
322322
MINIMAL_TIME_BETWEEN_EMPTY_BLOCKS_SECONDS)));
323323

324324
final BlockTimer timer = new BlockTimer(mockQueue, mockForksSchedule, bftExecutors, mockClock);
325-
timer.startTimer(round, header);
325+
timer.startTimer(round, header::getTimestamp);
326326

327327
assertThat(timer.getBlockPeriodSeconds()).isEqualTo(MINIMAL_TIME_BETWEEN_BLOCKS_SECONDS);
328328
assertThat(timer.getEmptyBlockPeriodSeconds())

consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManager.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public IbftBlockHeightManager(
117117

118118
currentRound = roundFactory.createNewRound(parentHeader, 0);
119119
if (finalState.isLocalNodeProposerForRound(currentRound.getRoundIdentifier())) {
120-
blockTimer.startTimer(currentRound.getRoundIdentifier(), parentHeader);
120+
blockTimer.startTimer(currentRound.getRoundIdentifier(), parentHeader::getTimestamp);
121121
}
122122
}
123123

consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/IntegrationTestHelpers.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@
1919
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
2020
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
2121
import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
22+
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockHashingAdaptor;
2223
import org.hyperledger.besu.consensus.qbft.adaptor.QbftBlockInterfaceAdaptor;
24+
import org.hyperledger.besu.consensus.qbft.adaptor.QbftExtraDataProviderAdaptor;
2325
import org.hyperledger.besu.consensus.qbft.core.payload.CommitPayload;
2426
import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory;
2527
import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate;
2628
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlock;
2729
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockCodec;
30+
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockHashing;
2831
import org.hyperledger.besu.consensus.qbft.core.types.QbftBlockInterface;
32+
import org.hyperledger.besu.consensus.qbft.core.types.QbftExtraDataProvider;
2933
import org.hyperledger.besu.consensus.qbft.core.types.QbftHashMode;
3034
import org.hyperledger.besu.crypto.SECPSignature;
3135
import org.hyperledger.besu.cryptoservices.NodeKey;
@@ -42,10 +46,14 @@ public static SignedData<CommitPayload> createSignedCommitPayload(
4246

4347
final QbftBlock commitBlock =
4448
createCommitBlockFromProposalBlock(block, roundId.getRoundNumber());
49+
final QbftBlockHashing blockHashing =
50+
new QbftBlockHashingAdaptor(new BftBlockHashing(qbftExtraDataEncoder));
51+
final QbftExtraDataProvider extraDataProvider =
52+
new QbftExtraDataProviderAdaptor(qbftExtraDataEncoder);
4553
final SECPSignature commitSeal =
4654
nodeKey.sign(
47-
new BftBlockHashing(qbftExtraDataEncoder)
48-
.calculateDataHashForCommittedSeal(commitBlock.getHeader()));
55+
blockHashing.calculateDataHashForCommittedSeal(
56+
commitBlock.getHeader(), extraDataProvider.getExtraData(commitBlock.getHeader())));
4957

5058
final MessageFactory messageFactory = new MessageFactory(nodeKey, blockEncoder);
5159

0 commit comments

Comments
 (0)