Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion packages/beacon-node/src/db/buckets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export enum Bucket {
// altair_lightClientSyncCommitteeProof = 35, // DEPRECATED on v0.32.0
// index_lightClientInitProof = 36, // DEPRECATED on v0.32.0

backfilled_ranges = 42, // Backfilled From to To, inclusive of both From, To
backfill_state = 42, // stores Epoch -> EpochBackfillState data and backfill range singleton object

// Buckets to support LightClient server v2
lightClient_syncCommitteeWitness = 51, // BlockRoot -> SyncCommitteeWitness
Expand Down
29 changes: 29 additions & 0 deletions packages/beacon-node/src/db/repositories/backfillState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {ContainerType, ListUintNum64Type, ValueOf} from "@chainsafe/ssz";
import {ChainForkConfig} from "@lodestar/config/lib";
import {DatabaseController, Repository} from "@lodestar/db";
import {Epoch, ssz} from "@lodestar/types";
import {Bucket, getBucketNameByValue} from "../buckets.js";
import {BACKFILL_RANGE_KEY} from "../single/backfillRange.js";

// TODO: Fix the null possibilities. ssz types dont work with null values
export const epochBackfillStateSSZ = new ContainerType(
{
hasBlock: ssz.Boolean,
hasBlobs: ssz.Boolean || null,
columnIndices: new ListUintNum64Type(128) || null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You cannot do union types like this with our ssz library. They will need to be handled a bit differently. Here are a couple of suggestions but you can also come up with another method if you prefer.

  • During deserialization. Have a non-nullable data type EpochBackfillStateSerialized (or called something similar like EpochBackfillStateWrapper) that lives in the DB and then on deserialization check the fork for the requested epoch and nullify as necessary and return EpochBackfillState
  • Creating additional fields for the presence of a data type like needsBlobs and needsColumns or perhaps storing the forkName on the type so it's interpreted correctly by the consumer

}
// {typeName: "EpochBackfillState", jsonCase: "eth2"}
);
export type EpochBackfillState = ValueOf<typeof epochBackfillStateSSZ>;

export class BackfillState extends Repository<Epoch, EpochBackfillState> {
constructor(config: ChainForkConfig, db: DatabaseController<Uint8Array, Uint8Array>) {
const bucket = Bucket.backfill_state;
super(config, db, bucket, epochBackfillStateSSZ, getBucketNameByValue(bucket));
}

encodeKey(key: Epoch): Uint8Array {
if (key === BACKFILL_RANGE_KEY) throw new Error("Reserved key for backfill range singleton object");
return super.encodeKey(key);
}
}
29 changes: 0 additions & 29 deletions packages/beacon-node/src/db/repositories/backfilledRanges.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/beacon-node/src/db/repositories/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ export {BestLightClientUpdateRepository} from "./lightclientBestUpdate.js";
export {CheckpointHeaderRepository} from "./lightclientCheckpointHeader.js";
export {SyncCommitteeRepository} from "./lightclientSyncCommittee.js";
export {SyncCommitteeWitnessRepository} from "./lightclientSyncCommitteeWitness.js";
export {BackfilledRanges} from "./backfilledRanges.js";
export {BackfillState} from "./backfillState.js";
export {BLSToExecutionChangeRepository} from "./blsToExecutionChange.js";
47 changes: 47 additions & 0 deletions packages/beacon-node/src/db/single/backfillRange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {ContainerType, Type, ValueOf} from "@chainsafe/ssz";
import {ChainForkConfig} from "@lodestar/config";
import {Db, DbReqOpts, encodeKey as _encodeKey} from "@lodestar/db";
import {ssz} from "@lodestar/types";
import {Bucket, getBucketNameByValue} from "../buckets.js";

export const backfillRangeSSZ = new ContainerType(
{
beginningEpoch: ssz.UintNum64,
endingEpoch: ssz.UintNum64,
}
// {typeName: "BackfillRange", jsonCase: "eth2"}
);
export type BackfillRangeWrapper = ValueOf<typeof backfillRangeSSZ>;

// unique & practically impossible key to store BackfillRange inside 'backfill_state'
// bucket which stores Epoch -> EpochBackfillState key value pairs
export const BACKFILL_RANGE_KEY = Infinity;

export class BackfillRange {
private readonly bucket: Bucket;
private readonly db: Db;
private readonly dbReqOpts: DbReqOpts; // to record metrics
private readonly key: Uint8Array;
private readonly type: Type<BackfillRangeWrapper>;

constructor(_config: ChainForkConfig, db: Db) {
this.db = db;
this.bucket = Bucket.backfill_state;
this.key = _encodeKey(this.bucket, BACKFILL_RANGE_KEY); // set unique key: [0x2a, 0xff, 0xff, ...0xff]
this.type = backfillRangeSSZ;
this.dbReqOpts = {bucketId: getBucketNameByValue(this.bucket)};
}

async put(value: BackfillRangeWrapper): Promise<void> {
await this.db.put(this.key, this.type.serialize(value), this.dbReqOpts);
}

async get(): Promise<BackfillRangeWrapper | null> {
const value = await this.db.get(this.key, this.dbReqOpts);
return value ? this.type.deserialize(value) : null;
}

async delete(): Promise<void> {
await this.db.delete(this.key, this.dbReqOpts);
}
}
1 change: 1 addition & 0 deletions packages/beacon-node/src/db/single/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export {BackfillRange} from "./backfillRange.js";
export {PreGenesisState} from "./preGenesisState.js";
export {PreGenesisStateLastProcessedBlock} from "./preGenesisStateLastProcessedBlock.js";