@lodestar/fork-choice 1.44.0-dev.16e0233677 → 1.44.0-dev.1b4e24f1ee
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 +84 -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 +13 -2
- package/lib/forkChoice/store.d.ts.map +1 -1
- package/lib/forkChoice/store.js +29 -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 +101 -6
- package/src/forkChoice/interface.ts +2 -0
- package/src/forkChoice/safeBlocks.ts +15 -7
- package/src/forkChoice/store.ts +34 -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);
|
|
@@ -51,7 +52,17 @@ export declare class ForkChoiceStore implements IForkChoiceStore {
|
|
|
51
52
|
equivocatingIndices: Set<number>;
|
|
52
53
|
justifiedBalancesGetter: JustifiedBalancesGetter;
|
|
53
54
|
currentSlot: Slot;
|
|
54
|
-
|
|
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,
|
|
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"}
|
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;
|
|
@@ -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.1b4e24f1ee",
|
|
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.1b4e24f1ee",
|
|
44
|
+
"@lodestar/params": "^1.44.0-dev.1b4e24f1ee",
|
|
45
|
+
"@lodestar/state-transition": "^1.44.0-dev.1b4e24f1ee",
|
|
46
|
+
"@lodestar/types": "^1.44.0-dev.1b4e24f1ee",
|
|
47
|
+
"@lodestar/utils": "^1.44.0-dev.1b4e24f1ee"
|
|
48
48
|
},
|
|
49
49
|
"keywords": [
|
|
50
50
|
"ethereum",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"beacon",
|
|
53
53
|
"blockchain"
|
|
54
54
|
],
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "1e2536e44728f286c7d4719fc4802f3a3381013d"
|
|
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
|
+
}
|