Search in sources :

Example 6 with ChainBuilder

use of tech.pegasys.teku.core.ChainBuilder 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 7 with ChainBuilder

use of tech.pegasys.teku.core.ChainBuilder in project teku by ConsenSys.

the class ForkChoiceTest method onBlock_shouldNotifyOptimisticSyncChangeOnlyWhenImportingOnCanonicalHead.

@Test
void onBlock_shouldNotifyOptimisticSyncChangeOnlyWhenImportingOnCanonicalHead() {
    doMerge();
    UInt64 slotToImport = prepFinalizeEpoch(2);
    // since protoArray initializes with optimistic nodes,
    // we expect a first notification to be optimistic false
    verify(optimisticSyncStateTracker).onOptimisticHeadChanged(false);
    final SignedBlockAndState epoch4Block = chainBuilder.generateBlockAtSlot(slotToImport);
    importBlock(epoch4Block);
    slotToImport = prepFinalizeEpoch(4);
    // make EL returning SYNCING
    executionEngine.setPayloadStatus(PayloadStatus.SYNCING);
    // generate block which finalize epoch 4
    final SignedBlockAndState epoch6Block = chainBuilder.generateBlockAtSlot(slotToImport);
    importBlockOptimistically(epoch6Block);
    verify(optimisticSyncStateTracker).onOptimisticHeadChanged(true);
    UInt64 forkSlot = slotToImport.increment();
    storageSystem.chainUpdater().setCurrentSlot(forkSlot);
    ChainBuilder alternativeChain = chainBuilder.fork();
    // make EL returning SYNCING
    executionEngine.setPayloadStatus(PayloadStatus.VALID);
    importBlock(chainBuilder.generateBlockAtSlot(forkSlot));
    verify(optimisticSyncStateTracker, times(2)).onOptimisticHeadChanged(false);
    // builds atop the canonical chain
    storageSystem.chainUpdater().setCurrentSlot(forkSlot.plus(1));
    importBlock(chainBuilder.generateBlockAtSlot(forkSlot.plus(1)));
    // make EL returning SYNCING
    executionEngine.setPayloadStatus(PayloadStatus.SYNCING);
    // import a fork which won't be canonical
    importBlockOptimistically(alternativeChain.generateBlockAtSlot(forkSlot));
    // no notification is expected
    verifyNoMoreInteractions(optimisticSyncStateTracker);
}
Also used : ChainBuilder(tech.pegasys.teku.core.ChainBuilder) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState) Test(org.junit.jupiter.api.Test)

Example 8 with ChainBuilder

use of tech.pegasys.teku.core.ChainBuilder in project teku by ConsenSys.

the class RecentChainDataTest method testCommitPruningOfParallelBlocks.

/**
 * Builds 2 parallel chains, one of which will get pruned when a block in the middle of the other
 * chain is finalized. Keep one chain in the finalizing transaction, the other chain is already
 * saved to the store.
 *
 * @param pruneNewBlocks Whether to keep the blocks to be pruned in the finalizing transaction, or
 *     keep the blocks to be kept in the finalizing transaction @
 */
