Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: unify blockStateCache naming convention #6695

Merged
merged 1 commit into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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