import {BeaconStateAllForks} from "@lodestar/state-transition"; import {Epoch, Root, RootHex, Slot, ssz} from "@lodestar/types"; import {IChainForkConfig} from "@lodestar/config"; import {bytesToInt, toHex} from "@lodestar/utils"; import {Db, Bucket, Repository} from "@lodestar/db"; import {getStateTypeFromBytes} from "../../util/multifork.js"; import {getRootIndexKey, storeRootIndex} from "./stateArchiveIndex.js"; /* eslint-disable @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call */ export class StateArchiveRepository extends Repository { constructor(config: IChainForkConfig, db: Db) { // Pick some type but won't be used. Casted to any because no type can match `BeaconStateAllForks` // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any const type = ssz.phase0.BeaconState as any; super(config, db, Bucket.allForks_stateArchive, type); } // Overrides for multi-fork encodeValue(value: BeaconStateAllForks): Uint8Array { return value.serialize(); } decodeValue(data: Uint8Array): BeaconStateAllForks { return getStateTypeFromBytes(this.config, data).deserializeToViewDU(data); } // Handle key as slot async put(key: Slot, value: BeaconStateAllForks): Promise { await Promise.all([super.put(key, value), storeRootIndex(this.db, key, value.hashTreeRoot())]); } getId(state: BeaconStateAllForks): Epoch { return state.slot; } decodeKey(data: Uint8Array): number { return bytesToInt((super.decodeKey(data) as unknown) as Uint8Array, "be"); } // Index Root -> Slot async getByRoot(stateRoot: Root): Promise { const slot = await this.getSlotByRoot(stateRoot); if (slot !== null && Number.isInteger(slot)) { return this.get(slot); } return null; } async dumpRootIndexEntries(): Promise<{root: RootHex; slot: Slot}[]> { const entries = await this.db.entries({ lte: getRootIndexKey(Buffer.alloc(32, 0xff)), gte: getRootIndexKey(Buffer.alloc(32, 0x00)), }); return entries.map((entry) => ({ root: toHex(entry.key), slot: bytesToInt(entry.value, "be"), })); } private async getSlotByRoot(root: Root): Promise { const value = await this.db.get(getRootIndexKey(root)); return value && bytesToInt(value, "be"); } }