@lodestar/fork-choice 1.50.0-dev.cc4428df4b → 1.50.0-dev.ce0e732118

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.
Files changed (47) hide show
  1. package/lib/forkChoice/fastConfirmation/rules.d.ts.map +1 -1
  2. package/lib/forkChoice/fastConfirmation/rules.js +4 -1
  3. package/lib/forkChoice/fastConfirmation/rules.js.map +1 -1
  4. package/lib/forkChoice/fastConfirmation/types.d.ts +3 -1
  5. package/lib/forkChoice/fastConfirmation/types.d.ts.map +1 -1
  6. package/lib/forkChoice/fastConfirmation/utils.d.ts +2 -2
  7. package/lib/forkChoice/fastConfirmation/utils.d.ts.map +1 -1
  8. package/lib/forkChoice/fastConfirmation/utils.js +8 -3
  9. package/lib/forkChoice/fastConfirmation/utils.js.map +1 -1
  10. package/lib/forkChoice/forkChoice.d.ts +2 -1
  11. package/lib/forkChoice/forkChoice.d.ts.map +1 -1
  12. package/lib/forkChoice/forkChoice.js +60 -5
  13. package/lib/forkChoice/forkChoice.js.map +1 -1
  14. package/lib/forkChoice/interface.d.ts +9 -1
  15. package/lib/forkChoice/interface.d.ts.map +1 -1
  16. package/lib/forkChoice/interface.js.map +1 -1
  17. package/lib/forkChoice/store.d.ts +4 -1
  18. package/lib/forkChoice/store.d.ts.map +1 -1
  19. package/lib/forkChoice/store.js +3 -0
  20. package/lib/forkChoice/store.js.map +1 -1
  21. package/lib/index.d.ts +3 -3
  22. package/lib/index.d.ts.map +1 -1
  23. package/lib/index.js +1 -1
  24. package/lib/index.js.map +1 -1
  25. package/lib/metrics.d.ts +3 -0
  26. package/lib/metrics.d.ts.map +1 -1
  27. package/lib/metrics.js +5 -0
  28. package/lib/metrics.js.map +1 -1
  29. package/lib/protoArray/interface.d.ts +15 -0
  30. package/lib/protoArray/interface.d.ts.map +1 -1
  31. package/lib/protoArray/interface.js +13 -0
  32. package/lib/protoArray/interface.js.map +1 -1
  33. package/lib/protoArray/protoArray.d.ts +6 -1
  34. package/lib/protoArray/protoArray.d.ts.map +1 -1
  35. package/lib/protoArray/protoArray.js +23 -0
  36. package/lib/protoArray/protoArray.js.map +1 -1
  37. package/package.json +7 -7
  38. package/src/forkChoice/fastConfirmation/rules.ts +3 -0
  39. package/src/forkChoice/fastConfirmation/types.ts +3 -2
  40. package/src/forkChoice/fastConfirmation/utils.ts +12 -5
  41. package/src/forkChoice/forkChoice.ts +65 -6
  42. package/src/forkChoice/interface.ts +6 -0
  43. package/src/forkChoice/store.ts +7 -1
  44. package/src/index.ts +3 -1
  45. package/src/metrics.ts +5 -0
  46. package/src/protoArray/interface.ts +21 -0
  47. package/src/protoArray/protoArray.ts +24 -0
@@ -180,3 +180,24 @@ export type ProtoNode = ProtoBlock & {
180
180
  bestChild?: number;
181
181
  bestDescendant?: number;
182
182
  };
183
+
184
+ /**
185
+ * PTC majority per PayloadAttestationData field: `true` or `false` once more than PTC_SIZE // 2
186
+ * members voted that way, `null` while neither outcome has a majority.
187
+ */
188
+ export type PtcQuorum = {
189
+ payloadPresent: boolean | null;
190
+ blobDataAvailable: boolean | null;
191
+ };
192
+
193
+ /**
194
+ * The PTC verdict fork choice acts on: `false` once either field has a majority against the
195
+ * payload, `true` once both have a majority for it, `null` while undecided. A single majority
196
+ * against is final on its own because should_extend_payload needs both in favour and
197
+ * should_build_on_full moves the proposer onto EMPTY on either.
198
+ */
199
+ export function getPtcVerdict({payloadPresent, blobDataAvailable}: PtcQuorum): boolean | null {
200
+ if (payloadPresent === false || blobDataAvailable === false) return false;
201
+ if (payloadPresent === true && blobDataAvailable === true) return true;
202
+ return null;
203
+ }
@@ -13,6 +13,7 @@ import {
13
13
  PayloadStatus,
14
14
  ProtoBlock,
15
15
  ProtoNode,
16
+ PtcQuorum,
16
17
  isGloasBlock,
17
18
  } from "./interface.js";
18
19
 
@@ -52,6 +53,12 @@ export function countNoVotes(attended: BitArray, yes: BitArray): number {
52
53
  return count;
53
54
  }
54
55
 
56
+ function majorityVote(attended: BitArray, yes: BitArray, threshold: number): boolean | null {
57
+ if (bitCount(yes.uint8Array) > threshold) return true;
58
+ if (countNoVotes(attended, yes) > threshold) return false;
59
+ return null;
60
+ }
61
+
55
62
  export const DEFAULT_PRUNE_THRESHOLD = 0;
56
63
  type ProposerBoost = {root: RootHex; score: bigint};
57
64
 
@@ -801,6 +808,23 @@ export class ProtoArray {
801
808
  };
802
809
  }
803
810
 
811
+ /**
812
+ * PTC majority per vote field from the raw tallies, regardless of whether the payload is locally
813
+ * available. Returns `null` for pre-Gloas (or pruned) roots, which have no vote maps.
814
+ */
815
+ getPtcQuorum(blockRoot: RootHex): PtcQuorum | null {
816
+ const attended = this.ptcAttested.get(blockRoot);
817
+ const timelinessVotes = this.payloadTimelinessVotes.get(blockRoot);
818
+ const daVotes = this.payloadDataAvailabilityVotes.get(blockRoot);
819
+ if (attended === undefined || timelinessVotes === undefined || daVotes === undefined) {
820
+ return null;
821
+ }
822
+ return {
823
+ payloadPresent: majorityVote(attended, timelinessVotes, PAYLOAD_TIMELY_THRESHOLD),
824
+ blobDataAvailable: majorityVote(attended, daVotes, DATA_AVAILABILITY_TIMELY_THRESHOLD),
825
+ };
826
+ }
827
+
804
828
  getPreviousProposerBoostRoot(): RootHex {
805
829
  return this.previousProposerBoost?.root ?? HEX_ZERO_HASH;
806
830
  }