@lodestar/fork-choice 1.43.0-dev.433e692fd9 → 1.43.0-dev.4358217e12

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,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;
@@ -707,7 +681,7 @@ export class ProtoArray {
707
681
  * Determine if we should extend the payload (prefer FULL over EMPTY)
708
682
  * Spec: gloas/fork-choice.md#new-should_extend_payload
709
683
  *
710
- * Returns true if:
684
+ * Returns true if payload is verified (FULL variant exists) AND:
711
685
  * 1. Payload is timely, OR
712
686
  * 2. No proposer boost root (empty/zero hash), OR
713
687
  * 3. Proposer boost root's parent is not this block, OR
@@ -717,6 +691,10 @@ export class ProtoArray {
717
691
  * @param proposerBoostRoot - Current proposer boost root (from ForkChoice)
718
692
  */
719
693
  shouldExtendPayload(blockRoot: RootHex, proposerBoostRoot: RootHex | null): boolean {
694
+ if (!this.hasPayload(blockRoot)) {
695
+ return false;
696
+ }
697
+
720
698
  // Condition 1: Payload is timely
721
699
  if (this.isPayloadTimely(blockRoot)) {
722
700
  return true;
@@ -1672,10 +1650,9 @@ export class ProtoArray {
1672
1650
  const ancestors: ProtoNode[] = [];
1673
1651
  const nonAncestors: ProtoNode[] = [];
1674
1652
 
1675
- // Include starting node if it's not PENDING (i.e., pre-Gloas or EMPTY/FULL variant post-Gloas)
1676
- if (node.payloadStatus !== PayloadStatus.PENDING) {
1677
- ancestors.push(node);
1678
- }
1653
+ // caller of this method may pass default status
1654
+ // this is the only node that we accept PENDING
1655
+ ancestors.push(node);
1679
1656
 
1680
1657
  let nodeIndex = startIndex;
1681
1658
  while (node.parent !== undefined) {