Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions packages/beacon-node/src/api/impl/beacon/blocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import {
ImportBlockOpts,
BlockInput,
BlobsSource,
BlockInputDataBlobs,
BlockInputDataDataColumns,
BlockInputBlobs,
BlockInputDataColumns,
DataColumnsSource,
BlockInputData,
BlockInputAvailableData,
} from "../../../../chain/blocks/types.js";
import {promiseAllMaybeAsync} from "../../../../util/promises.js";
import {isOptimisticBlock} from "../../../../util/forkChoice.js";
Expand Down Expand Up @@ -77,7 +77,7 @@ export function getBeaconBlockApi({
if (isSignedBlockContents(signedBlockOrContents)) {
({signedBlock} = signedBlockOrContents);
const fork = config.getForkName(signedBlock.message.slot);
let blockData: BlockInputData;
let blockData: BlockInputAvailableData;
if (fork === ForkName.peerdas) {
dataColumnSidecars = computeDataColumnSidecars(config, signedBlock, signedBlockOrContents);
blockData = {
Expand All @@ -88,7 +88,7 @@ export function getBeaconBlockApi({
dataColumns: dataColumnSidecars,
dataColumnsBytes: dataColumnSidecars.map(() => null),
dataColumnsSource: DataColumnsSource.api,
} as BlockInputDataDataColumns;
} as BlockInputDataColumns;
blobSidecars = [];
} else if (fork === ForkName.deneb) {
blobSidecars = computeBlobSidecars(config, signedBlock, signedBlockOrContents);
Expand All @@ -97,7 +97,7 @@ export function getBeaconBlockApi({
blobs: blobSidecars,
blobsSource: BlobsSource.api,
blobsBytes: blobSidecars.map(() => null),
} as BlockInputDataBlobs;
} as BlockInputBlobs;
dataColumnSidecars = [];
} else {
throw Error(`Invalid data fork=${fork} for publish`);
Expand Down
135 changes: 91 additions & 44 deletions packages/beacon-node/src/chain/blocks/types.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {CachedBeaconStateAllForks, computeEpochAtSlot} from "@lodestar/state-transition";
import {MaybeValidExecutionStatus, DataAvailabilityStatus} from "@lodestar/fork-choice";
import {deneb, Slot, RootHex, SignedBeaconBlock, peerdas, ColumnIndex} from "@lodestar/types";
import {ForkSeq, ForkName} from "@lodestar/params";
import {ChainForkConfig} from "@lodestar/config";
import type {ChainForkConfig} from "@lodestar/config";
import type {DataAvailabilityStatus, MaybeValidExecutionStatus} from "@lodestar/fork-choice";
import {type ForkName, ForkSeq} from "@lodestar/params";
import {type CachedBeaconStateAllForks, computeEpochAtSlot} from "@lodestar/state-transition";
import type {ColumnIndex, RootHex, SignedBeaconBlock, Slot, deneb, peerdas} from "@lodestar/types";

export enum BlockInputType {
// preData is preDeneb
preData = "preData",
// data is out of available window, can be used to sync forward and keep adding to forkchoice
outOfRangeData = "outOfRangeData",
availableData = "availableData",
dataPromise = "dataPromise",
dataPromise = "data_promise",
}

/** Enum to represent where blocks come from */
Expand All @@ -21,63 +21,110 @@ export enum BlockSource {
byRoot = "req_resp_by_root",
}

export enum GossipedInputType {
block = "block",
blob = "blob",
dataColumn = "data_column",
}

interface CachedDataItem {
cacheId: number;
}
interface Availability<T> {
availabilityPromise: Promise<T>;
resolveAvailability: (data: T) => void;
}

/**
*
* Deneb Blob Format Types
*
*/
/** Enum to represent where blobs come from */
export enum BlobsSource {
gossip = "gossip",
api = "api",
byRange = "req_resp_by_range",
byRoot = "req_resp_by_root",
}
type ForkBlobsInfo = {
fork: ForkName.deneb;
};
type BlobData = {
blobSidecar: deneb.BlobSidecar;
blobBytes: Uint8Array | null;
};
export type BlockInputBlobs = ForkBlobsInfo & {
blobs: deneb.BlobSidecars;
blobsBytes: (Uint8Array | null)[];
blobsSource: BlobsSource;
};
export type BlobsCacheMap = Map<number, BlobData>;
type CachedBlobs = CachedDataItem &
ForkBlobsInfo &
Availability<BlockInputBlobs> & {
blobsCache: BlobsCacheMap;
};

/**
*
* PeerDAS Column Format Types
*
*/
export enum DataColumnsSource {
gossip = "gossip",
api = "api",
byRange = "req_resp_by_range",
byRoot = "req_resp_by_root",
}

export enum GossipedInputType {
block = "block",
blob = "blob",
dataColumn = "dataColumn",
}

export type BlobsCacheMap = Map<number, {blobSidecar: deneb.BlobSidecar; blobBytes: Uint8Array | null}>;
export type DataColumnsCacheMap = Map<
number,
{dataColumnSidecar: peerdas.DataColumnSidecar; dataColumnBytes: Uint8Array | null}
>;

type ForkBlobsInfo = {fork: ForkName.deneb};
type BlobsData = {blobs: deneb.BlobSidecars; blobsBytes: (Uint8Array | null)[]; blobsSource: BlobsSource};
export type BlockInputDataBlobs = ForkBlobsInfo & BlobsData;

type ForkDataColumnsInfo = {fork: ForkName.peerdas};
type DataColumnsData = {
type ForkDataColumnsInfo = {
fork: ForkName.peerdas;
};
type DataColumnData = {
dataColumn: peerdas.DataColumnSidecar;
dataColumnBytes: Uint8Array | null;
};
export type DataColumnsCacheMap = Map<number, DataColumnData>;
export type BlockInputDataColumns = ForkDataColumnsInfo & {
// marker of that columns are to be custodied
dataColumns: peerdas.DataColumnSidecars;
dataColumnsBytes: (Uint8Array | null)[];
dataColumnsSource: DataColumnsSource;
};
export type BlockInputDataDataColumns = ForkDataColumnsInfo & DataColumnsData;
export type BlockInputData = BlockInputDataBlobs | BlockInputDataDataColumns;
type CachedDataColumns = CachedDataItem &
ForkDataColumnsInfo &
Availability<BlockInputDataColumns> & {
dataColumnsCache: DataColumnsCacheMap;
};

type Availability<T> = {availabilityPromise: Promise<T>; resolveAvailability: (data: T) => void};
type CachedBlobs = {blobsCache: BlobsCacheMap} & Availability<BlockInputDataBlobs>;
type CachedDataColumns = {dataColumnsCache: DataColumnsCacheMap} & Availability<BlockInputDataDataColumns>;
export type CachedData = {cacheId: number} & (
| (ForkBlobsInfo & CachedBlobs)
| (ForkDataColumnsInfo & CachedDataColumns)
);
/**
*
* Cross-Fork Data Types
*
*/
export type BlockInputAvailableData = BlockInputBlobs | BlockInputDataColumns;
export type BlockInputCachedData = CachedBlobs | CachedDataColumns;

export type BlockInput = {block: SignedBeaconBlock; source: BlockSource; blockBytes: Uint8Array | null} & (
export type BlockInput = {
block: SignedBeaconBlock;
source: BlockSource;
blockBytes: Uint8Array | null;
} & (
| {type: BlockInputType.preData | BlockInputType.outOfRangeData}
| ({type: BlockInputType.availableData} & {blockData: BlockInputData})
| ({type: BlockInputType.availableData} & {
blockData: BlockInputAvailableData;
})
// the blobsSource here is added to BlockInputBlobs when availability is resolved
| ({type: BlockInputType.dataPromise} & {cachedData: CachedData})
| ({type: BlockInputType.dataPromise} & {
cachedData: BlockInputCachedData;
})
);
export type NullBlockInput = {block: null; blockRootHex: RootHex; blockInputPromise: Promise<BlockInput>} & {
cachedData: CachedData;
export type NullBlockInput = {
block: null;
blockRootHex: RootHex;
blockInputPromise: Promise<BlockInput>;
} & {
cachedData: BlockInputCachedData;
};

export function blockRequiresBlobs(config: ChainForkConfig, blockSlot: Slot, clockSlot: Slot): boolean {
Expand Down Expand Up @@ -134,7 +181,7 @@ export const getBlockInput = {
block: SignedBeaconBlock,
source: BlockSource,
blockBytes: Uint8Array | null,
blockData: BlockInputData
blockData: BlockInputAvailableData
): BlockInput {
if (config.getForkSeq(block.message.slot) < ForkSeq.deneb) {
throw Error(`Pre Deneb block slot ${block.message.slot}`);
Expand All @@ -153,7 +200,7 @@ export const getBlockInput = {
block: SignedBeaconBlock,
source: BlockSource,
blockBytes: Uint8Array | null,
cachedData: CachedData
cachedData: BlockInputCachedData
): BlockInput {
if (config.getForkSeq(block.message.slot) < ForkSeq.deneb) {
throw Error(`Pre Deneb block slot ${block.message.slot}`);
Expand All @@ -168,7 +215,7 @@ export const getBlockInput = {
},
};

export function getBlockInputBlobs(blobsCache: BlobsCacheMap): Omit<BlobsData, "blobsSource"> {
export function getBlockInputBlobs(blobsCache: BlobsCacheMap): Omit<BlockInputBlobs, "fork" | "blobsSource"> {
const blobs = [];
const blobsBytes = [];

Expand All @@ -187,7 +234,7 @@ export function getBlockInputBlobs(blobsCache: BlobsCacheMap): Omit<BlobsData, "
export function getBlockInputDataColumns(
dataColumnsCache: DataColumnsCacheMap,
columnIndexes: ColumnIndex[]
): Omit<DataColumnsData, "dataColumnsLen" | "dataColumnsIndex" | "dataColumnsSource"> {
): Omit<BlockInputDataColumns, "fork" | "dataColumnsSource"> {
const dataColumns = [];
const dataColumnsBytes = [];

Expand All @@ -197,7 +244,7 @@ export function getBlockInputDataColumns(
// check if the index is correct as per the custody columns
throw Error(`Missing dataColumnCache at index=${index}`);
}
const {dataColumnSidecar, dataColumnBytes} = dataColumnCache;
const {dataColumn: dataColumnSidecar, dataColumnBytes} = dataColumnCache;
dataColumns.push(dataColumnSidecar);
dataColumnsBytes.push(dataColumnBytes);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
ImportBlockOpts,
BlobSidecarValidation,
getBlockInput,
BlockInputData,
BlockInputAvailableData,
} from "./types.js";

// we can now wait for full 12 seconds because unavailable block sync will try pulling
Expand Down Expand Up @@ -105,7 +105,7 @@ async function maybeValidateBlobs(
: await raceWithCutoff(
chain,
blockInput,
blockInput.cachedData.availabilityPromise as Promise<BlockInputData>
blockInput.cachedData.availabilityPromise as Promise<BlockInputAvailableData>
);

if (blockData.fork === ForkName.deneb) {
Expand Down
22 changes: 11 additions & 11 deletions packages/beacon-node/src/chain/seenCache/seenGossipBlockInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import {
NullBlockInput,
getBlockInput,
BlockSource,
BlockInputDataBlobs,
CachedData,
BlockInputBlobs,
BlockInputCachedData,
GossipedInputType,
getBlockInputBlobs,
BlobsSource,
DataColumnsSource,
getBlockInputDataColumns,
BlockInputDataDataColumns,
BlockInputDataColumns,
} from "../blocks/types.js";
import {Metrics} from "../../metrics/index.js";
import {CustodyConfig} from "../../util/dataColumns.js";
Expand All @@ -39,7 +39,7 @@ type BlockInputCacheType = {
fork: ForkName;
block?: SignedBeaconBlock;
blockBytes?: Uint8Array | null;
cachedData?: CachedData;
cachedData?: BlockInputCachedData;
// block promise and its callback cached for delayed resolution
blockInputPromise: Promise<BlockInput>;
resolveBlockInput: (blockInput: BlockInput) => void;
Expand Down Expand Up @@ -134,7 +134,7 @@ export class SeenGossipBlockInput {

// TODO: freetheblobs check if its the same blob or a duplicate and throw/take actions
blockCache.cachedData?.dataColumnsCache.set(dataColumnSidecar.index, {
dataColumnSidecar,
dataColumn: dataColumnSidecar,
// easily splice out the unsigned message as blob is a fixed length type
dataColumnBytes: dataColumnBytes?.slice(0, dataColumnBytes.length) ?? null,
});
Expand Down Expand Up @@ -369,8 +369,8 @@ export function getEmptyBlockInputCacheEntry(fork: ForkName, globalCacheId: numb
}

if (fork === ForkName.deneb) {
let resolveAvailability: ((blobs: BlockInputDataBlobs) => void) | null = null;
const availabilityPromise = new Promise<BlockInputDataBlobs>((resolveCB) => {
let resolveAvailability: ((blobs: BlockInputBlobs) => void) | null = null;
const availabilityPromise = new Promise<BlockInputBlobs>((resolveCB) => {
resolveAvailability = resolveCB;
});

Expand All @@ -379,7 +379,7 @@ export function getEmptyBlockInputCacheEntry(fork: ForkName, globalCacheId: numb
}

const blobsCache = new Map();
const cachedData: CachedData = {
const cachedData: BlockInputCachedData = {
fork,
blobsCache,
availabilityPromise,
Expand All @@ -388,8 +388,8 @@ export function getEmptyBlockInputCacheEntry(fork: ForkName, globalCacheId: numb
};
return {fork, blockInputPromise, resolveBlockInput, cachedData};
} else if (fork === ForkName.peerdas) {
let resolveAvailability: ((blobs: BlockInputDataDataColumns) => void) | null = null;
const availabilityPromise = new Promise<BlockInputDataDataColumns>((resolveCB) => {
let resolveAvailability: ((blobs: BlockInputDataColumns) => void) | null = null;
const availabilityPromise = new Promise<BlockInputDataColumns>((resolveCB) => {
resolveAvailability = resolveCB;
});

Expand All @@ -398,7 +398,7 @@ export function getEmptyBlockInputCacheEntry(fork: ForkName, globalCacheId: numb
}

const dataColumnsCache = new Map();
const cachedData: CachedData = {
const cachedData: BlockInputCachedData = {
fork,
dataColumnsCache,
availabilityPromise,
Expand Down
Loading