Skip to content

Commit

Permalink
Merge 2e63af8 into 05fe0ac
Browse files Browse the repository at this point in the history
  • Loading branch information
twoeths authored Apr 22, 2024
2 parents 05fe0ac + 2e63af8 commit 7405961
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 35 deletions.
2 changes: 1 addition & 1 deletion packages/api/src/beacon/routes/lodestar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export type Api = {
getRegenQueueItems(): Promise<ApiClientResponse<{[HttpStatusCode.OK]: {data: RegenQueueItem[]}}>>;
/** Dump all items in the block processor queue */
getBlockProcessorQueueItems(): Promise<ApiClientResponse<{[HttpStatusCode.OK]: {data: BlockProcessorQueueItem[]}}>>;
/** Dump a summary of the states in the StateContextCache */
/** Dump a summary of the states in the block state cache and checkpoint state cache */
getStateCacheItems(): Promise<ApiClientResponse<{[HttpStatusCode.OK]: {data: StateCacheItem[]}}>>;
/** Dump peer gossip stats by peer */
getGossipPeerScoreStats(): Promise<ApiClientResponse<{[HttpStatusCode.OK]: {data: GossipPeerScoreStat[]}}>>;
Expand Down
14 changes: 7 additions & 7 deletions packages/beacon-node/src/chain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ import {BlockInput} from "./blocks/types.js";
import {SeenAttestationDatas} from "./seenCache/seenAttestationData.js";
import {BlockRewards, computeBlockRewards} from "./rewards/blockRewards.js";
import {ShufflingCache} from "./shufflingCache.js";
import {StateContextCache} from "./stateCache/stateContextCache.js";
import {BlockStateCacheImpl} from "./stateCache/blockStateCacheImpl.js";
import {SeenGossipBlockInput} from "./seenCache/index.js";
import {InMemoryCheckpointStateCache} from "./stateCache/inMemoryCheckpointsCache.js";
import {FIFOBlockStateCache} from "./stateCache/fifoBlockStateCache.js";
Expand Down Expand Up @@ -247,17 +247,17 @@ export class BeaconChain implements IBeaconChain {
this.index2pubkey = cachedState.epochCtx.index2pubkey;

const fileDataStore = opts.nHistoricalStatesFileDataStore ?? false;
const stateCache = this.opts.nHistoricalStates
const blockStateCache = this.opts.nHistoricalStates
? new FIFOBlockStateCache(this.opts, {metrics})
: new StateContextCache({metrics});
: new BlockStateCacheImpl({metrics});
const checkpointStateCache = this.opts.nHistoricalStates
? new PersistentCheckpointStateCache(
{
metrics,
logger,
clock,
shufflingCache: this.shufflingCache,
blockStateCache: stateCache,
blockStateCache,
bufferPool: new BufferPool(anchorState.type.tree_serializedSize(anchorState.node), metrics),
datastore: fileDataStore
? // debug option if we want to investigate any issues with the DB
Expand All @@ -269,8 +269,8 @@ export class BeaconChain implements IBeaconChain {
)
: new InMemoryCheckpointStateCache({metrics});
const {checkpoint} = computeAnchorCheckpoint(config, anchorState);
stateCache.add(cachedState);
stateCache.setHeadState(cachedState);
blockStateCache.add(cachedState);
blockStateCache.setHeadState(cachedState);
checkpointStateCache.add(checkpoint, cachedState);

const forkChoice = initializeForkChoice(
Expand All @@ -284,7 +284,7 @@ export class BeaconChain implements IBeaconChain {
const regen = new QueuedStateRegenerator({
config,
forkChoice,
stateCache,
blockStateCache,
checkpointStateCache,
db,
metrics,
Expand Down
31 changes: 16 additions & 15 deletions packages/beacon-node/src/chain/regen/queued.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
private readonly regen: StateRegenerator;

private readonly forkChoice: IForkChoice;
private readonly stateCache: BlockStateCache;
private readonly blockStateCache: BlockStateCache;
private readonly checkpointStateCache: CheckpointStateCache;
private readonly metrics: Metrics | null;
private readonly logger: Logger;
Expand All @@ -47,7 +47,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
modules.metrics ? modules.metrics.regenQueue : undefined
);
this.forkChoice = modules.forkChoice;
this.stateCache = modules.stateCache;
this.blockStateCache = modules.blockStateCache;
this.checkpointStateCache = modules.checkpointStateCache;
this.metrics = modules.metrics;
this.logger = modules.logger;
Expand All @@ -64,20 +64,20 @@ export class QueuedStateRegenerator implements IStateRegenerator {
}

dropCache(): void {
this.stateCache.clear();
this.blockStateCache.clear();
this.checkpointStateCache.clear();
}

dumpCacheSummary(): routes.lodestar.StateCacheItem[] {
return [...this.stateCache.dumpSummary(), ...this.checkpointStateCache.dumpSummary()];
return [...this.blockStateCache.dumpSummary(), ...this.checkpointStateCache.dumpSummary()];
}

/**
* Get a state from block state cache.
* This is not for block processing so don't transfer cache
*/
getStateSync(stateRoot: RootHex): CachedBeaconStateAllForks | null {
return this.stateCache.get(stateRoot, {dontTransferCache: true});
return this.blockStateCache.get(stateRoot, {dontTransferCache: true});
}

/**
Expand Down Expand Up @@ -113,7 +113,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
// Otherwise the state transition may not be cached and wasted. Queue for regen since the
// work required will still be significant.
if (parentEpoch === blockEpoch) {
const state = this.stateCache.get(parentBlock.stateRoot, opts);
const state = this.blockStateCache.get(parentBlock.stateRoot, opts);
if (state) {
return state;
}
Expand All @@ -139,22 +139,23 @@ export class QueuedStateRegenerator implements IStateRegenerator {
getClosestHeadState(head: ProtoBlock): CachedBeaconStateAllForks | null {
const opts = {dontTransferCache: true};
return (
this.checkpointStateCache.getLatest(head.blockRoot, Infinity, opts) || this.stateCache.get(head.stateRoot, opts)
this.checkpointStateCache.getLatest(head.blockRoot, Infinity, opts) ||
this.blockStateCache.get(head.stateRoot, opts)
);
}

pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void {
this.checkpointStateCache.prune(finalizedEpoch, justifiedEpoch);
this.stateCache.prune(headStateRoot);
this.blockStateCache.prune(headStateRoot);
}

pruneOnFinalized(finalizedEpoch: number): void {
this.checkpointStateCache.pruneFinalized(finalizedEpoch);
this.stateCache.deleteAllBeforeEpoch(finalizedEpoch);
this.blockStateCache.deleteAllBeforeEpoch(finalizedEpoch);
}

processState(blockRootHex: RootHex, postState: CachedBeaconStateAllForks): void {
this.stateCache.add(postState);
this.blockStateCache.add(postState);
this.checkpointStateCache.processState(blockRootHex, postState).catch((e) => {
this.logger.debug("Error processing block state", {blockRootHex, slot: postState.slot}, e);
});
Expand All @@ -170,10 +171,10 @@ export class QueuedStateRegenerator implements IStateRegenerator {
const headState =
newHeadStateRoot === toHexString(maybeHeadState.hashTreeRoot())
? maybeHeadState
: this.stateCache.get(newHeadStateRoot, cloneOpts);
: this.blockStateCache.get(newHeadStateRoot, cloneOpts);

if (headState) {
this.stateCache.setHeadState(headState);
this.blockStateCache.setHeadState(headState);
} else {
// Trigger regen on head change if necessary
this.logger.warn("Head state not available, triggering regen", {stateRoot: newHeadStateRoot});
Expand All @@ -182,9 +183,9 @@ export class QueuedStateRegenerator implements IStateRegenerator {
// head has changed, so the existing cached head state is no longer useful. Set strong reference to null to free
// up memory for regen step below. During regen, node won't be functional but eventually head will be available
// for legacy StateContextCache only
this.stateCache.setHeadState(null);
this.blockStateCache.setHeadState(null);
this.regen.getState(newHeadStateRoot, RegenCaller.processBlock, cloneOpts, allowDiskReload).then(
(headStateRegen) => this.stateCache.setHeadState(headStateRegen),
(headStateRegen) => this.blockStateCache.setHeadState(headStateRegen),
(e) => this.logger.error("Error on head state regen", {}, e)
);
}
Expand Down Expand Up @@ -261,7 +262,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
this.metrics?.regenFnCallTotal.inc({caller: rCaller, entrypoint: RegenFnName.getState});

// First attempt to fetch the state from cache before queueing
const state = this.stateCache.get(stateRoot, opts);
const state = this.blockStateCache.get(stateRoot, opts);
if (state) {
return state;
}
Expand Down
8 changes: 4 additions & 4 deletions packages/beacon-node/src/chain/regen/regen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {RegenError, RegenErrorCode} from "./errors.js";
export type RegenModules = {
db: IBeaconDb;
forkChoice: IForkChoice;
stateCache: BlockStateCache;
blockStateCache: BlockStateCache;
checkpointStateCache: CheckpointStateCache;
config: ChainForkConfig;
emitter: ChainEventEmitter;
Expand Down Expand Up @@ -150,7 +150,7 @@ export class StateRegenerator implements IStateRegeneratorInternal {
allowDiskReload = false
): Promise<CachedBeaconStateAllForks> {
// Trivial case, state at stateRoot is already cached
const cachedStateCtx = this.modules.stateCache.get(stateRoot, opts);
const cachedStateCtx = this.modules.blockStateCache.get(stateRoot, opts);
if (cachedStateCtx) {
return cachedStateCtx;
}
Expand All @@ -167,7 +167,7 @@ export class StateRegenerator implements IStateRegeneratorInternal {
const {checkpointStateCache} = this.modules;
// iterateAncestorBlocks only returns ancestor blocks, not the block itself
for (const b of this.modules.forkChoice.iterateAncestorBlocks(block.blockRoot)) {
state = this.modules.stateCache.get(b.stateRoot, opts);
state = this.modules.blockStateCache.get(b.stateRoot, opts);
if (state) {
break;
}
Expand Down Expand Up @@ -235,7 +235,7 @@ export class StateRegenerator implements IStateRegeneratorInternal {

if (allowDiskReload) {
// also with allowDiskReload flag, we "reload" it to the state cache too
this.modules.stateCache.add(state);
this.modules.blockStateCache.add(state);
}

// this avoids keeping our node busy processing blocks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import {BlockStateCache} from "./types.js";
const MAX_STATES = 3 * 32;

/**
* Old implementation of StateCache
* Old implementation of StateCache (used to call `StateContextCache`)
* - Prune per checkpoint so number of states ranges from 96 to 128
* - Keep a separate head state to make sure it is always available
*/
export class StateContextCache implements BlockStateCache {
export class BlockStateCacheImpl implements BlockStateCache {
/**
* Max number of states allowed in the cache
*/
Expand Down Expand Up @@ -83,7 +83,7 @@ export class StateContextCache implements BlockStateCache {
* See ./fifoBlockStateCache.ts for implementation
*/
getSeedState(): CachedBeaconStateAllForks {
throw Error("Not implemented for StateContextCache");
throw Error("Not implemented for BlockStateCacheImpl");
}

clear(): void {
Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-node/src/chain/stateCache/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from "./stateContextCache.js";
export * from "./blockStateCacheImpl.js";
export * from "./inMemoryCheckpointsCache.js";
export * from "./fifoBlockStateCache.js";
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import {describe, it, expect, beforeEach} from "vitest";
import {EpochShuffling} from "@lodestar/state-transition";
import {SLOTS_PER_EPOCH} from "@lodestar/params";
import {Root} from "@lodestar/types";
import {StateContextCache} from "../../../../src/chain/stateCache/index.js";
import {BlockStateCacheImpl} from "../../../../src/chain/stateCache/index.js";
import {generateCachedState} from "../../../utils/state.js";
import {ZERO_HASH} from "../../../../src/constants/index.js";

describe("StateContextCache", function () {
let cache: StateContextCache;
describe("BlockStateCacheImpl", function () {
let cache: BlockStateCacheImpl;
let key1: Root, key2: Root;
const shuffling: EpochShuffling = {
epoch: 0,
Expand All @@ -20,7 +20,7 @@ describe("StateContextCache", function () {

beforeEach(function () {
// max 2 items
cache = new StateContextCache({maxStates: 2});
cache = new BlockStateCacheImpl({maxStates: 2});
const state1 = generateCachedState({slot: 0});
key1 = state1.hashTreeRoot();
state1.epochCtx.currentShuffling = {...shuffling, epoch: 0};
Expand Down

0 comments on commit 7405961

Please sign in to comment.