@lodestar/fork-choice 1.44.0-dev.41c6b9d097 → 1.44.0-dev.44ca853f73

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 (64) hide show
  1. package/lib/forkChoice/fastConfirmation/data.d.ts +4 -0
  2. package/lib/forkChoice/fastConfirmation/data.d.ts.map +1 -0
  3. package/lib/forkChoice/fastConfirmation/data.js +31 -0
  4. package/lib/forkChoice/fastConfirmation/data.js.map +1 -0
  5. package/lib/forkChoice/fastConfirmation/fastConfirmationRule.d.ts +17 -0
  6. package/lib/forkChoice/fastConfirmation/fastConfirmationRule.d.ts.map +1 -0
  7. package/lib/forkChoice/fastConfirmation/fastConfirmationRule.js +129 -0
  8. package/lib/forkChoice/fastConfirmation/fastConfirmationRule.js.map +1 -0
  9. package/lib/forkChoice/fastConfirmation/index.d.ts +4 -0
  10. package/lib/forkChoice/fastConfirmation/index.d.ts.map +1 -0
  11. package/lib/forkChoice/fastConfirmation/index.js +4 -0
  12. package/lib/forkChoice/fastConfirmation/index.js.map +1 -0
  13. package/lib/forkChoice/fastConfirmation/metrics.d.ts +21 -0
  14. package/lib/forkChoice/fastConfirmation/metrics.d.ts.map +1 -0
  15. package/lib/forkChoice/fastConfirmation/metrics.js +42 -0
  16. package/lib/forkChoice/fastConfirmation/metrics.js.map +1 -0
  17. package/lib/forkChoice/fastConfirmation/rules.d.ts +9 -0
  18. package/lib/forkChoice/fastConfirmation/rules.d.ts.map +1 -0
  19. package/lib/forkChoice/fastConfirmation/rules.js +91 -0
  20. package/lib/forkChoice/fastConfirmation/rules.js.map +1 -0
  21. package/lib/forkChoice/fastConfirmation/types.d.ts +101 -0
  22. package/lib/forkChoice/fastConfirmation/types.d.ts.map +1 -0
  23. package/lib/forkChoice/fastConfirmation/types.js +12 -0
  24. package/lib/forkChoice/fastConfirmation/types.js.map +1 -0
  25. package/lib/forkChoice/fastConfirmation/utils.d.ts +47 -0
  26. package/lib/forkChoice/fastConfirmation/utils.d.ts.map +1 -0
  27. package/lib/forkChoice/fastConfirmation/utils.js +681 -0
  28. package/lib/forkChoice/fastConfirmation/utils.js.map +1 -0
  29. package/lib/forkChoice/forkChoice.d.ts +8 -0
  30. package/lib/forkChoice/forkChoice.d.ts.map +1 -1
  31. package/lib/forkChoice/forkChoice.js +84 -5
  32. package/lib/forkChoice/forkChoice.js.map +1 -1
  33. package/lib/forkChoice/interface.d.ts +2 -0
  34. package/lib/forkChoice/interface.d.ts.map +1 -1
  35. package/lib/forkChoice/safeBlocks.d.ts +2 -6
  36. package/lib/forkChoice/safeBlocks.d.ts.map +1 -1
  37. package/lib/forkChoice/safeBlocks.js +15 -7
  38. package/lib/forkChoice/safeBlocks.js.map +1 -1
  39. package/lib/forkChoice/store.d.ts +13 -2
  40. package/lib/forkChoice/store.d.ts.map +1 -1
  41. package/lib/forkChoice/store.js +29 -1
  42. package/lib/forkChoice/store.js.map +1 -1
  43. package/lib/index.d.ts +1 -0
  44. package/lib/index.d.ts.map +1 -1
  45. package/lib/index.js +1 -0
  46. package/lib/index.js.map +1 -1
  47. package/lib/metrics.d.ts +12 -1
  48. package/lib/metrics.d.ts.map +1 -1
  49. package/lib/metrics.js +2 -0
  50. package/lib/metrics.js.map +1 -1
  51. package/package.json +7 -7
  52. package/src/forkChoice/fastConfirmation/data.ts +43 -0
  53. package/src/forkChoice/fastConfirmation/fastConfirmationRule.ts +159 -0
  54. package/src/forkChoice/fastConfirmation/index.ts +3 -0
  55. package/src/forkChoice/fastConfirmation/metrics.ts +44 -0
  56. package/src/forkChoice/fastConfirmation/rules.ts +124 -0
  57. package/src/forkChoice/fastConfirmation/types.ts +111 -0
  58. package/src/forkChoice/fastConfirmation/utils.ts +968 -0
  59. package/src/forkChoice/forkChoice.ts +101 -6
  60. package/src/forkChoice/interface.ts +2 -0
  61. package/src/forkChoice/safeBlocks.ts +15 -7
  62. package/src/forkChoice/store.ts +34 -1
  63. package/src/index.ts +11 -0
  64. package/src/metrics.ts +3 -1
@@ -1,5 +1,6 @@
1
1
  import { EffectiveBalanceIncrements, IBeaconStateView } from "@lodestar/state-transition";
2
2
  import { RootHex, Slot, ValidatorIndex, phase0 } from "@lodestar/types";
3
+ import { ForkChoiceStateGetter, IFastConfirmationStore } from "./fastConfirmation/types.ts";
3
4
  import { CheckpointWithBalance, CheckpointWithTotalBalance } from "./interface.js";
4
5
  /**
5
6
  * Stores checkpoints in a hybrid format:
@@ -29,7 +30,7 @@ export type JustifiedBalancesGetter = (checkpoint: CheckpointWithHex, blockState
29
30
  * - The actual block DAG in `ProtoArray`.
30
31
  * - `time` is represented using `Slot` instead of UNIX epoch `u64`.
31
32
  */
