From 2a52b0278b56eab556a8b20c34e9034d609723f2 Mon Sep 17 00:00:00 2001 From: Stefan Pingel <16143240+pinges@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:47:20 +1000 Subject: [PATCH 01/10] remove character accidentally added in CHANGELOG (#7586) Signed-off-by: stefan.pingel@consensys.net --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e151138641..aa6250508e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ - Correctly drops messages that exceeds local message size limit [#5455](https://github.com/hyperledger/besu/pull/7507) - **DebugMetrics**: Fixed a `ClassCastException` occurring in `DebugMetrics` when handling nested metric structures. Previously, `Double` values within these structures were incorrectly cast to `Map` objects, leading to errors. This update allows for proper handling of both direct values and nested structures at the same level. Issue# [#7383](https://github.com/hyperledger/besu/pull/7383) - `evmtool` was not respecting the `--genesis` setting, resulting in unexpected trace results. [#7433](https://github.com/hyperledger/besu/pull/7433) -- The genesis config override `contractSizeLimit`q was not wired into code size limits [#7557](https://github.com/hyperledger/besu/pull/7557) +- The genesis config override `contractSizeLimit` was not wired into code size limits [#7557](https://github.com/hyperledger/besu/pull/7557) - Fix incorrect key filtering in LayeredKeyValueStorage stream [#7535](https://github.com/hyperledger/besu/pull/7557) ## 24.8.0 From 9a570d415ec05c94473b8a8d92bfa3a4e914e48b Mon Sep 17 00:00:00 2001 From: Justin Florentine Date: Mon, 9 Sep 2024 09:25:37 -0400 Subject: [PATCH 02/10] Decouple block creators (#7468) * wip decoupled parent block header from block creators --------- Signed-off-by: Justin Florentine --- .../blockcreation/CliqueBlockCreator.java | 5 +- .../blockcreation/CliqueMinerExecutor.java | 1 - .../blockcreation/CliqueBlockCreatorTest.java | 12 +- .../blockcreation/CliqueBlockMinerTest.java | 4 +- .../bft/blockcreation/BftBlockCreator.java | 18 ++- .../blockcreation/BftBlockCreatorFactory.java | 4 +- .../consensus/ibft/support/TestContext.java | 4 +- .../tests/round/IbftRoundIntegrationTest.java | 7 +- .../ibft/statemachine/IbftRound.java | 11 +- .../ibft/statemachine/IbftRoundFactory.java | 5 +- .../blockcreation/BftBlockCreatorTest.java | 4 +- .../IbftBlockHeightManagerTest.java | 9 +- .../ibft/statemachine/IbftRoundTest.java | 42 +++-- .../blockcreation/MergeBlockCreator.java | 10 +- .../merge/blockcreation/MergeCoordinator.java | 16 +- .../blockcreation/MergeCoordinatorTest.java | 7 +- .../consensus/qbft/support/TestContext.java | 2 +- .../test/round/QbftRoundIntegrationTest.java | 7 +- .../qbft/statemachine/QbftRound.java | 13 +- .../qbft/statemachine/QbftRoundFactory.java | 5 +- .../QbftBlockHeightManagerTest.java | 9 +- .../qbft/statemachine/QbftRoundTest.java | 39 +++-- .../blockcreation/AbstractBlockCreator.java | 58 ++++--- .../ethereum/blockcreation/BlockCreator.java | 13 +- .../ethereum/blockcreation/BlockMiner.java | 6 +- .../blockcreation/PoWBlockCreator.java | 2 - .../blockcreation/PoWMinerExecutor.java | 1 - .../AbstractBlockCreatorTest.java | 144 ++++++++++-------- .../blockcreation/BlockMinerTest.java | 6 +- .../blockcreation/PoWBlockCreatorTest.java | 14 +- .../bonsai/AbstractIsolationTests.java | 8 +- .../retesteth/methods/TestMineBlocks.java | 5 +- 32 files changed, 295 insertions(+), 196 deletions(-) diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java index 099d66dc9f4..ed17529a9ff 100644 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java +++ b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java @@ -54,7 +54,6 @@ public class CliqueBlockCreator extends AbstractBlockCreator { * @param protocolContext the protocol context * @param protocolSchedule the protocol schedule * @param nodeKey the node key - * @param parentHeader the parent header * @param epochManager the epoch manager * @param ethScheduler the scheduler for asynchronous block creation tasks */ @@ -65,7 +64,6 @@ public CliqueBlockCreator( final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final NodeKey nodeKey, - final BlockHeader parentHeader, final EpochManager epochManager, final EthScheduler ethScheduler) { super( @@ -75,7 +73,6 @@ public CliqueBlockCreator( transactionPool, protocolContext, protocolSchedule, - parentHeader, ethScheduler); this.nodeKey = nodeKey; this.epochManager = epochManager; @@ -112,6 +109,8 @@ protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableB private Optional determineCliqueVote( final SealableBlockHeader sealableBlockHeader) { + BlockHeader parentHeader = + protocolContext.getBlockchain().getBlockHeader(sealableBlockHeader.getParentHash()).get(); if (epochManager.isEpochBlock(sealableBlockHeader.getNumber())) { return Optional.empty(); } else { diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java index 69b1fe70dd1..ef3d58fbffb 100644 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java +++ b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java @@ -103,7 +103,6 @@ public CliqueBlockMiner createMiner( protocolContext, protocolSchedule, nodeKey, - header, epochManager, ethScheduler); diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java index 9f2d848d452..ca76517c62c 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java @@ -156,11 +156,11 @@ public void proposerAddressCanBeExtractFromAConstructedBlock() { protocolContext, protocolSchedule, proposerNodeKey, - blockchain.getChainHeadHeader(), epochManager, ethScheduler); - final Block createdBlock = blockCreator.createBlock(5L).getBlock(); + final Block createdBlock = + blockCreator.createBlock(5L, blockchain.getChainHeadHeader()).getBlock(); assertThat(CliqueHelpers.getProposerOfBlock(createdBlock.getHeader())) .isEqualTo(proposerAddress); @@ -185,11 +185,11 @@ public void insertsValidVoteIntoConstructedBlock() { protocolContext, protocolSchedule, proposerNodeKey, - blockchain.getChainHeadHeader(), epochManager, ethScheduler); - final Block createdBlock = blockCreator.createBlock(0L).getBlock(); + final Block createdBlock = + blockCreator.createBlock(0L, blockchain.getChainHeadHeader()).getBlock(); assertThat(createdBlock.getHeader().getNonce()).isEqualTo(CliqueBlockInterface.ADD_NONCE); assertThat(createdBlock.getHeader().getCoinbase()).isEqualTo(a1); } @@ -219,11 +219,11 @@ public void insertsNoVoteWhenAtEpoch() { protocolContext, protocolSchedule, proposerNodeKey, - blockchain.getChainHeadHeader(), epochManager, ethScheduler); - final Block createdBlock = blockCreator.createBlock(0L).getBlock(); + final Block createdBlock = + blockCreator.createBlock(0L, blockchain.getChainHeadHeader()).getBlock(); assertThat(createdBlock.getHeader().getNonce()).isEqualTo(CliqueBlockInterface.DROP_NONCE); assertThat(createdBlock.getHeader().getCoinbase()).isEqualTo(Address.fromHexString("0")); } diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockMinerTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockMinerTest.java index 9dd3f2e03cd..8aca4713cd9 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockMinerTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockMinerTest.java @@ -91,7 +91,7 @@ void doesNotMineBlockIfNoTransactionsWhenEmptyBlocksNotAllowed() throws Interrup final CliqueBlockCreator blockCreator = mock(CliqueBlockCreator.class); final Function blockCreatorSupplier = (parentHeader) -> blockCreator; - when(blockCreator.createBlock(anyLong())) + when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreator.BlockCreationResult( blockToCreate, new TransactionSelectionResults(), new BlockCreationTiming())); @@ -147,7 +147,7 @@ void minesBlockIfHasTransactionsWhenEmptyBlocksNotAllowed() throws InterruptedEx final CliqueBlockCreator blockCreator = mock(CliqueBlockCreator.class); final Function blockCreatorSupplier = (parentHeader) -> blockCreator; - when(blockCreator.createBlock(anyLong())) + when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreator.BlockCreationResult( blockToCreate, new TransactionSelectionResults(), new BlockCreationTiming())); diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java index f461a77913e..6bc0254b691 100644 --- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java @@ -53,7 +53,6 @@ public class BftBlockCreator extends AbstractBlockCreator { * @param transactionPool the pending transactions * @param protocolContext the protocol context * @param protocolSchedule the protocol schedule - * @param parentHeader the parent header * @param bftExtraDataCodec the bft extra data codec * @param ethScheduler the scheduler for asynchronous block creation tasks */ @@ -65,7 +64,6 @@ public BftBlockCreator( final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final BlockHeader parentHeader, final BftExtraDataCodec bftExtraDataCodec, final EthScheduler ethScheduler) { super( @@ -75,21 +73,20 @@ public BftBlockCreator( transactionPool, protocolContext, protocolSchedule, - parentHeader, ethScheduler); this.bftExtraDataCodec = bftExtraDataCodec; } @Override - public BlockCreationResult createBlock(final long timestamp) { + public BlockCreationResult createBlock(final long timestamp, final BlockHeader parentHeader) { ProtocolSpec protocolSpec = ((BftProtocolSchedule) protocolSchedule) .getByBlockNumberOrTimestamp(parentHeader.getNumber() + 1, timestamp); if (protocolSpec.getWithdrawalsValidator() instanceof WithdrawalsValidator.AllowedWithdrawals) { - return createEmptyWithdrawalsBlock(timestamp); + return createEmptyWithdrawalsBlock(timestamp, parentHeader); } else { - return createBlock(Optional.empty(), Optional.empty(), timestamp); + return createBlock(Optional.empty(), Optional.empty(), timestamp, parentHeader); } } @@ -100,9 +97,14 @@ private static MiningBeneficiaryCalculator miningBeneficiaryCalculator( } @Override - public BlockCreationResult createEmptyWithdrawalsBlock(final long timestamp) { + public BlockCreationResult createEmptyWithdrawalsBlock( + final long timestamp, final BlockHeader parentHeader) { return createBlock( - Optional.empty(), Optional.empty(), Optional.of(Collections.emptyList()), timestamp); + Optional.empty(), + Optional.empty(), + Optional.of(Collections.emptyList()), + timestamp, + parentHeader); } @Override diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java index 64f7eef27dd..7c679763b60 100644 --- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java @@ -106,11 +106,10 @@ public BftBlockCreatorFactory( /** * Create block creator. * - * @param parentHeader the parent header * @param round the round * @return the block creator */ - public BlockCreator create(final BlockHeader parentHeader, final int round) { + public BlockCreator create(final int round) { return new BftBlockCreator( miningParameters, forksSchedule, @@ -119,7 +118,6 @@ public BlockCreator create(final BlockHeader parentHeader, final int round) { transactionPool, protocolContext, protocolSchedule, - parentHeader, bftExtraDataCodec, ethScheduler); } diff --git a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContext.java b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContext.java index fdd229c13ee..acf2507681b 100644 --- a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContext.java +++ b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContext.java @@ -90,8 +90,8 @@ public Block createBlockForProposal( final BlockHeader parent, final int round, final long timestamp) { return finalState .getBlockCreatorFactory() - .create(parent, round) - .createBlock(timestamp) + .create(round) + .createBlock(timestamp, parent) .getBlock(); } diff --git a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java index 5c43e086fb8..6a2199f7138 100644 --- a/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java +++ b/consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java @@ -90,6 +90,7 @@ public class IbftRoundIntegrationTest { private MessageFactory throwingMessageFactory; private IbftMessageTransmitter transmitter; @Mock private StubValidatorMulticaster multicaster; + @Mock BlockHeader parentHeader; private Block proposedBlock; @@ -145,7 +146,8 @@ public void signingFailsOnReceiptOfProposalUpdatesRoundButTransmitsNothing() { throwingMessageFactory, transmitter, roundTimer, - bftExtraDataEncoder); + bftExtraDataEncoder, + parentHeader); round.handleProposalMessage( peerMessageFactory.createProposal(roundIdentifier, proposedBlock, Optional.empty())); @@ -172,7 +174,8 @@ public void failuresToSignStillAllowBlockToBeImported() { throwingMessageFactory, transmitter, roundTimer, - bftExtraDataEncoder); + bftExtraDataEncoder, + parentHeader); // inject a block first, then a prepare on it. round.handleProposalMessage( diff --git a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java index 460213fa439..bff32dbf3cf 100644 --- a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java +++ b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java @@ -66,6 +66,7 @@ public class IbftRound { private final MessageFactory messageFactory; // used only to create stored local msgs private final IbftMessageTransmitter transmitter; private final BftExtraDataCodec bftExtraDataCodec; + private final BlockHeader parentHeader; /** * Instantiates a new Ibft round. @@ -80,6 +81,7 @@ public class IbftRound { * @param transmitter the transmitter * @param roundTimer the round timer * @param bftExtraDataCodec the bft extra data codec + * @param parentHeader the parent header */ public IbftRound( final RoundState roundState, @@ -91,7 +93,8 @@ public IbftRound( final MessageFactory messageFactory, final IbftMessageTransmitter transmitter, final RoundTimer roundTimer, - final BftExtraDataCodec bftExtraDataCodec) { + final BftExtraDataCodec bftExtraDataCodec, + final BlockHeader parentHeader) { this.roundState = roundState; this.blockCreator = blockCreator; this.protocolContext = protocolContext; @@ -101,6 +104,7 @@ public IbftRound( this.messageFactory = messageFactory; this.transmitter = transmitter; this.bftExtraDataCodec = bftExtraDataCodec; + this.parentHeader = parentHeader; roundTimer.startTimer(getRoundIdentifier()); } @@ -119,7 +123,8 @@ public ConsensusRoundIdentifier getRoundIdentifier() { * @param headerTimeStampSeconds the header time stamp seconds */ public void createAndSendProposalMessage(final long headerTimeStampSeconds) { - final Block block = blockCreator.createBlock(headerTimeStampSeconds).getBlock(); + final Block block = + blockCreator.createBlock(headerTimeStampSeconds, this.parentHeader).getBlock(); final BftExtraData extraData = bftExtraDataCodec.decode(block.getHeader()); LOG.debug("Creating proposed block. round={}", roundState.getRoundIdentifier()); LOG.trace( @@ -142,7 +147,7 @@ public void startRoundWith( final Block blockToPublish; if (!bestBlockFromRoundChange.isPresent()) { LOG.debug("Sending proposal with new block. round={}", roundState.getRoundIdentifier()); - blockToPublish = blockCreator.createBlock(headerTimestamp).getBlock(); + blockToPublish = blockCreator.createBlock(headerTimestamp, this.parentHeader).getBlock(); } else { LOG.debug( "Sending proposal from PreparedCertificate. round={}", roundState.getRoundIdentifier()); diff --git a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundFactory.java b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundFactory.java index 3c038fe01e5..489e23b58a4 100644 --- a/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundFactory.java +++ b/consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundFactory.java @@ -100,7 +100,7 @@ public IbftRound createNewRound(final BlockHeader parentHeader, final int round) public IbftRound createNewRoundWithState( final BlockHeader parentHeader, final RoundState roundState) { final BlockCreator blockCreator = - blockCreatorFactory.create(parentHeader, roundState.getRoundIdentifier().getRoundNumber()); + blockCreatorFactory.create(roundState.getRoundIdentifier().getRoundNumber()); final IbftMessageTransmitter messageTransmitter = new IbftMessageTransmitter(messageFactory, finalState.getValidatorMulticaster()); @@ -115,6 +115,7 @@ public IbftRound createNewRoundWithState( messageFactory, messageTransmitter, finalState.getRoundTimer(), - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); } } diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java index 15844578cdd..8b8406b6385 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java @@ -191,12 +191,12 @@ public BlockHeaderValidator.Builder createBlockHeaderRuleset( transactionPool, protContext, protocolSchedule, - parentHeader, bftExtraDataEncoder, new DeterministicEthScheduler()); final int secondsBetweenBlocks = 1; - final Block block = blockCreator.createBlock(parentHeader.getTimestamp() + 1).getBlock(); + final Block block = + blockCreator.createBlock(parentHeader.getTimestamp() + 1, parentHeader).getBlock(); final BlockHeaderValidator rules = IbftBlockHeaderValidationRulesetFactory.blockHeaderValidator( diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java index b388b80a3f1..b9f57debb6b 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java @@ -119,6 +119,7 @@ public class IbftBlockHeightManagerTest { @Mock private RoundTimer roundTimer; @Mock private FutureRoundProposalMessageValidator futureRoundProposalMessageValidator; @Mock private ValidatorMulticaster validatorMulticaster; + @Mock private BlockHeader parentHeader; @Captor private ArgumentCaptor sentMessageArgCaptor; @@ -158,7 +159,7 @@ public void setup() { lenient().when(finalState.getQuorum()).thenReturn(3); when(finalState.getValidatorMulticaster()).thenReturn(validatorMulticaster); lenient() - .when(blockCreator.createBlock(anyLong())) + .when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreationResult( createdBlock, new TransactionSelectionResults(), new BlockCreationTiming())); @@ -210,7 +211,8 @@ public void setup() { messageFactory, messageTransmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); }); lenient() @@ -228,7 +230,8 @@ public void setup() { messageFactory, messageTransmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); }); } diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java index e948f43f3bf..f4ee852a04f 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java @@ -98,6 +98,7 @@ public class IbftRoundTest { @Mock private RoundTimer roundTimer; @Mock private ProtocolSpec protocolSpec; @Mock private BlockImporter blockImporter; + @Mock private BlockHeader parentHeader; @Captor private ArgumentCaptor blockCaptor; @@ -131,7 +132,7 @@ public void setup() { proposedBlock = new Block(header, new BlockBody(emptyList(), emptyList())); lenient() - .when(blockCreator.createBlock(anyLong())) + .when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreationResult( proposedBlock, new TransactionSelectionResults(), new BlockCreationTiming())); @@ -159,7 +160,8 @@ public void onConstructionRoundTimerIsStarted() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); verify(roundTimer, times(1)).startTimer(roundIdentifier); } @@ -177,7 +179,8 @@ public void onReceptionOfValidProposalSendsAPrepareToNetworkPeers() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleProposalMessage( messageFactory.createProposal(roundIdentifier, proposedBlock, Optional.empty())); @@ -199,7 +202,8 @@ public void sendsAProposalWhenRequested() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.createAndSendProposalMessage(15); verify(transmitter, times(1)) @@ -222,7 +226,8 @@ public void singleValidatorImportBlocksImmediatelyOnProposalCreation() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.createAndSendProposalMessage(15); verify(transmitter, times(1)) .multicastProposal(roundIdentifier, proposedBlock, Optional.empty()); @@ -245,7 +250,8 @@ public void twoValidatorNetworkSendsPrepareOnProposalReceptionThenSendsCommitOnC messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); final Hash commitSealHash = new BftBlockHashing(new IbftExtraDataCodec()) @@ -292,7 +298,8 @@ public void localNodeProposesToNetworkOfTwoValidatorsImportsOnReceptionOfCommitF messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); final Hash commitSealHash = new BftBlockHashing(new IbftExtraDataCodec()) @@ -329,7 +336,8 @@ public void aProposalWithAnewBlockIsSentUponReceptionOfARoundChangeWithNoCertifi messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); final RoundChangeCertificate roundChangeCertificate = new RoundChangeCertificate(emptyList()); @@ -353,7 +361,8 @@ public void aProposalMessageWithTheSameBlockIsSentUponReceptionOfARoundChangeWit messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); final RoundChangeArtifacts roundChangeArtifacts = RoundChangeArtifacts.create( @@ -400,7 +409,8 @@ public void creatingNewBlockFromEmptyPreparedCertificateUpdatesInternalState() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); final RoundChangeArtifacts roundChangeArtifacts = RoundChangeArtifacts.create( @@ -434,7 +444,8 @@ public void creatingNewBlockNotifiesBlockMiningObservers() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.createAndSendProposalMessage(15); verify(minedBlockObserver).blockMined(any()); } @@ -455,7 +466,8 @@ public void blockIsOnlyImportedOnceWhenCommitsAreReceivedBeforeProposal() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleCommitMessage( messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal)); @@ -481,7 +493,8 @@ public void blockIsImportedOnlyOnceIfQuorumCommitsAreReceivedPriorToProposal() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleCommitMessage( messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal)); @@ -511,7 +524,8 @@ public void exceptionDuringNodeKeySigningDoesNotEscape() { throwingMessageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleProposalMessage( messageFactory.createProposal(roundIdentifier, proposedBlock, Optional.empty())); diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java index 10c21384adf..c56c62d80db 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java @@ -61,7 +61,6 @@ public MergeBlockCreator( transactionPool, protocolContext, protocolSchedule, - parentHeader, ethScheduler); } @@ -80,7 +79,8 @@ public BlockCreationResult createBlock( final Bytes32 random, final long timestamp, final Optional> withdrawals, - final Optional parentBeaconBlockRoot) { + final Optional parentBeaconBlockRoot, + final BlockHeader parentHeader) { return createBlock( maybeTransactions, @@ -89,14 +89,16 @@ public BlockCreationResult createBlock( Optional.of(random), parentBeaconBlockRoot, timestamp, - false); + false, + parentHeader); } @Override public BlockCreationResult createBlock( final Optional> maybeTransactions, final Optional> maybeOmmers, - final long timestamp) { + final long timestamp, + final BlockHeader parentHeader) { throw new UnsupportedOperationException("random is required"); } diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java index 4d4ca0638d3..c62b6e0de88 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java @@ -294,7 +294,8 @@ public PayloadIdentifier preparePayload( prevRandao, timestamp, withdrawals, - parentBeaconBlockRoot) + parentBeaconBlockRoot, + parentHeader) .getBlock(); BlockProcessingResult result = validateProposedBlock(emptyBlock); @@ -322,7 +323,8 @@ public PayloadIdentifier preparePayload( payloadIdentifier, mergeBlockCreator, withdrawals, - parentBeaconBlockRoot); + parentBeaconBlockRoot, + parentHeader); return payloadIdentifier; } @@ -363,12 +365,18 @@ private void tryToBuildBetterBlock( final PayloadIdentifier payloadIdentifier, final MergeBlockCreator mergeBlockCreator, final Optional> withdrawals, - final Optional parentBeaconBlockRoot) { + final Optional parentBeaconBlockRoot, + final BlockHeader parentHeader) { final Supplier blockCreator = () -> mergeBlockCreator.createBlock( - Optional.empty(), random, timestamp, withdrawals, parentBeaconBlockRoot); + Optional.empty(), + random, + timestamp, + withdrawals, + parentBeaconBlockRoot, + parentHeader); LOG.debug( "Block creation started for payload id {}, remaining time is {}ms", diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index a3dc6b6e0b7..9c1a3df075e 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -285,7 +285,12 @@ public void exceptionDuringBuildingBlockShouldNotBeInvalid() .doCallRealMethod() .when(beingSpiedOn) .createBlock( - any(), any(Bytes32.class), anyLong(), eq(Optional.empty()), eq(Optional.empty())); + any(), + any(Bytes32.class), + anyLong(), + eq(Optional.empty()), + eq(Optional.empty()), + any()); return beingSpiedOn; }; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContext.java b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContext.java index cbce344efcc..10cdfa91501 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContext.java +++ b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContext.java @@ -103,7 +103,7 @@ public Block createBlockForProposalFromChainHead(final long timestamp) { public Block createBlockForProposal( final BlockHeader parent, final long timestamp, final Address proposer) { final Block block = - finalState.getBlockCreatorFactory().create(parent, 0).createBlock(timestamp).getBlock(); + finalState.getBlockCreatorFactory().create(0).createBlock(timestamp, parent).getBlock(); final BlockHeaderBuilder headerBuilder = BlockHeaderBuilder.fromHeader(block.getHeader()); headerBuilder diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java index 7d579426550..7dcca442a7f 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java +++ b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java @@ -92,6 +92,7 @@ public class QbftRoundIntegrationTest { private MessageFactory throwingMessageFactory; private QbftMessageTransmitter transmitter; @Mock private StubValidatorMulticaster multicaster; + @Mock private BlockHeader parentHeader; private Block proposedBlock; @@ -148,7 +149,8 @@ public void signingFailsOnReceiptOfProposalUpdatesRoundButTransmitsNothing() { throwingMessageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleProposalMessage( peerMessageFactory.createProposal( @@ -176,7 +178,8 @@ public void failuresToSignStillAllowBlockToBeImported() { throwingMessageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); // inject a block first, then a prepare on it. round.handleProposalMessage( diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java index 47db570acc0..f7c43ef43dd 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java @@ -80,6 +80,8 @@ public class QbftRound { /** The Bft extra data codec. */ protected final BftExtraDataCodec bftExtraDataCodec; + private final BlockHeader parentHeader; + /** * Instantiates a new Qbft round. * @@ -93,6 +95,7 @@ public class QbftRound { * @param transmitter the transmitter * @param roundTimer the round timer * @param bftExtraDataCodec the bft extra data codec + * @param parentHeader the parent header */ public QbftRound( final RoundState roundState, @@ -104,7 +107,8 @@ public QbftRound( final MessageFactory messageFactory, final QbftMessageTransmitter transmitter, final RoundTimer roundTimer, - final BftExtraDataCodec bftExtraDataCodec) { + final BftExtraDataCodec bftExtraDataCodec, + final BlockHeader parentHeader) { this.roundState = roundState; this.blockCreator = blockCreator; this.protocolContext = protocolContext; @@ -114,7 +118,7 @@ public QbftRound( this.messageFactory = messageFactory; this.transmitter = transmitter; this.bftExtraDataCodec = bftExtraDataCodec; - + this.parentHeader = parentHeader; roundTimer.startTimer(getRoundIdentifier()); } @@ -134,7 +138,8 @@ public ConsensusRoundIdentifier getRoundIdentifier() { */ public void createAndSendProposalMessage(final long headerTimeStampSeconds) { LOG.debug("Creating proposed block. round={}", roundState.getRoundIdentifier()); - final Block block = blockCreator.createBlock(headerTimeStampSeconds).getBlock(); + final Block block = + blockCreator.createBlock(headerTimeStampSeconds, this.parentHeader).getBlock(); LOG.trace("Creating proposed block blockHeader={}", block.getHeader()); updateStateWithProposalAndTransmit(block, emptyList(), emptyList()); @@ -154,7 +159,7 @@ public void startRoundWith( final Block blockToPublish; if (bestPreparedCertificate.isEmpty()) { LOG.debug("Sending proposal with new block. round={}", roundState.getRoundIdentifier()); - blockToPublish = blockCreator.createBlock(headerTimestamp).getBlock(); + blockToPublish = blockCreator.createBlock(headerTimestamp, this.parentHeader).getBlock(); } else { LOG.debug( "Sending proposal from PreparedCertificate. round={}", roundState.getRoundIdentifier()); diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java index 7c1c9200f9d..30253300096 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java @@ -99,7 +99,7 @@ public QbftRound createNewRound(final BlockHeader parentHeader, final int round) */ public QbftRound createNewRoundWithState( final BlockHeader parentHeader, final RoundState roundState) { - final BlockCreator blockCreator = blockCreatorFactory.create(parentHeader, 0); + final BlockCreator blockCreator = blockCreatorFactory.create(0); // TODO(tmm): Why is this created everytime?! final QbftMessageTransmitter messageTransmitter = @@ -115,6 +115,7 @@ public QbftRound createNewRoundWithState( messageFactory, messageTransmitter, finalState.getRoundTimer(), - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); } } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java index 71ea4131a3b..171b1607f39 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java @@ -121,6 +121,7 @@ public class QbftBlockHeightManagerTest { @Mock private DefaultBlockchain blockchain; @Mock private FutureRoundProposalMessageValidator futureRoundProposalMessageValidator; @Mock private ValidatorMulticaster validatorMulticaster; + @Mock private BlockHeader parentHeader; @Captor private ArgumentCaptor sentMessageArgCaptor; @@ -158,7 +159,7 @@ public void setup() { when(finalState.getBlockTimer()).thenReturn(blockTimer); when(finalState.getQuorum()).thenReturn(3); when(finalState.getValidatorMulticaster()).thenReturn(validatorMulticaster); - when(blockCreator.createBlock(anyLong())) + when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreationResult( createdBlock, new TransactionSelectionResults(), new BlockCreationTiming())); @@ -210,7 +211,8 @@ BftContext.class, validators, new QbftExtraDataCodec()), messageFactory, messageTransmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); }); when(roundFactory.createNewRoundWithState(any(), any())) @@ -227,7 +229,8 @@ BftContext.class, validators, new QbftExtraDataCodec()), messageFactory, messageTransmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); }); } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java index 92e7131476b..514fd653a1d 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java @@ -106,6 +106,7 @@ public class QbftRoundTest { @Mock private RoundTimer roundTimer; @Mock private ProtocolSpec protocolSpec; @Mock private BlockImporter blockImporter; + @Mock private BlockHeader parentHeader; @Captor private ArgumentCaptor blockCaptor; @@ -139,7 +140,7 @@ BftContext.class, emptyList(), new QbftExtraDataCodec()), final BlockHeader header = headerTestFixture.buildHeader(); proposedBlock = new Block(header, new BlockBody(emptyList(), emptyList())); - when(blockCreator.createBlock(anyLong())) + when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreationResult( proposedBlock, new TransactionSelectionResults(), new BlockCreationTiming())); @@ -166,7 +167,8 @@ public void onConstructionRoundTimerIsStarted() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); verify(roundTimer, times(1)).startTimer(roundIdentifier); } @@ -184,7 +186,8 @@ public void onReceptionOfValidProposalSendsAPrepareToNetworkPeers() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleProposalMessage( messageFactory.createProposal( @@ -207,7 +210,8 @@ public void sendsAProposalAndPrepareWhenSendProposalRequested() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.createAndSendProposalMessage(15); verify(transmitter, times(1)) @@ -231,7 +235,8 @@ public void singleValidatorImportBlocksImmediatelyOnProposalCreation() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.createAndSendProposalMessage(15); verify(transmitter, times(1)) .multicastProposal( @@ -254,7 +259,8 @@ public void localNodeProposesToNetworkOfTwoValidatorsImportsOnReceptionOfCommitF messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); final Hash commitSealHash = new BftBlockHashing(new QbftExtraDataCodec()) @@ -288,7 +294,8 @@ public void aProposalWithAnewBlockIsSentUponReceptionOfARoundChangeWithNoCertifi messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.startRoundWith(new RoundChangeArtifacts(emptyList(), Optional.empty()), 15); verify(transmitter, times(1)) @@ -311,7 +318,8 @@ public void aProposalMessageWithTheSameBlockIsSentUponReceptionOfARoundChangeWit messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); final SignedData preparedPayload = messageFactory.createPrepare(priorRoundChange, proposedBlock.getHash()).getSignedPayload(); @@ -359,7 +367,8 @@ public void creatingNewBlockFromEmptyPreparedCertificateUpdatesInternalState() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); final RoundChange roundChange = messageFactory.createRoundChange(roundIdentifier, Optional.empty()); @@ -398,7 +407,8 @@ public void creatingNewBlockNotifiesBlockMiningObservers() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.createAndSendProposalMessage(15); verify(minedBlockObserver).blockMined(any()); } @@ -419,7 +429,8 @@ public void blockIsOnlyImportedOnceWhenCommitsAreReceivedBeforeProposal() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleCommitMessage( messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal)); @@ -444,7 +455,8 @@ public void blockIsImportedOnlyOnceIfQuorumCommitsAreReceivedPriorToProposal() { messageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleCommitMessage( messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal)); @@ -473,7 +485,8 @@ public void exceptionDuringNodeKeySigningDoesNotEscape() { throwingMessageFactory, transmitter, roundTimer, - bftExtraDataCodec); + bftExtraDataCodec, + parentHeader); round.handleProposalMessage( messageFactory.createProposal( diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index 78c32842ff7..b843389c0d3 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -88,7 +88,6 @@ public interface ExtraDataCalculator { protected final ProtocolContext protocolContext; protected final ProtocolSchedule protocolSchedule; protected final BlockHeaderFunctions blockHeaderFunctions; - protected final BlockHeader parentHeader; private final EthScheduler ethScheduler; private final AtomicBoolean isCancelled = new AtomicBoolean(false); @@ -99,7 +98,6 @@ protected AbstractBlockCreator( final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final BlockHeader parentHeader, final EthScheduler ethScheduler) { this.miningParameters = miningParameters; this.miningBeneficiaryCalculator = miningBeneficiaryCalculator; @@ -107,7 +105,6 @@ protected AbstractBlockCreator( this.transactionPool = transactionPool; this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; - this.parentHeader = parentHeader; this.ethScheduler = ethScheduler; blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule); } @@ -130,21 +127,25 @@ protected AbstractBlockCreator( * @return a block with appropriately selected transactions, seals and ommers. */ @Override - public BlockCreationResult createBlock(final long timestamp) { - return createBlock(Optional.empty(), Optional.empty(), timestamp); + public BlockCreationResult createBlock(final long timestamp, final BlockHeader parentHeader) { + return createBlock(Optional.empty(), Optional.empty(), timestamp, parentHeader); } @Override public BlockCreationResult createBlock( - final List transactions, final List ommers, final long timestamp) { - return createBlock(Optional.of(transactions), Optional.of(ommers), timestamp); + final List transactions, + final List ommers, + final long timestamp, + final BlockHeader parentHeader) { + return createBlock(Optional.of(transactions), Optional.of(ommers), timestamp, parentHeader); } @Override public BlockCreationResult createBlock( final Optional> maybeTransactions, final Optional> maybeOmmers, - final long timestamp) { + final long timestamp, + final BlockHeader parentHeader) { return createBlock( maybeTransactions, maybeOmmers, @@ -152,11 +153,13 @@ public BlockCreationResult createBlock( Optional.empty(), Optional.empty(), timestamp, - true); + true, + parentHeader); } @Override - public BlockCreationResult createEmptyWithdrawalsBlock(final long timestamp) { + public BlockCreationResult createEmptyWithdrawalsBlock( + final long timestamp, final BlockHeader parentHeader) { throw new UnsupportedOperationException("Only used by BFT block creators"); } @@ -164,7 +167,8 @@ public BlockCreationResult createBlock( final Optional> maybeTransactions, final Optional> maybeOmmers, final Optional> maybeWithdrawals, - final long timestamp) { + final long timestamp, + final BlockHeader parentHeader) { return createBlock( maybeTransactions, maybeOmmers, @@ -172,7 +176,8 @@ public BlockCreationResult createBlock( Optional.empty(), Optional.empty(), timestamp, - true); + true, + parentHeader); } protected BlockCreationResult createBlock( @@ -182,18 +187,23 @@ protected BlockCreationResult createBlock( final Optional maybePrevRandao, final Optional maybeParentBeaconBlockRoot, final long timestamp, - boolean rewardCoinbase) { + boolean rewardCoinbase, + final BlockHeader parentHeader) { final var timings = new BlockCreationTiming(); - try (final MutableWorldState disposableWorldState = duplicateWorldStateAtParent()) { + try (final MutableWorldState disposableWorldState = duplicateWorldStateAtParent(parentHeader)) { timings.register("duplicateWorldState"); final ProtocolSpec newProtocolSpec = protocolSchedule.getForNextBlockHeader(parentHeader, timestamp); final ProcessableBlockHeader processableBlockHeader = createPendingBlockHeader( - timestamp, maybePrevRandao, maybeParentBeaconBlockRoot, newProtocolSpec); + timestamp, + maybePrevRandao, + maybeParentBeaconBlockRoot, + newProtocolSpec, + parentHeader); final Address miningBeneficiary = miningBeneficiaryCalculator.getMiningBeneficiary(processableBlockHeader.getNumber()); @@ -223,7 +233,8 @@ protected BlockCreationResult createBlock( maybeTransactions, miningBeneficiary, newProtocolSpec, - pluginTransactionSelector); + pluginTransactionSelector, + parentHeader); transactionResults.logSelectionStats(); timings.register("txsSelection"); throwIfStopped(); @@ -273,7 +284,8 @@ protected BlockCreationResult createBlock( throwIfStopped(); - final GasUsage usage = computeExcessBlobGas(transactionResults, newProtocolSpec); + final GasUsage usage = + computeExcessBlobGas(transactionResults, newProtocolSpec, parentHeader); throwIfStopped(); @@ -324,7 +336,9 @@ protected BlockCreationResult createBlock( record GasUsage(BlobGas excessBlobGas, BlobGas used) {} private GasUsage computeExcessBlobGas( - final TransactionSelectionResults transactionResults, final ProtocolSpec newProtocolSpec) { + final TransactionSelectionResults transactionResults, + final ProtocolSpec newProtocolSpec, + final BlockHeader parentHeader) { if (newProtocolSpec.getFeeMarket().implementsDataFee()) { final var gasCalculator = newProtocolSpec.getGasCalculator(); @@ -349,7 +363,8 @@ private TransactionSelectionResults selectTransactions( final Optional> transactions, final Address miningBeneficiary, final ProtocolSpec protocolSpec, - final PluginTransactionSelector pluginTransactionSelector) + final PluginTransactionSelector pluginTransactionSelector, + final BlockHeader parentHeader) throws RuntimeException { final MainnetTransactionProcessor transactionProcessor = protocolSpec.getTransactionProcessor(); @@ -387,7 +402,7 @@ private TransactionSelectionResults selectTransactions( } } - private MutableWorldState duplicateWorldStateAtParent() { + private MutableWorldState duplicateWorldStateAtParent(final BlockHeader parentHeader) { final Hash parentStateRoot = parentHeader.getStateRoot(); return protocolContext .getWorldStateArchive() @@ -411,7 +426,8 @@ private ProcessableBlockHeader createPendingBlockHeader( final long timestamp, final Optional maybePrevRandao, final Optional maybeParentBeaconBlockRoot, - final ProtocolSpec protocolSpec) { + final ProtocolSpec protocolSpec, + final BlockHeader parentHeader) { final long newBlockNumber = parentHeader.getNumber() + 1; long gasLimit = protocolSpec diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockCreator.java index 24bff4c47ee..988cc7e7635 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockCreator.java @@ -50,15 +50,20 @@ public BlockCreationTiming getBlockCreationTimings() { } } - BlockCreationResult createBlock(final long timestamp); + BlockCreationResult createBlock(final long timestamp, final BlockHeader parentHeader); - BlockCreationResult createEmptyWithdrawalsBlock(final long timestamp); + BlockCreationResult createEmptyWithdrawalsBlock( + final long timestamp, final BlockHeader parentHeader); BlockCreationResult createBlock( - final List transactions, final List ommers, final long timestamp); + final List transactions, + final List ommers, + final long timestamp, + final BlockHeader parentHeader); BlockCreationResult createBlock( final Optional> maybeTransactions, final Optional> maybeOmmers, - final long timestamp); + final long timestamp, + final BlockHeader parentHeader); } diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java index 646e6d52510..f51451f2930 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java @@ -109,7 +109,7 @@ public BlockCreationResult createBlock( final List ommers) { final BlockCreator blockCreator = this.blockCreatorFactory.apply(parentHeader); final long timestamp = scheduler.getNextTimestamp(parentHeader).timestampForHeader(); - return blockCreator.createBlock(transactions, ommers, timestamp); + return blockCreator.createBlock(transactions, ommers, timestamp, parentHeader); } /** @@ -121,7 +121,7 @@ public BlockCreationResult createBlock( */ public BlockCreationResult createBlock(final BlockHeader parentHeader, final long timestamp) { final BlockCreator blockCreator = this.blockCreatorFactory.apply(parentHeader); - return blockCreator.createBlock(Optional.empty(), Optional.empty(), timestamp); + return blockCreator.createBlock(Optional.empty(), Optional.empty(), timestamp, parentHeader); } protected boolean shouldImportBlock(final Block block) throws InterruptedException { @@ -140,7 +140,7 @@ protected boolean mineBlock() throws InterruptedException { LOG.trace("Mining a new block with timestamp {}", newBlockTimestamp); - final var blockCreationResult = minerBlockCreator.createBlock(newBlockTimestamp); + final var blockCreationResult = minerBlockCreator.createBlock(newBlockTimestamp, parentHeader); timing.registerAll(blockCreationResult.getBlockCreationTimings()); final Block block = blockCreationResult.getBlock(); diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java index 39b055e817c..d0042a5ad96 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java @@ -45,7 +45,6 @@ public PoWBlockCreator( final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final PoWSolver nonceSolver, - final BlockHeader parentHeader, final EthScheduler ethScheduler) { super( miningParameters, @@ -54,7 +53,6 @@ public PoWBlockCreator( transactionPool, protocolContext, protocolSchedule, - parentHeader, ethScheduler); this.nonceSolver = nonceSolver; diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java index 78524e3035e..b14eb193405 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java @@ -93,7 +93,6 @@ public PoWBlockMiner createMiner( protocolContext, protocolSchedule, solver, - parentHeader, ethScheduler); return new PoWBlockMiner( diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index 88a39925b92..ffab847bbdc 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -161,18 +161,19 @@ void findDepositRequestsFromReceipts() { @Test void withAllowedDepositRequestsAndContractAddress_DepositRequestsAreParsed() { - final AbstractBlockCreator blockCreator = + final CreateOn miningOn = blockCreatorWithAllowedDepositRequests(DEFAULT_DEPOSIT_CONTRACT_ADDRESS); final BlockCreationResult blockCreationResult = - blockCreator.createBlock( + miningOn.blockCreator.createBlock( Optional.empty(), Optional.empty(), Optional.of(emptyList()), Optional.empty(), Optional.empty(), 1L, - false); + false, + miningOn.parentHeader); List depositRequests = emptyList(); final Hash requestsRoot = BodyValidation.requestsRoot(depositRequests); @@ -182,17 +183,18 @@ void withAllowedDepositRequestsAndContractAddress_DepositRequestsAreParsed() { @Test void withAllowedDepositRequestsAndNoContractAddress_DepositRequestsAreNotParsed() { - final AbstractBlockCreator blockCreator = blockCreatorWithAllowedDepositRequests(null); + final CreateOn miningOn = blockCreatorWithAllowedDepositRequests(null); final BlockCreationResult blockCreationResult = - blockCreator.createBlock( + miningOn.blockCreator.createBlock( Optional.empty(), Optional.empty(), Optional.of(emptyList()), Optional.empty(), Optional.empty(), 1L, - false); + false, + miningOn.parentHeader); assertThat(blockCreationResult.getBlock().getHeader().getRequestsRoot()).isEmpty(); assertThat(blockCreationResult.getBlock().getBody().getRequests()).isEmpty(); @@ -200,53 +202,28 @@ void withAllowedDepositRequestsAndNoContractAddress_DepositRequestsAreNotParsed( @Test void withProhibitedDepositRequests_DepositRequestsAreNotParsed() { - final AbstractBlockCreator blockCreator = blockCreatorWithProhibitedDepositRequests(); + + final CreateOn miningOn = blockCreatorWithProhibitedDepositRequests(); final BlockCreationResult blockCreationResult = - blockCreator.createBlock( + miningOn.blockCreator.createBlock( Optional.empty(), Optional.empty(), Optional.of(emptyList()), Optional.empty(), Optional.empty(), 1L, - false); + false, + miningOn.parentHeader); assertThat(blockCreationResult.getBlock().getHeader().getRequestsRoot()).isEmpty(); assertThat(blockCreationResult.getBlock().getBody().getRequests()).isEmpty(); } - private AbstractBlockCreator blockCreatorWithAllowedDepositRequests( - final Address depositContractAddress) { - final ProtocolSpecAdapters protocolSpecAdapters = - ProtocolSpecAdapters.create( - 0, - specBuilder -> - specBuilder - .requestsValidator( - new RequestsValidatorCoordinator.Builder() - .addValidator( - RequestType.DEPOSIT, - new DepositRequestValidator((depositContractAddress))) - .build()) - .requestProcessorCoordinator( - new RequestProcessorCoordinator.Builder() - .addProcessor( - RequestType.DEPOSIT, - new DepositRequestProcessor(depositContractAddress)) - .build())); - return createBlockCreator(protocolSpecAdapters); - } - - private AbstractBlockCreator blockCreatorWithProhibitedDepositRequests() { - final ProtocolSpecAdapters protocolSpecAdapters = - ProtocolSpecAdapters.create(0, specBuilder -> specBuilder); - return createBlockCreator(protocolSpecAdapters); - } - @Test void withProcessorAndEmptyWithdrawals_NoWithdrawalsAreProcessed() { - final AbstractBlockCreator blockCreator = blockCreatorWithWithdrawalsProcessor(); + final CreateOn miningOn = blockCreatorWithWithdrawalsProcessor(); + final AbstractBlockCreator blockCreator = miningOn.blockCreator; final BlockCreationResult blockCreationResult = blockCreator.createBlock( Optional.empty(), @@ -255,7 +232,8 @@ void withProcessorAndEmptyWithdrawals_NoWithdrawalsAreProcessed() { Optional.empty(), Optional.empty(), 1L, - false); + false, + miningOn.parentHeader); verify(withdrawalsProcessor, never()).processWithdrawals(any(), any()); assertThat(blockCreationResult.getBlock().getHeader().getWithdrawalsRoot()).isEmpty(); assertThat(blockCreationResult.getBlock().getBody().getWithdrawals()).isEmpty(); @@ -263,7 +241,8 @@ void withProcessorAndEmptyWithdrawals_NoWithdrawalsAreProcessed() { @Test void withNoProcessorAndEmptyWithdrawals_NoWithdrawalsAreNotProcessed() { - final AbstractBlockCreator blockCreator = blockCreatorWithoutWithdrawalsProcessor(); + final CreateOn miningOn = blockCreatorWithoutWithdrawalsProcessor(); + final AbstractBlockCreator blockCreator = miningOn.blockCreator; final BlockCreationResult blockCreationResult = blockCreator.createBlock( Optional.empty(), @@ -272,7 +251,8 @@ void withNoProcessorAndEmptyWithdrawals_NoWithdrawalsAreNotProcessed() { Optional.empty(), Optional.empty(), 1L, - false); + false, + miningOn.parentHeader); verify(withdrawalsProcessor, never()).processWithdrawals(any(), any()); assertThat(blockCreationResult.getBlock().getHeader().getWithdrawalsRoot()).isEmpty(); assertThat(blockCreationResult.getBlock().getBody().getWithdrawals()).isEmpty(); @@ -280,7 +260,8 @@ void withNoProcessorAndEmptyWithdrawals_NoWithdrawalsAreNotProcessed() { @Test void withProcessorAndWithdrawals_WithdrawalsAreProcessed() { - final AbstractBlockCreator blockCreator = blockCreatorWithWithdrawalsProcessor(); + final CreateOn miningOn = blockCreatorWithWithdrawalsProcessor(); + final AbstractBlockCreator blockCreator = miningOn.blockCreator; final List withdrawals = List.of(new Withdrawal(UInt64.ONE, UInt64.ONE, Address.fromHexString("0x1"), GWei.ONE)); final BlockCreationResult blockCreationResult = @@ -291,7 +272,8 @@ void withProcessorAndWithdrawals_WithdrawalsAreProcessed() { Optional.empty(), Optional.empty(), 1L, - false); + false, + miningOn.parentHeader); final Hash withdrawalsRoot = BodyValidation.withdrawalsRoot(withdrawals); verify(withdrawalsProcessor).processWithdrawals(eq(withdrawals), any()); @@ -302,7 +284,8 @@ void withProcessorAndWithdrawals_WithdrawalsAreProcessed() { @Test void withNoProcessorAndWithdrawals_WithdrawalsAreNotProcessed() { - final AbstractBlockCreator blockCreator = blockCreatorWithoutWithdrawalsProcessor(); + final CreateOn miningOn = blockCreatorWithoutWithdrawalsProcessor(); + final AbstractBlockCreator blockCreator = miningOn.blockCreator; final List withdrawals = List.of(new Withdrawal(UInt64.ONE, UInt64.ONE, Address.fromHexString("0x1"), GWei.ONE)); final BlockCreationResult blockCreationResult = @@ -313,7 +296,8 @@ void withNoProcessorAndWithdrawals_WithdrawalsAreNotProcessed() { Optional.empty(), Optional.empty(), 1L, - false); + false, + miningOn.parentHeader); verify(withdrawalsProcessor, never()).processWithdrawals(any(), any()); assertThat(blockCreationResult.getBlock().getHeader().getWithdrawalsRoot()).isEmpty(); assertThat(blockCreationResult.getBlock().getBody().getWithdrawals()).isEmpty(); @@ -321,7 +305,8 @@ void withNoProcessorAndWithdrawals_WithdrawalsAreNotProcessed() { @Test public void computesGasUsageFromIncludedTransactions() { - final AbstractBlockCreator blockCreator = blockCreatorWithBlobGasSupport(); + final CreateOn miningOn = blockCreatorWithBlobGasSupport(); + final AbstractBlockCreator blockCreator = miningOn.blockCreator; BlobTestFixture blobTestFixture = new BlobTestFixture(); BlobsWithCommitments bwc = blobTestFixture.createBlobsWithCommitments(6); TransactionTestFixture ttf = new TransactionTestFixture(); @@ -345,14 +330,15 @@ public void computesGasUsageFromIncludedTransactions() { Optional.empty(), Optional.empty(), 1L, - false); + false, + miningOn.parentHeader); long blobGasUsage = blockCreationResult.getBlock().getHeader().getGasUsed(); assertThat(blobGasUsage).isNotZero(); BlobGas excessBlobGas = blockCreationResult.getBlock().getHeader().getExcessBlobGas().get(); assertThat(excessBlobGas).isNotNull(); } - private AbstractBlockCreator blockCreatorWithBlobGasSupport() { + private CreateOn blockCreatorWithBlobGasSupport() { final var alwaysValidTransactionValidatorFactory = mock(TransactionValidatorFactory.class); when(alwaysValidTransactionValidatorFactory.get()) .thenReturn(new AlwaysValidTransactionValidator()); @@ -369,20 +355,49 @@ private AbstractBlockCreator blockCreatorWithBlobGasSupport() { return createBlockCreator(protocolSpecAdapters); } - private AbstractBlockCreator blockCreatorWithWithdrawalsProcessor() { + private CreateOn blockCreatorWithProhibitedDepositRequests() { + final ProtocolSpecAdapters protocolSpecAdapters = + ProtocolSpecAdapters.create(0, specBuilder -> specBuilder); + return createBlockCreator(protocolSpecAdapters); + } + + private CreateOn blockCreatorWithWithdrawalsProcessor() { final ProtocolSpecAdapters protocolSpecAdapters = ProtocolSpecAdapters.create( 0, specBuilder -> specBuilder.withdrawalsProcessor(withdrawalsProcessor)); return createBlockCreator(protocolSpecAdapters); } - private AbstractBlockCreator blockCreatorWithoutWithdrawalsProcessor() { + private CreateOn blockCreatorWithoutWithdrawalsProcessor() { final ProtocolSpecAdapters protocolSpecAdapters = ProtocolSpecAdapters.create(0, specBuilder -> specBuilder.withdrawalsProcessor(null)); return createBlockCreator(protocolSpecAdapters); } - private AbstractBlockCreator createBlockCreator(final ProtocolSpecAdapters protocolSpecAdapters) { + private CreateOn blockCreatorWithAllowedDepositRequests(final Address depositContractAddress) { + final ProtocolSpecAdapters protocolSpecAdapters = + ProtocolSpecAdapters.create( + 0, + specBuilder -> + specBuilder + .requestsValidator( + new RequestsValidatorCoordinator.Builder() + .addValidator( + RequestType.DEPOSIT, + new DepositRequestValidator((depositContractAddress))) + .build()) + .requestProcessorCoordinator( + new RequestProcessorCoordinator.Builder() + .addProcessor( + RequestType.DEPOSIT, + new DepositRequestProcessor(depositContractAddress)) + .build())); + return createBlockCreator(protocolSpecAdapters); + } + + record CreateOn(AbstractBlockCreator blockCreator, BlockHeader parentHeader) {} + + private CreateOn createBlockCreator(final ProtocolSpecAdapters protocolSpecAdapters) { final var genesisConfigFile = GenesisConfigFile.fromResource("/block-creation-genesis.json"); final ExecutionContextTestFixture executionContextTestFixture = @@ -403,11 +418,15 @@ private AbstractBlockCreator createBlockCreator(final ProtocolSpecAdapters proto .build(); final MutableBlockchain blockchain = executionContextTestFixture.getBlockchain(); + BlockHeader parentHeader = blockchain.getChainHeadHeader(); final TransactionPoolConfiguration poolConf = ImmutableTransactionPoolConfiguration.builder().txPoolMaxSize(100).build(); final AbstractPendingTransactionsSorter sorter = new GasPricePendingTransactionsSorter( - poolConf, Clock.systemUTC(), new NoOpMetricsSystem(), blockchain::getChainHeadHeader); + poolConf, + Clock.systemUTC(), + new NoOpMetricsSystem(), + Suppliers.ofInstance(parentHeader)); final EthContext ethContext = mock(EthContext.class, RETURNS_DEEP_STUBS); when(ethContext.getEthPeers().subscribeConnect(any())).thenReturn(1L); @@ -435,15 +454,16 @@ private AbstractBlockCreator createBlockCreator(final ProtocolSpecAdapters proto .build()) .build(); - return new TestBlockCreator( - miningParameters, - __ -> Address.ZERO, - __ -> Bytes.fromHexString("deadbeef"), - transactionPool, - executionContextTestFixture.getProtocolContext(), - executionContextTestFixture.getProtocolSchedule(), - blockchain.getChainHeadHeader(), - ethScheduler); + return new CreateOn( + new TestBlockCreator( + miningParameters, + __ -> Address.ZERO, + __ -> Bytes.fromHexString("deadbeef"), + transactionPool, + executionContextTestFixture.getProtocolContext(), + executionContextTestFixture.getProtocolSchedule(), + ethScheduler), + parentHeader); } static class TestBlockCreator extends AbstractBlockCreator { @@ -455,7 +475,6 @@ protected TestBlockCreator( final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final BlockHeader parentHeader, final EthScheduler ethScheduler) { super( miningParameters, @@ -464,7 +483,6 @@ protected TestBlockCreator( transactionPool, protocolContext, protocolSchedule, - parentHeader, ethScheduler); } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java index 3910d899d96..e5b46925aad 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java @@ -63,7 +63,7 @@ public void blockCreatedIsAddedToBlockChain() throws InterruptedException { final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class); final Function blockCreatorSupplier = (parentHeader) -> blockCreator; - when(blockCreator.createBlock(anyLong())) + when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreationResult( blockToCreate, new TransactionSelectionResults(), new BlockCreationTiming())); @@ -107,7 +107,7 @@ public void failureToImportDoesNotTriggerObservers() throws InterruptedException final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class); final Function blockCreatorSupplier = (parentHeader) -> blockCreator; - when(blockCreator.createBlock(anyLong())) + when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreationResult( blockToCreate, new TransactionSelectionResults(), new BlockCreationTiming())); @@ -155,7 +155,7 @@ public void blockValidationFailureBeforeImportDoesNotImportBlock() throws Interr final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class); final Function blockCreatorSupplier = (parentHeader) -> blockCreator; - when(blockCreator.createBlock(anyLong())) + when(blockCreator.createBlock(anyLong(), any())) .thenReturn( new BlockCreationResult( blockToCreate, new TransactionSelectionResults(), new BlockCreationTiming())); diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java index e9e727d99cb..509efd7b19b 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java @@ -123,13 +123,14 @@ void createMainnetBlock1() throws IOException { executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), solver, - executionContextTestFixture.getBlockchain().getChainHeadHeader(), ethScheduler); // A Hashrate should not exist in the block creator prior to creating a block assertThat(blockCreator.getHashesPerSecond()).isNotPresent(); - final BlockCreationResult blockResult = blockCreator.createBlock(BLOCK_1_TIMESTAMP); + final BlockCreationResult blockResult = + blockCreator.createBlock( + BLOCK_1_TIMESTAMP, executionContextTestFixture.getBlockchain().getChainHeadHeader()); final Block actualBlock = blockResult.getBlock(); final Block expectedBlock = ValidationTestUtils.readBlock(1); @@ -186,10 +187,13 @@ void createMainnetBlock1_fixedDifficulty1() { executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), solver, - executionContextTestFixture.getBlockchain().getChainHeadHeader(), ethScheduler); - assertThat(blockCreator.createBlock(BLOCK_1_TIMESTAMP)).isNotNull(); + assertThat( + blockCreator.createBlock( + BLOCK_1_TIMESTAMP, + executionContextTestFixture.getBlockchain().getChainHeadHeader())) + .isNotNull(); // If we weren't setting difficulty to 2^256-1 a difficulty of 1 would have caused a // IllegalArgumentException at the previous line, as 2^256 is 33 bytes. } @@ -242,7 +246,6 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), solver, - executionContextTestFixture.getBlockchain().getChainHeadHeader(), ethScheduler); final MutableWorldState mutableWorldState = @@ -320,7 +323,6 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() { executionContextTestFixture.getProtocolContext(), executionContextTestFixture.getProtocolSchedule(), solver, - executionContextTestFixture.getBlockchain().getChainHeadHeader(), ethScheduler); final MutableWorldState mutableWorldState = diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java index 939e3ec0cd6..dd9257441e8 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java @@ -260,7 +260,6 @@ private TestBlockCreator( final TransactionPool transactionPool, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, - final BlockHeader parentHeader, final EthScheduler ethScheduler) { super( miningParameters, @@ -269,12 +268,10 @@ private TestBlockCreator( transactionPool, protocolContext, protocolSchedule, - parentHeader, ethScheduler); } static TestBlockCreator forHeader( - final BlockHeader parentHeader, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final TransactionPool transactionPool, @@ -299,7 +296,6 @@ static TestBlockCreator forHeader( transactionPool, protocolContext, protocolSchedule, - parentHeader, ethScheduler); } @@ -332,8 +328,8 @@ protected Block forTransactions(final List transactions) { protected Block forTransactions( final List transactions, final BlockHeader forHeader) { return TestBlockCreator.forHeader( - forHeader, protocolContext, protocolSchedule, transactionPool, ethScheduler) - .createBlock(transactions, Collections.emptyList(), System.currentTimeMillis()) + protocolContext, protocolSchedule, transactionPool, ethScheduler) + .createBlock(transactions, Collections.emptyList(), System.currentTimeMillis(), forHeader) .getBlock(); } diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java index 80a4872442d..00a27bb7a8a 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.java @@ -78,10 +78,11 @@ private boolean mineNewBlock() { protocolContext, protocolSchedule, context.getEthHashSolver(), - blockchain.getChainHeadHeader(), context.getEthScheduler()); final Block block = - blockCreator.createBlock(retesethClock.instant().getEpochSecond()).getBlock(); + blockCreator + .createBlock(retesethClock.instant().getEpochSecond(), blockchain.getChainHeadHeader()) + .getBlock(); // advance clock so next mine won't hit the same timestamp retesethClock.advanceSeconds(1); From 9fe8547353806e35dfc7482b76def71cee55eaf0 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Mon, 9 Sep 2024 16:20:01 +0200 Subject: [PATCH 03/10] Improve release process Signed-off-by: Fabio Di Fabio --- .github/workflows/release.yml | 71 +++++++++++++++++++++++++++++++++ .github/workflows/workflow.yaml | 19 ++------- 2 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..18a18092f3c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,71 @@ +name: Release + +on: + release: + types: [released] + +jobs: + build: + + runs-on: ubuntu-latest-128 + + steps: + - name: Pre-process Release Name + id: pre_process_release_name + run: | + RELEASE_NAME="${{ github.event.release.name }}" + # strip all whitespace + RELEASE_NAME="${RELEASE_NAME//[[:space:]]/}" + if [[ ! "$RELEASE_NAME" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?(-.*)?$ ]]; then + echo "Release name does not conform to a valid besu release format YY.M.v[-suffix], e.g. 24.8.0-RC1." + exit 1 + fi + echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV # Store in environment variable + + - name: checkout + uses: actions/checkout@v3 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: 21 + distribution: temurin + + - name: Publish Java artifacts + run: ./gradlew -Prelease.releaseVersion=${{env.RELEASE_NAME}} -Pversion=${{env.RELEASE_NAME}} publish + env: + CLOUDSMITH_USER: ${{ secrets.CLOUDSMITH_USER }} + CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} + + - name: Publish distribution artifacts + run: | + sudo apt update + sudo apt install -y python3 python3-pip python3-venv + ./gradlew -Prelease.releaseVersion=${{env.RELEASE_NAME}} -Pversion=${{env.RELEASE_NAME}} cloudsmithUpload + env: + CLOUDSMITH_USER: ${{ secrets.CLOUDSMITH_USER }} + CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} + + - name: Set up QEMU for Docker + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + platforms: linux/amd64,linux/arm64 + + - name: Check Dockerfile syntax + run: | + docker run --rm -i hadolint/hadolint < docker/Dockerfile + + - name: Login to Docker Hub for self hosted + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USER_RW }} + password: ${{ secrets.DOCKER_PAT_RW }} + + - name: Build and Publish Docker Image + run: | + ./gradlew -Prelease.releaseVersion=${{env.RELEASE_NAME}} -Pversion=${{env.RELEASE_NAME}} -Pdocker-platform=linux/amd64,linux/arm64 distDocker diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index b3bf3745c06..b84c7928c20 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -25,19 +25,8 @@ jobs: java-version: 21 distribution: temurin - - name: Cache Gradle dependencies - uses: actions/cache@v3 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/gradle/versions.gradle') }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-gradle-${{ hashFiles('**/gradle/versions.gradle') }} - ${{ runner.os }}-gradle- - - name: Spotless - run: ./gradlew clean spotlessCheck + run: ./gradlew spotlessCheck - name: Test & Build run: ./gradlew build @@ -71,7 +60,7 @@ jobs: distribution: temurin - name: Publish Java artifacts - run: ./gradlew publish -x checkLicense + run: ./gradlew publish env: CLOUDSMITH_USER: ${{ secrets.CLOUDSMITH_USER }} CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} @@ -80,7 +69,7 @@ jobs: run: | sudo apt update sudo apt install -y python3 python3-pip python3-venv - ./gradlew cloudsmithUpload -x checkLicense + ./gradlew cloudsmithUpload env: CLOUDSMITH_USER: ${{ secrets.CLOUDSMITH_USER }} CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} @@ -107,4 +96,4 @@ jobs: - name: Build and Publish Docker Image run: | - ./gradlew -Pdocker-platform=linux/amd64,linux/arm64 distDocker -x checkLicense + ./gradlew -Pdocker-platform=linux/amd64,linux/arm64 distDocker From 36454b40d57cb699c7879746c6fb1e83e67717e1 Mon Sep 17 00:00:00 2001 From: ITStarMan100 Date: Tue, 10 Sep 2024 01:34:45 +0000 Subject: [PATCH 04/10] Added help for setting up Stratum mining (#7584) * Added help for setting up Stratum mining Signed-off-by: ITStarMan100 * removed duplication from help message; fixed spotless Signed-off-by: Sally MacFarlane --------- Signed-off-by: ITStarMan100 Signed-off-by: Sally MacFarlane Co-authored-by: Sally MacFarlane --- besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java | 2 +- .../java/org/hyperledger/besu/cli/options/MiningOptions.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index 9eaf254bbfc..39e4356a7f3 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -805,7 +805,7 @@ public Runner build() { if (miningParameters.isStratumMiningEnabled()) { if (!(miningCoordinator instanceof PoWMiningCoordinator powMiningCoordinator)) { throw new IllegalArgumentException( - "Stratum server requires an PoWMiningCoordinator not " + "Stratum mining requires the network option(--network) to be set to CLASSIC. Stratum server requires a PoWMiningCoordinator not " + ((miningCoordinator == null) ? "null" : miningCoordinator.getClass().getName())); } stratumServer = diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java index ba4d99bc830..a884edfe334 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java @@ -59,7 +59,10 @@ public class MiningOptions implements CLIOptions { @Option( names = {"--miner-stratum-enabled"}, - description = "Set if node will perform Stratum mining (default: ${DEFAULT-VALUE})") + description = + "Set if node will perform Stratum mining (default: ${DEFAULT-VALUE})." + + " Compatible with Proof of Work (PoW) only." + + " Requires the network option (--network) to be set to CLASSIC.") private Boolean iStratumMiningEnabled = false; @Option( From 01fcc7fcfb7b0a45ce73c02c537fa34d060ad44b Mon Sep 17 00:00:00 2001 From: daniellehrner Date: Tue, 10 Sep 2024 11:37:47 +0200 Subject: [PATCH 05/10] Fix tx validation if sender has delegated it's code via 7702 transaction (#7593) Signed-off-by: Daniel Lehrner --- ...deDelegationTransactionAcceptanceTest.java | 56 +++++++++++++++---- .../mainnet/MainnetTransactionValidator.java | 4 +- .../evm/worldstate/DelegatedCodeService.java | 16 ++++-- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/CodeDelegationTransactionAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/CodeDelegationTransactionAcceptanceTest.java index 6000915b441..ee896ccd278 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/CodeDelegationTransactionAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/ethereum/CodeDelegationTransactionAcceptanceTest.java @@ -175,29 +175,61 @@ public void shouldCheckNonceAfterNonceIncreaseOfSender() throws IOException { besuNode.execute(ethTransactions.sendRawTransaction(tx.encoded().toHexString())); testHelper.buildNewBlock(); - Optional maybeTransactionReceipt = + final Optional maybeFirstTransactionReceipt = besuNode.execute(ethTransactions.getTransactionReceipt(txHash)); - assertThat(maybeTransactionReceipt).isPresent(); + assertThat(maybeFirstTransactionReceipt).isPresent(); final String gasPriceWithout0x = - maybeTransactionReceipt.get().getEffectiveGasPrice().substring(2); + maybeFirstTransactionReceipt.get().getEffectiveGasPrice().substring(2); final BigInteger gasPrice = new BigInteger(gasPriceWithout0x, 16); - final BigInteger txCost = maybeTransactionReceipt.get().getGasUsed().multiply(gasPrice); + final BigInteger txCost = maybeFirstTransactionReceipt.get().getGasUsed().multiply(gasPrice); - final BigInteger authorizerBalance = besuNode.execute(ethTransactions.getBalance(authorizer)); + final BigInteger authorizerBalanceAfterFirstTx = + besuNode.execute(ethTransactions.getBalance(authorizer)); // The remaining balance of the authorizer should the gas limit multiplied by the gas price // minus the transaction cost. // The following executes this calculation in reverse. - assertThat(GAS_LIMIT).isEqualTo(authorizerBalance.add(txCost).divide(gasPrice).longValue()); + assertThat(GAS_LIMIT) + .isEqualTo(authorizerBalanceAfterFirstTx.add(txCost).divide(gasPrice).longValue()); // The other accounts balance should be the initial 9000 ETH balance from the authorizer minus // the remaining balance of the authorizer and minus the transaction cost - cluster.verify( - otherAccount.balanceEquals( - Amount.wei( - new BigInteger("90000000000000000000000") - .subtract(authorizerBalance) - .subtract(txCost)))); + final BigInteger otherAccountBalanceAfterFirstTx = + new BigInteger("90000000000000000000000") + .subtract(authorizerBalanceAfterFirstTx) + .subtract(txCost); + + cluster.verify(otherAccount.balanceEquals(Amount.wei(otherAccountBalanceAfterFirstTx))); + + final Transaction txSendEthToOtherAccount = + Transaction.builder() + .type(TransactionType.EIP1559) + .chainId(BigInteger.valueOf(20211)) + .nonce(2) + .maxPriorityFeePerGas(Wei.of(10)) + .maxFeePerGas(Wei.of(100)) + .gasLimit(21000) + .to(Address.fromHexStringStrict(otherAccount.getAddress())) + .value(Wei.ONE) + .payload(Bytes.EMPTY) + .signAndBuild( + secp256k1.createKeyPair( + secp256k1.createPrivateKey(AUTHORIZER_PRIVATE_KEY.toUnsignedBigInteger()))); + + final String txSendEthToOtherAccountHash = + besuNode.execute( + ethTransactions.sendRawTransaction(txSendEthToOtherAccount.encoded().toHexString())); + testHelper.buildNewBlock(); + + final Optional maybeSecondTransactionReceipt = + besuNode.execute(ethTransactions.getTransactionReceipt(txSendEthToOtherAccountHash)); + assertThat(maybeSecondTransactionReceipt).isPresent(); + + // the balance of the other account should be the previous balance plus the value of the 1 Wei + final BigInteger otherAccountBalanceAfterSecondTx = + besuNode.execute(ethTransactions.getBalance(otherAccount)); + assertThat(otherAccountBalanceAfterFirstTx.add(BigInteger.ONE)) + .isEqualTo(otherAccountBalanceAfterSecondTx); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java index 4f4c554f3ff..b5fbf7340b2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java @@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.gascalculator.GasCalculator; +import org.hyperledger.besu.evm.worldstate.DelegatedCodeService; import java.math.BigInteger; import java.util.List; @@ -305,7 +306,8 @@ public ValidationResult validateForSender( } private static boolean canSendTransaction(final Account sender, final Hash codeHash) { - return codeHash.equals(Hash.EMPTY) || sender.hasDelegatedCode(); + return codeHash.equals(Hash.EMPTY) + || DelegatedCodeService.hasDelegatedCode(sender.getUnprocessedCode()); } private ValidationResult validateTransactionSignature( diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java index 1c89fad8bcf..885324b10b6 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java @@ -85,13 +85,19 @@ public MutableAccount processMutableAccount( worldUpdater, account, resolveDelegatedAddress(account.getCode())); } - private Address resolveDelegatedAddress(final Bytes code) { - return Address.wrap(code.slice(DELEGATED_CODE_PREFIX.size())); - } - - private boolean hasDelegatedCode(final Bytes code) { + /** + * Returns if the provided code is delegated code. + * + * @param code the code to check. + * @return {@code true} if the code is delegated code, {@code false} otherwise. + */ + public static boolean hasDelegatedCode(final Bytes code) { return code != null && code.size() == DELEGATED_CODE_SIZE && code.slice(0, DELEGATED_CODE_PREFIX.size()).equals(DELEGATED_CODE_PREFIX); } + + private Address resolveDelegatedAddress(final Bytes code) { + return Address.wrap(code.slice(DELEGATED_CODE_PREFIX.size())); + } } From 500a98b6b605d25a9538f2d6d3b7eb955e8368da Mon Sep 17 00:00:00 2001 From: jonesho <81145364+jonesho@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:57:04 +0800 Subject: [PATCH 06/10] feat: exported metrics for current finalized and safe block number (#7592) * feat: exported metrics for current finalized and safe block number Signed-off-by: Jones Ho * Update ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java Co-authored-by: Fabio Di Fabio Signed-off-by: jonesho <81145364+jonesho@users.noreply.github.com> * Update ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java Co-authored-by: Fabio Di Fabio Signed-off-by: jonesho <81145364+jonesho@users.noreply.github.com> * fix: spotless issue Signed-off-by: Jones Ho --------- Signed-off-by: Jones Ho Signed-off-by: jonesho <81145364+jonesho@users.noreply.github.com> Co-authored-by: Fabio Di Fabio --- .../ethereum/chain/DefaultBlockchain.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java index 5849f3e676c..1b210490740 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java @@ -122,6 +122,18 @@ private DefaultBlockchain( "The current height of the canonical chain", this::getChainHeadBlockNumber); + metricsSystem.createLongGauge( + BesuMetricCategory.ETHEREUM, + "blockchain_finalized_block", + "The current finalized block number", + this::getFinalizedBlockNumber); + + metricsSystem.createLongGauge( + BesuMetricCategory.ETHEREUM, + "blockchain_safe_block", + "The current safe block number", + this::getSafeBlockNumber); + metricsSystem.createGauge( BesuMetricCategory.BLOCKCHAIN, "difficulty_total", @@ -759,6 +771,14 @@ public void setSafeBlock(final Hash blockHash) { updater.commit(); } + private long getFinalizedBlockNumber() { + return this.getFinalized().flatMap(this::getBlockHeader).map(BlockHeader::getNumber).orElse(0L); + } + + private long getSafeBlockNumber() { + return this.getSafeBlock().flatMap(this::getBlockHeader).map(BlockHeader::getNumber).orElse(0L); + } + private void updateCacheForNewCanonicalHead(final Block block, final Difficulty uInt256) { chainHeader = block.getHeader(); totalDifficulty = uInt256; From 07adb415eec5341fe22442ac9938e7f7b8a9de11 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Wed, 11 Sep 2024 00:26:17 +0200 Subject: [PATCH 07/10] Re-enable TxPoolOptionsTest::txpoolForcePriceBumpToZeroWhenZeroBaseFeeMarket (#7565) Signed-off-by: Fabio Di Fabio --- .../test/java/org/hyperledger/besu/cli/TxPoolOptionsTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/besu/src/test/java/org/hyperledger/besu/cli/TxPoolOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/TxPoolOptionsTest.java index 8389ab5bae8..a5ca07484a0 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/TxPoolOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/TxPoolOptionsTest.java @@ -30,7 +30,6 @@ import java.nio.file.Files; import java.nio.file.Path; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; public class TxPoolOptionsTest extends CommandTestAbstract { @@ -98,7 +97,6 @@ public void txpoolSaveFileAbsolutePathOutsideDataPath() throws IOException { } @Test - @Disabled // Failing in CI, but not locally public void txpoolForcePriceBumpToZeroWhenZeroBaseFeeMarket() throws IOException { final Path genesisFile = createFakeGenesisFile(GENESIS_WITH_ZERO_BASE_FEE_MARKET); parseCommand("--genesis-file", genesisFile.toString()); From 3d71254dfa781839f6cf7a54fc661bef13606a27 Mon Sep 17 00:00:00 2001 From: daniellehrner Date: Wed, 11 Sep 2024 00:50:23 +0200 Subject: [PATCH 08/10] Mandatoy to field for 7702 transactions (#7600) * fix 7702 tx validation in tx pool Signed-off-by: Daniel Lehrner * check that 7702 transactions always have a mandatory to field Signed-off-by: Daniel Lehrner --------- Signed-off-by: Daniel Lehrner Co-authored-by: Sally MacFarlane --- .../mainnet/MainnetTransactionValidator.java | 75 ++++++++++++------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java index b5fbf7340b2..e67ccbb4c62 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java @@ -132,42 +132,59 @@ public ValidationResult validate( } if (transactionType == TransactionType.DELEGATE_CODE) { - if (isDelegateCodeEmpty(transaction)) { - return ValidationResult.invalid( - TransactionInvalidReason.EMPTY_CODE_DELEGATION, - "transaction code delegation transactions must have a non-empty code delegation list"); + ValidationResult codeDelegationValidation = + validateCodeDelegation(transaction); + if (!codeDelegationValidation.isValid()) { + return codeDelegationValidation; } + } + + return validateCostAndFee(transaction, baseFee, blobFee, transactionValidationParams); + } - final BigInteger halfCurveOrder = SignatureAlgorithmFactory.getInstance().getHalfCurveOrder(); - final Optional> validationResult = - transaction - .getCodeDelegationList() - .map( - codeDelegations -> { - for (CodeDelegation codeDelegation : codeDelegations) { - if (codeDelegation.signature().getS().compareTo(halfCurveOrder) > 0) { - return ValidationResult.invalid( - TransactionInvalidReason.INVALID_SIGNATURE, - "Invalid signature for code delegation. S value must be less or equal than the half curve order."); - } - - if (codeDelegation.signature().getRecId() != 0 - && codeDelegation.signature().getRecId() != 1) { - return ValidationResult.invalid( - TransactionInvalidReason.INVALID_SIGNATURE, - "Invalid signature for code delegation. RecId value must be 0 or 1."); - } + private static ValidationResult validateCodeDelegation( + final Transaction transaction) { + if (isDelegateCodeEmpty(transaction)) { + return ValidationResult.invalid( + TransactionInvalidReason.EMPTY_CODE_DELEGATION, + "transaction code delegation transactions must have a non-empty code delegation list"); + } + + if (transaction.getTo().isEmpty()) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, + "transaction code delegation transactions must have a to address"); + } + + final BigInteger halfCurveOrder = SignatureAlgorithmFactory.getInstance().getHalfCurveOrder(); + final Optional> validationResult = + transaction + .getCodeDelegationList() + .map( + codeDelegations -> { + for (CodeDelegation codeDelegation : codeDelegations) { + if (codeDelegation.signature().getS().compareTo(halfCurveOrder) > 0) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_SIGNATURE, + "Invalid signature for code delegation. S value must be less or equal than the half curve order."); } - return ValidationResult.valid(); - }); + if (codeDelegation.signature().getRecId() != 0 + && codeDelegation.signature().getRecId() != 1) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_SIGNATURE, + "Invalid signature for code delegation. RecId value must be 0 or 1."); + } + } - if (validationResult.isPresent() && !validationResult.get().isValid()) { - return validationResult.get(); - } + return ValidationResult.valid(); + }); + + if (validationResult.isPresent() && !validationResult.get().isValid()) { + return validationResult.get(); } - return validateCostAndFee(transaction, baseFee, blobFee, transactionValidationParams); + return ValidationResult.valid(); } private static boolean isDelegateCodeEmpty(final Transaction transaction) { From 46636c7af279c3530fe30e99bfa5f7956150dcb5 Mon Sep 17 00:00:00 2001 From: Luis Pinto Date: Wed, 11 Sep 2024 00:37:08 +0100 Subject: [PATCH 09/10] block header cache not initialized before used (#7601) Signed-off-by: Luis Pinto Co-authored-by: Sally MacFarlane --- .../ethereum/chain/DefaultBlockchain.java | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java index 1b210490740..b2b4e6abfc8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java @@ -116,6 +116,37 @@ private DefaultBlockchain( chainHeadTransactionCount = chainHeadBody.getTransactions().size(); chainHeadOmmerCount = chainHeadBody.getOmmers().size(); + this.reorgLoggingThreshold = reorgLoggingThreshold; + this.blockChoiceRule = heaviestChainBlockChoiceRule; + this.numberOfBlocksToCache = numberOfBlocksToCache; + + if (numberOfBlocksToCache != 0) { + blockHeadersCache = + Optional.of( + CacheBuilder.newBuilder().recordStats().maximumSize(numberOfBlocksToCache).build()); + blockBodiesCache = + Optional.of( + CacheBuilder.newBuilder().recordStats().maximumSize(numberOfBlocksToCache).build()); + transactionReceiptsCache = + Optional.of( + CacheBuilder.newBuilder().recordStats().maximumSize(numberOfBlocksToCache).build()); + totalDifficultyCache = + Optional.of( + CacheBuilder.newBuilder().recordStats().maximumSize(numberOfBlocksToCache).build()); + CacheMetricsCollector cacheMetrics = new CacheMetricsCollector(); + cacheMetrics.addCache("blockHeaders", blockHeadersCache.get()); + cacheMetrics.addCache("blockBodies", blockBodiesCache.get()); + cacheMetrics.addCache("transactionReceipts", transactionReceiptsCache.get()); + cacheMetrics.addCache("totalDifficulty", totalDifficultyCache.get()); + if (metricsSystem instanceof PrometheusMetricsSystem prometheusMetricsSystem) + prometheusMetricsSystem.addCollector(BesuMetricCategory.BLOCKCHAIN, () -> cacheMetrics); + } else { + blockHeadersCache = Optional.empty(); + blockBodiesCache = Optional.empty(); + transactionReceiptsCache = Optional.empty(); + totalDifficultyCache = Optional.empty(); + } + metricsSystem.createLongGauge( BesuMetricCategory.ETHEREUM, "blockchain_height", @@ -179,37 +210,6 @@ private DefaultBlockchain( "chain_head_ommer_count", "Number of ommers in the current chain head block", () -> chainHeadOmmerCount); - - this.reorgLoggingThreshold = reorgLoggingThreshold; - this.blockChoiceRule = heaviestChainBlockChoiceRule; - this.numberOfBlocksToCache = numberOfBlocksToCache; - - if (numberOfBlocksToCache != 0) { - blockHeadersCache = - Optional.of( - CacheBuilder.newBuilder().recordStats().maximumSize(numberOfBlocksToCache).build()); - blockBodiesCache = - Optional.of( - CacheBuilder.newBuilder().recordStats().maximumSize(numberOfBlocksToCache).build()); - transactionReceiptsCache = - Optional.of( - CacheBuilder.newBuilder().recordStats().maximumSize(numberOfBlocksToCache).build()); - totalDifficultyCache = - Optional.of( - CacheBuilder.newBuilder().recordStats().maximumSize(numberOfBlocksToCache).build()); - CacheMetricsCollector cacheMetrics = new CacheMetricsCollector(); - cacheMetrics.addCache("blockHeaders", blockHeadersCache.get()); - cacheMetrics.addCache("blockBodies", blockBodiesCache.get()); - cacheMetrics.addCache("transactionReceipts", transactionReceiptsCache.get()); - cacheMetrics.addCache("totalDifficulty", totalDifficultyCache.get()); - if (metricsSystem instanceof PrometheusMetricsSystem prometheusMetricsSystem) - prometheusMetricsSystem.addCollector(BesuMetricCategory.BLOCKCHAIN, () -> cacheMetrics); - } else { - blockHeadersCache = Optional.empty(); - blockBodiesCache = Optional.empty(); - transactionReceiptsCache = Optional.empty(); - totalDifficultyCache = Optional.empty(); - } } public static MutableBlockchain createMutable( From 6ea0ed4c7001895863964fc0e30858c0f6b735ce Mon Sep 17 00:00:00 2001 From: garyschulte Date: Tue, 10 Sep 2024 18:55:45 -0700 Subject: [PATCH 10/10] propagate release name preprocessing via job output (#7599) Signed-off-by: garyschulte --- .github/workflows/release.yml | 59 ++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c7436653578..2f0661e3cfb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,8 +9,28 @@ env: GRADLE_OPTS: "-Dorg.gradle.parallel=true -Dorg.gradle.caching=true" jobs: + preprocess_release: + runs-on: ubuntu-22.04 + steps: + - name: Pre-process Release Name + id: pre_process_release_name + run: | + RELEASE_NAME="${{ github.event.release.name }}" + # strip all whitespace + RELEASE_NAME="${RELEASE_NAME//[[:space:]]/}" + if [[ ! "$RELEASE_NAME" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?(-.*)?$ ]]; then + echo "Release name does not conform to a valid besu release format YY.M.v[-suffix], e.g. 24.8.0-RC1." + exit 1 + fi + echo "release_name=$RELEASE_NAME" >> $GITHUB_OUTPUT # Set as output using the new syntax + outputs: + release_name: ${{ steps.pre_process_release_name.outputs.release_name }} + artifacts: runs-on: ubuntu-22.04 + needs: preprocess_release + env: + RELEASE_NAME: ${{ needs.preprocess_release.outputs.release_name }} # Use the output from the pre_process_release job permissions: contents: write outputs: @@ -19,17 +39,6 @@ jobs: steps: - name: checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: Pre-process Release Name - id: pre_process_release_name - run: | - RELEASE_NAME="${{ github.event.release.name }}" - # strip all whitespace - RELEASE_NAME="${RELEASE_NAME//[[:space:]]/}" - if [[ ! "$RELEASE_NAME" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?(-.*)?$ ]]; then - echo "Release name does not conform to a valid besu release format YY.M.v[-suffix], e.g. 24.8.0-RC1." - exit 1 - fi - echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV # Store in environment variable - name: Set up Java uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: @@ -90,7 +99,9 @@ jobs: publish: runs-on: ubuntu-22.04 - needs: [testWindows, artifacts] + needs: [preprocess_release, testWindows, artifacts] + env: + RELEASE_NAME: ${{ needs.preprocess_release.outputs.release_name }} # Use the output from the pre_process_release job permissions: contents: write steps: @@ -115,7 +126,9 @@ jobs: artifactoryPublish: runs-on: ubuntu-22.04 - needs: artifacts + needs: [preprocess_release, artifacts] + env: + RELEASE_NAME: ${{ needs.preprocess_release.outputs.release_name }} # Use the output from the pre_process_release job steps: - name: checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 @@ -152,7 +165,9 @@ jobs: run: docker run --rm -i hadolint/hadolint < docker/Dockerfile buildDocker: - needs: hadolint + needs: [preprocess_release, hadolint] + env: + RELEASE_NAME: ${{ needs.preprocess_release.outputs.release_name }} # Use the output from the pre_process_release job permissions: contents: read packages: write @@ -213,7 +228,9 @@ jobs: run: ./gradlew --no-daemon dockerUpload -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{env.RELEASE_NAME}} -Prelease.releaseVersion=${{ env.RELEASE_NAME }} multiArch: - needs: buildDocker + needs: [preprocess_release, buildDocker] + env: + RELEASE_NAME: ${{ needs.preprocess_release.outputs.release_name }} # Use the output from the pre_process_release job runs-on: ubuntu-22.04 permissions: contents: read @@ -240,7 +257,9 @@ jobs: run: ./gradlew manifestDocker -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{env.RELEASE_NAME}} -Prelease.releaseVersion=${{ env.RELEASE_NAME }} amendNotes: - needs: multiArch + needs: [preprocess_release, multiArch] + env: + RELEASE_NAME: ${{ needs.preprocess_release.outputs.release_name }} # Use the output from the pre_process_release job runs-on: ubuntu-22.04 permissions: contents: write @@ -253,7 +272,9 @@ jobs: `docker pull ${{env.registry}}/${{secrets.DOCKER_ORG}}/besu:${{env.RELEASE_NAME}}` dockerPromoteX64: - needs: multiArch + needs: [preprocess_release, multiArch] + env: + RELEASE_NAME: ${{ needs.preprocess_release.outputs.release_name }} # Use the output from the pre_process_release job runs-on: ubuntu-22.04 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 @@ -278,7 +299,9 @@ jobs: run: ./gradlew "-Prelease.releaseVersion=${{ env.RELEASE_NAME }}" "-PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }}" manifestDockerRelease verifyContainer: - needs: dockerPromoteX64 + needs: [preprocess_release, dockerPromoteX64] + env: + RELEASE_NAME: ${{ needs.preprocess_release.outputs.release_name }} # Use the output from the pre_process_release job runs-on: ubuntu-22.04 permissions: contents: read