@lodestar/fork-choice 1.43.0-dev.9fa9f08ef6 → 1.43.0-dev.a140dd987e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import {ChainForkConfig} from "@lodestar/config";
2
- import {ForkSeq, SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
2
+ import {SLOTS_PER_EPOCH} from "@lodestar/params";
3
3
  import {
4
4
  DataAvailabilityStatus,
5
5
  EffectiveBalanceIncrements,
@@ -11,7 +11,6 @@ import {
11
11
  getAttesterSlashableIndices,
12
12
  isExecutionBlockBodyType,
13
13
  isStatePostBellatrix,
14
- isStatePostGloas,
15
14
  } from "@lodestar/state-transition";
16
15
  import {
17
16
  AttesterSlashing,
@@ -53,7 +52,7 @@ import {
53
52
  NotReorgedReason,
54
53
  ShouldOverrideForkChoiceUpdateResult,
55
54
  } from "./interface.js";
56
- import {CheckpointWithPayloadStatus, IForkChoiceStore, JustifiedBalances, toCheckpointWithPayload} from "./store.js";
55
+ import {CheckpointWithHex, IForkChoiceStore, JustifiedBalances, toCheckpointWithHex} from "./store.js";
57
56
 
58
57
  export type ForkChoiceOpts = {
59
58
  proposerBoost?: boolean;
@@ -564,11 +563,11 @@ export class ForkChoice implements IForkChoice {
564
563
  return this.protoArray.nodes;
565
564
  }
566
565
 
567
- getFinalizedCheckpoint(): CheckpointWithPayloadStatus {
566
+ getFinalizedCheckpoint(): CheckpointWithHex {
568
567
  return this.fcStore.finalizedCheckpoint;
569
568
  }
570
569
 
571
- getJustifiedCheckpoint(): CheckpointWithPayloadStatus {
570
+ getJustifiedCheckpoint(): CheckpointWithHex {
572
571
  return this.fcStore.justified.checkpoint;
573
572
  }
574
573
 
@@ -675,18 +674,10 @@ export class ForkChoice implements IForkChoice {
675
674
  this.proposerBoostRoot = blockRootHex;
676
675
  }
677
676
 
678
- // Get justified checkpoint with payload status for Gloas
679
- const justifiedPayloadStatus = getCheckpointPayloadStatus(
680
- this.config,
681
- state,
682
- state.currentJustifiedCheckpoint.epoch
683
- );
684
- const justifiedCheckpoint = toCheckpointWithPayload(state.currentJustifiedCheckpoint, justifiedPayloadStatus);
677
+ const justifiedCheckpoint = toCheckpointWithHex(state.currentJustifiedCheckpoint);
685
678
  const stateJustifiedEpoch = justifiedCheckpoint.epoch;
686
679
 
687
- // Get finalized checkpoint with payload status for Gloas
688
- const finalizedPayloadStatus = getCheckpointPayloadStatus(this.config, state, state.finalizedCheckpoint.epoch);
689
- const finalizedCheckpoint = toCheckpointWithPayload(state.finalizedCheckpoint, finalizedPayloadStatus);
680
+ const finalizedCheckpoint = toCheckpointWithHex(state.finalizedCheckpoint);
690
681
 
691
682
  // Justified balances for `justifiedCheckpoint` are new to the fork-choice. Compute them on demand only if
692
683
  // the justified checkpoint changes
@@ -708,61 +699,29 @@ export class ForkChoice implements IForkChoice {
708
699
  // This is an optimization. It should reduce the amount of times we run
709
700
  // `process_justification_and_finalization` by approximately 1/3rd when the chain is
710
701
  // performing optimally.
711
- let unrealizedJustifiedCheckpoint: CheckpointWithPayloadStatus;
712
- let unrealizedFinalizedCheckpoint: CheckpointWithPayloadStatus;
702
+ let unrealizedJustifiedCheckpoint: CheckpointWithHex;
703
+ let unrealizedFinalizedCheckpoint: CheckpointWithHex;
713
704
  if (this.opts?.computeUnrealized) {
714
705
  if (
715
706
  parentBlock.unrealizedJustifiedEpoch === blockEpoch &&
716
707
  parentBlock.unrealizedFinalizedEpoch + 1 >= blockEpoch
717
708
  ) {
718
709
  // reuse from parent, happens at 1/3 last blocks of epoch as monitored in mainnet
719
- // Get payload status for unrealized justified checkpoint
720
- const unrealizedJustifiedPayloadStatus = getCheckpointPayloadStatus(
721
- this.config,
722
- state,
723
- parentBlock.unrealizedJustifiedEpoch
724
- );
725
710
  unrealizedJustifiedCheckpoint = {
726
711
  epoch: parentBlock.unrealizedJustifiedEpoch,
727
712
  root: fromHex(parentBlock.unrealizedJustifiedRoot),
728
713
  rootHex: parentBlock.unrealizedJustifiedRoot,
729
- payloadStatus: unrealizedJustifiedPayloadStatus,
730
714
  };
731
- // Get payload status for unrealized finalized checkpoint
732
- const unrealizedFinalizedPayloadStatus = getCheckpointPayloadStatus(
733
- this.config,
734
- state,
735
- parentBlock.unrealizedFinalizedEpoch
736
- );
737
715
  unrealizedFinalizedCheckpoint = {
738
716
  epoch: parentBlock.unrealizedFinalizedEpoch,
739
717
  root: fromHex(parentBlock.unrealizedFinalizedRoot),
740
718
  rootHex: parentBlock.unrealizedFinalizedRoot,
741
- payloadStatus: unrealizedFinalizedPayloadStatus,
742
719
  };
743
720
  } else {
744
721
  // compute new, happens 2/3 first blocks of epoch as monitored in mainnet
745
722
  const unrealized = state.computeUnrealizedCheckpoints();
746
- // Get payload status for unrealized justified checkpoint
747
- const unrealizedJustifiedPayloadStatus = getCheckpointPayloadStatus(
748
- this.config,
749
- state,
750
- unrealized.justifiedCheckpoint.epoch
751
- );
752
- unrealizedJustifiedCheckpoint = toCheckpointWithPayload(
753
- unrealized.justifiedCheckpoint,
754
- unrealizedJustifiedPayloadStatus
755
- );
756
- // Get payload status for unrealized finalized checkpoint
757
- const unrealizedFinalizedPayloadStatus = getCheckpointPayloadStatus(
758
- this.config,
759
- state,
760
- unrealized.finalizedCheckpoint.epoch
761
- );
762
- unrealizedFinalizedCheckpoint = toCheckpointWithPayload(
763
- unrealized.finalizedCheckpoint,
764
- unrealizedFinalizedPayloadStatus
765
- );
723
+ unrealizedJustifiedCheckpoint = toCheckpointWithHex(unrealized.justifiedCheckpoint);
724
+ unrealizedFinalizedCheckpoint = toCheckpointWithHex(unrealized.finalizedCheckpoint);
766
725
  }
767
726
  } else {
768
727
  unrealizedJustifiedCheckpoint = justifiedCheckpoint;
@@ -988,7 +947,6 @@ export class ForkChoice implements IForkChoice {
988
947
  blockRoot: RootHex,
989
948
  executionPayloadBlockHash: RootHex,
990
949
  executionPayloadNumber: number,
991
- executionPayloadStateRoot: RootHex,
992
950
  executionStatus: PayloadExecutionStatus
993
951
  ): void {
994
952
  this.protoArray.onExecutionPayload(
@@ -996,7 +954,6 @@ export class ForkChoice implements IForkChoice {
996
954
  this.fcStore.currentSlot,
997
955
  executionPayloadBlockHash,
998
956
  executionPayloadNumber,
999
- executionPayloadStateRoot,
1000
957
  this.proposerBoostRoot,
1001
958
  executionStatus
1002
959
  );
@@ -1127,8 +1084,8 @@ export class ForkChoice implements IForkChoice {
1127
1084
  }
1128
1085
 
1129
1086
  getJustifiedBlock(): ProtoBlock {
1130
- const {rootHex, payloadStatus} = this.fcStore.justified.checkpoint;
1131
- const block = this.getBlockHex(rootHex, payloadStatus);
1087
+ const {rootHex} = this.fcStore.justified.checkpoint;
1088
+ const block = this.getBlockHexDefaultStatus(rootHex);
1132
1089
  if (!block) {
1133
1090
  throw new ForkChoiceError({
1134
1091
  code: ForkChoiceErrorCode.MISSING_PROTO_ARRAY_BLOCK,
@@ -1139,8 +1096,8 @@ export class ForkChoice implements IForkChoice {
1139
1096
  }
1140
1097
 
1141
1098
  getFinalizedBlock(): ProtoBlock {
1142
- const {rootHex, payloadStatus} = this.fcStore.finalizedCheckpoint;
1143
- const block = this.getBlockHex(rootHex, payloadStatus);
1099
+ const {rootHex} = this.fcStore.finalizedCheckpoint;
1100
+ const block = this.getBlockHexDefaultStatus(rootHex);
1144
1101
  if (!block) {
1145
1102
  throw new ForkChoiceError({
1146
1103
  code: ForkChoiceErrorCode.MISSING_PROTO_ARRAY_BLOCK,
@@ -1233,18 +1190,33 @@ export class ForkChoice implements IForkChoice {
1233
1190
 
1234
1191
  /**
1235
1192
  * Returns both ancestor and non-ancestor blocks in a single traversal.
1193
+ *
1194
+ * `ancestors` is the raw walk and includes the previous finalized block as its last element —
1195
+ * callers that don't want the boundary should slice it off themselves.
1196
+ * Post-gloas for each block root, it returns exactly one variant of it.
1236
1197
  */
1237
1198
  getAllAncestorAndNonAncestorBlocks(
1238
1199
  blockRoot: RootHex,
1239
1200
  payloadStatus: PayloadStatus
1240
1201
  ): {ancestors: ProtoBlock[]; nonAncestors: ProtoBlock[]} {
1241
- const {ancestors, nonAncestors} = this.protoArray.getAllAncestorAndNonAncestorNodes(blockRoot, payloadStatus);
1202
+ return this.protoArray.getAllAncestorAndNonAncestorNodes(blockRoot, payloadStatus);
1203
+ }
1242
1204
 
1243
- return {
1244
- // the last node is the previous finalized one, it's there to check onBlock finalized checkpoint only.
1245
- ancestors: ancestors.slice(0, ancestors.length - 1),
1246
- nonAncestors,
1247
- };
1205
+ /**
1206
+ * Same to getAllAncestorAndNonAncestorBlocks with default variant of ${blockRoot} to start with
1207
+ */
1208
+ getAllAncestorAndNonAncestorBlocksDefaultStatus(blockRoot: RootHex): {
1209
+ ancestors: ProtoBlock[];
1210
+ nonAncestors: ProtoBlock[];
1211
+ } {
1212
+ const defaultStatus = this.protoArray.getDefaultVariant(blockRoot);
1213
+ if (defaultStatus === undefined) {
1214
+ throw new ForkChoiceError({
1215
+ code: ForkChoiceErrorCode.MISSING_PROTO_ARRAY_BLOCK,
1216
+ root: blockRoot,
1217
+ });
1218
+ }
1219
+ return this.getAllAncestorAndNonAncestorBlocks(blockRoot, defaultStatus);
1248
1220
  }
1249
1221
 
1250
1222
  getCanonicalBlockByRoot(blockRoot: Root): ProtoBlock | null {
@@ -1316,6 +1288,17 @@ export class ForkChoice implements IForkChoice {
1316
1288
  }
1317
1289
  }
1318
1290
 
1291
+ forwardIterateDescendantsDefaultStatus(blockRoot: RootHex): IterableIterator<ProtoBlock> {
1292
+ const defaultStatus = this.protoArray.getDefaultVariant(blockRoot);
1293
+ if (defaultStatus === undefined) {
1294
+ throw new ForkChoiceError({
1295
+ code: ForkChoiceErrorCode.MISSING_PROTO_ARRAY_BLOCK,
1296
+ root: blockRoot,
1297
+ });
1298
+ }
1299
+ return this.forwardIterateDescendants(blockRoot, defaultStatus);
1300
+ }
1301
+
1319
1302
  /** Very expensive function, iterates the entire ProtoArray. TODO: Is this function even necessary? */
1320
1303
  getBlockSummariesByParentRoot(parentRoot: RootHex): ProtoBlock[] {
1321
1304
  return this.protoArray.nodes.filter((node) => node.parentRoot === parentRoot);
@@ -1502,12 +1485,12 @@ export class ForkChoice implements IForkChoice {
1502
1485
  *
1503
1486
  * **`on_tick`**
1504
1487
  * May need the justified balances of:
1505
- * - unrealizedJustified: Already available in `CheckpointWithPayloadAndBalance`
1488
+ * - unrealizedJustified: Already available in `CheckpointWithBalance`
1506
1489
  * Since this balances are already available the getter is just `() => balances`, without cache interaction
1507
1490
  */
1508
1491
  private updateCheckpoints(
1509
- justifiedCheckpoint: CheckpointWithPayloadStatus,
1510
- finalizedCheckpoint: CheckpointWithPayloadStatus,
1492
+ justifiedCheckpoint: CheckpointWithHex,
1493
+ finalizedCheckpoint: CheckpointWithHex,
1511
1494
  getJustifiedBalances: () => JustifiedBalances
1512
1495
  ): void {
1513
1496
  // Update justified checkpoint.
@@ -1527,8 +1510,8 @@ export class ForkChoice implements IForkChoice {
1527
1510
  * Update unrealized checkpoints in store if necessary
1528
1511
  */
1529
1512
  private updateUnrealizedCheckpoints(
1530
- unrealizedJustifiedCheckpoint: CheckpointWithPayloadStatus,
1531
- unrealizedFinalizedCheckpoint: CheckpointWithPayloadStatus,
1513
+ unrealizedJustifiedCheckpoint: CheckpointWithHex,
1514
+ unrealizedFinalizedCheckpoint: CheckpointWithHex,
1532
1515
  getJustifiedBalances: () => JustifiedBalances
1533
1516
  ): void {
1534
1517
  if (unrealizedJustifiedCheckpoint.epoch > this.fcStore.unrealizedJustified.checkpoint.epoch) {
@@ -1903,38 +1886,3 @@ export function getCommitteeFraction(
1903
1886
  const committeeWeight = Math.floor(justifiedTotalActiveBalanceByIncrement / config.slotsPerEpoch);
1904
1887
  return Math.floor((committeeWeight * config.committeePercent) / 100);
1905
1888
  }
1906
-
1907
- /**
1908
- * Get the payload status for a checkpoint.
1909
- *
1910
- * Pre-Gloas: always FULL (payload embedded in block)
1911
- * Gloas: determined by state.execution_payload_availability
1912
- *
1913
- * @param config - The chain fork config to determine fork at checkpoint slot
1914
- * @param state - The state to check execution_payload_availability
1915
- * @param checkpointEpoch - The epoch of the checkpoint
1916
- */
1917
- export function getCheckpointPayloadStatus(
1918
- config: ChainForkConfig,
1919
- state: IBeaconStateView,
1920
- checkpointEpoch: number
1921
- ): PayloadStatus {
1922
- // Compute checkpoint slot first to determine the correct fork
1923
- const checkpointSlot = computeStartSlotAtEpoch(checkpointEpoch);
1924
- const fork = config.getForkSeq(checkpointSlot);
1925
-
1926
- // Pre-Gloas: always FULL
1927
- if (fork < ForkSeq.gloas) {
1928
- return PayloadStatus.FULL;
1929
- }
1930
- if (!isStatePostGloas(state)) {
1931
- throw new Error(`Expected gloas+ state for checkpoint payload status, got fork=${state.forkName}`);
1932
- }
1933
-
1934
- // For Gloas, check state.execution_payload_availability
1935
- // - For non-skipped slots at checkpoint: returns false (EMPTY) since payload hasn't arrived yet
1936
- // - For skipped slots at checkpoint: returns the actual availability status from state
1937
- const payloadAvailable = state.executionPayloadAvailability.get(checkpointSlot % SLOTS_PER_HISTORICAL_ROOT);
1938
-
1939
- return payloadAvailable ? PayloadStatus.FULL : PayloadStatus.EMPTY;
1940
- }
@@ -9,7 +9,7 @@ import {
9
9
  ProtoNode,
10
10
  } from "../protoArray/interface.js";
11
11
  import {UpdateAndGetHeadOpt} from "./forkChoice.js";
12
- import {CheckpointWithHex, CheckpointWithPayloadStatus} from "./store.js";
12
+ import {CheckpointWithHex} from "./store.js";
13
13
 
14
14
  export type CheckpointHex = {
15
15
  epoch: Epoch;
@@ -21,12 +21,12 @@ export type CheckpointsWithHex = {
21
21
  finalizedCheckpoint: CheckpointWithHex;
22
22
  };
23
23
 
24
- export type CheckpointWithPayloadAndBalance = {
25
- checkpoint: CheckpointWithPayloadStatus;
24
+ export type CheckpointWithBalance = {
25
+ checkpoint: CheckpointWithHex;
26
26
  balances: EffectiveBalanceIncrements;
27
27
  };
28
28
 
29
- export type CheckpointWithPayloadAndTotalBalance = CheckpointWithPayloadAndBalance & {
29
+ export type CheckpointWithTotalBalance = CheckpointWithBalance & {
30
30
  totalBalance: number;
31
31
  };
32
32
 
@@ -121,8 +121,8 @@ export interface IForkChoice {
121
121
  * Retrieve all nodes for the debug API.
122
122
  */
123
123
  getAllNodes(): ProtoNode[];
124
- getFinalizedCheckpoint(): CheckpointWithPayloadStatus;
125
- getJustifiedCheckpoint(): CheckpointWithPayloadStatus;
124
+ getFinalizedCheckpoint(): CheckpointWithHex;
125
+ getJustifiedCheckpoint(): CheckpointWithHex;
126
126
  /**
127
127
  * Add `block` to the fork choice DAG.
128
128
  *
@@ -198,13 +198,11 @@ export interface IForkChoice {
198
198
  * @param blockRoot - The beacon block root for which the payload arrived
199
199
  * @param executionPayloadBlockHash - The block hash of the execution payload
200
200
  * @param executionPayloadNumber - The block number of the execution payload
201
- * @param executionPayloadStateRoot - The execution payload state root ie. the root of post-state after processExecutionPayloadEnvelope()
202
201
  */
203
202
  onExecutionPayload(
204
203
  blockRoot: RootHex,
205
204
  executionPayloadBlockHash: RootHex,
206
205
  executionPayloadNumber: number,
207
- executionPayloadStateRoot: RootHex,
208
206
  executionStatus: PayloadExecutionStatus
209
207
  ): void;
210
208
  /**
@@ -273,11 +271,23 @@ export interface IForkChoice {
273
271
  getAllNonAncestorBlocks(blockRoot: RootHex, payloadStatus: PayloadStatus): ProtoBlock[];
274
272
  /**
275
273
  * Returns both ancestor and non-ancestor blocks in a single traversal.
274
+ *
275
+ * `ancestors` is the raw walk and includes the previous finalized block as its last element —
276
+ * callers that don't want the boundary should slice it off themselves.
276
277
  */
277
278
  getAllAncestorAndNonAncestorBlocks(
278
279
  blockRoot: RootHex,
279
280
  payloadStatus: PayloadStatus
280
281
  ): {ancestors: ProtoBlock[]; nonAncestors: ProtoBlock[]};
282
+ /**
283
+ * Same as `getAllAncestorAndNonAncestorBlocks` but resolves the default payload-status variant
284
+ * (FULL pre-Gloas, PENDING for Gloas) for the given root. Use when the caller holds a
285
+ * `CheckpointWithHex` / finalized root without a specific payload-status variant in mind.
286
+ */
287
+ getAllAncestorAndNonAncestorBlocksDefaultStatus(blockRoot: RootHex): {
288
+ ancestors: ProtoBlock[];
289
+ nonAncestors: ProtoBlock[];
290
+ };
281
291
  getCanonicalBlockByRoot(blockRoot: Root): ProtoBlock | null;
282
292
  getCanonicalBlockAtSlot(slot: Slot): ProtoBlock | null;
283
293
  getCanonicalBlockClosestLteSlot(slot: Slot): ProtoBlock | null;
@@ -289,6 +299,12 @@ export interface IForkChoice {
289
299
  * Iterates forward descendants of blockRoot. Does not yield blockRoot itself
290
300
  */
291
301
  forwardIterateDescendants(blockRoot: RootHex, payloadStatus: PayloadStatus): IterableIterator<ProtoBlock>;
302
+ /**
303
+ * Same as `forwardIterateDescendants` but resolves the default payload-status variant
304
+ * (FULL pre-Gloas, PENDING for Gloas) for the given root. Use when the caller holds a
305
+ * `CheckpointWithHex` / finalized root without a specific payload-status variant in mind.
306
+ */
307
+ forwardIterateDescendantsDefaultStatus(blockRoot: RootHex): IterableIterator<ProtoBlock>;
292
308
  getBlockSummariesByParentRoot(parentRoot: RootHex): ProtoBlock[];
293
309
  getBlockSummariesAtSlot(slot: Slot): ProtoBlock[];
294
310
  /** Returns the distance of common ancestor of nodes to the max of the newNode and the prevNode. */
@@ -1,8 +1,7 @@
1
1
  import {EffectiveBalanceIncrements, IBeaconStateView} from "@lodestar/state-transition";
2
2
  import {RootHex, Slot, ValidatorIndex, phase0} from "@lodestar/types";
3
3
  import {toRootHex} from "@lodestar/utils";
4
- import {PayloadStatus} from "../protoArray/interface.js";
5
- import {CheckpointWithPayloadAndBalance, CheckpointWithPayloadAndTotalBalance} from "./interface.js";
4
+ import {CheckpointWithBalance, CheckpointWithTotalBalance} from "./interface.js";
6
5
 
7
6
  /**
8
7
  * Stores checkpoints in a hybrid format:
@@ -11,15 +10,6 @@ import {CheckpointWithPayloadAndBalance, CheckpointWithPayloadAndTotalBalance} f
11
10
  */
12
11
  export type CheckpointWithHex = phase0.Checkpoint & {rootHex: RootHex};
13
12
 
14
- /**
15
- * Checkpoint with payload status for Gloas fork choice.
16
- * Used to track which variant (EMPTY or FULL) of the finalized/justified block to use.
17
- *
18
- * Pre-Gloas: payloadStatus is always FULL (payload embedded in block)
19
- * Gloas: determined by state.execution_payload_availability
20
- */
21
- export type CheckpointWithPayloadStatus = CheckpointWithHex & {payloadStatus: PayloadStatus};
22
-
23
13
  export type JustifiedBalances = EffectiveBalanceIncrements;
24
14
 
25
15
  /**
@@ -29,7 +19,7 @@ export type JustifiedBalances = EffectiveBalanceIncrements;
29
19
  * @param blockState state that declares justified checkpoint `checkpoint`
30
20
  */
31
21
  export type JustifiedBalancesGetter = (
32
- checkpoint: CheckpointWithPayloadStatus,
22
+ checkpoint: CheckpointWithHex,
33
23
  blockState: IBeaconStateView
34
24
  ) => JustifiedBalances;
35
25
 
@@ -47,11 +37,11 @@ export type JustifiedBalancesGetter = (
47
37
  */
48
38
  export interface IForkChoiceStore {
49
39
  currentSlot: Slot;
50
- get justified(): CheckpointWithPayloadAndTotalBalance;
51
- set justified(justified: CheckpointWithPayloadAndBalance);
52
- unrealizedJustified: CheckpointWithPayloadAndBalance;
53
- finalizedCheckpoint: CheckpointWithPayloadStatus;
54
- unrealizedFinalizedCheckpoint: CheckpointWithPayloadStatus;
40
+ get justified(): CheckpointWithTotalBalance;
41
+ set justified(justified: CheckpointWithBalance);
42
+ unrealizedJustified: CheckpointWithBalance;
43
+ finalizedCheckpoint: CheckpointWithHex;
44
+ unrealizedFinalizedCheckpoint: CheckpointWithHex;
55
45
  justifiedBalancesGetter: JustifiedBalancesGetter;
56
46
  equivocatingIndices: Set<ValidatorIndex>;
57
47
  }
@@ -60,10 +50,10 @@ export interface IForkChoiceStore {
60
50
  * IForkChoiceStore implementer which emits forkChoice events on updated justified and finalized checkpoints.
61
51
  */
62
52
  export class ForkChoiceStore implements IForkChoiceStore {
63
- private _justified: CheckpointWithPayloadAndTotalBalance;
64
- unrealizedJustified: CheckpointWithPayloadAndBalance;
65
- private _finalizedCheckpoint: CheckpointWithPayloadStatus;
66
- unrealizedFinalizedCheckpoint: CheckpointWithPayloadStatus;
53
+ private _justified: CheckpointWithTotalBalance;
54
+ unrealizedJustified: CheckpointWithBalance;
55
+ private _finalizedCheckpoint: CheckpointWithHex;
56
+ unrealizedFinalizedCheckpoint: CheckpointWithHex;
67
57
  equivocatingIndices = new Set<ValidatorIndex>();
68
58
  justifiedBalancesGetter: JustifiedBalancesGetter;
69
59
  currentSlot: Slot;
@@ -74,49 +64,37 @@ export class ForkChoiceStore implements IForkChoiceStore {
74
64
  finalizedCheckpoint: phase0.Checkpoint,
75
65
  justifiedBalances: EffectiveBalanceIncrements,
76
66
  justifiedBalancesGetter: JustifiedBalancesGetter,
77
- /**
78
- * Payload status for justified checkpoint.
79
- * Pre-Gloas: always FULL
80
- * Gloas: determined by state.execution_payload_availability
81
- */
82
- justifiedPayloadStatus: PayloadStatus,
83
- /**
84
- * Payload status for finalized checkpoint.
85
- * Pre-Gloas: always FULL
86
- * Gloas: determined by state.execution_payload_availability
87
- */
88
- finalizedPayloadStatus: PayloadStatus,
89
67
  private readonly events?: {
90
- onJustified: (cp: CheckpointWithPayloadStatus) => void;
91
- onFinalized: (cp: CheckpointWithPayloadStatus) => void;
68
+ onJustified: (cp: CheckpointWithHex) => void;
69
+ onFinalized: (cp: CheckpointWithHex) => void;
92
70
  }
93
71
  ) {
94
72
  this.justifiedBalancesGetter = justifiedBalancesGetter;
95
73
  this.currentSlot = currentSlot;
96
74
  const justified = {
97
- checkpoint: toCheckpointWithPayload(justifiedCheckpoint, justifiedPayloadStatus),
75
+ checkpoint: toCheckpointWithHex(justifiedCheckpoint),
98
76
  balances: justifiedBalances,
99
77
  totalBalance: computeTotalBalance(justifiedBalances),
100
78
  };
101
79
  this._justified = justified;
102
80
  this.unrealizedJustified = justified;
103
- this._finalizedCheckpoint = toCheckpointWithPayload(finalizedCheckpoint, finalizedPayloadStatus);
81
+ this._finalizedCheckpoint = toCheckpointWithHex(finalizedCheckpoint);
104
82
  this.unrealizedFinalizedCheckpoint = this._finalizedCheckpoint;
105
83
  }
106
84
 
107
- get justified(): CheckpointWithPayloadAndTotalBalance {
85
+ get justified(): CheckpointWithTotalBalance {
108
86
  return this._justified;
109
87
  }
110
- set justified(justified: CheckpointWithPayloadAndBalance) {
88
+ set justified(justified: CheckpointWithBalance) {
111
89
  this._justified = {...justified, totalBalance: computeTotalBalance(justified.balances)};
112
90
  this.events?.onJustified(justified.checkpoint);
113
91
  }
114
92
 
115
- get finalizedCheckpoint(): CheckpointWithPayloadStatus {
93
+ get finalizedCheckpoint(): CheckpointWithHex {
116
94
  return this._finalizedCheckpoint;
117
95
  }
118
- set finalizedCheckpoint(checkpoint: CheckpointWithPayloadStatus) {
119
- const cp = toCheckpointWithPayload(checkpoint, checkpoint.payloadStatus);
96
+ set finalizedCheckpoint(checkpoint: CheckpointWithHex) {
97
+ const cp = toCheckpointWithHex(checkpoint);
120
98
  this._finalizedCheckpoint = cp;
121
99
  this.events?.onFinalized(cp);
122
100
  }
@@ -133,16 +111,6 @@ export function toCheckpointWithHex(checkpoint: phase0.Checkpoint): CheckpointWi
133
111
  };
134
112
  }
135
113
 
136
- export function toCheckpointWithPayload(
137
- checkpoint: phase0.Checkpoint,
138
- payloadStatus: PayloadStatus
139
- ): CheckpointWithPayloadStatus {
140
- return {
141
- ...toCheckpointWithHex(checkpoint),
142
- payloadStatus,
143
- };
144
- }
145
-
146
114
  export function equalCheckpointWithHex(a: CheckpointWithHex, b: CheckpointWithHex): boolean {
147
115
  return a.epoch === b.epoch && a.rootHex === b.rootHex;
148
116
  }
package/src/index.ts CHANGED
@@ -6,17 +6,12 @@ export {
6
6
  type InvalidBlock,
7
7
  InvalidBlockCode,
8
8
  } from "./forkChoice/errors.js";
9
- export {
10
- ForkChoice,
11
- type ForkChoiceOpts,
12
- UpdateHeadOpt,
13
- getCheckpointPayloadStatus,
14
- } from "./forkChoice/forkChoice.js";
9
+ export {ForkChoice, type ForkChoiceOpts, UpdateHeadOpt} from "./forkChoice/forkChoice.js";
15
10
  export {
16
11
  type AncestorResult,
17
12
  AncestorStatus,
18
- type CheckpointWithPayloadAndBalance,
19
- type CheckpointWithPayloadAndTotalBalance,
13
+ type CheckpointWithBalance,
14
+ type CheckpointWithTotalBalance,
20
15
  EpochDifference,
21
16
  type IForkChoice,
22
17
  NotReorgedReason,
@@ -24,7 +19,6 @@ export {
24
19
  export * from "./forkChoice/safeBlocks.js";
25
20
  export {
26
21
  type CheckpointWithHex,
27
- type CheckpointWithPayloadStatus,
28
22
  ForkChoiceStore,
29
23
  type IForkChoiceStore,
30
24
  type JustifiedBalancesGetter,
@@ -109,30 +109,6 @@ export class ProtoArray {
109
109
  null
110
110
  );
111
111
 
112
- // Anchor block PTC votes must be all-true per spec get_forkchoice_store:
113
- // payload_timeliness_vote={anchor_root: Vector[boolean, PTC_SIZE](True for _ in range(PTC_SIZE))}
114
- // Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.4/specs/gloas/fork-choice.md#modified-get_forkchoice_store
115
- if (protoArray.ptcVotes.has(block.blockRoot)) {
116
- protoArray.ptcVotes.set(block.blockRoot, BitArray.fromBoolArray(Array.from({length: PTC_SIZE}, () => true)));
117
-
118
- // In the spec, we have payload_states = {anchor_root: anchor_state.copy()}
119
- // which means the anchor's "payload" is considered received
120
- // Without FULL, blocks extending FULL from the anchor would be orphaned.
121
- // TODO GLOAS: This is a bug in the spec. Keep this to pass the current spec test
122
- // for now. Need to remove this when we work on v1.7.0-alpha.5
123
- if (block.executionPayloadBlockHash !== null) {
124
- protoArray.onExecutionPayload(
125
- block.blockRoot,
126
- currentSlot,
127
- block.executionPayloadBlockHash,
128
- (block as {executionPayloadNumber?: number}).executionPayloadNumber ?? 0,
129
- block.stateRoot,
130
- null,
131
- ExecutionStatus.Valid
132
- );
133
- }
134
- }
135
-
136
112
  return protoArray;
137
113
  }
138
114
 
@@ -572,7 +548,6 @@ export class ProtoArray {
572
548
  currentSlot: Slot,
573
549
  executionPayloadBlockHash: RootHex,
574
550
  executionPayloadNumber: number,
575
- executionPayloadStateRoot: RootHex,
576
551
  proposerBoostRoot: RootHex | null,
577
552
  executionStatus: PayloadExecutionStatus
578
553
  ): void {
@@ -628,7 +603,6 @@ export class ProtoArray {
628
603
  executionStatus,
629
604
  executionPayloadBlockHash,
630
605
  executionPayloadNumber,
631
- stateRoot: executionPayloadStateRoot,
632
606
  };
633
607
 
634
608
  const fullIndex = this.nodes.length;
@@ -1676,10 +1650,9 @@ export class ProtoArray {
1676
1650
  const ancestors: ProtoNode[] = [];
1677
1651
  const nonAncestors: ProtoNode[] = [];
1678
1652
 
1679
- // Include starting node if it's not PENDING (i.e., pre-Gloas or EMPTY/FULL variant post-Gloas)
1680
- if (node.payloadStatus !== PayloadStatus.PENDING) {
1681
- ancestors.push(node);
1682
- }
1653
+ // caller of this method may pass default status
1654
+ // this is the only node that we accept PENDING
1655
+ ancestors.push(node);
1683
1656
 
1684
1657
  let nodeIndex = startIndex;
1685
1658
  while (node.parent !== undefined) {