@lodestar/beacon-node 1.48.0-dev.baa28132d2 → 1.48.0-dev.bb3ffba9e9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +4 -4
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +39 -39
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -0
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +12 -1
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
- package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +4 -1
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +31 -34
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +0 -13
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +3 -2
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +10 -1
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +9 -16
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +9 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +127 -73
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +1 -1
- package/lib/chain/emitter.js +1 -1
- package/lib/chain/errors/blockError.d.ts +19 -7
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +2 -2
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts +15 -2
- package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +10 -11
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +0 -2
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +13 -13
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +46 -64
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +35 -54
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +38 -13
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +10 -29
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +7 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +22 -5
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/beacon.d.ts +14 -5
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +17 -3
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/dataColumnStore.d.ts +39 -0
- package/lib/db/dataColumnStore.d.ts.map +1 -0
- package/lib/db/dataColumnStore.js +81 -0
- package/lib/db/dataColumnStore.js.map +1 -0
- package/lib/db/flatFileStore/atomicWrite.d.ts +8 -0
- package/lib/db/flatFileStore/atomicWrite.d.ts.map +1 -0
- package/lib/db/flatFileStore/atomicWrite.js +61 -0
- package/lib/db/flatFileStore/atomicWrite.js.map +1 -0
- package/lib/db/flatFileStore/dcolFormat.d.ts +90 -0
- package/lib/db/flatFileStore/dcolFormat.d.ts.map +1 -0
- package/lib/db/flatFileStore/dcolFormat.js +286 -0
- package/lib/db/flatFileStore/dcolFormat.js.map +1 -0
- package/lib/db/flatFileStore/errors.d.ts +82 -0
- package/lib/db/flatFileStore/errors.d.ts.map +1 -0
- package/lib/db/flatFileStore/errors.js +32 -0
- package/lib/db/flatFileStore/errors.js.map +1 -0
- package/lib/db/flatFileStore/flatFileStore.d.ts +41 -0
- package/lib/db/flatFileStore/flatFileStore.d.ts.map +1 -0
- package/lib/db/flatFileStore/flatFileStore.js +251 -0
- package/lib/db/flatFileStore/flatFileStore.js.map +1 -0
- package/lib/db/flatFileStore/index.d.ts +4 -0
- package/lib/db/flatFileStore/index.d.ts.map +1 -0
- package/lib/db/flatFileStore/index.js +2 -0
- package/lib/db/flatFileStore/index.js.map +1 -0
- package/lib/db/flatFileStore/interface.d.ts +25 -0
- package/lib/db/flatFileStore/interface.d.ts.map +1 -0
- package/lib/db/flatFileStore/interface.js +2 -0
- package/lib/db/flatFileStore/interface.js.map +1 -0
- package/lib/db/flatFileStore/metrics.d.ts +24 -0
- package/lib/db/flatFileStore/metrics.d.ts.map +1 -0
- package/lib/db/flatFileStore/metrics.js +25 -0
- package/lib/db/flatFileStore/metrics.js.map +1 -0
- package/lib/db/flatFileStore/path.d.ts +9 -0
- package/lib/db/flatFileStore/path.d.ts.map +1 -0
- package/lib/db/flatFileStore/path.js +21 -0
- package/lib/db/flatFileStore/path.js.map +1 -0
- package/lib/db/flatFileStore/slotIndex.d.ts +14 -0
- package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -0
- package/lib/db/flatFileStore/slotIndex.js +46 -0
- package/lib/db/flatFileStore/slotIndex.js.map +1 -0
- package/lib/db/flatFileStore/snappy.d.ts +3 -0
- package/lib/db/flatFileStore/snappy.d.ts.map +1 -0
- package/lib/db/flatFileStore/snappy.js +12 -0
- package/lib/db/flatFileStore/snappy.js.map +1 -0
- package/lib/db/index.d.ts +1 -0
- package/lib/db/index.d.ts.map +1 -1
- package/lib/db/interface.d.ts +8 -1
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.d.ts +8 -1
- package/lib/db/repositories/blockArchive.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +65 -28
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +1 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.js +3 -7
- package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +4 -1
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +18 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +55 -1
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/monitoring/clientStats.js +1 -1
- package/lib/monitoring/clientStats.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +0 -7
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +2 -1
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +4 -20
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +6 -7
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +49 -3
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +232 -98
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +112 -91
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +2 -0
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +6 -22
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/lib/network/reqresp/rateLimit.js +2 -1
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +2 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js +14 -9
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
- package/lib/node/nodejs.d.ts +2 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/util/sszBytes.d.ts +6 -0
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +1 -1
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +18 -19
- package/src/api/impl/beacon/blocks/index.ts +8 -4
- package/src/api/impl/validator/index.ts +44 -43
- package/src/chain/archiveStore/archiveStore.ts +6 -1
- package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -0
- package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
- package/src/chain/archiveStore/historicalState/types.ts +2 -0
- package/src/chain/archiveStore/historicalState/worker.ts +4 -1
- package/src/chain/archiveStore/utils/archiveBlocks.ts +34 -39
- package/src/chain/blocks/importBlock.ts +0 -13
- package/src/chain/blocks/index.ts +13 -2
- package/src/chain/blocks/utils/chainSegment.ts +10 -1
- package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
- package/src/chain/chain.ts +149 -80
- package/src/chain/emitter.ts +1 -1
- package/src/chain/errors/blockError.ts +22 -10
- package/src/chain/errors/dataColumnSidecarError.ts +24 -8
- package/src/chain/errors/executionPayloadEnvelope.ts +14 -11
- package/src/chain/interface.ts +2 -2
- package/src/chain/prepareNextSlot.ts +16 -16
- package/src/chain/produceBlock/produceBlockBody.ts +50 -71
- package/src/chain/validation/block.ts +35 -70
- package/src/chain/validation/dataColumnSidecar.ts +47 -14
- package/src/chain/validation/executionPayloadEnvelope.ts +10 -37
- package/src/chain/validatorMonitor.ts +24 -7
- package/src/db/beacon.ts +33 -6
- package/src/db/dataColumnStore.ts +113 -0
- package/src/db/flatFileStore/atomicWrite.ts +65 -0
- package/src/db/flatFileStore/dcolFormat.ts +389 -0
- package/src/db/flatFileStore/errors.ts +53 -0
- package/src/db/flatFileStore/flatFileStore.ts +310 -0
- package/src/db/flatFileStore/index.ts +3 -0
- package/src/db/flatFileStore/interface.ts +21 -0
- package/src/db/flatFileStore/metrics.ts +48 -0
- package/src/db/flatFileStore/path.ts +32 -0
- package/src/db/flatFileStore/slotIndex.ts +56 -0
- package/src/db/flatFileStore/snappy.ts +14 -0
- package/src/db/index.ts +1 -0
- package/src/db/interface.ts +9 -1
- package/src/db/repositories/blockArchive.ts +89 -30
- package/src/db/repositories/blockArchiveIndex.ts +4 -9
- package/src/execution/engine/mock.ts +4 -1
- package/src/metrics/metrics/lodestar.ts +57 -1
- package/src/monitoring/clientStats.ts +1 -1
- package/src/network/gossip/encoding.ts +0 -7
- package/src/network/gossip/topic.ts +3 -25
- package/src/network/processor/gossipHandlers.ts +11 -11
- package/src/network/processor/index.ts +263 -148
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +139 -105
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +2 -0
- package/src/network/reqresp/protocols.ts +7 -24
- package/src/network/reqresp/rateLimit.ts +2 -1
- package/src/network/reqresp/utils/dataColumnResponseValidation.ts +15 -7
- package/src/node/nodejs.ts +6 -1
- package/src/util/sszBytes.ts +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {LodestarError} from "@lodestar/utils";
|
|
2
|
+
|
|
3
|
+
export enum DataColumnStoreErrorCode {
|
|
4
|
+
INVALID_ROOT = "DATA_COLUMN_STORE_INVALID_ROOT",
|
|
5
|
+
INVALID_SLOT = "DATA_COLUMN_STORE_INVALID_SLOT",
|
|
6
|
+
SLOT_OUT_OF_RANGE = "DATA_COLUMN_STORE_SLOT_OUT_OF_RANGE",
|
|
7
|
+
INVALID_BITMAP_LENGTH = "DATA_COLUMN_STORE_INVALID_BITMAP_LENGTH",
|
|
8
|
+
INVALID_BLOCK_ROOT_LENGTH = "DATA_COLUMN_STORE_INVALID_BLOCK_ROOT_LENGTH",
|
|
9
|
+
FILE_TOO_SMALL = "DATA_COLUMN_STORE_FILE_TOO_SMALL",
|
|
10
|
+
UNSUPPORTED_VERSION = "DATA_COLUMN_STORE_UNSUPPORTED_VERSION",
|
|
11
|
+
EMPTY_COLUMNS = "DATA_COLUMN_STORE_EMPTY_COLUMNS",
|
|
12
|
+
INVALID_COLUMN_INDEX = "DATA_COLUMN_STORE_INVALID_COLUMN_INDEX",
|
|
13
|
+
DUPLICATE_COLUMN_INDEX = "DATA_COLUMN_STORE_DUPLICATE_COLUMN_INDEX",
|
|
14
|
+
INVALID_OFFSET_TABLE = "DATA_COLUMN_STORE_INVALID_OFFSET_TABLE",
|
|
15
|
+
SLOT_PRUNED = "DATA_COLUMN_STORE_SLOT_PRUNED",
|
|
16
|
+
SLOT_MISMATCH = "DATA_COLUMN_STORE_SLOT_MISMATCH",
|
|
17
|
+
ROOT_MISMATCH = "DATA_COLUMN_STORE_ROOT_MISMATCH",
|
|
18
|
+
UNEXPECTED_EOF = "DATA_COLUMN_STORE_UNEXPECTED_EOF",
|
|
19
|
+
OPERATION_FAILED = "DATA_COLUMN_STORE_OPERATION_FAILED",
|
|
20
|
+
BATCH_DELETE_FAILED = "DATA_COLUMN_STORE_BATCH_DELETE_FAILED",
|
|
21
|
+
STARTUP_FAILED = "DATA_COLUMN_STORE_STARTUP_FAILED",
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type DataColumnStoreErrorType =
|
|
25
|
+
| {code: DataColumnStoreErrorCode.INVALID_ROOT; root: string}
|
|
26
|
+
| {code: DataColumnStoreErrorCode.INVALID_SLOT; slot: number}
|
|
27
|
+
| {code: DataColumnStoreErrorCode.SLOT_OUT_OF_RANGE}
|
|
28
|
+
| {code: DataColumnStoreErrorCode.INVALID_BITMAP_LENGTH; length: number}
|
|
29
|
+
| {code: DataColumnStoreErrorCode.INVALID_BLOCK_ROOT_LENGTH; length: number}
|
|
30
|
+
| {code: DataColumnStoreErrorCode.FILE_TOO_SMALL; actual: number; minimum: number}
|
|
31
|
+
| {code: DataColumnStoreErrorCode.UNSUPPORTED_VERSION; version: number}
|
|
32
|
+
| {code: DataColumnStoreErrorCode.EMPTY_COLUMNS}
|
|
33
|
+
| {code: DataColumnStoreErrorCode.INVALID_COLUMN_INDEX; index: number}
|
|
34
|
+
| {code: DataColumnStoreErrorCode.DUPLICATE_COLUMN_INDEX; index: number}
|
|
35
|
+
| {code: DataColumnStoreErrorCode.INVALID_OFFSET_TABLE; reason: string}
|
|
36
|
+
| {code: DataColumnStoreErrorCode.SLOT_PRUNED; slot: number; minRetainedSlot: number}
|
|
37
|
+
| {code: DataColumnStoreErrorCode.SLOT_MISMATCH; headerSlot: number; pathSlot: number}
|
|
38
|
+
| {code: DataColumnStoreErrorCode.ROOT_MISMATCH; headerRoot: string; pathRoot: string}
|
|
39
|
+
| {code: DataColumnStoreErrorCode.UNEXPECTED_EOF; offset: number}
|
|
40
|
+
| {code: DataColumnStoreErrorCode.OPERATION_FAILED; operation: string}
|
|
41
|
+
| {code: DataColumnStoreErrorCode.BATCH_DELETE_FAILED; failures: number}
|
|
42
|
+
| {code: DataColumnStoreErrorCode.STARTUP_FAILED};
|
|
43
|
+
|
|
44
|
+
export class DataColumnStoreError extends LodestarError<DataColumnStoreErrorType> {
|
|
45
|
+
constructor(type: DataColumnStoreErrorType, message?: string, cause?: unknown) {
|
|
46
|
+
super(type, message);
|
|
47
|
+
this.cause = cause;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isFsNotFoundError(error: unknown): boolean {
|
|
52
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
53
|
+
}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {ChainForkConfig} from "@lodestar/config";
|
|
4
|
+
import {ForkPostFulu} from "@lodestar/params";
|
|
5
|
+
import {DataColumnSidecar, RootHex, Slot} from "@lodestar/types";
|
|
6
|
+
import {Logger, fromHex, toRootHex} from "@lodestar/utils";
|
|
7
|
+
import {atomicWrite, mkdirDurable} from "./atomicWrite.js";
|
|
8
|
+
import {
|
|
9
|
+
DCOL_HEADER_SIZE,
|
|
10
|
+
type DcolHeader,
|
|
11
|
+
encodeDcolFile,
|
|
12
|
+
getColumnByteRange,
|
|
13
|
+
mergeDcolColumns,
|
|
14
|
+
offsetTableSize,
|
|
15
|
+
parseDcolHeader,
|
|
16
|
+
parseDcolOffsets,
|
|
17
|
+
readAllColumns,
|
|
18
|
+
totalBits,
|
|
19
|
+
} from "./dcolFormat.js";
|
|
20
|
+
import {DataColumnStoreError, DataColumnStoreErrorCode, isFsNotFoundError} from "./errors.js";
|
|
21
|
+
import type {IFlatFileStore} from "./interface.js";
|
|
22
|
+
import {type FlatFileStoreMetrics, FlatFileStoreOperation, observeFlatFileStoreOperation} from "./metrics.js";
|
|
23
|
+
import {assertValidRootHex, padSlot} from "./path.js";
|
|
24
|
+
import {SlotIndex} from "./slotIndex.js";
|
|
25
|
+
import {uncompress} from "./snappy.js";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Filesystem storage for data columns, keyed by slot and block root.
|
|
29
|
+
* Hot and finalized data share the same layout. The top-level slot index is rebuilt on startup
|
|
30
|
+
* without inspecting the contents of slot directories.
|
|
31
|
+
* Per-slot mutation locking coordinates incremental writes, deletion, and pruning.
|
|
32
|
+
*/
|
|
33
|
+
export class FlatFileStore implements IFlatFileStore {
|
|
34
|
+
private readonly slotIndex = new SlotIndex();
|
|
35
|
+
private readonly mutationLocks = new Map<Slot, Promise<void>>();
|
|
36
|
+
private minRetainedSlot: Slot = 0;
|
|
37
|
+
private metrics: FlatFileStoreMetrics | null = null;
|
|
38
|
+
|
|
39
|
+
constructor(
|
|
40
|
+
private readonly dataColumnDir: string,
|
|
41
|
+
private readonly config: ChainForkConfig,
|
|
42
|
+
private readonly logger: Logger,
|
|
43
|
+
metrics: FlatFileStoreMetrics | null = null
|
|
44
|
+
) {
|
|
45
|
+
this.setMetrics(metrics);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
setMetrics(metrics: FlatFileStoreMetrics | null): void {
|
|
49
|
+
if (metrics === this.metrics) return;
|
|
50
|
+
this.metrics = metrics;
|
|
51
|
+
metrics?.slotIndexSize.addCollect((metric) => metric.set(this.slotIndex.size));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async init(): Promise<void> {
|
|
55
|
+
const endTimer = this.metrics?.startupDuration.startTimer();
|
|
56
|
+
try {
|
|
57
|
+
await mkdirDurable(this.dataColumnDir);
|
|
58
|
+
const stats = await this.slotIndex.rebuildFromDisk(this.dataColumnDir);
|
|
59
|
+
if (stats.ignoredEntries > 0) {
|
|
60
|
+
this.logger.warn("Ignored non-canonical flat file store entries", {
|
|
61
|
+
entries: stats.ignoredEntries,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
this.logger.info("Flat file store initialized", {
|
|
65
|
+
slots: stats.slots,
|
|
66
|
+
});
|
|
67
|
+
} catch (e) {
|
|
68
|
+
this.metrics?.startupErrors.inc();
|
|
69
|
+
if (e instanceof DataColumnStoreError) {
|
|
70
|
+
throw e;
|
|
71
|
+
}
|
|
72
|
+
throw new DataColumnStoreError(
|
|
73
|
+
{code: DataColumnStoreErrorCode.STARTUP_FAILED},
|
|
74
|
+
"Flat file store initialization failed",
|
|
75
|
+
e
|
|
76
|
+
);
|
|
77
|
+
} finally {
|
|
78
|
+
endTimer?.();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async close(): Promise<void> {
|
|
83
|
+
// All operations are stateless file I/O.
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async getDataColumns(slot: Slot, blockRoot: RootHex): Promise<DataColumnSidecar[]> {
|
|
87
|
+
return observeFlatFileStoreOperation(this.metrics, FlatFileStoreOperation.read, async () => {
|
|
88
|
+
const data = await this.readFile(slot, blockRoot);
|
|
89
|
+
if (!data) return [];
|
|
90
|
+
|
|
91
|
+
this.metrics?.readBytes.inc(data.length);
|
|
92
|
+
const header = parseDcolHeader(data);
|
|
93
|
+
validateDcolHeader(header, slot, blockRoot);
|
|
94
|
+
const columns = readAllColumns(data, header);
|
|
95
|
+
const dataColumnSidecarType = this.config.getForkTypes<ForkPostFulu>(slot).DataColumnSidecar;
|
|
96
|
+
|
|
97
|
+
return columns.map((col) => dataColumnSidecarType.deserialize(col.data));
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async getDataColumnsBinary(
|
|
102
|
+
slot: Slot,
|
|
103
|
+
blockRoot: RootHex,
|
|
104
|
+
indices: number[]
|
|
105
|
+
): Promise<(Uint8Array | undefined)[] | null> {
|
|
106
|
+
return observeFlatFileStoreOperation(this.metrics, FlatFileStoreOperation.read, () =>
|
|
107
|
+
this.getColumnsBinaryUninstrumented(slot, blockRoot, indices)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async putDataColumnsBinary(
|
|
112
|
+
slot: Slot,
|
|
113
|
+
blockRoot: RootHex,
|
|
114
|
+
columns: {index: number; data: Uint8Array}[]
|
|
115
|
+
): Promise<void> {
|
|
116
|
+
const rootBytes = fromHex(blockRoot);
|
|
117
|
+
if (columns.length === 0) return;
|
|
118
|
+
|
|
119
|
+
await observeFlatFileStoreOperation(this.metrics, FlatFileStoreOperation.write, async () => {
|
|
120
|
+
const release = await this.acquireMutationLock(slot);
|
|
121
|
+
try {
|
|
122
|
+
if (slot < this.minRetainedSlot) {
|
|
123
|
+
throw new DataColumnStoreError(
|
|
124
|
+
{code: DataColumnStoreErrorCode.SLOT_PRUNED, slot, minRetainedSlot: this.minRetainedSlot},
|
|
125
|
+
`Cannot write pruned data column slot=${slot} minRetainedSlot=${this.minRetainedSlot}`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const existing = await this.readFile(slot, blockRoot);
|
|
129
|
+
let fileData: Uint8Array;
|
|
130
|
+
|
|
131
|
+
if (existing) {
|
|
132
|
+
this.metrics?.readBytes.inc(existing.length);
|
|
133
|
+
const header = parseDcolHeader(existing);
|
|
134
|
+
validateDcolHeader(header, slot, blockRoot);
|
|
135
|
+
fileData = mergeDcolColumns(existing, columns);
|
|
136
|
+
} else {
|
|
137
|
+
fileData = encodeDcolFile(rootBytes, slot, columns);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// The rename can succeed even if syncing its directory fails.
|
|
141
|
+
this.slotIndex.add(slot);
|
|
142
|
+
await atomicWrite(this.filePath(slot, blockRoot), fileData);
|
|
143
|
+
this.metrics?.writeBytes.inc(fileData.length);
|
|
144
|
+
} finally {
|
|
145
|
+
release();
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async deleteMany(items: {slot: Slot; blockRoot: RootHex}[]): Promise<void> {
|
|
151
|
+
const results = await Promise.allSettled(items.map(({slot, blockRoot}) => this.delete(slot, blockRoot)));
|
|
152
|
+
const errors = results
|
|
153
|
+
.filter((result): result is PromiseRejectedResult => result.status === "rejected")
|
|
154
|
+
.map((result) => result.reason);
|
|
155
|
+
if (errors.length > 0) {
|
|
156
|
+
throw new DataColumnStoreError(
|
|
157
|
+
{code: DataColumnStoreErrorCode.BATCH_DELETE_FAILED, failures: errors.length},
|
|
158
|
+
"Failed to delete flat file data",
|
|
159
|
+
new AggregateError(errors)
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async pruneBefore(minSlot: Slot): Promise<Slot[]> {
|
|
165
|
+
return observeFlatFileStoreOperation(this.metrics, FlatFileStoreOperation.prune, async () => {
|
|
166
|
+
this.minRetainedSlot = Math.max(this.minRetainedSlot, minSlot);
|
|
167
|
+
const slotsToPrune = new Set(this.slotIndex.getBefore(this.minRetainedSlot));
|
|
168
|
+
for (const slot of this.mutationLocks.keys()) {
|
|
169
|
+
if (slot < this.minRetainedSlot) slotsToPrune.add(slot);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
for (const slot of slotsToPrune) {
|
|
173
|
+
const release = await this.acquireMutationLock(slot);
|
|
174
|
+
try {
|
|
175
|
+
await fs.promises.rm(path.join(this.dataColumnDir, padSlot(slot)), {recursive: true, force: true});
|
|
176
|
+
this.slotIndex.remove(slot);
|
|
177
|
+
this.metrics?.prunedDirectories.inc();
|
|
178
|
+
} finally {
|
|
179
|
+
release();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return [...slotsToPrune].sort((a, b) => a - b);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private filePath(slot: Slot, rootHex: RootHex): string {
|
|
187
|
+
assertValidRootHex(rootHex);
|
|
188
|
+
return path.join(this.dataColumnDir, padSlot(slot), `${rootHex}.dcol`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private acquireMutationLock(slot: Slot): Promise<() => void> {
|
|
192
|
+
let release!: () => void;
|
|
193
|
+
const prev = this.mutationLocks.get(slot) ?? Promise.resolve();
|
|
194
|
+
const next = new Promise<void>((resolve) => {
|
|
195
|
+
release = resolve;
|
|
196
|
+
});
|
|
197
|
+
const chained = prev.then(() => next);
|
|
198
|
+
this.mutationLocks.set(slot, chained);
|
|
199
|
+
|
|
200
|
+
return prev.then(() => {
|
|
201
|
+
let released = false;
|
|
202
|
+
return () => {
|
|
203
|
+
if (released) return;
|
|
204
|
+
released = true;
|
|
205
|
+
release();
|
|
206
|
+
if (this.mutationLocks.get(slot) === chained) {
|
|
207
|
+
this.mutationLocks.delete(slot);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private async readFile(slot: Slot, rootHex: RootHex): Promise<Uint8Array | null> {
|
|
214
|
+
try {
|
|
215
|
+
return await fs.promises.readFile(this.filePath(slot, rootHex));
|
|
216
|
+
} catch (e) {
|
|
217
|
+
if (!isFsNotFoundError(e)) throw e;
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private async getColumnsBinaryUninstrumented(
|
|
223
|
+
slot: Slot,
|
|
224
|
+
rootHex: RootHex,
|
|
225
|
+
indices: number[]
|
|
226
|
+
): Promise<(Uint8Array | undefined)[] | null> {
|
|
227
|
+
let fd: fs.promises.FileHandle;
|
|
228
|
+
try {
|
|
229
|
+
fd = await fs.promises.open(this.filePath(slot, rootHex), "r");
|
|
230
|
+
} catch (e) {
|
|
231
|
+
if (!isFsNotFoundError(e)) throw e;
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
const headerBuf = new Uint8Array(DCOL_HEADER_SIZE);
|
|
237
|
+
await readExactly(fd, headerBuf, 0);
|
|
238
|
+
this.metrics?.readBytes.inc(headerBuf.length);
|
|
239
|
+
const header = parseDcolHeader(headerBuf);
|
|
240
|
+
validateDcolHeader(header, slot, rootHex);
|
|
241
|
+
|
|
242
|
+
const N = totalBits(header.bitmap);
|
|
243
|
+
const tableSize = offsetTableSize(N);
|
|
244
|
+
const offsetTable = new Uint8Array(tableSize);
|
|
245
|
+
await readExactly(fd, offsetTable, DCOL_HEADER_SIZE);
|
|
246
|
+
this.metrics?.readBytes.inc(offsetTable.length);
|
|
247
|
+
const fileSize = (await fd.stat()).size;
|
|
248
|
+
const offsets = parseDcolOffsets(offsetTable, N, fileSize - DCOL_HEADER_SIZE - tableSize);
|
|
249
|
+
|
|
250
|
+
const results: (Uint8Array | undefined)[] = [];
|
|
251
|
+
for (const idx of indices) {
|
|
252
|
+
const range = getColumnByteRange(header, offsets, idx);
|
|
253
|
+
if (!range) {
|
|
254
|
+
results.push(undefined);
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
const buf = new Uint8Array(range.length);
|
|
258
|
+
await readExactly(fd, buf, range.offset);
|
|
259
|
+
this.metrics?.readBytes.inc(buf.length);
|
|
260
|
+
results.push(uncompress(buf));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return results;
|
|
264
|
+
} finally {
|
|
265
|
+
await fd.close();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private async delete(slot: Slot, rootHex: RootHex): Promise<void> {
|
|
270
|
+
await observeFlatFileStoreOperation(this.metrics, FlatFileStoreOperation.delete, async () => {
|
|
271
|
+
const release = await this.acquireMutationLock(slot);
|
|
272
|
+
try {
|
|
273
|
+
await fs.promises.rm(this.filePath(slot, rootHex), {force: true});
|
|
274
|
+
} finally {
|
|
275
|
+
release();
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function validateDcolHeader(header: DcolHeader, slot: Slot, rootHex: RootHex): void {
|
|
282
|
+
if (header.slot !== slot) {
|
|
283
|
+
throw new DataColumnStoreError(
|
|
284
|
+
{code: DataColumnStoreErrorCode.SLOT_MISMATCH, headerSlot: header.slot, pathSlot: slot},
|
|
285
|
+
`Dcol slot mismatch: header=${header.slot} path=${slot}`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
const headerRoot = toRootHex(header.blockRoot);
|
|
289
|
+
if (headerRoot !== rootHex) {
|
|
290
|
+
throw new DataColumnStoreError(
|
|
291
|
+
{code: DataColumnStoreErrorCode.ROOT_MISMATCH, headerRoot, pathRoot: rootHex},
|
|
292
|
+
`Dcol block root mismatch: header=${headerRoot} path=${rootHex}`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async function readExactly(fd: fs.promises.FileHandle, buffer: Uint8Array, position: number): Promise<void> {
|
|
298
|
+
let totalRead = 0;
|
|
299
|
+
while (totalRead < buffer.length) {
|
|
300
|
+
const {bytesRead} = await fd.read(buffer, totalRead, buffer.length - totalRead, position + totalRead);
|
|
301
|
+
if (bytesRead === 0) {
|
|
302
|
+
const offset = position + totalRead;
|
|
303
|
+
throw new DataColumnStoreError(
|
|
304
|
+
{code: DataColumnStoreErrorCode.UNEXPECTED_EOF, offset},
|
|
305
|
+
`Unexpected end of dcol file at offset ${offset}`
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
totalRead += bytesRead;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {DataColumnSidecar, RootHex, Slot} from "@lodestar/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Flat file storage interface for data columns.
|
|
5
|
+
*
|
|
6
|
+
* No hot/cold distinction — data is always keyed by (slot, blockRoot).
|
|
7
|
+
* All filesystem operations are crash-safe via atomic writes.
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
export interface IFlatFileStore {
|
|
11
|
+
init(): Promise<void>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
|
|
14
|
+
getDataColumns(slot: Slot, blockRoot: RootHex): Promise<DataColumnSidecar[]>;
|
|
15
|
+
/** Returns null if the file is absent, and undefined entries for columns missing from an existing file. */
|
|
16
|
+
getDataColumnsBinary(slot: Slot, blockRoot: RootHex, indices: number[]): Promise<(Uint8Array | undefined)[] | null>;
|
|
17
|
+
putDataColumnsBinary(slot: Slot, blockRoot: RootHex, columns: {index: number; data: Uint8Array}[]): Promise<void>;
|
|
18
|
+
|
|
19
|
+
deleteMany(items: {slot: Slot; blockRoot: RootHex}[]): Promise<void>;
|
|
20
|
+
pruneBefore(slot: Slot): Promise<Slot[]>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type {Counter, GaugeExtra, Histogram} from "@lodestar/utils";
|
|
2
|
+
import {DataColumnStoreError, DataColumnStoreErrorCode} from "./errors.js";
|
|
3
|
+
|
|
4
|
+
export const FlatFileStoreOperation = {
|
|
5
|
+
read: "read",
|
|
6
|
+
write: "write",
|
|
7
|
+
delete: "delete",
|
|
8
|
+
prune: "prune",
|
|
9
|
+
} as const;
|
|
10
|
+
|
|
11
|
+
export type FlatFileStoreOperation = (typeof FlatFileStoreOperation)[keyof typeof FlatFileStoreOperation];
|
|
12
|
+
|
|
13
|
+
type OperationLabels = {operation: FlatFileStoreOperation};
|
|
14
|
+
|
|
15
|
+
export type FlatFileStoreMetrics = {
|
|
16
|
+
operationDuration: Record<FlatFileStoreOperation, Histogram>;
|
|
17
|
+
operationErrors: Counter<OperationLabels>;
|
|
18
|
+
readBytes: Counter;
|
|
19
|
+
writeBytes: Counter;
|
|
20
|
+
prunedDirectories: Counter;
|
|
21
|
+
slotIndexSize: GaugeExtra;
|
|
22
|
+
startupDuration: Histogram;
|
|
23
|
+
startupErrors: Counter;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export async function observeFlatFileStoreOperation<T>(
|
|
27
|
+
metrics: FlatFileStoreMetrics | null,
|
|
28
|
+
operation: FlatFileStoreOperation,
|
|
29
|
+
fn: () => Promise<T>
|
|
30
|
+
): Promise<T> {
|
|
31
|
+
const labels = {operation};
|
|
32
|
+
const endTimer = metrics?.operationDuration[operation].startTimer();
|
|
33
|
+
try {
|
|
34
|
+
return await fn();
|
|
35
|
+
} catch (e) {
|
|
36
|
+
metrics?.operationErrors.inc(labels);
|
|
37
|
+
if (e instanceof DataColumnStoreError) {
|
|
38
|
+
throw e;
|
|
39
|
+
}
|
|
40
|
+
throw new DataColumnStoreError(
|
|
41
|
+
{code: DataColumnStoreErrorCode.OPERATION_FAILED, operation},
|
|
42
|
+
`Flat file store ${operation} operation failed`,
|
|
43
|
+
e
|
|
44
|
+
);
|
|
45
|
+
} finally {
|
|
46
|
+
endTimer?.();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type {RootHex} from "@lodestar/types";
|
|
2
|
+
import {DataColumnStoreError, DataColumnStoreErrorCode} from "./errors.js";
|
|
3
|
+
|
|
4
|
+
const ROOT_HEX_PATTERN = /^0x[0-9a-f]{64}$/;
|
|
5
|
+
|
|
6
|
+
export function isValidRootHex(rootHex: string): rootHex is RootHex {
|
|
7
|
+
return ROOT_HEX_PATTERN.test(rootHex);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function assertValidRootHex(rootHex: string): asserts rootHex is RootHex {
|
|
11
|
+
if (!isValidRootHex(rootHex)) {
|
|
12
|
+
throw new DataColumnStoreError(
|
|
13
|
+
{code: DataColumnStoreErrorCode.INVALID_ROOT, root: rootHex},
|
|
14
|
+
`Invalid flat file root: ${rootHex}`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Zero-pad a slot number to 12 digits for lexicographic ordering in directory names.
|
|
21
|
+
* Twelve digits covers many centuries of Ethereum; larger safe integers remain untruncated.
|
|
22
|
+
*/
|
|
23
|
+
export function padSlot(slot: number): string {
|
|
24
|
+
if (!Number.isSafeInteger(slot) || slot < 0) {
|
|
25
|
+
throw new DataColumnStoreError(
|
|
26
|
+
{code: DataColumnStoreErrorCode.INVALID_SLOT, slot},
|
|
27
|
+
`Invalid flat file slot: ${slot}`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return String(slot).padStart(12, "0");
|
|
32
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import {Slot} from "@lodestar/types";
|
|
3
|
+
import {isFsNotFoundError} from "./errors.js";
|
|
4
|
+
import {padSlot} from "./path.js";
|
|
5
|
+
|
|
6
|
+
export type SlotIndexRebuildStats = {
|
|
7
|
+
slots: number;
|
|
8
|
+
ignoredEntries: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export class SlotIndex {
|
|
12
|
+
private readonly slots = new Set<Slot>();
|
|
13
|
+
|
|
14
|
+
get size(): number {
|
|
15
|
+
return this.slots.size;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
add(slot: Slot): void {
|
|
19
|
+
this.slots.add(slot);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
remove(slot: Slot): void {
|
|
23
|
+
this.slots.delete(slot);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getBefore(minSlot: Slot): Slot[] {
|
|
27
|
+
const slots: Slot[] = [];
|
|
28
|
+
for (const slot of this.slots) {
|
|
29
|
+
if (slot < minSlot) slots.push(slot);
|
|
30
|
+
}
|
|
31
|
+
return slots;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async rebuildFromDisk(columnsDir: string): Promise<SlotIndexRebuildStats> {
|
|
35
|
+
this.slots.clear();
|
|
36
|
+
let entries: fs.Dirent[];
|
|
37
|
+
try {
|
|
38
|
+
entries = await fs.promises.readdir(columnsDir, {withFileTypes: true});
|
|
39
|
+
} catch (e) {
|
|
40
|
+
if (!isFsNotFoundError(e)) throw e;
|
|
41
|
+
return {slots: 0, ignoredEntries: 0};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let ignoredEntries = 0;
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
const slot = Number(entry.name);
|
|
47
|
+
if (!entry.isDirectory() || !Number.isSafeInteger(slot) || slot < 0 || entry.name !== padSlot(slot)) {
|
|
48
|
+
ignoredEntries++;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
this.slots.add(slot);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {slots: this.slots.size, ignoredEntries};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {compressSync, uncompressSync} from "snappy";
|
|
2
|
+
|
|
3
|
+
export function compress(data: Uint8Array): Uint8Array {
|
|
4
|
+
return compressSync(toBuffer(data));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function uncompress(data: Uint8Array): Uint8Array {
|
|
8
|
+
const result = uncompressSync(toBuffer(data), {asBuffer: true}) as Buffer;
|
|
9
|
+
return new Uint8Array(result.buffer, result.byteOffset, result.byteLength);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function toBuffer(data: Uint8Array): Buffer {
|
|
13
|
+
return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
14
|
+
}
|
package/src/db/index.ts
CHANGED
package/src/db/interface.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import {LevelDbControllerMetrics} from "@lodestar/db";
|
|
2
|
+
import {Slot} from "@lodestar/types";
|
|
3
|
+
import type {IDataColumnStore} from "./dataColumnStore.js";
|
|
4
|
+
import type {FlatFileStoreMetrics} from "./flatFileStore/metrics.js";
|
|
2
5
|
import {CheckpointStateRepository} from "./repositories/checkpointState.js";
|
|
3
6
|
import {
|
|
4
7
|
AttesterSlashingRepository,
|
|
@@ -59,6 +62,11 @@ export interface IBeaconDb {
|
|
|
59
62
|
|
|
60
63
|
backfilledRanges: BackfilledRanges;
|
|
61
64
|
|
|
65
|
+
dataColumns: IDataColumnStore;
|
|
66
|
+
/** Highest legacy column slot at startup; later archival writes the block-root index first. */
|
|
67
|
+
readonly lastLegacyArchiveSlot: Slot | null;
|
|
68
|
+
init(): Promise<void>;
|
|
69
|
+
|
|
62
70
|
pruneHotDb(): Promise<void>;
|
|
63
71
|
|
|
64
72
|
deleteDeprecatedEth1Data(): Promise<void>;
|
|
@@ -66,5 +74,5 @@ export interface IBeaconDb {
|
|
|
66
74
|
/** Close the connection to the db instance and close the db store. */
|
|
67
75
|
close(): Promise<void>;
|
|
68
76
|
/** To inject metrics after CLI initialization */
|
|
69
|
-
setMetrics(metrics: LevelDbControllerMetrics): void;
|
|
77
|
+
setMetrics(metrics: LevelDbControllerMetrics, flatFileStoreMetrics?: FlatFileStoreMetrics | null): void;
|
|
70
78
|
}
|