@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
150 lines • 6.83 kB
TypeScript
import { ChainForkConfig } from "@lodestar/config";
import { Logger } from "@lodestar/utils";
import { IBeaconChain } from "../chain/index.js";
import { Metrics } from "../metrics/index.js";
import { INetwork } from "../network/index.js";
import { PeerSyncMeta } from "../network/peers/peersData.js";
import { PeerIdStr } from "../util/peerId.js";
import { SyncOptions } from "./options.js";
/**
* BlockInputSync is a class that handles ReqResp to find blocks and data related to a specific blockRoot. The
* blockRoot may have been found via object gossip, or the API. Gossip objects that can trigger a search are block,
* blobs, columns, attestations, etc. In the case of blocks and data this is generally during the current slot but
* can also be for items that are received late but are not fully verified and thus not in fork-choice (old blocks on
* an unknown fork). It can also be triggered via an attestation (or sync committee message or any other item that
* gets gossiped) that references a blockRoot that is not in fork-choice. In rare (and realistically should not happen)
* situations it can get triggered via the API when the validator attempts to publish a block, attestation, aggregate
* and proof or a sync committee contribution that has unknown information included (parentRoot for instance).
*
* The goal of the class is to make sure that all information that is necessary for import into fork-choice is pulled
* from peers so that the block and data can be processed, and thus the object that triggered the search can be
* referenced and validated.
*
* The most common case for this search is a set of block/data that comes across gossip for the current slot, during
* normal chain operation, but not everything was received before the gossip cutoff window happens so it is necessary
* to pull remaining data via req/resp so that fork-choice can be updated prior to making an attestation for the
* current slot.
*
* Event sources for old UnknownBlock
*
* - publishBlock
* - gossipHandlers
* - searchUnknownBlock
* = produceSyncCommitteeContribution
* = validateGossipFnRetryUnknownRoot
* * submitPoolAttestationsV2
* * publishAggregateAndProofsV2
* = onPendingGossipsubMessage
* * NetworkEvent.pendingGossipsubMessage
* - onGossipsubMessage
*/
export declare class BlockInputSync {
private readonly config;
private readonly network;
private readonly chain;
private readonly logger;
private readonly metrics;
private readonly opts?;
/**
* block RootHex -> PendingBlock. To avoid finding same root at the same time
*/
private readonly pendingBlocks;
private readonly pendingPayloads;
private readonly knownBadBlocks;
private readonly maxPendingBlocks;
private subscribedToNetworkEvents;
private peerBalancer;
private rateLimitBackoffTimeout;
constructor(config: ChainForkConfig, network: INetwork, chain: IBeaconChain, logger: Logger, metrics: Metrics | null, opts?: SyncOptions | undefined);
subscribeToNetwork(): void;
unsubscribeFromNetwork(): void;
close(): void;
isSubscribedToNetwork(): boolean;
/**
* Process an unknownBlock event and register the block in `pendingBlocks` Map.
*/
private onUnknownBlockRoot;
/**
* Process an unknownBlockInput event and register the block in `pendingBlocks` Map.
*/
private onIncompleteBlockInput;
private onUnknownEnvelopeBlockRoot;
private onIncompletePayloadEnvelope;
/**
* Process an unknownBlockParent event and register the block in `pendingBlocks` Map.
*/
private onUnknownParent;
private onBlockImported;
private onPayloadImported;
private addByRootHex;
private addByBlockInput;
private addByPayloadRootHex;
private addByPayloadInput;
private onPeerConnected;
private onPeerDisconnected;
/**
* Post-gloas, a locally complete block can still be blocked on its parent's execution payload lineage.
* Distinguish which dependency is missing so the scheduler can enqueue the right follow-up work.
*/
private getMissingBlockDependency;
private advancePendingBlock;
private toPendingPayloadInput;
/**
* Gather tip parent blocks with unknown parent and do a search for all of them
*/
private triggerUnknownBlockSearch;
private scheduleRateLimitBackoffRetry;
private clearRateLimitBackoffTimer;
private downloadBlock;
private processReadyBlock;
private reconcilePayloadEnvelope;
private downloadPayload;
private processPayload;
private fetchPayloadInput;
private fetchExecutionPayloadEnvelope;
private fetchPayloadColumns;
private fetchBlockInput;
/**
* Gets all descendant blocks of `block` recursively from `pendingBlocks`.
* Assumes that if a parent block does not exist or is not processable, all descendant blocks are bad too.
* Downscore all peers that have referenced any of this bad blocks. May report peers multiple times if they have
* referenced more than one bad block.
*/
private removeAndDownScoreAllDescendants;
private removePendingPayloadAndDescendants;
private removeAllDescendants;
private getMaxDownloadAttempts;
}
/**
* Class to track active byRoots requests and balance them across eligible peers.
*/
export declare class UnknownBlockPeerBalancer {
readonly peersMeta: Map<PeerIdStr, PeerSyncMeta>;
readonly activeRequests: Map<PeerIdStr, number>;
readonly rateLimitedUntilByPeer: Map<PeerIdStr, number>;
constructor();
/** Trigger on each peer re-status */
onPeerConnected(peerId: PeerIdStr, syncMeta: PeerSyncMeta): void;
onPeerDisconnected(peerId: PeerIdStr): void;
onRateLimited(peerId: PeerIdStr, rateLimitedUntilMs: number): void;
getNextRateLimitRetryAt(pendingColumns?: Set<number>, excludedPeers?: Set<PeerIdStr>): number | null;
/**
* called from fetchBlockInput() where we only have block root and nothing else
* excludedPeers are the peers that we requested already so we don't want to try again
* pendingColumns is empty for prefulu, or the 1st time we we download a block by root
*/
bestPeerForPendingColumns(pendingColumns: Set<number>, excludedPeers: Set<PeerIdStr>): PeerSyncMeta | null;
/**
* Consumers don't need to call this method directly, it is called internally by bestPeer*() methods
* make this public for testing
*/
onRequest(peerId: PeerIdStr): void;
/**
* Consumers should call this method when a request is completed for a peer.
*/
onRequestCompleted(peerId: PeerIdStr): void;
getTotalActiveRequests(): number;
private filterPeers;
private peerHasPendingColumns;
}
//# sourceMappingURL=unknownBlock.d.ts.map