private void testCommitPruningOfParallelBlocks(final boolean pruneNewBlocks) {
    final UInt64 epoch2Slot = spec.computeStartSlotAtEpoch(UInt64.valueOf(2));
    // Create a fork by skipping the next slot on the fork chain
    ChainBuilder fork = chainBuilder.fork();
    // Generate the next 2 blocks on the primary chain
    final SignedBlockAndState firstCanonicalBlock = chainBuilder.generateNextBlock();
    saveBlock(recentChainData, firstCanonicalBlock);
    saveBlock(recentChainData, chainBuilder.generateNextBlock());
    // Skip a block and then generate the next block on the fork chain
    final SignedBlockAndState firstForkBlock = fork.generateNextBlock(1);
    saveBlock(recentChainData, firstForkBlock);
    // Build both the primary and fork chain past epoch1
    // Make sure both chains are at the same slot
    assertThat(chainBuilder.getLatestSlot()).isEqualTo(fork.getLatestSlot());
    while (chainBuilder.getLatestSlot().compareTo(epoch2Slot) < 0) {
        chainBuilder.generateNextBlock();
        fork.generateNextBlock();
    }
    // Save one chain to the store, setup the other chain to be saved in the finalizing transaction
    final List<SignedBlockAndState> newBlocks = new ArrayList<>();
    if (pruneNewBlocks) {
        // Save canonical blocks now, put fork blocks in the transaction
        chainBuilder.streamBlocksAndStates(firstCanonicalBlock.getSlot()).forEach(b -> saveBlock(recentChainData, b));
        fork.streamBlocksAndStates(firstForkBlock.getSlot()).forEach(newBlocks::add);
    } else {
        // Save fork blocks now, put canonical blocks in the transaction
        chainBuilder.streamBlocksAndStates(firstCanonicalBlock.getSlot()).forEach(newBlocks::add);
        fork.streamBlocksAndStates(firstForkBlock.getSlot()).forEach(b -> saveBlock(recentChainData, b));
    }
    // Add blocks and finalize epoch 1, so that blocks will be pruned
    final StoreTransaction tx = recentChainData.startStoreTransaction();
    final Checkpoint finalizedCheckpoint = chainBuilder.getCurrentCheckpointForEpoch(1);
    tx.setFinalizedCheckpoint(finalizedCheckpoint);
    newBlocks.forEach(tx::putBlockAndState);
    tx.commit().reportExceptions();
    // Check that only recent, canonical blocks at or after the latest finalized block are left in
    // the store
    final List<SignedBlockAndState> expectedBlocks = chainBuilder.streamBlocksAndStates(finalizedCheckpoint.getEpochStartSlot(spec)).collect(Collectors.toList());
    final Set<Bytes32> blockRoots = expectedBlocks.stream().map(SignedBlockAndState::getRoot).collect(Collectors.toSet());
    // Collect blocks that should be pruned
    final Set<Bytes32> prunedBlocks = fork.streamBlocksAndStates(firstForkBlock.getSlot()).map(SignedBlockAndState::getRoot).collect(Collectors.toSet());
    // Check expected blocks
    assertThat(recentChainData.getStore().getOrderedBlockRoots()).containsExactlyInAnyOrderElementsOf(blockRoots);
    for (SignedBlockAndState expectedBlock : expectedBlocks) {
        assertThat(recentChainData.retrieveSignedBlockByRoot(expectedBlock.getRoot())).isCompletedWithValue(Optional.of(expectedBlock.getBlock()));
        assertThat(recentChainData.retrieveBlockState(expectedBlock.getRoot())).isCompletedWithValue(Optional.of(expectedBlock.getState()));
    }
    // Check pruned blocks
    for (Bytes32 prunedBlock : prunedBlocks) {
        assertThatSafeFuture(recentChainData.retrieveSignedBlockByRoot(prunedBlock)).isCompletedWithEmptyOptional();
        assertThat(recentChainData.retrieveBlockState(prunedBlock)).isCompletedWithValue(Optional.empty());
    }
}
Also used : ChainBuilder(tech.pegasys.teku.core.ChainBuilder) Checkpoint(tech.pegasys.teku.spec.datastructures.state.Checkpoint) StoreTransaction(tech.pegasys.teku.storage.store.UpdatableStore.StoreTransaction) ArrayList(java.util.ArrayList) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState) Bytes32(org.apache.tuweni.bytes.Bytes32)

Example 9 with ChainBuilder

use of tech.pegasys.teku.core.ChainBuilder in project teku by ConsenSys.

the class RecentChainDataTest method initializeFromAnchorPoint_withTimeLessThanGenesisTime.

