Decouple block creators (#7468)

* wip decoupled parent block header from block creators

---------

Signed-off-by: Justin Florentine <justin+github@florentine.us>
pull/7593/head
Justin Florentine 2 months ago committed by GitHub
parent 2a52b0278b
commit 9a570d415e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java
  2. 1
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutor.java
  3. 12
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java
  4. 4
      consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockMinerTest.java
  5. 18
      consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java
  6. 4
      consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java
  7. 4
      consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/support/TestContext.java
  8. 7
      consensus/ibft/src/integration-test/java/org/hyperledger/besu/consensus/ibft/tests/round/IbftRoundIntegrationTest.java
  9. 11
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRound.java
  10. 5
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundFactory.java
  11. 4
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java
  12. 9
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftBlockHeightManagerTest.java
  13. 42
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/statemachine/IbftRoundTest.java
  14. 10
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java
  15. 16
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java
  16. 7
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java
  17. 2
      consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContext.java
  18. 7
      consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java
  19. 13
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java
  20. 5
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java
  21. 9
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java
  22. 39
      consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java
  23. 58
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java
  24. 13
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockCreator.java
  25. 6
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java
  26. 2
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java
  27. 1
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMinerExecutor.java
  28. 144
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java
  29. 6
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockMinerTest.java
  30. 14
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java
  31. 8
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java
  32. 5
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestMineBlocks.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 class CliqueBlockCreator extends AbstractBlockCreator {
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final NodeKey nodeKey,
final BlockHeader parentHeader,
final EpochManager epochManager,
final EthScheduler ethScheduler) {
super(
@ -75,7 +73,6 @@ public class CliqueBlockCreator extends AbstractBlockCreator {
transactionPool,
protocolContext,
protocolSchedule,
parentHeader,
ethScheduler);
this.nodeKey = nodeKey;
this.epochManager = epochManager;
@ -112,6 +109,8 @@ public class CliqueBlockCreator extends AbstractBlockCreator {
private Optional<ValidatorVote> determineCliqueVote(
final SealableBlockHeader sealableBlockHeader) {
BlockHeader parentHeader =
protocolContext.getBlockchain().getBlockHeader(sealableBlockHeader.getParentHash()).get();
if (epochManager.isEpochBlock(sealableBlockHeader.getNumber())) {
return Optional.empty();
} else {

@ -103,7 +103,6 @@ public class CliqueMinerExecutor extends AbstractMinerExecutor<CliqueBlockMiner>
protocolContext,
protocolSchedule,
nodeKey,
header,
epochManager,
ethScheduler);

@ -156,11 +156,11 @@ public class CliqueBlockCreatorTest {
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 class CliqueBlockCreatorTest {
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 class CliqueBlockCreatorTest {
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"));
}

@ -91,7 +91,7 @@ class CliqueBlockMinerTest {
final CliqueBlockCreator blockCreator = mock(CliqueBlockCreator.class);
final Function<BlockHeader, CliqueBlockCreator> 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 @@ class CliqueBlockMinerTest {
final CliqueBlockCreator blockCreator = mock(CliqueBlockCreator.class);
final Function<BlockHeader, CliqueBlockCreator> blockCreatorSupplier =
(parentHeader) -> blockCreator;
when(blockCreator.createBlock(anyLong()))
when(blockCreator.createBlock(anyLong(), any()))
.thenReturn(
new BlockCreator.BlockCreationResult(
blockToCreate, new TransactionSelectionResults(), new BlockCreationTiming()));

@ -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 class BftBlockCreator extends AbstractBlockCreator {
final TransactionPool transactionPool,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final BlockHeader parentHeader,
final BftExtraDataCodec bftExtraDataCodec,
final EthScheduler ethScheduler) {
super(
@ -75,21 +73,20 @@ public class BftBlockCreator extends AbstractBlockCreator {
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 @@ public class BftBlockCreator extends AbstractBlockCreator {
}
@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

@ -106,11 +106,10 @@ public class BftBlockCreatorFactory<T extends BftConfigOptions> {
/**
* 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 class BftBlockCreatorFactory<T extends BftConfigOptions> {
transactionPool,
protocolContext,
protocolSchedule,
parentHeader,
bftExtraDataCodec,
ethScheduler);
}

@ -90,8 +90,8 @@ public class TestContext {
final BlockHeader parent, final int round, final long timestamp) {
return finalState
.getBlockCreatorFactory()
.create(parent, round)
.createBlock(timestamp)
.create(round)
.createBlock(timestamp, parent)
.getBlock();
}

@ -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 class IbftRoundIntegrationTest {
throwingMessageFactory,
transmitter,
roundTimer,
bftExtraDataEncoder);
bftExtraDataEncoder,
parentHeader);
round.handleProposalMessage(
peerMessageFactory.createProposal(roundIdentifier, proposedBlock, Optional.empty()));
@ -172,7 +174,8 @@ public class IbftRoundIntegrationTest {
throwingMessageFactory,
transmitter,
roundTimer,
bftExtraDataEncoder);
bftExtraDataEncoder,
parentHeader);
// inject a block first, then a prepare on it.
round.handleProposalMessage(

@ -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 class 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 class IbftRound {
this.messageFactory = messageFactory;
this.transmitter = transmitter;
this.bftExtraDataCodec = bftExtraDataCodec;
this.parentHeader = parentHeader;
roundTimer.startTimer(getRoundIdentifier());
}
@ -119,7 +123,8 @@ public class IbftRound {
* @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 class IbftRound {
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());

@ -100,7 +100,7 @@ public class IbftRoundFactory {
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 class IbftRoundFactory {
messageFactory,
messageTransmitter,
finalState.getRoundTimer(),
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
}
}

@ -191,12 +191,12 @@ public class BftBlockCreatorTest {
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(

@ -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<MessageData> sentMessageArgCaptor;
@ -158,7 +159,7 @@ public class IbftBlockHeightManagerTest {
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 class IbftBlockHeightManagerTest {
messageFactory,
messageTransmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
});
lenient()
@ -228,7 +230,8 @@ public class IbftBlockHeightManagerTest {
messageFactory,
messageTransmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
});
}

@ -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<Block> blockCaptor;
@ -131,7 +132,7 @@ public class IbftRoundTest {
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 class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
verify(roundTimer, times(1)).startTimer(roundIdentifier);
}
@ -177,7 +179,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleProposalMessage(
messageFactory.createProposal(roundIdentifier, proposedBlock, Optional.empty()));
@ -199,7 +202,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.createAndSendProposalMessage(15);
verify(transmitter, times(1))
@ -222,7 +226,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.createAndSendProposalMessage(15);
verify(transmitter, times(1))
.multicastProposal(roundIdentifier, proposedBlock, Optional.empty());
@ -245,7 +250,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
final Hash commitSealHash =
new BftBlockHashing(new IbftExtraDataCodec())
@ -292,7 +298,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
final Hash commitSealHash =
new BftBlockHashing(new IbftExtraDataCodec())
@ -329,7 +336,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
final RoundChangeCertificate roundChangeCertificate = new RoundChangeCertificate(emptyList());
@ -353,7 +361,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
final RoundChangeArtifacts roundChangeArtifacts =
RoundChangeArtifacts.create(
@ -400,7 +409,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
final RoundChangeArtifacts roundChangeArtifacts =
RoundChangeArtifacts.create(
@ -434,7 +444,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.createAndSendProposalMessage(15);
verify(minedBlockObserver).blockMined(any());
}
@ -455,7 +466,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleCommitMessage(
messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal));
@ -481,7 +493,8 @@ public class IbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleCommitMessage(
messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal));
@ -511,7 +524,8 @@ public class IbftRoundTest {
throwingMessageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleProposalMessage(
messageFactory.createProposal(roundIdentifier, proposedBlock, Optional.empty()));

@ -61,7 +61,6 @@ class MergeBlockCreator extends AbstractBlockCreator {
transactionPool,
protocolContext,
protocolSchedule,
parentHeader,
ethScheduler);
}
@ -80,7 +79,8 @@ class MergeBlockCreator extends AbstractBlockCreator {
final Bytes32 random,
final long timestamp,
final Optional<List<Withdrawal>> withdrawals,
final Optional<Bytes32> parentBeaconBlockRoot) {
final Optional<Bytes32> parentBeaconBlockRoot,
final BlockHeader parentHeader) {
return createBlock(
maybeTransactions,
@ -89,14 +89,16 @@ class MergeBlockCreator extends AbstractBlockCreator {
Optional.of(random),
parentBeaconBlockRoot,
timestamp,
false);
false,
parentHeader);
}
@Override
public BlockCreationResult createBlock(
final Optional<List<Transaction>> maybeTransactions,
final Optional<List<BlockHeader>> maybeOmmers,
final long timestamp) {
final long timestamp,
final BlockHeader parentHeader) {
throw new UnsupportedOperationException("random is required");
}

@ -294,7 +294,8 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
prevRandao,
timestamp,
withdrawals,
parentBeaconBlockRoot)
parentBeaconBlockRoot,
parentHeader)
.getBlock();
BlockProcessingResult result = validateProposedBlock(emptyBlock);
@ -322,7 +323,8 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
payloadIdentifier,
mergeBlockCreator,
withdrawals,
parentBeaconBlockRoot);
parentBeaconBlockRoot,
parentHeader);
return payloadIdentifier;
}
@ -363,12 +365,18 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
final PayloadIdentifier payloadIdentifier,
final MergeBlockCreator mergeBlockCreator,
final Optional<List<Withdrawal>> withdrawals,
final Optional<Bytes32> parentBeaconBlockRoot) {
final Optional<Bytes32> parentBeaconBlockRoot,
final BlockHeader parentHeader) {
final Supplier<BlockCreationResult> 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",

@ -285,7 +285,12 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
.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;
};

@ -103,7 +103,7 @@ public class TestContext {
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

@ -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 class QbftRoundIntegrationTest {
throwingMessageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleProposalMessage(
peerMessageFactory.createProposal(
@ -176,7 +178,8 @@ public class QbftRoundIntegrationTest {
throwingMessageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
// inject a block first, then a prepare on it.
round.handleProposalMessage(

@ -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 class 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 class QbftRound {
this.messageFactory = messageFactory;
this.transmitter = transmitter;
this.bftExtraDataCodec = bftExtraDataCodec;
this.parentHeader = parentHeader;
roundTimer.startTimer(getRoundIdentifier());
}
@ -134,7 +138,8 @@ public class QbftRound {
*/
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 class QbftRound {
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());

@ -99,7 +99,7 @@ public class QbftRoundFactory {
*/
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 class QbftRoundFactory {
messageFactory,
messageTransmitter,
finalState.getRoundTimer(),
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
}
}

@ -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<MessageData> sentMessageArgCaptor;
@ -158,7 +159,7 @@ public class QbftBlockHeightManagerTest {
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 @@ public class QbftBlockHeightManagerTest {
messageFactory,
messageTransmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
});
when(roundFactory.createNewRoundWithState(any(), any()))
@ -227,7 +229,8 @@ public class QbftBlockHeightManagerTest {
messageFactory,
messageTransmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
});
}

@ -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<Block> blockCaptor;
@ -139,7 +140,7 @@ public class QbftRoundTest {
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 class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
verify(roundTimer, times(1)).startTimer(roundIdentifier);
}
@ -184,7 +186,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleProposalMessage(
messageFactory.createProposal(
@ -207,7 +210,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.createAndSendProposalMessage(15);
verify(transmitter, times(1))
@ -231,7 +235,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.createAndSendProposalMessage(15);
verify(transmitter, times(1))
.multicastProposal(
@ -254,7 +259,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
final Hash commitSealHash =
new BftBlockHashing(new QbftExtraDataCodec())
@ -288,7 +294,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.startRoundWith(new RoundChangeArtifacts(emptyList(), Optional.empty()), 15);
verify(transmitter, times(1))
@ -311,7 +318,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
final SignedData<PreparePayload> preparedPayload =
messageFactory.createPrepare(priorRoundChange, proposedBlock.getHash()).getSignedPayload();
@ -359,7 +367,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
final RoundChange roundChange =
messageFactory.createRoundChange(roundIdentifier, Optional.empty());
@ -398,7 +407,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.createAndSendProposalMessage(15);
verify(minedBlockObserver).blockMined(any());
}
@ -419,7 +429,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleCommitMessage(
messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal));
@ -444,7 +455,8 @@ public class QbftRoundTest {
messageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleCommitMessage(
messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal));
@ -473,7 +485,8 @@ public class QbftRoundTest {
throwingMessageFactory,
transmitter,
roundTimer,
bftExtraDataCodec);
bftExtraDataCodec,
parentHeader);
round.handleProposalMessage(
messageFactory.createProposal(

@ -88,7 +88,6 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
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 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
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 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
this.transactionPool = transactionPool;
this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule;
this.parentHeader = parentHeader;
this.ethScheduler = ethScheduler;
blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
}
@ -130,21 +127,25 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
* @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<Transaction> transactions, final List<BlockHeader> ommers, final long timestamp) {
return createBlock(Optional.of(transactions), Optional.of(ommers), timestamp);
final List<Transaction> transactions,
final List<BlockHeader> ommers,
final long timestamp,
final BlockHeader parentHeader) {
return createBlock(Optional.of(transactions), Optional.of(ommers), timestamp, parentHeader);
}
@Override
public BlockCreationResult createBlock(
final Optional<List<Transaction>> maybeTransactions,
final Optional<List<BlockHeader>> maybeOmmers,
final long timestamp) {
final long timestamp,
final BlockHeader parentHeader) {
return createBlock(
maybeTransactions,
maybeOmmers,
@ -152,11 +153,13 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
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 abstract class AbstractBlockCreator implements AsyncBlockCreator {
final Optional<List<Transaction>> maybeTransactions,
final Optional<List<BlockHeader>> maybeOmmers,
final Optional<List<Withdrawal>> maybeWithdrawals,
final long timestamp) {
final long timestamp,
final BlockHeader parentHeader) {
return createBlock(
maybeTransactions,
maybeOmmers,
@ -172,7 +176,8 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
Optional.empty(),
Optional.empty(),
timestamp,
true);
true,
parentHeader);
}
protected BlockCreationResult createBlock(
@ -182,18 +187,23 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final Optional<Bytes32> maybePrevRandao,
final Optional<Bytes32> 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 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
maybeTransactions,
miningBeneficiary,
newProtocolSpec,
pluginTransactionSelector);
pluginTransactionSelector,
parentHeader);
transactionResults.logSelectionStats();
timings.register("txsSelection");
throwIfStopped();
@ -273,7 +284,8 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
throwIfStopped();
final GasUsage usage = computeExcessBlobGas(transactionResults, newProtocolSpec);
final GasUsage usage =
computeExcessBlobGas(transactionResults, newProtocolSpec, parentHeader);
throwIfStopped();
@ -324,7 +336,9 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
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 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final Optional<List<Transaction>> 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 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
}
}
private MutableWorldState duplicateWorldStateAtParent() {
private MutableWorldState duplicateWorldStateAtParent(final BlockHeader parentHeader) {
final Hash parentStateRoot = parentHeader.getStateRoot();
return protocolContext
.getWorldStateArchive()
@ -411,7 +426,8 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final long timestamp,
final Optional<Bytes32> maybePrevRandao,
final Optional<Bytes32> maybeParentBeaconBlockRoot,
final ProtocolSpec protocolSpec) {
final ProtocolSpec protocolSpec,
final BlockHeader parentHeader) {
final long newBlockNumber = parentHeader.getNumber() + 1;
long gasLimit =
protocolSpec

@ -50,15 +50,20 @@ public interface BlockCreator {
}
}
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<Transaction> transactions, final List<BlockHeader> ommers, final long timestamp);
final List<Transaction> transactions,
final List<BlockHeader> ommers,
final long timestamp,
final BlockHeader parentHeader);
BlockCreationResult createBlock(
final Optional<List<Transaction>> maybeTransactions,
final Optional<List<BlockHeader>> maybeOmmers,
final long timestamp);
final long timestamp,
final BlockHeader parentHeader);
}

@ -109,7 +109,7 @@ public class BlockMiner<M extends AbstractBlockCreator> implements Runnable {
final List<BlockHeader> 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 class BlockMiner<M extends AbstractBlockCreator> implements Runnable {
*/
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 @@ public class BlockMiner<M extends AbstractBlockCreator> implements Runnable {
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();

@ -45,7 +45,6 @@ public class PoWBlockCreator extends AbstractBlockCreator {
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final PoWSolver nonceSolver,
final BlockHeader parentHeader,
final EthScheduler ethScheduler) {
super(
miningParameters,
@ -54,7 +53,6 @@ public class PoWBlockCreator extends AbstractBlockCreator {
transactionPool,
protocolContext,
protocolSchedule,
parentHeader,
ethScheduler);
this.nonceSolver = nonceSolver;

@ -93,7 +93,6 @@ public class PoWMinerExecutor extends AbstractMinerExecutor<PoWBlockMiner> {
protocolContext,
protocolSchedule,
solver,
parentHeader,
ethScheduler);
return new PoWBlockMiner(

@ -161,18 +161,19 @@ abstract class AbstractBlockCreatorTest {
@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<Request> depositRequests = emptyList();
final Hash requestsRoot = BodyValidation.requestsRoot(depositRequests);
@ -182,17 +183,18 @@ abstract class AbstractBlockCreatorTest {
@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 @@ abstract class AbstractBlockCreatorTest {
@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 @@ abstract class AbstractBlockCreatorTest {
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 @@ abstract class AbstractBlockCreatorTest {
@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 @@ abstract class AbstractBlockCreatorTest {
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 @@ abstract class AbstractBlockCreatorTest {
@Test
void withProcessorAndWithdrawals_WithdrawalsAreProcessed() {
final AbstractBlockCreator blockCreator = blockCreatorWithWithdrawalsProcessor();
final CreateOn miningOn = blockCreatorWithWithdrawalsProcessor();
final AbstractBlockCreator blockCreator = miningOn.blockCreator;
final List<Withdrawal> withdrawals =
List.of(new Withdrawal(UInt64.ONE, UInt64.ONE, Address.fromHexString("0x1"), GWei.ONE));
final BlockCreationResult blockCreationResult =
@ -291,7 +272,8 @@ abstract class AbstractBlockCreatorTest {
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 @@ abstract class AbstractBlockCreatorTest {
@Test
void withNoProcessorAndWithdrawals_WithdrawalsAreNotProcessed() {
final AbstractBlockCreator blockCreator = blockCreatorWithoutWithdrawalsProcessor();
final CreateOn miningOn = blockCreatorWithoutWithdrawalsProcessor();
final AbstractBlockCreator blockCreator = miningOn.blockCreator;
final List<Withdrawal> withdrawals =
List.of(new Withdrawal(UInt64.ONE, UInt64.ONE, Address.fromHexString("0x1"), GWei.ONE));
final BlockCreationResult blockCreationResult =
@ -313,7 +296,8 @@ abstract class AbstractBlockCreatorTest {
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 @@ abstract class AbstractBlockCreatorTest {
@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 @@ abstract class AbstractBlockCreatorTest {
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 @@ abstract class AbstractBlockCreatorTest {
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 @@ abstract class AbstractBlockCreatorTest {
.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 @@ abstract class AbstractBlockCreatorTest {
.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 @@ abstract class AbstractBlockCreatorTest {
final TransactionPool transactionPool,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final BlockHeader parentHeader,
final EthScheduler ethScheduler) {
super(
miningParameters,
@ -464,7 +483,6 @@ abstract class AbstractBlockCreatorTest {
transactionPool,
protocolContext,
protocolSchedule,
parentHeader,
ethScheduler);
}

@ -63,7 +63,7 @@ public class BlockMinerTest {
final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class);
final Function<BlockHeader, PoWBlockCreator> 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 class BlockMinerTest {
final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class);
final Function<BlockHeader, PoWBlockCreator> 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 class BlockMinerTest {
final PoWBlockCreator blockCreator = mock(PoWBlockCreator.class);
final Function<BlockHeader, PoWBlockCreator> blockCreatorSupplier =
(parentHeader) -> blockCreator;
when(blockCreator.createBlock(anyLong()))
when(blockCreator.createBlock(anyLong(), any()))
.thenReturn(
new BlockCreationResult(
blockToCreate, new TransactionSelectionResults(), new BlockCreationTiming()));

@ -123,13 +123,14 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
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 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
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 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
executionContextTestFixture.getProtocolContext(),
executionContextTestFixture.getProtocolSchedule(),
solver,
executionContextTestFixture.getBlockchain().getChainHeadHeader(),
ethScheduler);
final MutableWorldState mutableWorldState =
@ -320,7 +323,6 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
executionContextTestFixture.getProtocolContext(),
executionContextTestFixture.getProtocolSchedule(),
solver,
executionContextTestFixture.getBlockchain().getChainHeadHeader(),
ethScheduler);
final MutableWorldState mutableWorldState =

@ -260,7 +260,6 @@ public abstract class AbstractIsolationTests {
final TransactionPool transactionPool,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final BlockHeader parentHeader,
final EthScheduler ethScheduler) {
super(
miningParameters,
@ -269,12 +268,10 @@ public abstract class AbstractIsolationTests {
transactionPool,
protocolContext,
protocolSchedule,
parentHeader,
ethScheduler);
}
static TestBlockCreator forHeader(
final BlockHeader parentHeader,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final TransactionPool transactionPool,
@ -299,7 +296,6 @@ public abstract class AbstractIsolationTests {
transactionPool,
protocolContext,
protocolSchedule,
parentHeader,
ethScheduler);
}
@ -332,8 +328,8 @@ public abstract class AbstractIsolationTests {
protected Block forTransactions(
final List<Transaction> 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();
}

@ -78,10 +78,11 @@ public class TestMineBlocks implements JsonRpcMethod {
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);

Loading…
Cancel
Save