Search in sources :

Example 1 with BlockOptions

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));
}
Also used : ChainBuilder(tech.pegasys.teku.core.ChainBuilder) BlockOptions(tech.pegasys.teku.core.ChainBuilder.BlockOptions) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState) Eth1Data(tech.pegasys.teku.spec.datastructures.blocks.Eth1Data) BLSPublicKey(tech.pegasys.teku.bls.BLSPublicKey) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) Attestation(tech.pegasys.teku.spec.datastructures.operations.Attestation) ValidateableAttestation(tech.pegasys.teku.spec.datastructures.attestation.ValidateableAttestation) Test(org.junit.jupiter.api.Test)

Example 2 with BlockOptions

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);
}
Also used : BlockOptions(tech.pegasys.teku.core.ChainBuilder.BlockOptions) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState)

Example 3 with BlockOptions

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;
}
Also used : BlockOptions(tech.pegasys.teku.core.ChainBuilder.BlockOptions) Checkpoint(tech.pegasys.teku.spec.datastructures.state.Checkpoint) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState)

Example 4 with BlockOptions

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));
}
Also used : ChainBuilder(tech.pegasys.teku.core.ChainBuilder) BlockOptions(tech.pegasys.teku.core.ChainBuilder.BlockOptions) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState) Bytes32(org.apache.tuweni.bytes.Bytes32) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test)

Example 5 with BlockOptions

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));
}
Also used : ChainBuilder(tech.pegasys.teku.core.ChainBuilder) BlockOptions(tech.pegasys.teku.core.ChainBuilder.BlockOptions) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState) ReorgEvent(tech.pegasys.teku.storage.api.TrackingChainHeadChannel.ReorgEvent) Test(org.junit.jupiter.api.Test)

Aggregations

BlockOptions (tech.pegasys.teku.core.ChainBuilder.BlockOptions)9 SignedBlockAndState (tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState)9 Test (org.junit.jupiter.api.Test)7 ChainBuilder (tech.pegasys.teku.core.ChainBuilder)7 UInt64 (tech.pegasys.teku.infrastructure.unsigned.UInt64)5 Eth1Data (tech.pegasys.teku.spec.datastructures.blocks.Eth1Data)2 ReorgEvent (tech.pegasys.teku.storage.api.TrackingChainHeadChannel.ReorgEvent)2 HashSet (java.util.HashSet)1 Bytes32 (org.apache.tuweni.bytes.Bytes32)1 BLSPublicKey (tech.pegasys.teku.bls.BLSPublicKey)1 ValidateableAttestation (tech.pegasys.teku.spec.datastructures.attestation.ValidateableAttestation)1 Attestation (tech.pegasys.teku.spec.datastructures.operations.Attestation)1 Checkpoint (tech.pegasys.teku.spec.datastructures.state.Checkpoint)1 StoreTransaction (tech.pegasys.teku.storage.store.UpdatableStore.StoreTransaction)1