use of tech.pegasys.teku.core.ChainBuilder.BlockOptions in project teku by ConsenSys.
the class ForkChoiceTest method onBlock_shouldNotProcessAttestationsForBlocksThatDoNotYetExist.
@Test
void onBlock_shouldNotProcessAttestationsForBlocksThatDoNotYetExist() {
final ChainBuilder forkChain = chainBuilder.fork();
// Create a fork block, but don't import it.
final SignedBlockAndState forkBlock = forkChain.generateBlockAtSlot(UInt64.valueOf(2), BlockOptions.create().setEth1Data(new Eth1Data(Bytes32.ZERO, UInt64.valueOf(6), Bytes32.ZERO)));
// Now create the canonical chain and import.
final List<SignedBlockAndState> betterChain = chainBuilder.generateBlocksUpToSlot(3);
betterChain.forEach(this::importBlock);
// And create a block containing an attestation for forkBlock
final BlockOptions options = BlockOptions.create();
final Attestation attestation = chainBuilder.streamValidAttestationsWithTargetBlock(forkBlock).findFirst().orElseThrow(() -> new IllegalStateException("Failed to create attestation for block " + forkBlock.getRoot() + " genesis root: " + genesis.getRoot() + " chain head: " + chainBuilder.getLatestBlockAndState().getRoot() + " fork block: " + forkBlock.getRoot() + " validators: " + chainBuilder.getValidatorKeys().stream().map(BLSKeyPair::getPublicKey).map(BLSPublicKey::toString).collect(Collectors.joining(", "))));
options.addAttestation(attestation);
final SignedBlockAndState blockWithAttestations = chainBuilder.generateBlockAtSlot(UInt64.valueOf(4), options);
importBlock(blockWithAttestations);
// Apply these votes
processHead(blockWithAttestations.getSlot());
assertThat(recentChainData.getBestBlockRoot()).contains(blockWithAttestations.getRoot());
// Now we import the fork block
importBlock(forkBlock);
// Then we get a later attestation from the same validator pointing to a different chain
final UInt64 updatedAttestationSlot = applyAttestationFromValidator(UInt64.ZERO, blockWithAttestations);
// And we should be able to apply the new weightings without making the fork block's weight
// negative
assertDoesNotThrow(() -> forkChoice.processHead(updatedAttestationSlot));
}
use of tech.pegasys.teku.core.ChainBuilder.BlockOptions in project teku by ConsenSys.
the class ForkChoiceTest method prepEpochForJustification.
private void prepEpochForJustification(final ChainUpdater chainUpdater, final UInt64 nextEpochStartSlot) {
UInt64 headSlot = chainUpdater.getHeadSlot();
final UInt64 targetHeadSlot = nextEpochStartSlot.minus(2);
while (headSlot.isLessThan(targetHeadSlot)) {
SignedBlockAndState headBlock = chainBuilder.generateBlockAtSlot(headSlot.plus(1));
importBlock(headBlock);
assertThat(recentChainData.getBestBlockRoot()).contains(headBlock.getRoot());
headSlot = headBlock.getSlot();
}
// Add a block with enough attestations to justify the epoch.
final BlockOptions epoch2BlockOptions = BlockOptions.create();
final UInt64 newBlockSlot = headSlot.increment();
chainBuilder.streamValidAttestationsForBlockAtSlot(newBlockSlot).forEach(epoch2BlockOptions::addAttestation);
final SignedBlockAndState epoch2Block = chainBuilder.generateBlockAtSlot(newBlockSlot, epoch2BlockOptions);
importBlock(epoch2Block);
}
use of tech.pegasys.teku.core.ChainBuilder.BlockOptions in project teku by ConsenSys.
the class ChainUpdater method finalizeCurrentChain.
public SignedBlockAndState finalizeCurrentChain() {
final UInt64 chainHeadSlot = recentChainData.getHeadSlot();
final UInt64 finalizeEpoch = spec.computeEpochAtSlot(chainHeadSlot).max(2);
final UInt64 finalHeadEpoch = finalizeEpoch.plus(3);
final UInt64 finalHeadSlot = spec.computeStartSlotAtEpoch(finalHeadEpoch);
SignedBlockAndState newChainHead = null;
for (UInt64 slot = chainHeadSlot.plus(1); slot.isLessThan(finalHeadSlot); slot = slot.increment()) {
final BlockOptions blockOptions = BlockOptions.create();
chainBuilder.streamValidAttestationsForBlockAtSlot(slot).forEach(blockOptions::addAttestation);
newChainHead = chainBuilder.generateBlockAtSlot(slot, blockOptions);
saveBlock(newChainHead);
updateBestBlock(newChainHead);
}
final Checkpoint finalizedCheckpoint = newChainHead.getState().getFinalized_checkpoint();
assertThat(finalizedCheckpoint.getEpoch()).describedAs("Failed to finalize epoch %s", finalizeEpoch).isEqualTo(finalizeEpoch);
assertThat(finalizedCheckpoint.getRoot()).describedAs("Failed to finalize epoch %s", finalizeEpoch).isNotEqualTo(Bytes32.ZERO);
return newChainHead;
}
use of tech.pegasys.teku.core.ChainBuilder.BlockOptions in project teku by ConsenSys.
the class AbstractDatabaseTest method shouldPruneHotBlocksAddedOverMultipleSessions.
@Test
public void shouldPruneHotBlocksAddedOverMultipleSessions() throws Exception {
final UInt64 targetSlot = UInt64.valueOf(10);
chainBuilder.generateBlocksUpToSlot(targetSlot.minus(UInt64.ONE));
final ChainBuilder forkA = chainBuilder.fork();
final ChainBuilder forkB = chainBuilder.fork();
// Add base blocks
addBlocks(chainBuilder.streamBlocksAndStates().collect(toList()));
// Set target slot at which to create duplicate blocks
// and generate block options to make each block unique
final List<BlockOptions> blockOptions = chainBuilder.streamValidAttestationsForBlockAtSlot(targetSlot).map(attestation -> BlockOptions.create().addAttestation(attestation)).limit(2).collect(toList());
// Create several different blocks at the same slot
final SignedBlockAndState blockA = forkA.generateBlockAtSlot(targetSlot, blockOptions.get(0));
final SignedBlockAndState blockB = forkB.generateBlockAtSlot(targetSlot, blockOptions.get(1));
final SignedBlockAndState blockC = chainBuilder.generateBlockAtSlot(10);
final Set<Bytes32> block10Roots = Set.of(blockA.getRoot(), blockB.getRoot(), blockC.getRoot());
// Sanity check
assertThat(block10Roots.size()).isEqualTo(3);
// Add blocks at same height sequentially
add(List.of(blockA));
add(List.of(blockB));
add(List.of(blockC));
// Verify all blocks are available
assertThat(store.retrieveBlock(blockA.getRoot())).isCompletedWithValue(Optional.of(blockA.getBlock().getMessage()));
assertThat(store.retrieveBlock(blockB.getRoot())).isCompletedWithValue(Optional.of(blockB.getBlock().getMessage()));
assertThat(store.retrieveBlock(blockC.getRoot())).isCompletedWithValue(Optional.of(blockC.getBlock().getMessage()));
// Finalize subsequent block to prune blocks a, b, and c
final SignedBlockAndState finalBlock = chainBuilder.generateNextBlock();
add(List.of(finalBlock));
final UInt64 finalEpoch = chainBuilder.getLatestEpoch().plus(ONE);
final SignedBlockAndState finalizedBlock = chainBuilder.getLatestBlockAndStateAtEpochBoundary(finalEpoch);
justifyAndFinalizeEpoch(finalEpoch, finalizedBlock);
// Check pruning result
final Set<Bytes32> rootsToPrune = new HashSet<>(block10Roots);
rootsToPrune.add(genesisBlockAndState.getRoot());
// Check that all blocks at slot 10 were pruned
assertRecentDataWasPruned(store, rootsToPrune, Set.of(genesisCheckpoint));
}
use of tech.pegasys.teku.core.ChainBuilder.BlockOptions in project teku by ConsenSys.
the class RecentChainDataTest method updateHead_reorgEventWhenChainSwitchesToNewBlockAtSameSlot.
@Test
public void updateHead_reorgEventWhenChainSwitchesToNewBlockAtSameSlot() {
initPreGenesis();
final ChainBuilder chainBuilder = ChainBuilder.create(spec, BLSKeyGenerator.generateKeyPairs(16));
final SignedBlockAndState genesis = chainBuilder.generateGenesis();
recentChainData.initializeFromGenesis(genesis.getState(), UInt64.ZERO);
assertThat(storageSystem.chainHeadChannel().getReorgEvents()).isEmpty();
chainBuilder.generateBlockAtSlot(1);
// Set target slot at which to create duplicate blocks
// and generate block options to make each block unique
final List<BlockOptions> blockOptions = chainBuilder.streamValidAttestationsForBlockAtSlot(ONE).map(attestation -> BlockOptions.create().addAttestation(attestation)).limit(2).collect(toList());
final ChainBuilder forkBuilder = chainBuilder.fork();
final SignedBlockAndState latestBlockAndState = chainBuilder.generateBlockAtSlot(UInt64.valueOf(2), blockOptions.get(0));
final SignedBlockAndState latestForkBlockAndState = forkBuilder.generateBlockAtSlot(UInt64.valueOf(2), blockOptions.get(1));
importBlocksAndStates(recentChainData, chainBuilder, forkBuilder);
// Update to head block of original chain.
recentChainData.updateHead(latestBlockAndState.getRoot(), latestBlockAndState.getSlot());
assertThat(storageSystem.chainHeadChannel().getReorgEvents()).isEmpty();
// Switch to fork.
recentChainData.updateHead(latestForkBlockAndState.getRoot(), latestForkBlockAndState.getSlot());
// Check reorg event
assertThat(storageSystem.chainHeadChannel().getReorgEvents()).containsExactly(new ReorgEvent(latestForkBlockAndState.getRoot(), latestForkBlockAndState.getSlot(), latestForkBlockAndState.getStateRoot(), latestBlockAndState.getRoot(), latestBlockAndState.getStateRoot(), ONE));
}
Aggregations