@Test
public void initializeFromAnchorPoint_withTimeLessThanGenesisTime() {
    initPreGenesis();
    final ChainBuilder chainBuilder = ChainBuilder.create(spec);
    final UInt64 genesisTime = UInt64.valueOf(5000);
    chainBuilder.generateGenesis(genesisTime, true);
    // Build a small chain
    chainBuilder.generateBlocksUpToSlot(10);
    final SignedBlockAndState anchor = chainBuilder.generateNextBlock();
    final AnchorPoint anchorPoint = AnchorPoint.fromInitialState(spec, anchor.getState());
    final UInt64 anchorBlockTime = anchorPoint.getBlockSlot().times(genesisSpecConfig.getSecondsPerSlot()).plus(genesisTime);
    recentChainData.initializeFromAnchorPoint(anchorPoint, UInt64.valueOf(100));
    assertThat(recentChainData.getStore().getTime()).isEqualTo(anchorBlockTime);
}
Also used : ChainBuilder(tech.pegasys.teku.core.ChainBuilder) AnchorPoint(tech.pegasys.teku.spec.datastructures.state.AnchorPoint) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState) Test(org.junit.jupiter.api.Test)

Example 10 with ChainBuilder

use of tech.pegasys.teku.core.ChainBuilder in project teku by ConsenSys.

the class RecentChainDataTest method initializeFromAnchorPoint_withTimeGreaterThanAnchorBlockTime.

@Test
public void initializeFromAnchorPoint_withTimeGreaterThanAnchorBlockTime() {
    initPreGenesis();
    final ChainBuilder chainBuilder = ChainBuilder.create(spec);
    final UInt64 genesisTime = UInt64.valueOf(5000);
    chainBuilder.generateGenesis(genesisTime, true);
    // Build a small chain
    chainBuilder.generateBlocksUpToSlot(10);
    final SignedBlockAndState anchor = chainBuilder.generateNextBlock();
    final AnchorPoint anchorPoint = AnchorPoint.fromInitialState(spec, anchor.getState());
    final UInt64 anchorBlockTime = anchorPoint.getBlockSlot().times(genesisSpecConfig.getSecondsPerSlot()).plus(genesisTime);
    final UInt64 time = anchorBlockTime.plus(100);
    recentChainData.initializeFromAnchorPoint(anchorPoint, time);
    assertThat(recentChainData.getStore().getTime()).isEqualTo(time);
}
Also used : ChainBuilder(tech.pegasys.teku.core.ChainBuilder) AnchorPoint(tech.pegasys.teku.spec.datastructures.state.AnchorPoint) UInt64(tech.pegasys.teku.infrastructure.unsigned.UInt64) SignedBlockAndState(tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState) Test(org.junit.jupiter.api.Test)

Aggregations

ChainBuilder (tech.pegasys.teku.core.ChainBuilder)33 SignedBlockAndState (tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState)30 Test (org.junit.jupiter.api.Test)27 UInt64 (tech.pegasys.teku.infrastructure.unsigned.UInt64)18 BlockOptions (tech.pegasys.teku.core.ChainBuilder.BlockOptions)7 Checkpoint (tech.pegasys.teku.spec.datastructures.state.Checkpoint)6 Bytes32 (org.apache.tuweni.bytes.Bytes32)5 SignedBeaconBlock (tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock)5 AnchorPoint (tech.pegasys.teku.spec.datastructures.state.AnchorPoint)5 Eth1Data (tech.pegasys.teku.spec.datastructures.blocks.Eth1Data)4 StoreTransaction (tech.pegasys.teku.storage.store.UpdatableStore.StoreTransaction)4 Attestation (tech.pegasys.teku.spec.datastructures.operations.Attestation)3 ChainUpdater (tech.pegasys.teku.storage.client.ChainUpdater)3 HashSet (java.util.HashSet)2 AttestationGenerator (tech.pegasys.teku.core.AttestationGenerator)2 BlockAndCheckpointEpochs (tech.pegasys.teku.spec.datastructures.blocks.BlockAndCheckpointEpochs)2 BeaconState (tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState)2 ReorgEvent (tech.pegasys.teku.storage.api.TrackingChainHeadChannel.ReorgEvent)2 StorageSystem (tech.pegasys.teku.storage.storageSystem.StorageSystem)2 ArrayList (java.util.ArrayList)1