@lodestar/validator 1.43.0 → 1.44.0-dev.1d0e0b9081
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/services/block.d.ts +2 -1
- package/lib/services/block.d.ts.map +1 -1
- package/lib/services/block.js +4 -3
- package/lib/services/block.js.map +1 -1
- package/lib/services/blockDuties.d.ts +85 -7
- package/lib/services/blockDuties.d.ts.map +1 -1
- package/lib/services/blockDuties.js +186 -74
- package/lib/services/blockDuties.js.map +1 -1
- package/lib/services/proposerPreferences.d.ts +25 -0
- package/lib/services/proposerPreferences.d.ts.map +1 -0
- package/lib/services/proposerPreferences.js +101 -0
- package/lib/services/proposerPreferences.js.map +1 -0
- package/lib/services/validatorStore.d.ts +1 -0
- package/lib/services/validatorStore.d.ts.map +1 -1
- package/lib/services/validatorStore.js +25 -1
- package/lib/services/validatorStore.js.map +1 -1
- package/lib/util/externalSignerClient.d.ts +5 -1
- package/lib/util/externalSignerClient.d.ts.map +1 -1
- package/lib/util/externalSignerClient.js +4 -0
- package/lib/util/externalSignerClient.js.map +1 -1
- package/lib/util/params.js +1 -0
- package/lib/util/params.js.map +1 -1
- package/lib/validator.d.ts.map +1 -1
- package/lib/validator.js +5 -1
- package/lib/validator.js.map +1 -1
- package/package.json +12 -12
- package/src/services/block.ts +3 -9
- package/src/services/blockDuties.ts +212 -79
- package/src/services/proposerPreferences.ts +124 -0
- package/src/services/validatorStore.ts +37 -0
- package/src/util/externalSignerClient.ts +7 -1
- package/src/util/params.ts +1 -0
- package/src/validator.ts +27 -4
package/lib/services/block.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ChainForkConfig } from "@lodestar/config";
|
|
|
3
3
|
import { Metrics } from "../metrics.js";
|
|
4
4
|
import { PubkeyHex } from "../types.js";
|
|
5
5
|
import { IClock, LoggerVc } from "../util/index.js";
|
|
6
|
+
import { BlockDutiesService } from "./blockDuties.js";
|
|
6
7
|
import { ValidatorStore } from "./validatorStore.js";
|
|
7
8
|
type BlockProposalOpts = {
|
|
8
9
|
broadcastValidation: routes.beacon.BroadcastValidation;
|
|
@@ -20,7 +21,7 @@ export declare class BlockProposingService {
|
|
|
20
21
|
private readonly metrics;
|
|
21
22
|
private readonly opts;
|
|
22
23
|
private readonly dutiesService;
|
|
23
|
-
constructor(config: ChainForkConfig, logger: LoggerVc, api: ApiClient, clock: IClock, validatorStore: ValidatorStore, metrics: Metrics | null, opts: BlockProposalOpts);
|
|
24
|
+
constructor(config: ChainForkConfig, logger: LoggerVc, api: ApiClient, clock: IClock, validatorStore: ValidatorStore, dutiesService: BlockDutiesService, metrics: Metrics | null, opts: BlockProposalOpts);
|
|
24
25
|
removeDutiesForKey(pubkey: PubkeyHex): void;
|
|
25
26
|
/**
|
|
26
27
|
* `BlockDutiesService` must call this fn to trigger block creation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block.d.ts","sourceRoot":"","sources":["../../src/services/block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAChD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAejD,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"block.d.ts","sourceRoot":"","sources":["../../src/services/block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAChD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAejD,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAC,kBAAkB,EAAe,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAkBnD,KAAK,iBAAiB,GAAG;IACvB,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC;IACvD,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AACF;;GAEG;AACH,qBAAa,qBAAqB;IAI9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAVvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IAEnD,YACmB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,QAAQ,EAChB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,cAAc,EAC/C,aAAa,EAAE,kBAAkB,EAChB,OAAO,EAAE,OAAO,GAAG,IAAI,EACvB,IAAI,EAAE,iBAAiB,EAIzC;IAED,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAE1C;IAED;;;OAGG;IACH,OAAO,CAAC,uBAAuB,CAa7B;YAGY,qBAAqB;YAwFrB,0BAA0B;IA0FxC,OAAO,CAAC,mBAAmB,CAmBzB;IAEF,OAAO,CAAC,mBAAmB,CAmCzB;CACH"}
|
package/lib/services/block.js
CHANGED
|
@@ -2,7 +2,7 @@ import { routes } from "@lodestar/api";
|
|
|
2
2
|
import { isForkPostGloas } from "@lodestar/params";
|
|
3
3
|
import { ProducedBlockSource, isBlindedSignedBeaconBlock, } from "@lodestar/types";
|
|
4
4
|
import { extendError, prettyBytes, prettyWeiToEth, toPubkeyHex, toRootHex } from "@lodestar/utils";
|
|
5
|
-
import {
|
|
5
|
+
import { GENESIS_SLOT } from "./blockDuties.js";
|
|
6
6
|
/**
|
|
7
7
|
* Service that sets up and handles validator block proposal duties.
|
|
8
8
|
*/
|
|
@@ -15,7 +15,7 @@ export class BlockProposingService {
|
|
|
15
15
|
metrics;
|
|
16
16
|
opts;
|
|
17
17
|
dutiesService;
|
|
18
|
-
constructor(config, logger, api, clock, validatorStore, metrics, opts) {
|
|
18
|
+
constructor(config, logger, api, clock, validatorStore, dutiesService, metrics, opts) {
|
|
19
19
|
this.config = config;
|
|
20
20
|
this.logger = logger;
|
|
21
21
|
this.api = api;
|
|
@@ -23,7 +23,8 @@ export class BlockProposingService {
|
|
|
23
23
|
this.validatorStore = validatorStore;
|
|
24
24
|
this.metrics = metrics;
|
|
25
25
|
this.opts = opts;
|
|
26
|
-
this.dutiesService =
|
|
26
|
+
this.dutiesService = dutiesService;
|
|
27
|
+
this.dutiesService.setNotifyBlockProductionFn(this.notifyBlockProductionFn);
|
|
27
28
|
}
|
|
28
29
|
removeDutiesForKey(pubkey) {
|
|
29
30
|
this.dutiesService.removeDutiesForKey(pubkey);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block.js","sourceRoot":"","sources":["../../src/services/block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAC,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAML,mBAAmB,EAInB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAIjG,OAAO,
|
|
1
|
+
{"version":3,"file":"block.js","sourceRoot":"","sources":["../../src/services/block.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { ApiClient } from "@lodestar/api";
|
|
1
|
+
import { ApiClient, routes } from "@lodestar/api";
|
|
2
2
|
import { ChainForkConfig } from "@lodestar/config";
|
|
3
|
-
import { BLSPubkey, Slot } from "@lodestar/types";
|
|
3
|
+
import { BLSPubkey, Epoch, RootHex, Slot } from "@lodestar/types";
|
|
4
4
|
import { Metrics } from "../metrics.js";
|
|
5
5
|
import { PubkeyHex } from "../types.js";
|
|
6
6
|
import { IClock, LoggerVc } from "../util/index.js";
|
|
7
|
+
import { ChainHeaderTracker } from "./chainHeaderTracker.js";
|
|
7
8
|
import { ValidatorStore } from "./validatorStore.js";
|
|
8
9
|
export declare const GENESIS_SLOT = 0;
|
|
10
|
+
export type BlockDutyAtEpoch = {
|
|
11
|
+
dependentRoot: RootHex;
|
|
12
|
+
data: routes.validator.ProposerDuty[];
|
|
13
|
+
};
|
|
9
14
|
type NotifyBlockProductionFn = (slot: Slot, proposers: BLSPubkey[]) => void;
|
|
10
15
|
export declare class BlockDutiesService {
|
|
11
16
|
private readonly config;
|
|
@@ -15,11 +20,29 @@ export declare class BlockDutiesService {
|
|
|
15
20
|
private readonly validatorStore;
|
|
16
21
|
private readonly metrics;
|
|
17
22
|
/** Notify the block service if it should produce a block. */
|
|
18
|
-
private
|
|
23
|
+
private notifyBlockProductionFn;
|
|
19
24
|
/** Maps an epoch to all *local* proposers in this epoch. Notably, this does not contain
|
|
20
25
|
proposals for any validators which are not registered locally. */
|
|
21
26
|
private readonly proposers;
|
|
22
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Tracks which proposer pubkeys we have already notified for the active slot so that
|
|
29
|
+
* a late-arriving cache update (SSE-driven refetch, slow initial poll) only fires
|
|
30
|
+
* `notifyBlockProductionFn` for *newly discovered* proposers, never duplicates.
|
|
31
|
+
*/
|
|
32
|
+
private notifiedSlot;
|
|
33
|
+
private readonly notifiedProposers;
|
|
34
|
+
/**
|
|
35
|
+
* True once `notifyProposersForSlot` has been invoked for `notifiedSlot`, regardless of
|
|
36
|
+
* whether anything was notified. Any subsequent invocation that finds *new* proposers is
|
|
37
|
+
* therefore a late detection — the signal tracked by `newProposalDutiesDetected`.
|
|
38
|
+
*/
|
|
39
|
+
private notifiedSlotInitialPass;
|
|
40
|
+
constructor(config: ChainForkConfig, logger: LoggerVc, api: ApiClient, clock: IClock, validatorStore: ValidatorStore, chainHeaderTracker: ChainHeaderTracker, metrics: Metrics | null);
|
|
41
|
+
/**
|
|
42
|
+
* Late-bind the production callback. Allows the duties service to be constructed
|
|
43
|
+
* before the consumer that handles proposal production.
|
|
44
|
+
*/
|
|
45
|
+
setNotifyBlockProductionFn(notifyBlockProductionFn: NotifyBlockProductionFn): void;
|
|
23
46
|
/**
|
|
24
47
|
* Returns the pubkeys of the validators which are assigned to propose in the given slot.
|
|
25
48
|
*
|
|
@@ -27,10 +50,65 @@ export declare class BlockDutiesService {
|
|
|
27
50
|
* likely the result of heavy forking (lol) or inconsistent beacon node connections.
|
|
28
51
|
*/
|
|
29
52
|
getblockProposersAtSlot(slot: Slot): BLSPubkey[];
|
|
53
|
+
/**
|
|
54
|
+
* Returns the cached `{dependentRoot, data}` entry for `epoch`, or `undefined` if duties
|
|
55
|
+
* for that epoch are not yet known. Consumers can detect a proposer-shuffling change
|
|
56
|
+
* (e.g. after a reorg) by observing a different `dependentRoot` than the one they last
|
|
57
|
+
* read for the same epoch.
|
|
58
|
+
*/
|
|
59
|
+
getProposersAtEpoch(epoch: Epoch): BlockDutyAtEpoch | undefined;
|
|
30
60
|
removeDutiesForKey(pubkey: PubkeyHex): void;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Baseline per-epoch fetch. Fires at epoch boundaries (and once at startup). Post-Fulu the
|
|
63
|
+
* deterministic 1-epoch lookahead lets us also pre-fetch `epoch + 1`; pre-Fulu the next
|
|
64
|
+
* epoch's dep_root only stabilizes at the boundary and is handled by `runEverySlotTask`.
|
|
65
|
+
*
|
|
66
|
+
* Mid-epoch refreshes (e.g. reorgs) are driven by `onNewHead` instead of polling every slot.
|
|
67
|
+
*/
|
|
68
|
+
private runEveryEpochTask;
|
|
69
|
+
/**
|
|
70
|
+
* Slot-tick handler. Notifies block production for cached proposers in this slot, and on
|
|
71
|
+
* the last slot of a pre-Fulu epoch schedules the boundary fetch for `nextEpoch` duties.
|
|
72
|
+
* Reorg detection is handled by `onNewHead`, so this task does not re-poll on every slot.
|
|
73
|
+
*/
|
|
74
|
+
private runEverySlotTask;
|
|
75
|
+
/**
|
|
76
|
+
* SSE head-event handler. The beacon-API `head` event carries attester-duty dep_roots,
|
|
77
|
+
* which coincide with the proposer dep_roots at a fork-dependent offset:
|
|
78
|
+
*
|
|
79
|
+
* Pre-Fulu (proposer dep_root(E) = block@startSlot(E) - 1):
|
|
80
|
+
* currentDutyDependentRoot ≡ proposer_dep_root(currentEpoch)
|
|
81
|
+
* (next-epoch proposer dep_root is not exposed; pre-Fulu falls back to the
|
|
82
|
+
* `runEverySlotTask` boundary poll.)
|
|
83
|
+
*
|
|
84
|
+
* Post-Fulu (proposer dep_root(E) = block@startSlot(E - 1) - 1, EIP-7917):
|
|
85
|
+
* previousDutyDependentRoot ≡ proposer_dep_root(currentEpoch)
|
|
86
|
+
* currentDutyDependentRoot ≡ proposer_dep_root(nextEpoch)
|
|
87
|
+
*
|
|
88
|
+
* On a dep_root mismatch (reorg, or initial sync delivering a fresher head) we refetch
|
|
89
|
+
* just the affected epoch, mirroring `AttestationDutiesService.onNewHead`.
|
|
90
|
+
*/
|
|
91
|
+
private onNewHead;
|
|
92
|
+
private refetchIfDepRootChanged;
|
|
93
|
+
private pollBeaconProposersBeforeBoundary;
|
|
94
|
+
/**
|
|
95
|
+
* Notify block production for *newly discovered* proposers in this slot. Notifications are
|
|
96
|
+
* deduplicated per-slot so that a late SSE refetch can extend the proposer set without
|
|
97
|
+
* triggering a duplicate `createAndPublishBlock` for already-notified validators.
|
|
98
|
+
*
|
|
99
|
+
* ## Multi-notification safety
|
|
100
|
+
*
|
|
101
|
+
* Within a single slot the cache can be updated from several sources (cold-cache backfill at
|
|
102
|
+
* startup, SSE-driven reorg refetch). Each update may fire this function again. The contract
|
|
103
|
+
* we keep is: each pubkey is notified *at most once per slot*. The additional notifications
|
|
104
|
+
* only carry proposers that were not part of an earlier notification.
|
|
105
|
+
*
|
|
106
|
+
* Is this safe? Firstly, the dedup above guarantees we never ask the same validator to
|
|
107
|
+
* propose twice for the same slot. Secondly, slashing protection in `ValidatorStore` acts as
|
|
108
|
+
* a second line of defense should the dedup ever fail. Together they provide an acceptable
|
|
109
|
+
* level of safety for the "notify-from-cache, refine-after-refetch" pattern.
|
|
110
|
+
*/
|
|
111
|
+
private notifyProposersForSlot;
|
|
34
112
|
private pollBeaconProposers;
|
|
35
113
|
/** Run once per epoch to prune `this.proposers` map */
|
|
36
114
|
private pruneOldDuties;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blockDuties.d.ts","sourceRoot":"","sources":["../../src/services/blockDuties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"blockDuties.d.ts","sourceRoot":"","sources":["../../src/services/blockDuties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAChD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAC,kBAAkB,EAAgB,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAoBnD,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,MAAM,MAAM,gBAAgB,GAAG;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,CAAA;CAAC,CAAC;AAC/F,KAAK,uBAAuB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;AAE5E,qBAAa,kBAAkB;IAsB3B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IA3B1B,6DAA6D;IAC7D,OAAO,CAAC,uBAAuB,CAAqC;IACpE;yEACqE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAEhE;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwB;IAC1D;;;;OAIG;IACH,OAAO,CAAC,uBAAuB,CAAS;IAExC,YACmB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,QAAQ,EAChB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,cAAc,EAC/C,kBAAkB,EAAE,kBAAkB,EACrB,OAAO,EAAE,OAAO,GAAG,IAAI,EAWzC;IAED;;;OAGG;IACH,0BAA0B,CAAC,uBAAuB,EAAE,uBAAuB,GAAG,IAAI,CAEjF;IAED;;;;;OAKG;IACH,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,EAAE,CAc/C;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,GAAG,SAAS,CAE9D;IAED,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAM1C;IAED;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB,CAuBvB;IAEF;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAqBtB;IAEF;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,SAAS,CAcf;YAEY,uBAAuB;YAuBvB,iCAAiC;IAa/C;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,sBAAsB;YA8BhB,mBAAmB;IA0CjC,uDAAuD;IACvD,OAAO,CAAC,cAAc;CAOvB"}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
+
import { isForkPostFulu } from "@lodestar/params";
|
|
1
2
|
import { computeEpochAtSlot, computeStartSlotAtEpoch } from "@lodestar/state-transition";
|
|
2
3
|
import { sleep, toPubkeyHex } from "@lodestar/utils";
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Pre-Fulu only: poll next-epoch proposer duties ~1s before the boundary. Post-Fulu the 1-epoch
|
|
6
|
+
* deterministic lookahead lets us pre-fetch via `runEveryEpoch`, so this fast path is unused.
|
|
7
|
+
*
|
|
8
|
+
* Historical context: starting Jul 2023 we poll 1s before the next epoch because
|
|
9
|
+
* `PrepareNextSlotScheduler` (BN-side) usually finishes the upcoming-epoch transition in ~3s,
|
|
10
|
+
* so the proposer-duties query at ~1s pre-boundary lands on a hot cache. See:
|
|
11
|
+
* - https://github.com/ChainSafe/lodestar/issues/5792
|
|
12
|
+
*/
|
|
5
13
|
// TODO: change to 8333 (5/6 of slot) to do it 2s before the next epoch
|
|
6
14
|
// once we have some improvement on epoch transition time
|
|
7
15
|
// see https://github.com/ChainSafe/lodestar/issues/5792#issuecomment-1647457442
|
|
8
|
-
// TODO GLOAS: re-evaluate timing
|
|
16
|
+
// TODO GLOAS: re-evaluate timing — Gloas may want the offset *after* the boundary
|
|
9
17
|
const BLOCK_DUTIES_LOOKAHEAD_BPS = 9167;
|
|
10
18
|
/** Only retain `HISTORICAL_DUTIES_EPOCHS` duties prior to the current epoch */
|
|
11
19
|
const HISTORICAL_DUTIES_EPOCHS = 2;
|
|
@@ -20,28 +28,46 @@ export class BlockDutiesService {
|
|
|
20
28
|
validatorStore;
|
|
21
29
|
metrics;
|
|
22
30
|
/** Notify the block service if it should produce a block. */
|
|
23
|
-
notifyBlockProductionFn;
|
|
31
|
+
notifyBlockProductionFn = () => { };
|
|
24
32
|
/** Maps an epoch to all *local* proposers in this epoch. Notably, this does not contain
|
|
25
33
|
proposals for any validators which are not registered locally. */
|
|
26
34
|
proposers = new Map();
|
|
27
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Tracks which proposer pubkeys we have already notified for the active slot so that
|
|
37
|
+
* a late-arriving cache update (SSE-driven refetch, slow initial poll) only fires
|
|
38
|
+
* `notifyBlockProductionFn` for *newly discovered* proposers, never duplicates.
|
|
39
|
+
*/
|
|
40
|
+
notifiedSlot = -1;
|
|
41
|
+
notifiedProposers = new Set();
|
|
42
|
+
/**
|
|
43
|
+
* True once `notifyProposersForSlot` has been invoked for `notifiedSlot`, regardless of
|
|
44
|
+
* whether anything was notified. Any subsequent invocation that finds *new* proposers is
|
|
45
|
+
* therefore a late detection — the signal tracked by `newProposalDutiesDetected`.
|
|
46
|
+
*/
|
|
47
|
+
notifiedSlotInitialPass = false;
|
|
48
|
+
constructor(config, logger, api, clock, validatorStore, chainHeaderTracker, metrics) {
|
|
28
49
|
this.config = config;
|
|
29
50
|
this.logger = logger;
|
|
30
51
|
this.api = api;
|
|
31
52
|
this.clock = clock;
|
|
32
53
|
this.validatorStore = validatorStore;
|
|
33
54
|
this.metrics = metrics;
|
|
34
|
-
this.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// properly emit the re-org event
|
|
38
|
-
clock.runEverySlot(this.runBlockDutiesTask);
|
|
55
|
+
clock.runEveryEpoch(this.runEveryEpochTask);
|
|
56
|
+
clock.runEverySlot(this.runEverySlotTask);
|
|
57
|
+
chainHeaderTracker.runOnNewHead(this.onNewHead);
|
|
39
58
|
if (metrics) {
|
|
40
59
|
metrics.proposerDutiesEpochCount.addCollect(() => {
|
|
41
60
|
metrics.proposerDutiesEpochCount.set(this.proposers.size);
|
|
42
61
|
});
|
|
43
62
|
}
|
|
44
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Late-bind the production callback. Allows the duties service to be constructed
|
|
66
|
+
* before the consumer that handles proposal production.
|
|
67
|
+
*/
|
|
68
|
+
setNotifyBlockProductionFn(notifyBlockProductionFn) {
|
|
69
|
+
this.notifyBlockProductionFn = notifyBlockProductionFn;
|
|
70
|
+
}
|
|
45
71
|
/**
|
|
46
72
|
* Returns the pubkeys of the validators which are assigned to propose in the given slot.
|
|
47
73
|
*
|
|
@@ -61,6 +87,15 @@ export class BlockDutiesService {
|
|
|
61
87
|
}
|
|
62
88
|
return Array.from(publicKeys.values());
|
|
63
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns the cached `{dependentRoot, data}` entry for `epoch`, or `undefined` if duties
|
|
92
|
+
* for that epoch are not yet known. Consumers can detect a proposer-shuffling change
|
|
93
|
+
* (e.g. after a reorg) by observing a different `dependentRoot` than the one they last
|
|
94
|
+
* read for the same epoch.
|
|
95
|
+
*/
|
|
96
|
+
getProposersAtEpoch(epoch) {
|
|
97
|
+
return this.proposers.get(epoch);
|
|
98
|
+
}
|
|
64
99
|
removeDutiesForKey(pubkey) {
|
|
65
100
|
for (const blockDutyAtEpoch of this.proposers.values()) {
|
|
66
101
|
blockDutyAtEpoch.data = blockDutyAtEpoch.data.filter((proposer) => {
|
|
@@ -68,102 +103,169 @@ export class BlockDutiesService {
|
|
|
68
103
|
});
|
|
69
104
|
}
|
|
70
105
|
}
|
|
71
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Baseline per-epoch fetch. Fires at epoch boundaries (and once at startup). Post-Fulu the
|
|
108
|
+
* deterministic 1-epoch lookahead lets us also pre-fetch `epoch + 1`; pre-Fulu the next
|
|
109
|
+
* epoch's dep_root only stabilizes at the boundary and is handled by `runEverySlotTask`.
|
|
110
|
+
*
|
|
111
|
+
* Mid-epoch refreshes (e.g. reorgs) are driven by `onNewHead` instead of polling every slot.
|
|
112
|
+
*/
|
|
113
|
+
runEveryEpochTask = async (epoch) => {
|
|
72
114
|
try {
|
|
73
|
-
if (
|
|
74
|
-
//
|
|
75
|
-
// Only fetch
|
|
115
|
+
if (epoch < GENESIS_EPOCH) {
|
|
116
|
+
// Pre-genesis: prime the genesis-epoch duties exactly once so the slot-0 proposer
|
|
117
|
+
// doesn't have to wait on a cold cache. Only fetch once since a pre-genesis re-org
|
|
118
|
+
// is not possible. TODO: Review.
|
|
76
119
|
if (!this.proposers.has(GENESIS_EPOCH)) {
|
|
77
120
|
await this.pollBeaconProposers(GENESIS_EPOCH);
|
|
78
121
|
}
|
|
122
|
+
return;
|
|
79
123
|
}
|
|
80
|
-
|
|
81
|
-
|
|
124
|
+
await this.pollBeaconProposers(epoch);
|
|
125
|
+
const nextEpoch = epoch + 1;
|
|
126
|
+
if (isForkPostFulu(this.config.getForkName(computeStartSlotAtEpoch(nextEpoch)))) {
|
|
127
|
+
await this.pollBeaconProposers(nextEpoch);
|
|
82
128
|
}
|
|
83
129
|
}
|
|
84
130
|
catch (e) {
|
|
85
|
-
this.logger.error("Error on
|
|
131
|
+
this.logger.error("Error on runEveryEpochTask", { epoch }, e);
|
|
86
132
|
}
|
|
87
133
|
finally {
|
|
88
|
-
this.pruneOldDuties(
|
|
134
|
+
this.pruneOldDuties(Math.max(epoch, GENESIS_EPOCH));
|
|
89
135
|
}
|
|
90
136
|
};
|
|
91
137
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
138
|
+
* Slot-tick handler. Notifies block production for cached proposers in this slot, and on
|
|
139
|
+
* the last slot of a pre-Fulu epoch schedules the boundary fetch for `nextEpoch` duties.
|
|
140
|
+
* Reorg detection is handled by `onNewHead`, so this task does not re-poll on every slot.
|
|
141
|
+
*/
|
|
142
|
+
runEverySlotTask = async (slot, signal) => {
|
|
143
|
+
try {
|
|
144
|
+
if (slot < GENESIS_SLOT) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
this.notifyProposersForSlot(slot);
|
|
148
|
+
const nextEpoch = computeEpochAtSlot(slot) + 1;
|
|
149
|
+
const isLastSlotOfEpoch = computeStartSlotAtEpoch(nextEpoch) === slot + 1;
|
|
150
|
+
if (isLastSlotOfEpoch && !isForkPostFulu(this.config.getForkName(slot + 1))) {
|
|
151
|
+
// Pre-Fulu: 0-epoch proposer lookahead, so the next-epoch dep_root only becomes stable
|
|
152
|
+
// as the last block of the current epoch lands. Sleep until ~1s before the boundary
|
|
153
|
+
// then fetch — same timing as before this refactor.
|
|
154
|
+
this.pollBeaconProposersBeforeBoundary(slot, nextEpoch, signal).catch((e) => {
|
|
155
|
+
this.logger.error("Error on pollBeaconProposersBeforeBoundary", { nextEpoch }, e);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
this.logger.error("Error on runEverySlotTask", { slot }, e);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* SSE head-event handler. The beacon-API `head` event carries attester-duty dep_roots,
|
|
165
|
+
* which coincide with the proposer dep_roots at a fork-dependent offset:
|
|
100
166
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
167
|
+
* Pre-Fulu (proposer dep_root(E) = block@startSlot(E) - 1):
|
|
168
|
+
* currentDutyDependentRoot ≡ proposer_dep_root(currentEpoch)
|
|
169
|
+
* (next-epoch proposer dep_root is not exposed; pre-Fulu falls back to the
|
|
170
|
+
* `runEverySlotTask` boundary poll.)
|
|
104
171
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* provide an acceptable level of safety.
|
|
172
|
+
* Post-Fulu (proposer dep_root(E) = block@startSlot(E - 1) - 1, EIP-7917):
|
|
173
|
+
* previousDutyDependentRoot ≡ proposer_dep_root(currentEpoch)
|
|
174
|
+
* currentDutyDependentRoot ≡ proposer_dep_root(nextEpoch)
|
|
109
175
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* through the slow path every time. I.e., the proposal will only happen after we've been able to
|
|
113
|
-
* download and process the duties from the BN. This means it is very important to ensure this
|
|
114
|
-
* function is as fast as possible.
|
|
115
|
-
* - Starting from Jul 2023, we poll proposers 1s before the next epoch thanks to PrepareNextSlotScheduler
|
|
116
|
-
* usually finishes in 3s.
|
|
176
|
+
* On a dep_root mismatch (reorg, or initial sync delivering a fresher head) we refetch
|
|
177
|
+
* just the affected epoch, mirroring `AttestationDutiesService.onNewHead`.
|
|
117
178
|
*/
|
|
118
|
-
async
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
this.
|
|
124
|
-
this.logger.error("Error on pollBeaconProposersNextEpoch", {}, e);
|
|
125
|
-
});
|
|
179
|
+
onNewHead = async ({ slot, previousDutyDependentRoot, currentDutyDependentRoot, }) => {
|
|
180
|
+
const currentEpoch = computeEpochAtSlot(slot);
|
|
181
|
+
const isPostFulu = isForkPostFulu(this.config.getForkName(slot));
|
|
182
|
+
if (isPostFulu) {
|
|
183
|
+
await this.refetchIfDepRootChanged(currentEpoch, previousDutyDependentRoot);
|
|
184
|
+
await this.refetchIfDepRootChanged(currentEpoch + 1, currentDutyDependentRoot);
|
|
126
185
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
//
|
|
136
|
-
// Then, compute the difference between these two sets to obtain a set of block proposers
|
|
137
|
-
// which were not included in the initial notification to the `BlockService`.
|
|
138
|
-
const newBlockProducers = this.getblockProposersAtSlot(currentSlot);
|
|
139
|
-
const additionalBlockProducers = differenceHex(initialBlockProposers, newBlockProducers);
|
|
140
|
-
// If there are any new proposers for this slot, send a notification so they produce a block.
|
|
141
|
-
//
|
|
142
|
-
// See the function-level documentation for more reasoning about this behaviour.
|
|
143
|
-
if (additionalBlockProducers.length > 0) {
|
|
144
|
-
this.notifyBlockProductionFn(currentSlot, additionalBlockProducers);
|
|
145
|
-
this.logger.debug("Detected new block proposer", { currentSlot });
|
|
146
|
-
this.metrics?.newProposalDutiesDetected.inc();
|
|
186
|
+
else {
|
|
187
|
+
await this.refetchIfDepRootChanged(currentEpoch, currentDutyDependentRoot);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
async refetchIfDepRootChanged(epoch, expectedDepRoot) {
|
|
191
|
+
const cached = this.proposers.get(epoch);
|
|
192
|
+
if (!cached || cached.dependentRoot === expectedDepRoot) {
|
|
193
|
+
return;
|
|
147
194
|
}
|
|
195
|
+
this.logger.debug("Proposer duties dep_root changed, refetching", {
|
|
196
|
+
epoch,
|
|
197
|
+
priorDependentRoot: cached.dependentRoot,
|
|
198
|
+
newDependentRoot: expectedDepRoot,
|
|
199
|
+
});
|
|
200
|
+
await this.pollBeaconProposers(epoch);
|
|
148
201
|
}
|
|
149
202
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
203
|
+
* Pre-Fulu boundary fetch. Because pre-Fulu proposer shuffling has 0-epoch look-ahead, a
|
|
204
|
+
* proposal for the first slot of the new epoch otherwise goes through the slow path every
|
|
205
|
+
* time: the proposal can only happen *after* we download and process the new duties from
|
|
206
|
+
* the BN. Polling ~1s before the boundary, while `PrepareNextSlotScheduler` is finishing
|
|
207
|
+
* the upcoming-epoch transition, lets us land on a hot BN cache and avoid the miss.
|
|
208
|
+
*
|
|
209
|
+
* See https://github.com/ChainSafe/lodestar/issues/5792.
|
|
152
210
|
*/
|
|
153
|
-
async
|
|
211
|
+
async pollBeaconProposersBeforeBoundary(currentSlot, nextEpoch, signal) {
|
|
154
212
|
const nextSlot = currentSlot + 1;
|
|
155
213
|
const lookAheadMs = this.config.SLOT_DURATION_MS - this.config.getSlotComponentDurationMs(BLOCK_DUTIES_LOOKAHEAD_BPS);
|
|
156
214
|
await sleep(this.clock.msToSlot(nextSlot) - lookAheadMs, signal);
|
|
157
|
-
this.logger.debug("Polling proposers for next epoch", { nextEpoch,
|
|
158
|
-
// Poll proposers for the next epoch
|
|
215
|
+
this.logger.debug("Polling proposers for the next epoch", { nextEpoch, currentSlot });
|
|
159
216
|
await this.pollBeaconProposers(nextEpoch);
|
|
160
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Notify block production for *newly discovered* proposers in this slot. Notifications are
|
|
220
|
+
* deduplicated per-slot so that a late SSE refetch can extend the proposer set without
|
|
221
|
+
* triggering a duplicate `createAndPublishBlock` for already-notified validators.
|
|
222
|
+
*
|
|
223
|
+
* ## Multi-notification safety
|
|
224
|
+
*
|
|
225
|
+
* Within a single slot the cache can be updated from several sources (cold-cache backfill at
|
|
226
|
+
* startup, SSE-driven reorg refetch). Each update may fire this function again. The contract
|
|
227
|
+
* we keep is: each pubkey is notified *at most once per slot*. The additional notifications
|
|
228
|
+
* only carry proposers that were not part of an earlier notification.
|
|
229
|
+
*
|
|
230
|
+
* Is this safe? Firstly, the dedup above guarantees we never ask the same validator to
|
|
231
|
+
* propose twice for the same slot. Secondly, slashing protection in `ValidatorStore` acts as
|
|
232
|
+
* a second line of defense should the dedup ever fail. Together they provide an acceptable
|
|
233
|
+
* level of safety for the "notify-from-cache, refine-after-refetch" pattern.
|
|
234
|
+
*/
|
|
235
|
+
notifyProposersForSlot(slot) {
|
|
236
|
+
if (slot !== this.notifiedSlot) {
|
|
237
|
+
this.notifiedSlot = slot;
|
|
238
|
+
this.notifiedSlotInitialPass = false;
|
|
239
|
+
this.notifiedProposers.clear();
|
|
240
|
+
}
|
|
241
|
+
const isLateDetection = this.notifiedSlotInitialPass;
|
|
242
|
+
this.notifiedSlotInitialPass = true;
|
|
243
|
+
const newProposers = [];
|
|
244
|
+
for (const pubkey of this.getblockProposersAtSlot(slot)) {
|
|
245
|
+
const pubkeyHex = toPubkeyHex(pubkey);
|
|
246
|
+
if (!this.notifiedProposers.has(pubkeyHex)) {
|
|
247
|
+
this.notifiedProposers.add(pubkeyHex);
|
|
248
|
+
newProposers.push(pubkey);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (newProposers.length === 0) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (isLateDetection) {
|
|
255
|
+
this.metrics?.newProposalDutiesDetected.inc();
|
|
256
|
+
this.logger.debug("Detected new block proposer", { slot });
|
|
257
|
+
}
|
|
258
|
+
this.notifyBlockProductionFn(slot, newProposers);
|
|
259
|
+
}
|
|
161
260
|
async pollBeaconProposers(epoch) {
|
|
162
261
|
// Only download duties and push out additional block production events if we have some validators.
|
|
163
262
|
if (!this.validatorStore.hasSomeValidators()) {
|
|
164
263
|
return;
|
|
165
264
|
}
|
|
166
|
-
|
|
265
|
+
// Post-Fulu the proposer dependent root changed (deterministic proposer lookahead)
|
|
266
|
+
const res = isForkPostFulu(this.config.getForkName(computeStartSlotAtEpoch(epoch)))
|
|
267
|
+
? await this.api.validator.getProposerDutiesV2({ epoch })
|
|
268
|
+
: await this.api.validator.getProposerDuties({ epoch });
|
|
167
269
|
const proposerDuties = res.value();
|
|
168
270
|
const { dependentRoot } = res.meta();
|
|
169
271
|
const relevantDuties = proposerDuties.filter((duty) => {
|
|
@@ -172,6 +274,11 @@ export class BlockDutiesService {
|
|
|
172
274
|
});
|
|
173
275
|
this.logger.debug("Downloaded proposer duties", { epoch, dependentRoot, count: relevantDuties.length });
|
|
174
276
|
const prior = this.proposers.get(epoch);
|
|
277
|
+
// Concurrent polls for the same epoch (e.g. `onNewHead` and `runEveryEpochTask` racing)
|
|
278
|
+
// both write here last-write-wins. The pre-refactor per-slot poll healed any stale write
|
|
279
|
+
// on the next slot; in the event-driven model staleness can persist until the next
|
|
280
|
+
// dep_root change. In practice the same BN serves both calls so they return identical
|
|
281
|
+
// payloads — accept the rare race rather than serialising fetches.
|
|
175
282
|
this.proposers.set(epoch, { dependentRoot, data: relevantDuties });
|
|
176
283
|
if (prior && prior.dependentRoot !== dependentRoot) {
|
|
177
284
|
this.metrics?.proposerDutiesReorg.inc();
|
|
@@ -180,6 +287,11 @@ export class BlockDutiesService {
|
|
|
180
287
|
dependentRoot,
|
|
181
288
|
});
|
|
182
289
|
}
|
|
290
|
+
// If this fetch revealed proposer(s) for the active slot that the last `runEverySlotTask`
|
|
291
|
+
// missed (cold cache at startup, or duties shifted by a reorg), notify now.
|
|
292
|
+
if (this.notifiedSlot >= GENESIS_SLOT && computeEpochAtSlot(this.notifiedSlot) === epoch) {
|
|
293
|
+
this.notifyProposersForSlot(this.notifiedSlot);
|
|
294
|
+
}
|
|
183
295
|
}
|
|
184
296
|
/** Run once per epoch to prune `this.proposers` map */
|
|
185
297
|
pruneOldDuties(currentEpoch) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blockDuties.js","sourceRoot":"","sources":["../../src/services/blockDuties.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"blockDuties.js","sourceRoot":"","sources":["../../src/services/blockDuties.ts"],"names":[],"mappings":"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"}
|