@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
47 lines (40 loc) • 1.85 kB
text/typescript
import {CheckpointWithHex} from "@lodestar/fork-choice";
import {EffectiveBalanceIncrements, IBeaconStateView, computeStartSlotAtEpoch} from "@lodestar/state-transition";
import {Epoch, RootHex} from "@lodestar/types";
import {toRootHex} from "@lodestar/utils";
/** The number of validator balance sets that are cached within `CheckpointBalancesCache`. */
const MAX_BALANCE_CACHE_SIZE = 4;
type BalancesCacheItem = {
rootHex: RootHex;
epoch: Epoch;
balances: EffectiveBalanceIncrements;
};
/**
* Cache EffectiveBalanceIncrements of checkpoint blocks
*/
export class CheckpointBalancesCache {
private readonly items: BalancesCacheItem[] = [];
/**
* Inspect the given `state` and determine the root of the block at the first slot of
* `state.current_epoch`. If there is not already some entry for the given block root, then
* add the effective balances from the `state` to the cache.
*/
processState(blockRootHex: RootHex, state: IBeaconStateView): void {
const epoch = state.epoch;
const epochBoundarySlot = computeStartSlotAtEpoch(epoch);
const epochBoundaryRoot =
epochBoundarySlot === state.slot ? blockRootHex : toRootHex(state.getBlockRootAtSlot(epochBoundarySlot));
const index = this.items.findIndex((item) => item.epoch === epoch && item.rootHex === epochBoundaryRoot);
if (index === -1) {
if (this.items.length === MAX_BALANCE_CACHE_SIZE) {
this.items.shift();
}
// expect to reach this once per epoch
this.items.push({epoch, rootHex: epochBoundaryRoot, balances: state.getEffectiveBalanceIncrementsZeroInactive()});
}
}
get(checkpoint: CheckpointWithHex): EffectiveBalanceIncrements | undefined {
const {rootHex, epoch} = checkpoint;
return this.items.find((item) => item.epoch === epoch && item.rootHex === rootHex)?.balances;
}
}