import {concat} from "uint8arrays"; import {digest} from "@chainsafe/as-sha256"; import {Proof} from "@chainsafe/persistent-merkle-tree"; import {JsonPath} from "@chainsafe/ssz"; import {routes, ServerApi} from "@lodestar/api"; import {altair, RootHex, SyncPeriod} from "@lodestar/types"; import {notNullish} from "@lodestar/utils"; import {ForkName} from "@lodestar/params"; import {BeaconStateAltair} from "../utils/types.js"; export class ProofServerApiMock implements ServerApi { readonly states = new Map(); async getStateProof(stateId: string, paths: JsonPath[]): Promise<{data: Proof}> { const state = this.states.get(stateId); if (!state) throw Error(`stateId ${stateId} not available`); return {data: state.createProof(paths)}; } } type VersionedLightClientUpdate = { version: ForkName; data: altair.LightClientUpdate; }; export class LightclientServerApiMock implements ServerApi { readonly updates = new Map(); readonly snapshots = new Map(); latestHeadUpdate: altair.LightClientOptimisticUpdate | null = null; finalized: altair.LightClientFinalityUpdate | null = null; async getUpdates(from: SyncPeriod, to: SyncPeriod): Promise { const updates: VersionedLightClientUpdate[] = []; for (let period = parseInt(String(from)); period <= parseInt(String(to)); period++) { const update = this.updates.get(period); if (update) { updates.push({ version: ForkName.bellatrix, data: update, }); } } return updates; } async getOptimisticUpdate(): Promise<{version: ForkName; data: altair.LightClientOptimisticUpdate}> { if (!this.latestHeadUpdate) throw Error("No latest head update"); return {version: ForkName.bellatrix, data: this.latestHeadUpdate}; } async getFinalityUpdate(): Promise<{version: ForkName; data: altair.LightClientFinalityUpdate}> { if (!this.finalized) throw Error("No finalized head update"); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment return {version: ForkName.bellatrix, data: this.finalized}; } async getBootstrap(blockRoot: string): Promise<{version: ForkName; data: altair.LightClientBootstrap}> { const snapshot = this.snapshots.get(blockRoot); if (!snapshot) throw Error(`snapshot for blockRoot ${blockRoot} not available`); return {version: ForkName.bellatrix, data: snapshot}; } async getCommitteeRoot(startPeriod: SyncPeriod, count: number): Promise<{data: Uint8Array[]}> { const periods = Array.from({length: count}, (_ignored, i) => i + startPeriod); const committeeHashes = periods .map((period) => this.updates.get(period)?.nextSyncCommittee.pubkeys) .filter(notNullish) .map((pubkeys) => digest(concat(pubkeys))); return {data: committeeHashes}; } } export type IStateRegen = { getStateByRoot(stateRoot: string): Promise; }; export type IBlockCache = { getBlockByRoot(blockRoot: string): Promise; };