32
- export interface IForkChoiceStore {
33
+ export interface IForkChoiceStore extends IFastConfirmationStore {
33
34
  currentSlot: Slot;
34
35
  get justified(): CheckpointWithTotalBalance;
35
36
  set justified(justified: CheckpointWithBalance);
@@ -51,7 +52,17 @@ export declare class ForkChoiceStore implements IForkChoiceStore {
51
52
  equivocatingIndices: Set<number>;
52
53
  justifiedBalancesGetter: JustifiedBalancesGetter;
53
54
  currentSlot: Slot;
54
- constructor(currentSlot: Slot, justifiedCheckpoint: phase0.Checkpoint, finalizedCheckpoint: phase0.Checkpoint, justifiedBalances: EffectiveBalanceIncrements, justifiedBalancesGetter: JustifiedBalancesGetter, events?: {
55
+ confirmedRoot: RootHex;
56
+ previousEpochObservedJustifiedCheckpoint: CheckpointWithHex;
57
+ currentEpochObservedJustifiedCheckpoint: CheckpointWithHex;
58
+ previousEpochGreatestUnrealizedCheckpoint: CheckpointWithHex;
59
+ previousSlotHead: RootHex;
60
+ currentSlotHead: RootHex;
61
+ previousEpochObservedJustifiedBalances: JustifiedBalances;
62
+ currentEpochObservedJustifiedBalances: JustifiedBalances;
63
+ previousEpochGreatestUnrealizedBalances: JustifiedBalances;
64
+ stateGetter: ForkChoiceStateGetter;
65
+ constructor(currentSlot: Slot, justifiedCheckpoint: phase0.Checkpoint, finalizedCheckpoint: phase0.Checkpoint, justifiedBalances: EffectiveBalanceIncrements, justifiedBalancesGetter: JustifiedBalancesGetter, stateGetter: ForkChoiceStateGetter, events?: {
55
66
  onJustified: (cp: CheckpointWithHex) => void;
56
67
  onFinalized: (cp: CheckpointWithHex) => void;
57
68
  } | undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/forkChoice/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,0BAA0B,EAAE,gBAAgB,EAAC,MAAM,4BAA4B,CAAC;AACxF,OAAO,EAAC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAC,qBAAqB,EAAE,0BAA0B,EAAC,MAAM,gBAAgB,CAAC;AAEjF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,UAAU,GAAG;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CAAC;AAEvE,MAAM,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,CACpC,UAAU,EAAE,iBAAiB,EAC7B,UAAU,EAAE,gBAAgB,KACzB,iBAAiB,CAAC;AAEvB;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,IAAI,CAAC;IAClB,IAAI,SAAS,IAAI,0BAA0B,CAAC;IAC5C,IAAI,SAAS,CAAC,SAAS,EAAE,qBAAqB,EAAE;IAChD,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,mBAAmB,EAAE,iBAAiB,CAAC;IACvC,6BAA6B,EAAE,iBAAiB,CAAC;IACjD,uBAAuB,EAAE,uBAAuB,CAAC;IACjD,mBAAmB,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC1C;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IAepD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAd1B,OAAO,CAAC,UAAU,CAA6B;IAC/C,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,OAAO,CAAC,oBAAoB,CAAoB;IAChD,6BAA6B,EAAE,iBAAiB,CAAC;IACjD,mBAAmB,cAA6B;IAChD,uBAAuB,EAAE,uBAAuB,CAAC;IACjD,WAAW,EAAE,IAAI,CAAC;IAElB,YACE,WAAW,EAAE,IAAI,EACjB,mBAAmB,EAAE,MAAM,CAAC,UAAU,EACtC,mBAAmB,EAAE,MAAM,CAAC,UAAU,EACtC,iBAAiB,EAAE,0BAA0B,EAC7C,uBAAuB,EAAE,uBAAuB,EAC/B,MAAM,CAAC;;;iBAGvB,EAaF;IAED,IAAI,SAAS,IAAI,0BAA0B,CAE1C;IACD,IAAI,SAAS,CAAC,SAAS,EAAE,qBAAqB,EAG7C;IAED,IAAI,mBAAmB,IAAI,iBAAiB,CAE3C;IACD,IAAI,mBAAmB,CAAC,UAAU,EAAE,iBAAiB,EAIpD;CACF;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,GAAG,iBAAiB,CASpF;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAE1F;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,0BAA0B,GAAG,MAAM,CAMhF"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/forkChoice/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,0BAA0B,EAAE,gBAAgB,EAAC,MAAM,4BAA4B,CAAC;AACxF,OAAO,EAAC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAC,qBAAqB,EAAE,sBAAsB,EAAC,MAAM,6BAA6B,CAAC;AAC1F,OAAO,EAAC,qBAAqB,EAAE,0BAA0B,EAAC,MAAM,gBAAgB,CAAC;AAEjF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,UAAU,GAAG;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CAAC;AAEvE,MAAM,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,CACpC,UAAU,EAAE,iBAAiB,EAC7B,UAAU,EAAE,gBAAgB,KACzB,iBAAiB,CAAC;AAEvB;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAiB,SAAQ,sBAAsB;IAC9D,WAAW,EAAE,IAAI,CAAC;IAClB,IAAI,SAAS,IAAI,0BAA0B,CAAC;IAC5C,IAAI,SAAS,CAAC,SAAS,EAAE,qBAAqB,EAAE;IAChD,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,mBAAmB,EAAE,iBAAiB,CAAC;IACvC,6BAA6B,EAAE,iBAAiB,CAAC;IACjD,uBAAuB,EAAE,uBAAuB,CAAC;IACjD,mBAAmB,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CAC1C;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IA8BpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IA7B1B,OAAO,CAAC,UAAU,CAA6B;IAC/C,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,OAAO,CAAC,oBAAoB,CAAoB;IAChD,6BAA6B,EAAE,iBAAiB,CAAC;IACjD,mBAAmB,cAA6B;IAChD,uBAAuB,EAAE,uBAAuB,CAAC;IACjD,WAAW,EAAE,IAAI,CAAC;IAGlB,aAAa,EAAE,OAAO,CAAC;IACvB,wCAAwC,EAAE,iBAAiB,CAAC;IAC5D,uCAAuC,EAAE,iBAAiB,CAAC;IAC3D,yCAAyC,EAAE,iBAAiB,CAAC;IAC7D,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IAGzB,sCAAsC,EAAE,iBAAiB,CAAC;IAC1D,qCAAqC,EAAE,iBAAiB,CAAC;IACzD,uCAAuC,EAAE,iBAAiB,CAAC;IAC3D,WAAW,EAAE,qBAAqB,CAAC;IAEnC,YACE,WAAW,EAAE,IAAI,EACjB,mBAAmB,EAAE,MAAM,CAAC,UAAU,EACtC,mBAAmB,EAAE,MAAM,CAAC,UAAU,EACtC,iBAAiB,EAAE,0BAA0B,EAC7C,uBAAuB,EAAE,uBAAuB,EAChD,WAAW,EAAE,qBAAqB,EACjB,MAAM,CAAC;;;iBAGvB,EA8BF;IAED,IAAI,SAAS,IAAI,0BAA0B,CAE1C;IACD,IAAI,SAAS,CAAC,SAAS,EAAE,qBAAqB,EAG7C;IAED,IAAI,mBAAmB,IAAI,iBAAiB,CAE3C;IACD,IAAI,mBAAmB,CAAC,UAAU,EAAE,iBAAiB,EAIpD;CACF;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,GAAG,iBAAiB,CASpF;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAE1F;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,0BAA0B,GAAG,MAAM,CAMhF"}
@@ -11,10 +11,23 @@ export class ForkChoiceStore {
11
11
  equivocatingIndices = new Set();
12
12
  justifiedBalancesGetter;
13
13
  currentSlot;
14
- constructor(currentSlot, justifiedCheckpoint, finalizedCheckpoint, justifiedBalances, justifiedBalancesGetter, events) {
14
+ // Fast Confirmation Rule spec fields
15
+ confirmedRoot;
16
+ previousEpochObservedJustifiedCheckpoint;
17
+ currentEpochObservedJustifiedCheckpoint;
18
+ previousEpochGreatestUnrealizedCheckpoint;
19
+ previousSlotHead;
20
+ currentSlotHead;
21
+ // Fast Confirmation Rule internal fields
22
+ previousEpochObservedJustifiedBalances;
23
+ currentEpochObservedJustifiedBalances;
24
+ previousEpochGreatestUnrealizedBalances;
25
+ stateGetter;
26
+ constructor(currentSlot, justifiedCheckpoint, finalizedCheckpoint, justifiedBalances, justifiedBalancesGetter, stateGetter, events) {
15
27
  this.events = events;
16
28
  this.justifiedBalancesGetter = justifiedBalancesGetter;
17
29
  this.currentSlot = currentSlot;
30
+ this.stateGetter = stateGetter;
18
31
  const justified = {
19
32
  checkpoint: toCheckpointWithHex(justifiedCheckpoint),
20
33
  balances: justifiedBalances,
@@ -24,6 +37,21 @@ export class ForkChoiceStore {
24
37
  this.unrealizedJustified = justified;
25
38
  this._finalizedCheckpoint = toCheckpointWithHex(finalizedCheckpoint);
26
39
  this.unrealizedFinalizedCheckpoint = this._finalizedCheckpoint;
40
+ // Initialize Fast Confirmation fields conservatively from finalized, matching
41
+ // the spec's get_fast_confirmation_store() behavior.
42
+ const finalizedCheckpointWithHex = toCheckpointWithHex(finalizedCheckpoint);
43
+ const finalizedState = stateGetter({ checkpoint: finalizedCheckpointWithHex });
44
+ const finalizedBalances = finalizedState?.effectiveBalanceIncrements ?? justifiedBalances;
45
+ const anchorRoot = finalizedCheckpointWithHex.rootHex;
46
+ this.previousEpochObservedJustifiedCheckpoint = finalizedCheckpointWithHex;
47
+ this.currentEpochObservedJustifiedCheckpoint = finalizedCheckpointWithHex;
48
+ this.previousEpochGreatestUnrealizedCheckpoint = finalizedCheckpointWithHex;
49
+ this.confirmedRoot = anchorRoot;
50
+ this.previousEpochObservedJustifiedBalances = finalizedBalances;
51
+ this.currentEpochObservedJustifiedBalances = finalizedBalances;
52
+ this.previousEpochGreatestUnrealizedBalances = finalizedBalances;
53
+ this.previousSlotHead = anchorRoot;
54
+ this.currentSlotHead = anchorRoot;
27
55
  }
28
56
  get justified() {
29
57
  return this._justified;
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/forkChoice/store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AA8C1C;;GAEG;AACH,MAAM,OAAO,eAAe;IAeP,MAAM;IAdjB,UAAU,CAA6B;IAC/C,mBAAmB,CAAwB;IACnC,oBAAoB,CAAoB;IAChD,6BAA6B,CAAoB;IACjD,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,uBAAuB,CAA0B;IACjD,WAAW,CAAO;IAElB,YACE,WAAiB,EACjB,mBAAsC,EACtC,mBAAsC,EACtC,iBAA6C,EAC7C,uBAAgD,EAC/B,MAGhB,EACD;sBAJiB,MAAM;QAKvB,IAAI,CAAC,uBAAuB,GAAG,uBAAuB,CAAC;QACvD,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,MAAM,SAAS,GAAG;YAChB,UAAU,EAAE,mBAAmB,CAAC,mBAAmB,CAAC;YACpD,QAAQ,EAAE,iBAAiB;YAC3B,YAAY,EAAE,mBAAmB,CAAC,iBAAiB,CAAC;SACrD,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;QACrC,IAAI,CAAC,oBAAoB,GAAG,mBAAmB,CAAC,mBAAmB,CAAC,CAAC;QACrE,IAAI,CAAC,6BAA6B,GAAG,IAAI,CAAC,oBAAoB,CAAC;IAAA,CAChE;IAED,IAAI,SAAS,GAA+B;QAC1C,OAAO,IAAI,CAAC,UAAU,CAAC;IAAA,CACxB;IACD,IAAI,SAAS,CAAC,SAAgC,EAAE;QAC9C,IAAI,CAAC,UAAU,GAAG,EAAC,GAAG,SAAS,EAAE,YAAY,EAAE,mBAAmB,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAC,CAAC;QACxF,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAAA,CAChD;IAED,IAAI,mBAAmB,GAAsB;QAC3C,OAAO,IAAI,CAAC,oBAAoB,CAAC;IAAA,CAClC;IACD,IAAI,mBAAmB,CAAC,UAA6B,EAAE;QACrD,MAAM,EAAE,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;IAAA,CAC9B;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,UAA6B,EAAqB;IACpF,uFAAuF;IACvF,wDAAwD;IACxD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC;IAC7B,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,IAAI;QACJ,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC;KACzB,CAAC;AAAA,CACH;AAED,MAAM,UAAU,sBAAsB,CAAC,CAAoB,EAAE,CAAoB,EAAW;IAC1F,OAAO,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC;AAAA,CACvD;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAoC,EAAU;IAChF,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,YAAY,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,YAAY,CAAC;AAAA,CACrB"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/forkChoice/store.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { ForkChoiceError, ForkChoiceErrorCode, type InvalidAttestation, InvalidAttestationCode, type InvalidBlock, InvalidBlockCode, } from "./forkChoice/errors.js";
2
+ export { type FastConfirmationBalanceSource, type FastConfirmationContext, type FastConfirmationMetrics, type FastConfirmationResult, FastConfirmationRule, type ForkChoiceStateGetter, type IFastConfirmationRule, type IFastConfirmationStore, getFastConfirmationMetrics, } from "./forkChoice/fastConfirmation/fastConfirmationRule.ts";
2
3
  export { ForkChoice, type ForkChoiceOpts, UpdateHeadOpt } from "./forkChoice/forkChoice.js";
3
4
  export { type AncestorResult, AncestorStatus, type CheckpointWithBalance, type CheckpointWithTotalBalance, EpochDifference, type IForkChoice, NotReorgedReason, } from "./forkChoice/interface.js";
4
5
  export * from "./forkChoice/safeBlocks.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,sBAAsB,EACtB,KAAK,YAAY,EACjB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAC,UAAU,EAAE,KAAK,cAAc,EAAE,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,eAAe,EACf,KAAK,WAAW,EAChB,gBAAgB,GACjB,MAAM,2BAA2B,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EACL,KAAK,iBAAiB,EACtB,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,KAAK,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAC1E,YAAY,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,EACV,SAAS,GACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAC,eAAe,EAAE,aAAa,EAAE,YAAY,EAAC,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAC,UAAU,EAAC,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,sBAAsB,EACtB,KAAK,YAAY,EACjB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,0BAA0B,GAC3B,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAC,UAAU,EAAE,KAAK,cAAc,EAAE,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,eAAe,EACf,KAAK,WAAW,EAChB,gBAAgB,GACjB,MAAM,2BAA2B,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EACL,KAAK,iBAAiB,EACtB,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,KAAK,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAC1E,YAAY,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,EACV,SAAS,GACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAC,eAAe,EAAE,aAAa,EAAE,YAAY,EAAC,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAC,UAAU,EAAC,MAAM,4BAA4B,CAAC"}
package/lib/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { ForkChoiceError, ForkChoiceErrorCode, InvalidAttestationCode, InvalidBlockCode, } from "./forkChoice/errors.js";
2
+ export { FastConfirmationRule, getFastConfirmationMetrics, } from "./forkChoice/fastConfirmation/fastConfirmationRule.js";
2
3
  export { ForkChoice, UpdateHeadOpt } from "./forkChoice/forkChoice.js";
3
4
  export { AncestorStatus, EpochDifference, NotReorgedReason, } from "./forkChoice/interface.js";
4
5
  export * from "./forkChoice/safeBlocks.js";
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EAEnB,sBAAsB,EAEtB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAC,UAAU,EAAuB,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EAEL,cAAc,EAGd,eAAe,EAEf,gBAAgB,GACjB,MAAM,2BAA2B,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAEL,eAAe,GAGhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAyB,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAU1E,OAAO,EAAC,eAAe,EAAE,aAAa,EAAE,YAAY,EAAC,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAC,UAAU,EAAC,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EAEnB,sBAAsB,EAEtB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAKL,oBAAoB,EAIpB,0BAA0B,GAC3B,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAC,UAAU,EAAuB,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EAEL,cAAc,EAGd,eAAe,EAEf,gBAAgB,GACjB,MAAM,2BAA2B,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAEL,eAAe,GAGhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAyB,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAU1E,OAAO,EAAC,eAAe,EAAE,aAAa,EAAE,YAAY,EAAC,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAC,UAAU,EAAC,MAAM,4BAA4B,CAAC"}
package/lib/metrics.d.ts CHANGED
@@ -1,8 +1,19 @@
1
1
  import { MetricsRegisterExtra } from "@lodestar/utils";
2
+ import { FastConfirmationMetrics } from "./forkChoice/fastConfirmation/metrics.ts";
2
3
  import { UpdateHeadOpt } from "./forkChoice/forkChoice.js";
3
4
  import { NotReorgedReason } from "./forkChoice/interface.js";
4
- export type ForkChoiceMetrics = ReturnType<typeof getForkChoiceMetrics>;
5
+ export type ForkChoiceMetrics = ReturnType<typeof getForkChoiceMetrics> & FastConfirmationMetrics;
5
6
  export declare function getForkChoiceMetrics(register: MetricsRegisterExtra): {
7
+ fastConfirmation: {
8
+ totalDuration: import("@lodestar/utils").Histogram<import("@lodestar/utils").NoLabels>;
9
+ stepsDuration: import("@lodestar/utils").Histogram<{
10
+ step: import("./forkChoice/fastConfirmation/metrics.ts").FastConfirmationSteps;
11
+ }>;
12
+ confirmedEpoch: import("@lodestar/utils").GaugeExtra<import("@lodestar/utils").NoLabels>;
13
+ confirmedSlot: import("@lodestar/utils").GaugeExtra<import("@lodestar/utils").NoLabels>;
14
+ votesTracked: import("@lodestar/utils").GaugeExtra<import("@lodestar/utils").NoLabels>;
15
+ resets: import("@lodestar/utils").GaugeExtra<import("@lodestar/utils").NoLabels>;
16
+ };
6
17
  forkChoice: {
7
18
  findHead: import("@lodestar/utils").Histogram<{
8
19
  caller: string;
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAC,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAE3D,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmGlE"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAC,uBAAuB,EAA6B,MAAM,0CAA0C,CAAC;AAC7G,OAAO,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAC,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAE3D,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,GAAG,uBAAuB,CAAC;AAElG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoGlE"}
package/lib/metrics.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { getFastConfirmationMetrics } from "./forkChoice/fastConfirmation/metrics.js";
1
2
  export function getForkChoiceMetrics(register) {
2
3
  return {
4
+ ...getFastConfirmationMetrics(register),
3
5
  forkChoice: {
4
6
  findHead: register.histogram({
5
7
  name: "beacon_fork_choice_find_head_seconds",
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/ChainSafe/lodestar/issues"
13
13
  },
14
- "version": "1.44.0-dev.41c6b9d097",
14
+ "version": "1.44.0-dev.44ca853f73",
15
15
  "type": "module",
16
16
  "exports": {
17
17
  ".": {
@@ -40,11 +40,11 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@chainsafe/ssz": "^1.4.0",
43
- "@lodestar/config": "^1.44.0-dev.41c6b9d097",
44
- "@lodestar/params": "^1.44.0-dev.41c6b9d097",
45
- "@lodestar/state-transition": "^1.44.0-dev.41c6b9d097",
46
- "@lodestar/types": "^1.44.0-dev.41c6b9d097",
47
- "@lodestar/utils": "^1.44.0-dev.41c6b9d097"
43
+ "@lodestar/config": "^1.44.0-dev.44ca853f73",
44
+ "@lodestar/params": "^1.44.0-dev.44ca853f73",
45
+ "@lodestar/state-transition": "^1.44.0-dev.44ca853f73",
46
+ "@lodestar/types": "^1.44.0-dev.44ca853f73",
47
+ "@lodestar/utils": "^1.44.0-dev.44ca853f73"
48
48
  },
49
49
  "keywords": [
50
50
  "ethereum",
@@ -52,5 +52,5 @@
52
52
  "beacon",
53
53
  "blockchain"
54
54
  ],
55
- "gitHead": "bd2d4c7382cfd09e91f3b780f8f2c3bc72d7ee2c"
55
+ "gitHead": "4c423d3101a01d3dde533c2668774446ea8a1485"
56
56
  }
@@ -0,0 +1,43 @@
1
+ import {computeEpochAtSlot} from "@lodestar/state-transition";
2
+ import {
3
+ FastConfirmationCache,
4
+ FastConfirmationContext,
5
+ FastConfirmationSnapshot,
6
+ IFastConfirmationStore,
7
+ } from "./types.ts";
8
+ import {getBlock, getUnrealizedJustification} from "./utils.ts";
9
+
10
+ export function createFastConfirmationCache(): FastConfirmationCache {
11
+ return {
12
+ blockByRoot: new Map(),
13
+ ancestorRoots: new Map(),
14
+ committeeBySlot: new Map(),
15
+ isDescendantByRootPair: new Map(),
16
+ voteWeightBySource: new Map(),
17
+ checkpointStateByKey: new Map(),
18
+ };
19
+ }
20
+
21
+ export function buildFastConfirmationSnapshot(
22
+ ctx: FastConfirmationContext,
23
+ store: IFastConfirmationStore,
24
+ cache: FastConfirmationCache
25
+ ): FastConfirmationSnapshot {
26
+ const currentSlot = ctx.getCurrentSlot();
27
+ const currentEpoch = computeEpochAtSlot(currentSlot);
28
+ const headRoot = ctx.getHead().blockRoot;
29
+ const confirmedRoot = store.confirmedRoot;
30
+ const confirmedBlock = getBlock(ctx, cache, confirmedRoot);
31
+
32
+ return {
33
+ currentSlot,
34
+ currentEpoch,
35
+ headRoot,
36
+ confirmedRoot,
37
+ confirmedEpoch: confirmedBlock ? computeEpochAtSlot(confirmedBlock.slot) : null,
38
+ confirmedSlot: confirmedBlock?.slot ?? null,
39
+ observedJustified: store.currentEpochObservedJustifiedCheckpoint,
40
+ headUnrealized: getUnrealizedJustification(ctx, cache, headRoot),
41
+ finalizedRoot: ctx.getFinalizedCheckpoint().rootHex,
42
+ };
43
+ }
@@ -0,0 +1,159 @@
1
+ import {computeEpochAtSlot, isStartSlotOfEpoch} from "@lodestar/state-transition";
2
+ import {RootHex} from "@lodestar/types";
3
+ import {Logger, withObservedDuration} from "@lodestar/utils";
4
+ import {buildFastConfirmationSnapshot, createFastConfirmationCache} from "./data.ts";
5
+ import {FastConfirmationMetrics, FastConfirmationSteps} from "./metrics.ts";
6
+ import {runFastConfirmationRules} from "./rules.ts";
7
+ import {
8
+ FastConfirmationContext,
9
+ FastConfirmationResult,
10
+ IFastConfirmationRule,
11
+ IFastConfirmationStore,
12
+ } from "./types.ts";
13
+
14
+ export * from "./metrics.ts";
15
+ export * from "./types.ts";
16
+
17
+ export class FastConfirmationRule implements IFastConfirmationRule {
18
+ constructor(
19
+ private readonly store: IFastConfirmationStore,
20
+ readonly metrics: FastConfirmationMetrics | null,
21
+ readonly logger?: Logger
22
+ ) {}
23
+
24
+ getConfirmedRoot(): RootHex {
25
+ return this.store.confirmedRoot;
26
+ }
27
+
28
+ onSlotStartAfterPastAttestationsApplied(ctx: FastConfirmationContext): FastConfirmationResult {
29
+ const currentSlot = ctx.getCurrentSlot();
30
+ const previousConfirmedRoot = this.store.confirmedRoot;
31
+
32
+ this.logger?.debug("Running fast confirmation rule", {
33
+ slot: currentSlot,
34
+ epoch: computeEpochAtSlot(currentSlot),
35
+ });
36
+ this.updateFastConfirmationVariables(ctx);
37
+
38
+ const cache = withObservedDuration(
39
+ this.metrics?.fastConfirmation.stepsDuration.startTimer({
40
+ step: FastConfirmationSteps.buildCache,
41
+ }),
42
+ createFastConfirmationCache
43
+ );
44
+
45
+ const snapshot = withObservedDuration(
46
+ this.metrics?.fastConfirmation.stepsDuration.startTimer({
47
+ step: FastConfirmationSteps.buildSnapshot,
48
+ }),
49
+ () => buildFastConfirmationSnapshot(ctx, this.store, cache)
50
+ );
51
+
52
+ this.logger?.verbose("Built fast confirmation snapshot", {
53
+ confirmedSlot: snapshot.confirmedSlot,
54
+ confirmedEpoch: snapshot.confirmedEpoch,
55
+ confirmedRoot: snapshot.confirmedRoot,
56
+ headRoot: snapshot.headRoot,
57
+ finalizedRoot: snapshot.finalizedRoot,
58
+ headUnrealizedRoot: snapshot.headUnrealized?.rootHex,
59
+ headUnrealizedEpoch: snapshot.headUnrealized?.epoch,
60
+ observedJustifiedRoot: snapshot.observedJustified.rootHex,
61
+ observedJustifiedEpoch: snapshot.observedJustified.epoch,
62
+ });
63
+
64
+ const {confirmedRoot, didReset, reason} = withObservedDuration(
65
+ this.metrics?.fastConfirmation.stepsDuration.startTimer({step: FastConfirmationSteps.runRules}),
66
+ () => runFastConfirmationRules(snapshot, ctx, this.store, cache, this.logger)
67
+ );
68
+
69
+ const changed = confirmedRoot !== previousConfirmedRoot;
70
+ const confirmedBlock = cache.blockByRoot.get(confirmedRoot) ?? null;
71
+ const confirmedSlot = confirmedBlock?.slot ?? null;
72
+ const confirmedEpoch = confirmedBlock ? computeEpochAtSlot(confirmedBlock.slot) : null;
73
+ const logContext = {
74
+ previousConfirmedRoot,
75
+ confirmedRoot,
76
+ changed,
77
+ didReset,
78
+ reason,
79
+ confirmedSlot,
80
+ confirmedEpoch,
81
+ };
82
+
83
+ if (changed) {
84
+ if (didReset) {
85
+ this.logger?.warn("Reset fast confirmation", logContext);
86
+ } else {
87
+ this.logger?.debug("Updated fast confirmation", logContext);
88
+ }
89
+ } else {
90
+ this.logger?.debug("Unchanged fast confirmation", logContext);
91
+ }
92
+
93
+ this.store.confirmedRoot = confirmedRoot;
94
+ this.updateFastConfirmationMetrics(ctx, {confirmedRoot, didReset});
95
+
96
+ return {confirmedRoot, didReset};
97
+ }
98
+
99
+ private updateFastConfirmationVariables(ctx: FastConfirmationContext): void {
100
+ const previousSlotHead = this.store.currentSlotHead;
101
+ const currentSlotHead = ctx.getHead().blockRoot;
102
+ const currentSlot = ctx.getCurrentSlot();
103
+ const isStartSlotOfCurrentEpoch = isStartSlotOfEpoch(currentSlot);
104
+ const isLastSlotOfCurrentEpoch = isStartSlotOfEpoch(currentSlot + 1);
105
+
106
+ this.store.previousSlotHead = previousSlotHead;
107
+ this.store.currentSlotHead = currentSlotHead;
108
+
109
+ this.logger?.verbose("Updating fast confirmation variables", {
110
+ previousSlotHead,
111
+ currentSlotHead,
112
+ currentSlot,
113
+ isStartSlotOfCurrentEpoch,
114
+ isLastSlotOfCurrentEpoch,
115
+ });
116
+
117
+ // Spec step 1: freeze the greatest unrealized justified checkpoint at the
118
+ // last slot of the epoch so the next epoch consumes a stable snapshot.
119
+ if (isLastSlotOfCurrentEpoch) {
120
+ const unrealized = ctx.getUnrealizedJustified();
121
+ this.store.previousEpochGreatestUnrealizedCheckpoint = unrealized.checkpoint;
122
+ this.store.previousEpochGreatestUnrealizedBalances = unrealized.balances;
123
+
124
+ this.logger?.verbose("Updated fast confirmation greatest unrealized snapshot", {
125
+ previousEpochGreatestUnrealizedCheckpointRoot: this.store.previousEpochGreatestUnrealizedCheckpoint.rootHex,
126
+ previousEpochGreatestUnrealizedCheckpointEpoch: this.store.previousEpochGreatestUnrealizedCheckpoint.epoch,
127
+ });
128
+ }
129
+
130
+ // Spec step 2: rotate observed justified checkpoints at the first slot of
131
+ // the new epoch using the snapshot taken at the end of the previous epoch.
132
+ if (isStartSlotOfCurrentEpoch) {
133
+ this.store.previousEpochObservedJustifiedCheckpoint = this.store.currentEpochObservedJustifiedCheckpoint;
134
+ this.store.previousEpochObservedJustifiedBalances = this.store.currentEpochObservedJustifiedBalances;
135
+ this.store.currentEpochObservedJustifiedCheckpoint = this.store.previousEpochGreatestUnrealizedCheckpoint;
136
+ this.store.currentEpochObservedJustifiedBalances = this.store.previousEpochGreatestUnrealizedBalances;
137
+
138
+ this.logger?.verbose("Updated fast confirmation observed justified checkpoints", {
139
+ previousEpochObservedJustifiedCheckpointRoot: this.store.previousEpochObservedJustifiedCheckpoint.rootHex,
140
+ previousEpochObservedJustifiedCheckpointEpoch: this.store.previousEpochObservedJustifiedCheckpoint.epoch,
141
+ currentEpochObservedJustifiedCheckpointRoot: this.store.currentEpochObservedJustifiedCheckpoint.rootHex,
142
+ currentEpochObservedJustifiedCheckpointEpoch: this.store.currentEpochObservedJustifiedCheckpoint.epoch,
143
+ });
144
+ }
145
+ }
146
+
147
+ private updateFastConfirmationMetrics(ctx: FastConfirmationContext, result: FastConfirmationResult): void {
148
+ if (!this.metrics) return;
149
+ const confirmedBlock = ctx.getBlock(result.confirmedRoot);
150
+ if (confirmedBlock) {
151
+ this.metrics.fastConfirmation.confirmedSlot.set(confirmedBlock.slot);
152
+ this.metrics.fastConfirmation.confirmedEpoch.set(computeEpochAtSlot(confirmedBlock.slot));
153
+ }
154
+ if (result.didReset) {
155
+ this.metrics.fastConfirmation.resets.inc();
156
+ }
157
+ this.metrics.fastConfirmation.votesTracked.set(ctx.getTrackedVotesCount());
158
+ }
159
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./fastConfirmationRule.ts";
2
+ export * from "./metrics.ts";
3
+ export * from "./types.ts";
@@ -0,0 +1,44 @@
1
+ import {MetricsRegisterExtra} from "@lodestar/utils";
2
+
3
+ export type FastConfirmationMetrics = ReturnType<typeof getFastConfirmationMetrics>;
4
+
5
+ export enum FastConfirmationSteps {
6
+ updateHead = "updateHead",
7
+ buildCache = "buildCache",
8
+ buildSnapshot = "buildSnapshot",
9
+ runRules = "runRules",
10
+ }
11
+
12
+ export function getFastConfirmationMetrics(register: MetricsRegisterExtra) {
13
+ return {
14
+ fastConfirmation: {
15
+ totalDuration: register.histogram({
16
+ name: "lodestar_fast_confirmation_duration_seconds",
17
+ help: "Time to run Fast Confirmation Rule algorithm",
18
+ buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2],
19
+ }),
20
+ stepsDuration: register.histogram<{step: FastConfirmationSteps}>({
21
+ name: "lodestar_fast_confirmation_steps_duration_seconds",
22
+ help: "Time to run Fast Confirmation Steps",
23
+ buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2],
24
+ labelNames: ["step"],
25
+ }),
26
+ confirmedEpoch: register.gauge({
27
+ name: "lodestar_fast_confirmation_confirmed_epoch",
28
+ help: "Current confirmed epoch from fast confirmation",
29
+ }),
30
+ confirmedSlot: register.gauge({
31
+ name: "lodestar_fast_confirmation_confirmed_slot",
32
+ help: "Current confirmed slot from fast confirmation",
33
+ }),
34
+ votesTracked: register.gauge({
35
+ name: "lodestar_fast_confirmation_votes_tracked",
36
+ help: "Number of checkpoint votes tracked by fast confirmation",
37
+ }),
38
+ resets: register.gauge({
39
+ name: "lodestar_fast_confirmation_resets_total",
40
+ help: "Count of fast confirmation resets due to reorgs",
41
+ }),
42
+ },
43
+ };
44
+ }
@@ -0,0 +1,124 @@
1
+ import {computeEpochAtSlot, isStartSlotOfEpoch} from "@lodestar/state-transition";
2
+ import {Logger} from "@lodestar/utils";
3
+ import {equalCheckpointWithHex} from "../store.ts";
4
+ import {
5
+ FastConfirmationCache,
6
+ FastConfirmationContext,
7
+ FastConfirmationDecision,
8
+ FastConfirmationDecisionReason,
9
+ FastConfirmationRule,
10
+ FastConfirmationSnapshot,
11
+ IFastConfirmationStore,
12
+ } from "./types.ts";
13
+ import {findLatestConfirmedDescendant, getBlock, isAncestor, isConfirmedChainSafe} from "./utils.ts";
14
+
15
+ export const resetIfConfirmedUnavailable: FastConfirmationRule = (snapshot, ctx, _store, cache, decision) => {
16
+ const confirmedBlock = getBlock(ctx, cache, decision.confirmedRoot);
17
+ if (!confirmedBlock) {
18
+ return {
19
+ confirmedRoot: snapshot.finalizedRoot,
20
+ didReset: true,
21
+ reason: FastConfirmationDecisionReason.ConfirmedNotFound,
22
+ };
23
+ }
24
+ return decision;
25
+ };
26
+
27
+ export const resetIfBehindOrNotAncestorOrUnsafe: FastConfirmationRule = (
28
+ snapshot,
29
+ ctx,
30
+ store,
31
+ cache,
32
+ decision,
33
+ logger
34
+ ) => {
35
+ const confirmedBlock = getBlock(ctx, cache, decision.confirmedRoot);
36
+ if (!confirmedBlock) return decision;
37
+ const confirmedEpoch = computeEpochAtSlot(confirmedBlock.slot);
38
+
39
+ const confirmedEpochBehindHead = confirmedEpoch + 1 < snapshot.currentEpoch;
40
+ const notAncestorOfHead = !isAncestor(ctx, cache, snapshot.headRoot, decision.confirmedRoot);
41
+ const allChildrenNotConfirmed =
42
+ isStartSlotOfEpoch(snapshot.currentSlot) &&
43
+ !isConfirmedChainSafe(ctx, store, cache, decision.confirmedRoot, logger);
44
+
45
+ if (confirmedEpochBehindHead || notAncestorOfHead || allChildrenNotConfirmed) {
46
+ const didReset = decision.didReset || decision.confirmedRoot !== snapshot.finalizedRoot;
47
+ const reason = confirmedEpochBehindHead
48
+ ? FastConfirmationDecisionReason.ResetBehind
49
+ : notAncestorOfHead
50
+ ? FastConfirmationDecisionReason.ResetNotAncestor
51
+ : FastConfirmationDecisionReason.ResetChainUnsafe;
52
+ return {confirmedRoot: snapshot.finalizedRoot, didReset, reason};
53
+ }
54
+ return decision;
55
+ };
56
+
57
+ export const advanceIfObservedJustified: FastConfirmationRule = (snapshot, ctx, store, cache, decision) => {
58
+ if (!isStartSlotOfEpoch(snapshot.currentSlot)) return decision;
59
+ if (store.currentEpochObservedJustifiedCheckpoint.epoch + 1 !== snapshot.currentEpoch) return decision;
60
+ if (!snapshot.headUnrealized) return decision;
61
+ if (!equalCheckpointWithHex(store.currentEpochObservedJustifiedCheckpoint, snapshot.headUnrealized)) return decision;
62
+ const observedBlock = getBlock(ctx, cache, store.currentEpochObservedJustifiedCheckpoint.rootHex);
63
+ if (!observedBlock || computeEpochAtSlot(observedBlock.slot) + 1 < snapshot.currentEpoch) return decision;
64
+
65
+ const confirmedSlot = getBlock(ctx, cache, decision.confirmedRoot)?.slot ?? null;
66
+ const observedSlot = observedBlock.slot;
67
+ if (confirmedSlot !== null && observedSlot !== null && confirmedSlot < observedSlot) {
68
+ return {
69
+ ...decision,
70
+ confirmedRoot: store.currentEpochObservedJustifiedCheckpoint.rootHex,
71
+ reason: FastConfirmationDecisionReason.ObservedJustified,
72
+ };
73
+ }
74
+ return decision;
75
+ };
76
+
77
+ export const advanceToLatestConfirmedDescendant: FastConfirmationRule = (
78
+ snapshot,
79
+ ctx,
80
+ store,
81
+ cache,
82
+ decision,
83
+ logger
84
+ ) => {
85
+ const confirmedBlock = getBlock(ctx, cache, decision.confirmedRoot);
86
+ const confirmedEpoch = confirmedBlock ? computeEpochAtSlot(confirmedBlock.slot) : null;
87
+ if (confirmedEpoch !== null && confirmedEpoch + 1 >= snapshot.currentEpoch) {
88
+ const newConfirmed = findLatestConfirmedDescendant(snapshot, ctx, store, cache, decision.confirmedRoot, logger);
89
+ return {
90
+ ...decision,
91
+ confirmedRoot: newConfirmed,
92
+ reason: FastConfirmationDecisionReason.ConfirmedDescendant,
93
+ };
94
+ }
95
+ return decision;
96
+ };
97
+
98
+ export const FAST_CONFIRMATION_RULES: FastConfirmationRule[] = [
99
+ resetIfConfirmedUnavailable,
100
+ resetIfBehindOrNotAncestorOrUnsafe,
101
+ advanceIfObservedJustified,
102
+ advanceToLatestConfirmedDescendant,
103
+ ];
104
+
105
+ // Spec mapping: this rule runner implements the `get_latest_confirmed` decision flow
106
+ // over Lodestar's snapshot/store/cache abstractions.
107
+ export function runFastConfirmationRules(
108
+ snapshot: FastConfirmationSnapshot,
109
+ ctx: FastConfirmationContext,
110
+ store: IFastConfirmationStore,
111
+ cache: FastConfirmationCache,
112
+ logger?: Logger
113
+ ): FastConfirmationDecision {
114
+ let decision: FastConfirmationDecision = {
115
+ confirmedRoot: snapshot.confirmedRoot,
116
+ didReset: false,
117
+ reason: FastConfirmationDecisionReason.Unchanged,
118
+ };
119
+
120
+ for (const rule of FAST_CONFIRMATION_RULES) {
121
+ decision = rule(snapshot, ctx, store, cache, decision, logger);
122
+ }
123
+ return decision;
124
+ }