Decouple block creators (#7468)

* wip decoupled parent block header from block creators

---------

Signed-off-by: Justin Florentine <justin+github@florentine.us>
This commit is contained in:
Justin Florentine
2024-09-09 09:25:37 -04:00
committed by GitHub
parent 2a52b0278b
commit 9a570d415e
32 changed files with 295 additions and 196 deletions

View File

@@ -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 {

View File

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

View File

@@ -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"));
}

View File

@@ -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()));

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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(

View File

@@ -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());

View File

@@ -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);
}
}

View File

@@ -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(

View File

@@ -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);
});
}

View File

@@ -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()));

View File

@@ -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");
}

View File

@@ -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",

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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(

View File

@@ -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());

View File

@@ -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);
}
}

View File

@@ -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);
});
}

View File

@@ -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(

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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;

View File

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

View File

@@ -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);
}

View File

@@ -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()));

View File

@@ -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 =

View File

@@ -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();
}

View File

@@ -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);