@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
222 lines • 8.4 kB
TypeScript
import { ChainForkConfig } from "@lodestar/config";
import { ForkName } from "@lodestar/params";
import { Epoch, RootHex, Slot, gloas } from "@lodestar/types";
import { LodestarError } from "@lodestar/utils";
import { IBlockInput } from "../../chain/blocks/blockInput/types.js";
import { PayloadEnvelopeInput } from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
import { PeerSyncMeta } from "../../network/peers/peersData.js";
import { IClock } from "../../util/clock.js";
import { CustodyConfig } from "../../util/dataColumns.js";
import { PeerIdStr } from "../../util/peerId.js";
import { DownloadByRangeRequests, ParentPayloadCommitments } from "../utils/downloadByRange.js";
/**
* Current state of a batch
*/
export declare enum BatchStatus {
/** The batch has failed either downloading or processing, but can be requested again. */
AwaitingDownload = "AwaitingDownload",
/** The batch is being downloaded. */
Downloading = "Downloading",
/** The batch has been completely downloaded and is ready for processing. */
AwaitingProcessing = "AwaitingProcessing",
/** The batch is being processed. */
Processing = "Processing",
/**
* The batch was successfully processed and is waiting to be validated.
*
* It is not sufficient to process a batch successfully to consider it correct. This is
* because batches could be erroneously empty, or incomplete. Therefore, a batch is considered
* valid, only if the next sequential batch imports at least a block.
*/
AwaitingValidation = "AwaitingValidation"
}
export type Attempt = {
/** The peer that made the attempt */
peers: PeerIdStr[];
/** The hash of the blocks of the attempt */
hash: RootHex;
};
type TrackedRequest = {
/** only happen for the 1st batch in checkpoint sync */
parentPayload: boolean;
/**
* we always issue by_range before parent_payload, so we don't model this as null
*/
byRangeColumns: Set<number>;
};
export type AwaitingDownloadState = {
status: BatchStatus.AwaitingDownload;
blocks: IBlockInput[];
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
};
export type DownloadSuccessState = {
status: BatchStatus.AwaitingProcessing;
blocks: IBlockInput[];
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
};
export type BatchState = AwaitingDownloadState | {
status: BatchStatus.Downloading;
peer: PeerIdStr;
request: TrackedRequest;
blocks: IBlockInput[];
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
} | DownloadSuccessState | {
status: BatchStatus.Processing;
blocks: IBlockInput[];
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
attempt: Attempt;
} | {
status: BatchStatus.AwaitingValidation;
blocks: IBlockInput[];
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
attempt: Attempt;
};
export type BatchMetadata = {
startEpoch: Epoch;
startSlot: Slot;
count: number;
status: BatchStatus;
blocksReq?: string;
blobsReq?: string;
columnsReq?: string;
envelopesReq?: string;
downloadAttempts: number;
processingAttempts: number;
failedDownloadPeers?: string;
failedProcessingPeers?: string;
};
/**
* Batches are downloaded at the first block of the epoch.
*
* For example:
*
* Epoch boundary | |
* ... | 30 | 31 | 32 | 33 | 34 | ... | 61 | 62 | 63 | 64 | 65 |
* Batch 1 | Batch 2 | Batch 3
*
* Jul2022: Offset changed from 1 to 0, see rationale in {@link BATCH_SLOT_OFFSET}
*/
export declare class Batch {
readonly forkName: ForkName;
readonly startEpoch: Epoch;
readonly startSlot: Slot;
readonly count: number;
/** Block, blob and column requests that are used to determine the best peer and are used in downloadByRange */
requests: DownloadByRangeRequests;
/** State of the batch. */
state: BatchState;
/** Peers that provided good data, with column coverage for by_range requests */
private readonly successfulDownloads;
/** The `Attempts` that have been made and failed to send us this batch. */
readonly failedProcessingAttempts: Attempt[];
/** The `Attempts` that have been made and failed because of execution malfunction. */
readonly executionErrorAttempts: Attempt[];
/** The number of download retries this batch has undergone due to a failed request. */
private readonly failedDownloadAttempts;
private readonly config;
private readonly clock;
private readonly custodyConfig;
private readonly isFirstBatchInChain;
private readonly latestBid;
constructor(startEpoch: Epoch, config: ChainForkConfig, clock: IClock, custodyConfig: CustodyConfig, isFirstBatchInChain: boolean, latestBid: gloas.ExecutionPayloadBid | undefined, targetSlot: Slot);
private shouldDownloadParentEnvelope;
getParentPayloadCommitments(parentBlockRoot: Uint8Array): ParentPayloadCommitments;
/**
* Builds ByRange requests for block, blobs and columns
*/
private getRequests;
/**
* Post-fulu we should only get columns that peer has advertised
*/
getRequestsForPeer(peer: PeerSyncMeta): DownloadByRangeRequests;
/**
* Gives a list of peers from which this batch has had a failed download or processing attempt.
*/
getFailedPeers(): PeerIdStr[];
/**
* True only if the peer has already returned a successful response for the current request.
* A by_range success may update `this.requests` to parent_payload, and the same peer is then
* still eligible for the newly discovered parent payload data.
* For by_range, a peer that previously succeeded with a superset of requested columns is skipped.
*/
hasPeerSucceededCurrentRequest(peer: PeerSyncMeta): boolean;
private getSuccessfulPeers;
getMetadata(): BatchMetadata;
getBlocks(): IBlockInput[];
getPayloadEnvelopes(): Map<Slot, PayloadEnvelopeInput> | null;
/**
* AwaitingDownload -> Downloading
*/
startDownloading(peer: PeerSyncMeta): void;
/**
* Downloading -> AwaitingProcessing
*/
downloadingSuccess(peer: PeerIdStr, blocks: IBlockInput[], payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null): DownloadSuccessState;
/**
* Downloading -> AwaitingDownload
*/
downloadingError(peer: PeerIdStr): void;
/**
* Downloading -> AwaitingDownload (without counting as a failed attempt).
* Used when the peer rate-limited us — the request was never actually served.
*/
downloadingRateLimited(): void;
/**
* AwaitingProcessing -> Processing
*/
startProcessing(): {
blocks: IBlockInput[];
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
peers: PeerIdStr[];
};
/**
* Processing -> AwaitingValidation
*/
processingSuccess(): void;
/**
* Processing -> AwaitingDownload
*/
processingError(err: Error): void;
/**
* AwaitingValidation -> AwaitingDownload
*/
validationError(err: Error): void;
/**
* AwaitingValidation -> Done
*/
validationSuccess(): Attempt;
private onExecutionEngineError;
private onProcessingError;
/** Helper to construct typed BatchError. Stack traces are correct as the error is thrown above */
private errorType;
private wrongStatusErrorType;
}
export declare enum BatchErrorCode {
WRONG_STATUS = "BATCH_ERROR_WRONG_STATUS",
INVALID_COUNT = "BATCH_ERROR_INVALID_COUNT",
MAX_DOWNLOAD_ATTEMPTS = "BATCH_ERROR_MAX_DOWNLOAD_ATTEMPTS",
MAX_PROCESSING_ATTEMPTS = "BATCH_ERROR_MAX_PROCESSING_ATTEMPTS",
MAX_EXECUTION_ENGINE_ERROR_ATTEMPTS = "MAX_EXECUTION_ENGINE_ERROR_ATTEMPTS"
}
type BatchErrorType = {
code: BatchErrorCode.WRONG_STATUS;
expectedStatus: BatchStatus;
} | {
code: BatchErrorCode.INVALID_COUNT;
count: number;
expected: number;
} | {
code: BatchErrorCode.MAX_DOWNLOAD_ATTEMPTS;
} | {
code: BatchErrorCode.MAX_PROCESSING_ATTEMPTS;
} | {
code: BatchErrorCode.MAX_EXECUTION_ENGINE_ERROR_ATTEMPTS;
};
type BatchErrorMetadata = {
startEpoch: number;
status: BatchStatus;
};
export declare class BatchError extends LodestarError<BatchErrorType & BatchErrorMetadata> {
}
export {};
//# sourceMappingURL=batch.d.ts.map