Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
d49bb94
Pass gloas to protoArray
ensi321 Jan 10, 2026
23f01a7
Interface
ensi321 Jan 13, 2026
a826cc9
Update store
ensi321 Jan 13, 2026
be363a3
Update store
ensi321 Jan 13, 2026
ab1afef
ProtoArray to store nodes instead of roots
ensi321 Jan 13, 2026
a0d8e0b
PTC
ensi321 Jan 13, 2026
64fbd09
import latest message
ensi321 Jan 13, 2026
c0bb5f2
compute deltas
ensi321 Jan 13, 2026
74ab002
onBlock
ensi321 Jan 13, 2026
19d15ed
Best child and decendant
ensi321 Jan 13, 2026
fed7b93
onExecutionPayload
ensi321 Jan 13, 2026
0d8f97e
prune
ensi321 Jan 13, 2026
60fa974
Misc
ensi321 Jan 13, 2026
3728726
lint
ensi321 Jan 13, 2026
f3df981
Update tests
ensi321 Jan 13, 2026
b8bc7b3
Address comment
ensi321 Jan 13, 2026
36a213e
check-types
ensi321 Jan 13, 2026
7e91801
Partially address @twoeths's comment
ensi321 Jan 14, 2026
c6aa641
fix build
ensi321 Jan 14, 2026
56e5c24
check-types
ensi321 Jan 15, 2026
0bc18eb
Partial address @twoeths's comments
ensi321 Jan 16, 2026
3ad24ca
Remove unintended folders
ensi321 Jan 16, 2026
6ae6ada
Partial address @twoeths's comments
ensi321 Jan 16, 2026
71b6635
Update getAncestor
ensi321 Jan 16, 2026
8a89f50
Update test
ensi321 Jan 16, 2026
b865485
improve readability
ensi321 Jan 17, 2026
756ac57
Remove executionPayloadStates
ensi321 Jan 22, 2026
7fab3c1
check-types
ensi321 Jan 23, 2026
cb3e4ef
Clean up access methods
ensi321 Jan 24, 2026
a1d1c59
Tree walk skip EMPTY/FULL variants
ensi321 Jan 24, 2026
ff558e3
fix types-check
ensi321 Jan 24, 2026
bdcc295
lint
ensi321 Jan 24, 2026
777e461
reduce diff
ensi321 Jan 24, 2026
7ff0752
Merge branch 'unstable' into nc/epbs-fc
ensi321 Jan 27, 2026
3e3de40
Fix unit tests
ensi321 Jan 27, 2026
eca79a3
lint
ensi321 Jan 27, 2026
ee6f91f
Merge branch 'unstable' into nc/epbs-fc
ensi321 Jan 27, 2026
14eb5f7
Partially address @twoeths's comment
ensi321 Jan 29, 2026
818a2d9
Update api
ensi321 Jan 29, 2026
e39ae11
Fix check-types
ensi321 Jan 29, 2026
ee1cc32
Fix unit tests
ensi321 Jan 29, 2026
638d15f
lint
ensi321 Jan 29, 2026
acf48ee
Fix tests
ensi321 Jan 29, 2026
20cc97a
Merge branch 'unstable' into nc/epbs-fc
ensi321 Jan 30, 2026
aa7d204
Fix merge
ensi321 Jan 30, 2026
20588c8
fix ci
ensi321 Jan 31, 2026
8859b5b
check-types
ensi321 Feb 2, 2026
ced6c41
Address @twoeths's comments
ensi321 Feb 3, 2026
f9a1253
chore: fork choice stores checkpoints with payload status (#8845)
ensi321 Feb 3, 2026
1dc21c4
chore: model pre-gloas block index as number (#8858)
twoeths Feb 4, 2026
c911e16
address comments
ensi321 Feb 5, 2026
d6f911b
address comments
ensi321 Feb 5, 2026
ef44693
Merge branch 'unstable' into nc/epbs-fc
ensi321 Feb 5, 2026
330f23e
Update types
ensi321 Feb 6, 2026
6e1493d
check-types
ensi321 Feb 6, 2026
f6b589e
refactor: ePBS forkchoice getParentPayloadStatus() (#8869)
twoeths Feb 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/beacon-node/src/api/impl/beacon/blocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export function getBeaconBlockApi({
case routes.beacon.BroadcastValidation.consensus: {
// check if this beacon node produced the block else run validations
if (!blockLocallyProduced) {
const parentBlock = chain.forkChoice.getBlock(signedBlock.message.parentRoot);
const parentBlock = chain.forkChoice.getBlockDefaultStatus(signedBlock.message.parentRoot);
if (parentBlock === null) {
chain.emitter.emit(ChainEvent.unknownParent, {
blockInput: blockForImport,
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/api/impl/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ export function getValidatorApi(
*/

function notOnOptimisticBlockRoot(beaconBlockRoot: Root): void {
const protoBeaconBlock = chain.forkChoice.getBlock(beaconBlockRoot);
const protoBeaconBlock = chain.forkChoice.getBlockDefaultStatus(beaconBlockRoot);
if (!protoBeaconBlock) {
throw new ApiError(404, `Block not in forkChoice, beaconBlockRoot=${toRootHex(beaconBlockRoot)}`);
}
Expand All @@ -398,7 +398,7 @@ export function getValidatorApi(
}

function notOnOutOfRangeData(beaconBlockRoot: Root): void {
const protoBeaconBlock = chain.forkChoice.getBlock(beaconBlockRoot);
const protoBeaconBlock = chain.forkChoice.getBlockDefaultStatus(beaconBlockRoot);
if (!protoBeaconBlock) {
throw new ApiError(404, `Block not in forkChoice, beaconBlockRoot=${toRootHex(beaconBlockRoot)}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function updateBackfillRange(
try {
// Mark the sequence in backfill db from finalized block's slot till anchor slot as
// filled.
const finalizedBlockFC = chain.forkChoice.getBlockHex(finalized.rootHex);
const finalizedBlockFC = chain.forkChoice.getBlockHexDefaultStatus(finalized.rootHex);
if (finalizedBlockFC && finalizedBlockFC.slot > chain.anchorStateLatestBlockSlot) {
await db.backfilledRanges.put(finalizedBlockFC.slot, chain.anchorStateLatestBlockSlot);

Expand Down
11 changes: 8 additions & 3 deletions packages/beacon-node/src/chain/blocks/importBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
isStartSlotOfEpoch,
isStateValidatorsNodesPopulated,
} from "@lodestar/state-transition";
import {Attestation, BeaconBlock, altair, capella, electra, phase0, ssz} from "@lodestar/types";
import {Attestation, BeaconBlock, altair, capella, electra, isGloasBeaconBlock, phase0, ssz} from "@lodestar/types";
import {isErrorAborted, toRootHex} from "@lodestar/utils";
import {ZERO_HASH_HEX} from "../../constants/index.js";
import {callInNextEventLoop} from "../../util/eventLoop.js";
Expand Down Expand Up @@ -340,7 +340,7 @@ export async function importBlock(
// 3) Proposer boost reorg related flag is turned on (this is checked inside the function)
// 4) Block meets the criteria of being re-orged out (this is also checked inside the function)
const result = this.forkChoice.shouldOverrideForkChoiceUpdate(
blockSummary.blockRoot,
blockSummary,
this.clock.secFromSlot(currentSlot),
currentSlot
);
Expand Down Expand Up @@ -436,7 +436,12 @@ export async function importBlock(
this.metrics?.currentActiveValidators.set(activeValidatorsCount);
this.metrics?.currentValidators.set({status: "active"}, activeValidatorsCount);

const parentBlockSummary = this.forkChoice.getBlock(checkpointState.latestBlockHeader.parentRoot);
const parentBlockSummary = isGloasBeaconBlock(block.message)
? this.forkChoice.getBlockHexAndBlockHash(
toRootHex(checkpointState.latestBlockHeader.parentRoot),
toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash)
)
: this.forkChoice.getBlockDefaultStatus(checkpointState.latestBlockHeader.parentRoot);

if (parentBlockSummary) {
const justifiedCheckpoint = checkpointState.currentJustifiedCheckpoint;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ChainForkConfig} from "@lodestar/config";
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
import {RootHex, Slot} from "@lodestar/types";
import {RootHex, Slot, isGloasBeaconBlock} from "@lodestar/types";
import {toRootHex} from "@lodestar/utils";
import {IClock} from "../../util/clock.js";
import {BlockError, BlockErrorCode} from "../errors/index.js";
Expand Down Expand Up @@ -90,7 +90,12 @@ export function verifyBlocksSanityChecks(
} else {
// When importing a block segment, only the first NON-IGNORED block must be known to the fork-choice.
const parentRoot = toRootHex(block.message.parentRoot);
parentBlock = chain.forkChoice.getBlockHex(parentRoot);
parentBlock = isGloasBeaconBlock(block.message)
? chain.forkChoice.getBlockHexAndBlockHash(
parentRoot,
toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash)
)
: chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
if (!parentBlock) {
throw new BlockError(block, {code: BlockErrorCode.PARENT_UNKNOWN, parentRoot});
}
Expand Down
12 changes: 6 additions & 6 deletions packages/beacon-node/src/chain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ export class BeaconChain implements IBeaconChain {
): Promise<{state: CachedBeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
if (opts?.allowRegen) {
const state = await this.regen.getState(stateRoot, RegenCaller.restApi);
const block = this.forkChoice.getBlock(state.latestBlockHeader.hashTreeRoot());
const block = this.forkChoice.getBlockDefaultStatus(state.latestBlockHeader.hashTreeRoot());
const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
return {
state,
Expand All @@ -608,7 +608,7 @@ export class BeaconChain implements IBeaconChain {
// TODO: This is very inneficient for debug requests of serialized content, since it deserializes to serialize again
const cachedStateCtx = this.regen.getStateSync(stateRoot);
if (cachedStateCtx) {
const block = this.forkChoice.getBlock(cachedStateCtx.latestBlockHeader.hashTreeRoot());
const block = this.forkChoice.getBlockDefaultStatus(cachedStateCtx.latestBlockHeader.hashTreeRoot());
const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
return {
state: cachedStateCtx,
Expand Down Expand Up @@ -642,7 +642,7 @@ export class BeaconChain implements IBeaconChain {
// finalized or justified checkpoint states maynot be available with PersistentCheckpointStateCache, use getCheckpointStateOrBytes() api to get Uint8Array
const cachedStateCtx = this.regen.getCheckpointStateSync(checkpoint);
if (cachedStateCtx) {
const block = this.forkChoice.getBlock(cachedStateCtx.latestBlockHeader.hashTreeRoot());
const block = this.forkChoice.getBlockDefaultStatus(cachedStateCtx.latestBlockHeader.hashTreeRoot());
const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
return {
state: cachedStateCtx,
Expand All @@ -659,7 +659,7 @@ export class BeaconChain implements IBeaconChain {
): Promise<{state: CachedBeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(checkpoint);
if (cachedStateCtx) {
const block = this.forkChoice.getBlock(checkpoint.root);
const block = this.forkChoice.getBlockDefaultStatus(checkpoint.root);
const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
return {
state: cachedStateCtx,
Expand Down Expand Up @@ -703,7 +703,7 @@ export class BeaconChain implements IBeaconChain {
async getBlockByRoot(
root: string
): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null> {
const block = this.forkChoice.getBlockHex(root);
const block = this.forkChoice.getBlockHexDefaultStatus(root);
if (block) {
// Block found in fork-choice.
// It may be in the block input cache, awaiting full DA reconstruction, check there first
Expand All @@ -727,7 +727,7 @@ export class BeaconChain implements IBeaconChain {
async getSerializedBlockByRoot(
root: string
): Promise<{block: Uint8Array; executionOptimistic: boolean; finalized: boolean; slot: Slot} | null> {
const block = this.forkChoice.getBlockHex(root);
const block = this.forkChoice.getBlockHexDefaultStatus(root);
if (block) {
// Block found in fork-choice.
// It may be in the block input cache, awaiting full DA reconstruction, check there first
Expand Down
6 changes: 3 additions & 3 deletions packages/beacon-node/src/chain/emitter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {EventEmitter} from "node:events";
import {StrictEventEmitter} from "strict-event-emitter-types";
import {routes} from "@lodestar/api";
import {CheckpointWithHex} from "@lodestar/fork-choice";
import {CheckpointWithPayload} from "@lodestar/fork-choice";
import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
import {RootHex, deneb, fulu, phase0} from "@lodestar/types";
import {PeerIdStr} from "../util/peerId.js";
Expand Down Expand Up @@ -83,8 +83,8 @@ export type ChainEventData = {
export type IChainEvents = ApiEvents & {
[ChainEvent.checkpoint]: (checkpoint: phase0.Checkpoint, state: CachedBeaconStateAllForks) => void;

[ChainEvent.forkChoiceJustified]: (checkpoint: CheckpointWithHex) => void;
[ChainEvent.forkChoiceFinalized]: (checkpoint: CheckpointWithHex) => void;
[ChainEvent.forkChoiceJustified]: (checkpoint: CheckpointWithPayload) => void;
[ChainEvent.forkChoiceFinalized]: (checkpoint: CheckpointWithPayload) => void;

[ChainEvent.updateTargetCustodyGroupCount]: (targetGroupCount: number) => void;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ export type ExecutionPayloadEnvelopeErrorType =
| {
code: ExecutionPayloadEnvelopeErrorCode.BUILDER_INDEX_MISMATCH;
envelopeBuilderIndex: BuilderIndex;
bidBuilderIndex: BuilderIndex;
bidBuilderIndex: BuilderIndex | null;
}
| {
code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH;
envelopeBlockHash: RootHex;
bidBlockHash: RootHex | null;
}
| {code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH; envelopeBlockHash: RootHex; bidBlockHash: RootHex}
| {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE}
| {code: ExecutionPayloadEnvelopeErrorCode.CACHE_FAIL; blockRoot: RootHex};

Expand Down
54 changes: 36 additions & 18 deletions packages/beacon-node/src/chain/forkChoice/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import {
ForkChoice,
ForkChoiceStore,
JustifiedBalancesGetter,
PayloadStatus,
ProtoArray,
ProtoBlock,
ForkChoiceOpts as RawForkChoiceOpts,
getCheckpointPayloadStatus,
} from "@lodestar/fork-choice";
import {ZERO_HASH_HEX} from "@lodestar/params";
import {
Expand Down Expand Up @@ -104,6 +106,14 @@ export function initializeForkChoiceFromFinalizedState(
// production code use ForkChoice constructor directly
const forkchoiceConstructor = opts.forkchoiceConstructor ?? ForkChoice;

const isForkPostGloas = (state as CachedBeaconStateGloas).latestBlockHash !== undefined;

// Determine justified checkpoint payload status
const justifiedPayloadStatus = getCheckpointPayloadStatus(state, justifiedCheckpoint.epoch);

// Determine finalized checkpoint payload status
const finalizedPayloadStatus = getCheckpointPayloadStatus(state, finalizedCheckpoint.epoch);

return new forkchoiceConstructor(
config,

Expand All @@ -113,6 +123,8 @@ export function initializeForkChoiceFromFinalizedState(
finalizedCheckpoint,
justifiedBalances,
justifiedBalancesGetter,
justifiedPayloadStatus,
finalizedPayloadStatus,
{
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
Expand Down Expand Up @@ -145,15 +157,12 @@ export function initializeForkChoiceFromFinalizedState(
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),

dataAvailabilityStatus: DataAvailabilityStatus.PreData,
...(computeEpochAtSlot(blockHeader.slot) < state.config.GLOAS_FORK_EPOCH
? {
builderIndex: undefined,
blockHashHex: undefined,
}
: {
builderIndex: (state as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex,
blockHashHex: toRootHex((state as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash),
}),
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
builderIndex: isForkPostGloas ? (state as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex : null,
blockHashFromBid: isForkPostGloas
? toRootHex((state as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash)
: null,
parentBlockHash: isForkPostGloas ? toRootHex((state as CachedBeaconStateGloas).latestBlockHash) : null,
},
currentSlot
),
Expand Down Expand Up @@ -196,12 +205,22 @@ export function initializeForkChoiceFromUnfinalizedState(

// this is not the justified state, but there is no other ways to get justified balances
const justifiedBalances = getEffectiveBalanceIncrementsZeroInactive(unfinalizedState);

const isForkPostGloas = (unfinalizedState as CachedBeaconStateGloas).latestBlockHash !== undefined;

// For unfinalized state, use getCheckpointPayloadStatus to determine the correct status.
// It checks state.execution_payload_availability to determine EMPTY vs FULL.
const justifiedPayloadStatus = getCheckpointPayloadStatus(unfinalizedState, justifiedCheckpoint.epoch);
const finalizedPayloadStatus = getCheckpointPayloadStatus(unfinalizedState, finalizedCheckpoint.epoch);

const store = new ForkChoiceStore(
currentSlot,
justifiedCheckpoint,
finalizedCheckpoint,
justifiedBalances,
justifiedBalancesGetter,
justifiedPayloadStatus,
finalizedPayloadStatus,
{
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
Expand Down Expand Up @@ -235,15 +254,14 @@ export function initializeForkChoiceFromUnfinalizedState(
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),

dataAvailabilityStatus: DataAvailabilityStatus.PreData,
...(computeEpochAtSlot(blockHeader.slot) < unfinalizedState.config.GLOAS_FORK_EPOCH
? {
builderIndex: undefined,
blockHashHex: undefined,
}
: {
builderIndex: (unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex,
blockHashHex: toRootHex((unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash),
}),
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
builderIndex: isForkPostGloas
? (unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex
: null,
blockHashFromBid: isForkPostGloas
? toRootHex((unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash)
: null,
parentBlockHash: isForkPostGloas ? toRootHex((unfinalizedState as CachedBeaconStateGloas).latestBlockHash) : null,
};

const parentSlot = blockHeader.slot - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ function isValidShuffling(
// attestation's shuffling is the same as the current state's.
// To account for skipped slots, find the first block at *or before* the pivot slot.
const beaconBlockRootHex = blockRootHex;
const beaconBlock = forkChoice.getBlockHex(beaconBlockRootHex);
const beaconBlock = forkChoice.getBlockHexDefaultStatus(beaconBlockRootHex);
if (!beaconBlock) {
return InvalidAttestationData.BlockNotInForkChoice;
}
Expand Down
9 changes: 7 additions & 2 deletions packages/beacon-node/src/chain/regen/queued.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {routes} from "@lodestar/api";
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
import {CachedBeaconStateAllForks, computeEpochAtSlot} from "@lodestar/state-transition";
import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lodestar/types";
import {Logger, toRootHex} from "@lodestar/utils";
import {Metrics} from "../../metrics/index.js";
import {JobItemQueue} from "../../util/queue/index.js";
Expand Down Expand Up @@ -88,7 +88,12 @@ export class QueuedStateRegenerator implements IStateRegenerator {
*/
getPreStateSync(block: BeaconBlock): CachedBeaconStateAllForks | null {
const parentRoot = toRootHex(block.parentRoot);
const parentBlock = this.forkChoice.getBlockHex(parentRoot);
const parentBlock = isGloasBeaconBlock(block)
? this.forkChoice.getBlockHexAndBlockHash(
parentRoot,
toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
)
: this.forkChoice.getBlockHexDefaultStatus(parentRoot);
if (!parentBlock) {
throw new RegenError({
code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
Expand Down
10 changes: 8 additions & 2 deletions packages/beacon-node/src/chain/regen/regen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
processSlots,
stateTransition,
} from "@lodestar/state-transition";
import {BeaconBlock, RootHex, SignedBeaconBlock, Slot} from "@lodestar/types";
import {BeaconBlock, RootHex, SignedBeaconBlock, Slot, isGloasBeaconBlock} from "@lodestar/types";
import {Logger, fromHex, toRootHex} from "@lodestar/utils";
import {IBeaconDb} from "../../db/index.js";
import {Metrics} from "../../metrics/index.js";
Expand Down Expand Up @@ -58,7 +58,13 @@ export class StateRegenerator implements IStateRegeneratorInternal {
opts: StateRegenerationOpts,
regenCaller: RegenCaller
): Promise<CachedBeaconStateAllForks> {
const parentBlock = this.modules.forkChoice.getBlock(block.parentRoot);
const parentRoot = toRootHex(block.parentRoot);
const parentBlock = isGloasBeaconBlock(block)
? this.modules.forkChoice.getBlockHexAndBlockHash(
parentRoot,
toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
)
: this.modules.forkChoice.getBlockHexDefaultStatus(parentRoot);
if (!parentBlock) {
throw new RegenError({
code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ async function validateAggregateAndProof(
});
}
// [REJECT] `aggregate.data.index == 0` if `block.slot == aggregate.data.slot`.
const block = chain.forkChoice.getBlock(attData.beaconBlockRoot);
const block = chain.forkChoice.getBlockDefaultStatus(attData.beaconBlockRoot);

// If block is unknown, we don't handle it here. It will throw error later on at `verifyHeadBlockAndTargetRoot()`
if (block !== null && block.slot === attData.slot && attData.index !== 0) {
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/chain/validation/attestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ async function validateAttestationNoSignatureCheck(
}

// [REJECT] `attestation.data.index == 0` if `block.slot == attestation.data.slot`.
const block = chain.forkChoice.getBlock(attData.beaconBlockRoot);
const block = chain.forkChoice.getBlockDefaultStatus(attData.beaconBlockRoot);

// block being null will be handled by `verifyHeadBlockAndTargetRoot`
if (block !== null && block.slot === attSlot && attData.index !== 0) {
Expand Down Expand Up @@ -753,7 +753,7 @@ export function getAttestationDataSigningRoot(config: BeaconConfig, data: phase0
function verifyHeadBlockIsKnown(chain: IBeaconChain, beaconBlockRoot: Root): ProtoBlock {
// TODO (LH): Enforce a maximum skip distance for unaggregated attestations.

const headBlock = chain.forkChoice.getBlock(beaconBlockRoot);
const headBlock = chain.forkChoice.getBlockDefaultStatus(beaconBlockRoot);
if (headBlock === null) {
throw new AttestationError(GossipAction.IGNORE, {
code: AttestationErrorCode.UNKNOWN_OR_PREFINALIZED_BEACON_BLOCK_ROOT,
Expand Down
Loading
Loading