use of tech.pegasys.teku.ethereum.forkchoice.ForkChoiceStrategy in project teku by ConsenSys.
the class Store method create.
public static UpdatableStore create(final AsyncRunner asyncRunner, final MetricsSystem metricsSystem, final Spec spec, final BlockProvider blockProvider, final StateAndBlockSummaryProvider stateAndBlockProvider, final Optional<Checkpoint> initialCheckpoint, final UInt64 time, final UInt64 genesisTime, final AnchorPoint finalizedAnchor, final Optional<SlotAndExecutionPayload> finalizedOptimisticTransitionPayload, final Checkpoint justifiedCheckpoint, final Checkpoint bestJustifiedCheckpoint, final Map<Bytes32, StoredBlockMetadata> blockInfoByRoot, final Map<UInt64, VoteTracker> votes, final StoreConfig config) {
// Create limited collections for non-final data
final Map<Bytes32, SignedBeaconBlock> blocks = LimitedMap.create(config.getBlockCacheSize());
final CachingTaskQueue<SlotAndBlockRoot, BeaconState> checkpointStateTaskQueue = CachingTaskQueue.create(asyncRunner, metricsSystem, "memory_checkpoint_states", config.getCheckpointStateCacheSize());
final CachingTaskQueue<Bytes32, StateAndBlockSummary> stateTaskQueue = CachingTaskQueue.create(asyncRunner, metricsSystem, "memory_states", config.getStateCacheSize());
final ForkChoiceStrategy forkChoiceStrategy = ForkChoiceStrategy.initialize(spec, buildProtoArray(spec, blockInfoByRoot, initialCheckpoint, justifiedCheckpoint, finalizedAnchor));
return new Store(metricsSystem, spec, config.getHotStatePersistenceFrequencyInEpochs(), blockProvider, stateAndBlockProvider, stateTaskQueue, initialCheckpoint, time, genesisTime, finalizedAnchor, finalizedOptimisticTransitionPayload, justifiedCheckpoint, bestJustifiedCheckpoint, forkChoiceStrategy, votes, blocks, checkpointStateTaskQueue);
}
use of tech.pegasys.teku.ethereum.forkchoice.ForkChoiceStrategy in project teku by ConsenSys.
the class RecentChainData method computeReorgContext.
private Optional<ReorgContext> computeReorgContext(final ReadOnlyForkChoiceStrategy forkChoiceStrategy, final Optional<ChainHead> originalChainHead, final ChainHead newChainHead) {
final Optional<ReorgContext> optionalReorgContext;
if (originalChainHead.map(head -> hasReorgedFrom(head.getRoot(), head.getSlot())).orElse(false)) {
final ChainHead previousChainHead = originalChainHead.get();
final SlotAndBlockRoot commonAncestorSlotAndBlockRoot = forkChoiceStrategy.findCommonAncestor(previousChainHead.getRoot(), newChainHead.getRoot()).orElseGet(() -> store.getFinalizedCheckpoint().toSlotAndBlockRoot(spec));
reorgCounter.inc();
optionalReorgContext = ReorgContext.of(previousChainHead.getRoot(), previousChainHead.getSlot(), previousChainHead.getStateRoot(), commonAncestorSlotAndBlockRoot.getSlot(), commonAncestorSlotAndBlockRoot.getBlockRoot());
} else {
optionalReorgContext = ReorgContext.empty();
}
return optionalReorgContext;
}
use of tech.pegasys.teku.ethereum.forkchoice.ForkChoiceStrategy in project teku by ConsenSys.
the class ForkChoice method applyVotesFromBlock.
private void applyVotesFromBlock(final ForkChoiceStrategy forkChoiceStrategy, final UInt64 currentEpoch, final CapturingIndexedAttestationCache indexedAttestationProvider) {
final VoteUpdater voteUpdater = recentChainData.startVoteUpdate();
indexedAttestationProvider.getIndexedAttestations().stream().filter(attestation -> validateBlockAttestation(forkChoiceStrategy, currentEpoch, attestation)).forEach(attestation -> forkChoiceStrategy.onAttestation(voteUpdater, attestation));
voteUpdater.commit();
}
use of tech.pegasys.teku.ethereum.forkchoice.ForkChoiceStrategy in project teku by ConsenSys.
the class ForkChoice method importBlockAndState.
private BlockImportResult importBlockAndState(final SignedBeaconBlock block, final BeaconState blockSlotState, final ForkChoiceUtil forkChoiceUtil, final CapturingIndexedAttestationCache indexedAttestationCache, final BeaconState postState, final PayloadValidationResult payloadValidationResult) {
final PayloadStatus payloadResult = payloadValidationResult.getStatus();
if (payloadResult.hasInvalidStatus()) {
final BlockImportResult result = BlockImportResult.failedStateTransition(new IllegalStateException("Invalid ExecutionPayload: " + payloadResult.getValidationError().orElse("No reason provided")));
reportInvalidBlock(block, result);
payloadValidationResult.getInvalidTransitionBlockRoot().ifPresent(invalidTransitionBlockRoot -> getForkChoiceStrategy().onExecutionPayloadResult(invalidTransitionBlockRoot, payloadResult));
return result;
}
if (payloadResult.hasNotValidatedStatus() && !recentChainData.isOptimisticSyncPossible(block.getSlot())) {
return BlockImportResult.FAILED_EXECUTION_PAYLOAD_EXECUTION_SYNCING;
}
if (payloadResult.hasFailedExecution()) {
return BlockImportResult.failedExecutionPayloadExecution(payloadResult.getFailureCause().orElseThrow());
}
final ForkChoiceStrategy forkChoiceStrategy = getForkChoiceStrategy();
// (which may have changed while we were processing the block)
if (!forkChoiceUtil.blockDescendsFromLatestFinalizedBlock(block, recentChainData.getStore(), forkChoiceStrategy)) {
return BlockImportResult.FAILED_INVALID_ANCESTRY;
}
final StoreTransaction transaction = recentChainData.startStoreTransaction();
addParentStateRoots(spec, blockSlotState, transaction);
forkChoiceUtil.applyBlockToStore(transaction, block, postState);
if (proposerBoostEnabled && spec.getCurrentSlot(transaction).equals(block.getSlot())) {
final int secondsPerSlot = spec.getSecondsPerSlot(block.getSlot());
final UInt64 timeIntoSlot = transaction.getTime().minus(transaction.getGenesisTime()).mod(secondsPerSlot);
final boolean isBeforeAttestingInterval = timeIntoSlot.isLessThan(secondsPerSlot / INTERVALS_PER_SLOT);
if (isBeforeAttestingInterval) {
transaction.setProposerBoostRoot(block.getRoot());
}
}
if (payloadResult.hasValidStatus()) {
UInt64 latestValidFinalizedSlot = transaction.getLatestFinalized().getSlot();
if (latestValidFinalizedSlot.isGreaterThan(transaction.getLatestValidFinalizedSlot())) {
transaction.setLatestValidFinalizedSlot(latestValidFinalizedSlot);
}
}
// Note: not using thenRun here because we want to ensure each step is on the event thread
transaction.commit().join();
forkChoiceStrategy.onExecutionPayloadResult(block.getRoot(), payloadResult);
final UInt64 currentEpoch = spec.computeEpochAtSlot(spec.getCurrentSlot(transaction));
// before that, none of the attestations will be applicable so just skip the whole step.
if (spec.computeEpochAtSlot(block.getSlot()).isGreaterThanOrEqualTo(currentEpoch.minusMinZero(1))) {
applyVotesFromBlock(forkChoiceStrategy, currentEpoch, indexedAttestationCache);
}
final BlockImportResult result;
if (payloadResult.hasValidStatus()) {
result = BlockImportResult.successful(block);
} else {
result = BlockImportResult.optimisticallySuccessful(block);
}
updateForkChoiceForImportedBlock(block, result, forkChoiceStrategy);
notifyForkChoiceUpdatedAndOptimisticSyncingChanged();
return result;
}
use of tech.pegasys.teku.ethereum.forkchoice.ForkChoiceStrategy in project teku by ConsenSys.
the class ForkChoice method findNewChainHead.
private SlotAndBlockRoot findNewChainHead(final SignedBeaconBlock block, final ForkChoiceStrategy forkChoiceStrategy) {
// child of the current chain head we'd have already selected it as head.
if (recentChainData.getBestBlockRoot().map(chainHeadRoot -> chainHeadRoot.equals(block.getParentRoot())).orElse(false)) {
return new SlotAndBlockRoot(block.getSlot(), block.getRoot());
}
// Otherwise, use fork choice to find the new chain head as if this block is on time the
// proposer weighting may cause us to reorg.
// During sync, this may be noticeably slower than just comparing the chain head due to the way
// ProtoArray skips updating all ancestors when adding a new block but it's cheap when in sync.
final Checkpoint justifiedCheckpoint = recentChainData.getJustifiedCheckpoint().orElseThrow();
final Checkpoint finalizedCheckpoint = recentChainData.getFinalizedCheckpoint().orElseThrow();
return forkChoiceStrategy.findHead(justifiedCheckpoint, finalizedCheckpoint);
}
Aggregations