@lodestar/fork-choice 1.44.0-dev.be2850b7bb → 1.44.0-dev.c04b424ca8
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.
- package/lib/forkChoice/fastConfirmation/data.d.ts +4 -0
- package/lib/forkChoice/fastConfirmation/data.d.ts.map +1 -0
- package/lib/forkChoice/fastConfirmation/data.js +31 -0
- package/lib/forkChoice/fastConfirmation/data.js.map +1 -0
- package/lib/forkChoice/fastConfirmation/fastConfirmationRule.d.ts +17 -0
- package/lib/forkChoice/fastConfirmation/fastConfirmationRule.d.ts.map +1 -0
- package/lib/forkChoice/fastConfirmation/fastConfirmationRule.js +129 -0
- package/lib/forkChoice/fastConfirmation/fastConfirmationRule.js.map +1 -0
- package/lib/forkChoice/fastConfirmation/index.d.ts +4 -0
- package/lib/forkChoice/fastConfirmation/index.d.ts.map +1 -0
- package/lib/forkChoice/fastConfirmation/index.js +4 -0
- package/lib/forkChoice/fastConfirmation/index.js.map +1 -0
- package/lib/forkChoice/fastConfirmation/metrics.d.ts +21 -0
- package/lib/forkChoice/fastConfirmation/metrics.d.ts.map +1 -0
- package/lib/forkChoice/fastConfirmation/metrics.js +42 -0
- package/lib/forkChoice/fastConfirmation/metrics.js.map +1 -0
- package/lib/forkChoice/fastConfirmation/rules.d.ts +9 -0
- package/lib/forkChoice/fastConfirmation/rules.d.ts.map +1 -0
- package/lib/forkChoice/fastConfirmation/rules.js +91 -0
- package/lib/forkChoice/fastConfirmation/rules.js.map +1 -0
- package/lib/forkChoice/fastConfirmation/types.d.ts +101 -0
- package/lib/forkChoice/fastConfirmation/types.d.ts.map +1 -0
- package/lib/forkChoice/fastConfirmation/types.js +12 -0
- package/lib/forkChoice/fastConfirmation/types.js.map +1 -0
- package/lib/forkChoice/fastConfirmation/utils.d.ts +47 -0
- package/lib/forkChoice/fastConfirmation/utils.d.ts.map +1 -0
- package/lib/forkChoice/fastConfirmation/utils.js +681 -0
- package/lib/forkChoice/fastConfirmation/utils.js.map +1 -0
- package/lib/forkChoice/forkChoice.d.ts +8 -0
- package/lib/forkChoice/forkChoice.d.ts.map +1 -1
- package/lib/forkChoice/forkChoice.js +93 -5
- package/lib/forkChoice/forkChoice.js.map +1 -1
- package/lib/forkChoice/interface.d.ts +2 -0
- package/lib/forkChoice/interface.d.ts.map +1 -1
- package/lib/forkChoice/safeBlocks.d.ts +2 -6
- package/lib/forkChoice/safeBlocks.d.ts.map +1 -1
- package/lib/forkChoice/safeBlocks.js +15 -7
- package/lib/forkChoice/safeBlocks.js.map +1 -1
- package/lib/forkChoice/store.d.ts +33 -2
- package/lib/forkChoice/store.d.ts.map +1 -1
- package/lib/forkChoice/store.js +37 -1
- package/lib/forkChoice/store.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/metrics.d.ts +12 -1
- package/lib/metrics.d.ts.map +1 -1
- package/lib/metrics.js +2 -0
- package/lib/metrics.js.map +1 -1
- package/package.json +7 -7
- package/src/forkChoice/fastConfirmation/data.ts +43 -0
- package/src/forkChoice/fastConfirmation/fastConfirmationRule.ts +159 -0
- package/src/forkChoice/fastConfirmation/index.ts +3 -0
- package/src/forkChoice/fastConfirmation/metrics.ts +44 -0
- package/src/forkChoice/fastConfirmation/rules.ts +124 -0
- package/src/forkChoice/fastConfirmation/types.ts +111 -0
- package/src/forkChoice/fastConfirmation/utils.ts +968 -0
- package/src/forkChoice/forkChoice.ts +111 -6
- package/src/forkChoice/interface.ts +2 -0
- package/src/forkChoice/safeBlocks.ts +15 -7
- package/src/forkChoice/store.ts +45 -1
- package/src/index.ts +11 -0
- 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);
|
|
@@ -38,6 +39,11 @@ export interface IForkChoiceStore {
|
|
|
38
39
|
unrealizedFinalizedCheckpoint: CheckpointWithHex;
|
|
39
40
|
justifiedBalancesGetter: JustifiedBalancesGetter;
|
|
40
41
|
equivocatingIndices: Set<ValidatorIndex>;
|
|
42
|
+
notifyFastConfirmation?(data: {
|
|
43
|
+
block: RootHex;
|
|
44
|
+
slot: Slot;
|
|
45
|
+
currentSlot: Slot;
|
|
46
|
+
}): void;
|
|
41
47
|
}
|
|
42
48
|
/**
|
|
43
49
|
* IForkChoiceStore implementer which emits forkChoice events on updated justified and finalized checkpoints.
|
|
@@ -51,14 +57,39 @@ export declare class ForkChoiceStore implements IForkChoiceStore {
|
|
|
51
57
|
equivocatingIndices: Set<number>;
|
|
52
58
|
justifiedBalancesGetter: JustifiedBalancesGetter;
|
|
53
59
|
currentSlot: Slot;
|
|
54
|
-
|
|
60
|
+
confirmedRoot: RootHex;
|
|
61
|
+
previousEpochObservedJustifiedCheckpoint: CheckpointWithHex;
|
|
62
|
+
currentEpochObservedJustifiedCheckpoint: CheckpointWithHex;
|
|
63
|
+
previousEpochGreatestUnrealizedCheckpoint: CheckpointWithHex;
|
|
64
|
+
previousSlotHead: RootHex;
|
|
65
|
+
currentSlotHead: RootHex;
|
|
66
|
+
previousEpochObservedJustifiedBalances: JustifiedBalances;
|
|
67
|
+
currentEpochObservedJustifiedBalances: JustifiedBalances;
|
|
68
|
+
previousEpochGreatestUnrealizedBalances: JustifiedBalances;
|
|
69
|
+
stateGetter: ForkChoiceStateGetter;
|
|
70
|
+
constructor(currentSlot: Slot, justifiedCheckpoint: phase0.Checkpoint, finalizedCheckpoint: phase0.Checkpoint, justifiedBalances: EffectiveBalanceIncrements, justifiedBalancesGetter: JustifiedBalancesGetter, stateGetter: ForkChoiceStateGetter, events?: {
|
|
55
71
|
onJustified: (cp: CheckpointWithHex) => void;
|
|
56
72
|
onFinalized: (cp: CheckpointWithHex) => void;
|
|
73
|
+
onFastConfirmation?: ((data: {
|
|
74
|
+
block: string;
|
|
75
|
+
slot: number;
|
|
76
|
+
currentSlot: number;
|
|
77
|
+
}) => void) | undefined;
|
|
57
78
|
} | undefined);
|
|
58
79
|
get justified(): CheckpointWithTotalBalance;
|
|
59
80
|
set justified(justified: CheckpointWithBalance);
|
|
60
81
|
get finalizedCheckpoint(): CheckpointWithHex;
|
|
61
82
|
set finalizedCheckpoint(checkpoint: CheckpointWithHex);
|
|
83
|
+
/**
|
|
84
|
+
* Notify subscribers that the Fast Confirmation Rule executed and produced
|
|
85
|
+
* `data.block` at `data.slot`. Fires once per FCR execution, even when
|
|
86
|
+
* `confirmedRoot` did not change from the prior slot.
|
|
87
|
+
*/
|
|
88
|
+
notifyFastConfirmation(data: {
|
|
89
|
+
block: RootHex;
|
|
90
|
+
slot: Slot;
|
|
91
|
+
currentSlot: Slot;
|
|
92
|
+
}): void;
|
|
62
93
|
}
|
|
63
94
|
export declare function toCheckpointWithHex(checkpoint: phase0.Checkpoint): CheckpointWithHex;
|
|
64
95
|
export declare function equalCheckpointWithHex(a: CheckpointWithHex, b: CheckpointWithHex): boolean;
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/forkChoice/store.ts"],"names":[],"mappings":"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"}
|
package/lib/forkChoice/store.js
CHANGED
|
@@ -11,10 +11,23 @@ export class ForkChoiceStore {
|
|
|
11
11
|
equivocatingIndices = new Set();
|
|
12
12
|
justifiedBalancesGetter;
|
|
13
13
|
currentSlot;
|
|
14
|
-
|
|
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;
|
|
@@ -40,6 +68,14 @@ export class ForkChoiceStore {
|
|
|
40
68
|
this._finalizedCheckpoint = cp;
|
|
41
69
|
this.events?.onFinalized(cp);
|
|
42
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Notify subscribers that the Fast Confirmation Rule executed and produced
|
|
73
|
+
* `data.block` at `data.slot`. Fires once per FCR execution, even when
|
|
74
|
+
* `confirmedRoot` did not change from the prior slot.
|
|
75
|
+
*/
|
|
76
|
+
notifyFastConfirmation(data) {
|
|
77
|
+
this.events?.onFastConfirmation?.(data);
|
|
78
|
+
}
|
|
43
79
|
}
|
|
44
80
|
export function toCheckpointWithHex(checkpoint) {
|
|
45
81
|
// `valueOf` coerses the checkpoint, which may be tree-backed, into a javascript object
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/forkChoice/store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;
|
|
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";
|
package/lib/index.d.ts.map
CHANGED
|
@@ -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;
|
package/lib/metrics.d.ts.map
CHANGED
|
@@ -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;
|
|
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",
|
package/lib/metrics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"
|
|
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.
|
|
14
|
+
"version": "1.44.0-dev.c04b424ca8",
|
|
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.
|
|
44
|
-
"@lodestar/params": "^1.44.0-dev.
|
|
45
|
-
"@lodestar/state-transition": "^1.44.0-dev.
|
|
46
|
-
"@lodestar/types": "^1.44.0-dev.
|
|
47
|
-
"@lodestar/utils": "^1.44.0-dev.
|
|
43
|
+
"@lodestar/config": "^1.44.0-dev.c04b424ca8",
|
|
44
|
+
"@lodestar/params": "^1.44.0-dev.c04b424ca8",
|
|
45
|
+
"@lodestar/state-transition": "^1.44.0-dev.c04b424ca8",
|
|
46
|
+
"@lodestar/types": "^1.44.0-dev.c04b424ca8",
|
|
47
|
+
"@lodestar/utils": "^1.44.0-dev.c04b424ca8"
|
|
48
48
|
},
|
|
49
49
|
"keywords": [
|
|
50
50
|
"ethereum",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"beacon",
|
|
53
53
|
"blockchain"
|
|
54
54
|
],
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "565458b8d82801799bb633b9e724ec37c145b78a"
|
|
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,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
|
+
}
|