@lodestar/validator 1.45.0-dev.51a1c44b27 → 1.45.0-dev.85227cfbe5
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/proposerPreferences.d.ts +6 -1
- package/lib/services/proposerPreferences.d.ts.map +1 -1
- package/lib/services/proposerPreferences.js +20 -3
- package/lib/services/proposerPreferences.js.map +1 -1
- package/lib/services/ptc.d.ts +0 -1
- package/lib/services/ptc.d.ts.map +1 -1
- package/lib/services/ptc.js +3 -10
- package/lib/services/ptc.js.map +1 -1
- package/package.json +12 -12
- package/src/services/proposerPreferences.ts +20 -3
- package/src/services/ptc.ts +4 -11
|
@@ -10,7 +10,10 @@ import { ValidatorStore } from "./validatorStore.js";
|
|
|
10
10
|
* dependent root for an epoch shifts (e.g. after a reorg) — detected by comparing the cached
|
|
11
11
|
* `dependentRoot` reported by `BlockDutiesService` against the one we last submitted under.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* Proposers should broadcast their preferences before the fork so the proposer preference caches
|
|
14
|
+
* of beacon nodes and builders are warm for the first Gloas slots. We start submitting
|
|
15
|
+
* as soon as a duty's proposal slot is in Gloas, which is up to `SUBMIT_BEFORE_PROPOSAL_SLOTS`
|
|
16
|
+
* before the fork, so only the first few Gloas slots are affected by this pre-fork submission.
|
|
14
17
|
*/
|
|
15
18
|
export declare class ProposerPreferencesService {
|
|
16
19
|
private readonly config;
|
|
@@ -21,5 +24,7 @@ export declare class ProposerPreferencesService {
|
|
|
21
24
|
private readonly submitted;
|
|
22
25
|
constructor(config: ChainForkConfig, logger: LoggerVc, api: ApiClient, clock: IClock, validatorStore: ValidatorStore, blockDutiesService: BlockDutiesService, _metrics: Metrics | null);
|
|
23
26
|
private runProposerPreferencesTask;
|
|
27
|
+
/** Drop tracking for past epochs; only currentEpoch and currentEpoch + 1 are ever processed. */
|
|
28
|
+
private pruneSubmitted;
|
|
24
29
|
}
|
|
25
30
|
//# sourceMappingURL=proposerPreferences.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposerPreferences.d.ts","sourceRoot":"","sources":["../../src/services/proposerPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAKjD,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAC,kBAAkB,EAAC,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAgBnD
|
|
1
|
+
{"version":3,"file":"proposerPreferences.d.ts","sourceRoot":"","sources":["../../src/services/proposerPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAKjD,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAC,kBAAkB,EAAC,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAgBnD;;;;;;;;;;GAUG;AACH,qBAAa,0BAA0B;IAInC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAEpB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IARrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAEhE,YACmB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,QAAQ,EAChB,GAAG,EAAE,SAAS,EAC/B,KAAK,EAAE,MAAM,EACI,cAAc,EAAE,cAAc,EAC9B,kBAAkB,EAAE,kBAAkB,EACvD,QAAQ,EAAE,OAAO,GAAG,IAAI,EAIzB;IAED,OAAO,CAAC,0BAA0B,CA8EhC;IAEF,gGAAgG;IAChG,OAAO,CAAC,cAAc,CAMpB;CACH"}
|
|
@@ -17,7 +17,10 @@ const SUBMIT_BEFORE_PROPOSAL_SLOTS = Math.floor(SLOTS_PER_EPOCH / 4);
|
|
|
17
17
|
* dependent root for an epoch shifts (e.g. after a reorg) — detected by comparing the cached
|
|
18
18
|
* `dependentRoot` reported by `BlockDutiesService` against the one we last submitted under.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
20
|
+
* Proposers should broadcast their preferences before the fork so the proposer preference caches
|
|
21
|
+
* of beacon nodes and builders are warm for the first Gloas slots. We start submitting
|
|
22
|
+
* as soon as a duty's proposal slot is in Gloas, which is up to `SUBMIT_BEFORE_PROPOSAL_SLOTS`
|
|
23
|
+
* before the fork, so only the first few Gloas slots are affected by this pre-fork submission.
|
|
21
24
|
*/
|
|
22
25
|
export class ProposerPreferencesService {
|
|
23
26
|
config;
|
|
@@ -33,9 +36,13 @@ export class ProposerPreferencesService {
|
|
|
33
36
|
this.validatorStore = validatorStore;
|
|
34
37
|
this.blockDutiesService = blockDutiesService;
|
|
35
38
|
clock.runEverySlot(this.runProposerPreferencesTask);
|
|
39
|
+
clock.runEveryEpoch(this.pruneSubmitted);
|
|
36
40
|
}
|
|
37
41
|
runProposerPreferencesTask = async (slot) => {
|
|
38
|
-
|
|
42
|
+
// Start running once the submission window (`slot + SUBMIT_BEFORE_PROPOSAL_SLOTS`) reaches
|
|
43
|
+
// Gloas, i.e. already in the epoch before the fork. This allows builders to prepare and
|
|
44
|
+
// submit bids for the first Gloas slots.
|
|
45
|
+
if (!isForkPostGloas(this.config.getForkName(slot + SUBMIT_BEFORE_PROPOSAL_SLOTS))) {
|
|
39
46
|
return;
|
|
40
47
|
}
|
|
41
48
|
const currentEpoch = computeEpochAtSlot(slot);
|
|
@@ -68,6 +75,8 @@ export class ProposerPreferencesService {
|
|
|
68
75
|
continue;
|
|
69
76
|
if (duty.slot > slot + SUBMIT_BEFORE_PROPOSAL_SLOTS)
|
|
70
77
|
continue;
|
|
78
|
+
if (!isForkPostGloas(this.config.getForkName(duty.slot)))
|
|
79
|
+
continue;
|
|
71
80
|
if (submission.slots.has(duty.slot))
|
|
72
81
|
continue;
|
|
73
82
|
try {
|
|
@@ -85,7 +94,7 @@ export class ProposerPreferencesService {
|
|
|
85
94
|
return;
|
|
86
95
|
}
|
|
87
96
|
try {
|
|
88
|
-
await this.api.
|
|
97
|
+
await this.api.validator.submitProposerPreferences({ signedProposerPreferences: batch });
|
|
89
98
|
// Only mark as submitted after the API call succeeds; a thrown error leaves the
|
|
90
99
|
// slot eligible for retry on the next tick.
|
|
91
100
|
for (const { submission, slot: submittedSlot } of pending) {
|
|
@@ -97,5 +106,13 @@ export class ProposerPreferencesService {
|
|
|
97
106
|
this.logger.error("Error submitting signed proposer preferences", { count: batch.length }, e);
|
|
98
107
|
}
|
|
99
108
|
};
|
|
109
|
+
/** Drop tracking for past epochs; only currentEpoch and currentEpoch + 1 are ever processed. */
|
|
110
|
+
pruneSubmitted = async (epoch) => {
|
|
111
|
+
for (const trackedEpoch of this.submitted.keys()) {
|
|
112
|
+
if (trackedEpoch < epoch) {
|
|
113
|
+
this.submitted.delete(trackedEpoch);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
100
117
|
}
|
|
101
118
|
//# sourceMappingURL=proposerPreferences.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposerPreferences.js","sourceRoot":"","sources":["../../src/services/proposerPreferences.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,eAAe,EAAE,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAC,kBAAkB,EAAC,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,iBAAiB,CAAC;AAMrD;;;;;;;;GAQG;AACH,MAAM,4BAA4B,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;AAKrE
|
|
1
|
+
{"version":3,"file":"proposerPreferences.js","sourceRoot":"","sources":["../../src/services/proposerPreferences.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,eAAe,EAAE,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAC,kBAAkB,EAAC,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,iBAAiB,CAAC;AAMrD;;;;;;;;GAQG;AACH,MAAM,4BAA4B,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;AAKrE;;;;;;;;;;GAUG;AACH,MAAM,OAAO,0BAA0B;IAIlB,MAAM;IACN,MAAM;IACN,GAAG;IAEH,cAAc;IACd,kBAAkB;IARpB,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEhE,YACmB,MAAuB,EACvB,MAAgB,EAChB,GAAc,EAC/B,KAAa,EACI,cAA8B,EAC9B,kBAAsC,EACvD,QAAwB,EACxB;sBAPiB,MAAM;sBACN,MAAM;mBACN,GAAG;8BAEH,cAAc;kCACd,kBAAkB;QAGnC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACpD,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAAA,CAC1C;IAEO,0BAA0B,GAAG,KAAK,EAAE,IAAU,EAAiB,EAAE,CAAC;QACxE,2FAA2F;QAC3F,wFAAwF;QACxF,yCAAyC;QACzC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,GAAG,4BAA4B,CAAC,CAAC,EAAE,CAAC;YACnF,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAsC,EAAE,CAAC;QACpD,sFAAsF;QACtF,kFAAkF;QAClF,8EAA8E;QAC9E,MAAM,OAAO,GAAiD,EAAE,CAAC;QAEjE,KAAK,MAAM,KAAK,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,CAAC,CAAC,EAAE,CAAC;YACrD,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;YACzE,IAAI,CAAC,aAAa;gBAAE,SAAS;YAE7B,6EAA6E;YAC7E,6EAA6E;YAC7E,IAAI,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,aAAa,KAAK,aAAa,CAAC,aAAa,EAAE,CAAC;gBACzF,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;oBAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qEAAqE,EAAE;wBACtF,KAAK;wBACL,kBAAkB,EAAE,UAAU,CAAC,aAAa;wBAC5C,aAAa,EAAE,aAAa,CAAC,aAAa;qBAC3C,CAAC,CAAC;gBACL,CAAC;gBACD,UAAU,GAAG,EAAC,aAAa,EAAE,aAAa,CAAC,aAAa,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAC,CAAC;gBAC5E,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YACxC,CAAC;YAED,MAAM,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YAEhE,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC;gBACtC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;oBAAE,SAAS;gBAChC,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,4BAA4B;oBAAE,SAAS;gBAC9D,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAAE,SAAS;gBACnE,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAE9C,IAAI,CAAC;oBACH,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,uBAAuB,CAC9D,IAAI,EACJ,kBAAkB,EAClB,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,SAAS,CAAC,EAC9C,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,SAAS,CAAC,EAC1C,IAAI,CACL,CAAC;oBACF,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACnB,OAAO,CAAC,IAAI,CAAC,EAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAC,CAAC,CAAC;gBAC9C,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,oCAAoC,EACpC,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAC,EACtD,CAAU,CACX,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,yBAAyB,CAAC,EAAC,yBAAyB,EAAE,KAAK,EAAC,CAAC,CAAC;YACvF,gFAAgF;YAChF,4CAA4C;YAC5C,KAAK,MAAM,EAAC,UAAU,EAAE,IAAI,EAAE,aAAa,EAAC,IAAI,OAAO,EAAE,CAAC;gBACxD,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,EAAE,EAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;QACpF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8CAA8C,EAAE,EAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAC,EAAE,CAAU,CAAC,CAAC;QACvG,CAAC;IAAA,CACF,CAAC;IAEF,gGAAgG;IACxF,cAAc,GAAG,KAAK,EAAE,KAAY,EAAiB,EAAE,CAAC;QAC9D,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YACjD,IAAI,YAAY,GAAG,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;IAAA,CACF,CAAC;CACH"}
|
package/lib/services/ptc.d.ts
CHANGED
|
@@ -22,7 +22,6 @@ export declare class PtcService {
|
|
|
22
22
|
constructor(config: ChainForkConfig, logger: LoggerVc, api: ApiClient, clock: IClock, validatorStore: ValidatorStore, emitter: ValidatorEventEmitter, chainHeadTracker: ChainHeaderTracker, syncingStatusTracker: SyncingStatusTracker, metrics: Metrics | null);
|
|
23
23
|
removeDutiesForKey(pubkey: PubkeyHex): void;
|
|
24
24
|
private runPtcTasks;
|
|
25
|
-
private producePayloadAttestationData;
|
|
26
25
|
private signAndPublishPayloadAttestations;
|
|
27
26
|
}
|
|
28
27
|
//# sourceMappingURL=ptc.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ptc.d.ts","sourceRoot":"","sources":["../../src/services/ptc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"ptc.d.ts","sourceRoot":"","sources":["../../src/services/ptc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAS,MAAM,eAAe,CAAC;AAChD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAIjD,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,EAAC,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAC,qBAAqB,EAAC,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAC,oBAAoB,EAAC,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAEnD;;GAEG;AACH,qBAAa,UAAU;IAInB,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;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAGxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX1B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IAEjD,YACmB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,QAAQ,EAChB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,qBAAqB,EAC/C,gBAAgB,EAAE,kBAAkB,EACpC,oBAAoB,EAAE,oBAAoB,EACzB,OAAO,EAAE,OAAO,GAAG,IAAI,EAczC;IAED,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAE1C;IAED,OAAO,CAAC,WAAW,CAiCjB;YAEY,iCAAiC;CAkDhD"}
|
package/lib/services/ptc.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { HttpStatusCode } from "@lodestar/api";
|
|
2
1
|
import { isForkPostGloas } from "@lodestar/params";
|
|
3
2
|
import { prettyBytes, sleep, toRootHex } from "@lodestar/utils";
|
|
4
3
|
import { PtcDutiesService } from "./ptcDuties.js";
|
|
@@ -44,9 +43,10 @@ export class PtcService {
|
|
|
44
43
|
]);
|
|
45
44
|
this.metrics?.ptcStepCallProducePayloadAttestation.observe(this.clock.secFromSlot(slot) - payloadAttestationDueMs / 1000);
|
|
46
45
|
try {
|
|
47
|
-
|
|
46
|
+
// No canonical block at slot resolves to `undefined`
|
|
47
|
+
const payloadAttestationData = (await this.api.validator.producePayloadAttestationData({ slot })).value();
|
|
48
48
|
// If no beacon block was seen for the assigned slot, do not submit a payload attestation
|
|
49
|
-
if (payloadAttestationData
|
|
49
|
+
if (!payloadAttestationData) {
|
|
50
50
|
this.logger.debug("Skipping payload attestation, no beacon block seen for slot", { slot });
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
@@ -56,13 +56,6 @@ export class PtcService {
|
|
|
56
56
|
this.logger.error("Error on PTC routine", { slot }, e);
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
|
-
async producePayloadAttestationData(slot) {
|
|
60
|
-
const res = await this.api.validator.producePayloadAttestationData({ slot });
|
|
61
|
-
if (!res.ok && res.status === HttpStatusCode.NOT_FOUND) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
return res.value();
|
|
65
|
-
}
|
|
66
59
|
async signAndPublishPayloadAttestations(slot, payloadAttestationData, duties) {
|
|
67
60
|
const payloadAttestationMessages = [];
|
|
68
61
|
const beaconBlockRootHex = toRootHex(payloadAttestationData.beaconBlockRoot);
|
package/lib/services/ptc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ptc.js","sourceRoot":"","sources":["../../src/services/ptc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ptc.js","sourceRoot":"","sources":["../../src/services/ptc.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lodestar/validator",
|
|
3
|
-
"version": "1.45.0-dev.
|
|
3
|
+
"version": "1.45.0-dev.85227cfbe5",
|
|
4
4
|
"description": "A Typescript implementation of the validator client",
|
|
5
5
|
"author": "ChainSafe Systems",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -50,21 +50,21 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@chainsafe/blst": "^2.2.0",
|
|
52
52
|
"@chainsafe/ssz": "^1.4.0",
|
|
53
|
-
"@lodestar/api": "^1.45.0-dev.
|
|
54
|
-
"@lodestar/config": "^1.45.0-dev.
|
|
55
|
-
"@lodestar/db": "^1.45.0-dev.
|
|
56
|
-
"@lodestar/params": "^1.45.0-dev.
|
|
57
|
-
"@lodestar/state-transition": "^1.45.0-dev.
|
|
58
|
-
"@lodestar/types": "^1.45.0-dev.
|
|
59
|
-
"@lodestar/utils": "^1.45.0-dev.
|
|
53
|
+
"@lodestar/api": "^1.45.0-dev.85227cfbe5",
|
|
54
|
+
"@lodestar/config": "^1.45.0-dev.85227cfbe5",
|
|
55
|
+
"@lodestar/db": "^1.45.0-dev.85227cfbe5",
|
|
56
|
+
"@lodestar/params": "^1.45.0-dev.85227cfbe5",
|
|
57
|
+
"@lodestar/state-transition": "^1.45.0-dev.85227cfbe5",
|
|
58
|
+
"@lodestar/types": "^1.45.0-dev.85227cfbe5",
|
|
59
|
+
"@lodestar/utils": "^1.45.0-dev.85227cfbe5",
|
|
60
60
|
"strict-event-emitter-types": "^2.0.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@lodestar/logger": "^1.45.0-dev.
|
|
64
|
-
"@lodestar/spec-test-util": "^1.45.0-dev.
|
|
65
|
-
"@lodestar/test-utils": "^1.45.0-dev.
|
|
63
|
+
"@lodestar/logger": "^1.45.0-dev.85227cfbe5",
|
|
64
|
+
"@lodestar/spec-test-util": "^1.45.0-dev.85227cfbe5",
|
|
65
|
+
"@lodestar/test-utils": "^1.45.0-dev.85227cfbe5",
|
|
66
66
|
"@vekexasia/bigint-buffer2": "^1.1.1",
|
|
67
67
|
"rimraf": "^4.4.1"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "bd183bff2666327a75b389254a812a5f729c836f"
|
|
70
70
|
}
|
|
@@ -29,7 +29,10 @@ type SubmittedAtEpoch = {dependentRoot: RootHex; slots: Set<Slot>};
|
|
|
29
29
|
* dependent root for an epoch shifts (e.g. after a reorg) — detected by comparing the cached
|
|
30
30
|
* `dependentRoot` reported by `BlockDutiesService` against the one we last submitted under.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
32
|
+
* Proposers should broadcast their preferences before the fork so the proposer preference caches
|
|
33
|
+
* of beacon nodes and builders are warm for the first Gloas slots. We start submitting
|
|
34
|
+
* as soon as a duty's proposal slot is in Gloas, which is up to `SUBMIT_BEFORE_PROPOSAL_SLOTS`
|
|
35
|
+
* before the fork, so only the first few Gloas slots are affected by this pre-fork submission.
|
|
33
36
|
*/
|
|
34
37
|
export class ProposerPreferencesService {
|
|
35
38
|
private readonly submitted = new Map<Epoch, SubmittedAtEpoch>();
|
|
@@ -44,10 +47,14 @@ export class ProposerPreferencesService {
|
|
|
44
47
|
_metrics: Metrics | null
|
|
45
48
|
) {
|
|
46
49
|
clock.runEverySlot(this.runProposerPreferencesTask);
|
|
50
|
+
clock.runEveryEpoch(this.pruneSubmitted);
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
private runProposerPreferencesTask = async (slot: Slot): Promise<void> => {
|
|
50
|
-
|
|
54
|
+
// Start running once the submission window (`slot + SUBMIT_BEFORE_PROPOSAL_SLOTS`) reaches
|
|
55
|
+
// Gloas, i.e. already in the epoch before the fork. This allows builders to prepare and
|
|
56
|
+
// submit bids for the first Gloas slots.
|
|
57
|
+
if (!isForkPostGloas(this.config.getForkName(slot + SUBMIT_BEFORE_PROPOSAL_SLOTS))) {
|
|
51
58
|
return;
|
|
52
59
|
}
|
|
53
60
|
|
|
@@ -82,6 +89,7 @@ export class ProposerPreferencesService {
|
|
|
82
89
|
for (const duty of dutiesAtEpoch.data) {
|
|
83
90
|
if (duty.slot <= slot) continue;
|
|
84
91
|
if (duty.slot > slot + SUBMIT_BEFORE_PROPOSAL_SLOTS) continue;
|
|
92
|
+
if (!isForkPostGloas(this.config.getForkName(duty.slot))) continue;
|
|
85
93
|
if (submission.slots.has(duty.slot)) continue;
|
|
86
94
|
|
|
87
95
|
try {
|
|
@@ -110,7 +118,7 @@ export class ProposerPreferencesService {
|
|
|
110
118
|
}
|
|
111
119
|
|
|
112
120
|
try {
|
|
113
|
-
await this.api.
|
|
121
|
+
await this.api.validator.submitProposerPreferences({signedProposerPreferences: batch});
|
|
114
122
|
// Only mark as submitted after the API call succeeds; a thrown error leaves the
|
|
115
123
|
// slot eligible for retry on the next tick.
|
|
116
124
|
for (const {submission, slot: submittedSlot} of pending) {
|
|
@@ -121,4 +129,13 @@ export class ProposerPreferencesService {
|
|
|
121
129
|
this.logger.error("Error submitting signed proposer preferences", {count: batch.length}, e as Error);
|
|
122
130
|
}
|
|
123
131
|
};
|
|
132
|
+
|
|
133
|
+
/** Drop tracking for past epochs; only currentEpoch and currentEpoch + 1 are ever processed. */
|
|
134
|
+
private pruneSubmitted = async (epoch: Epoch): Promise<void> => {
|
|
135
|
+
for (const trackedEpoch of this.submitted.keys()) {
|
|
136
|
+
if (trackedEpoch < epoch) {
|
|
137
|
+
this.submitted.delete(trackedEpoch);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
124
141
|
}
|
package/src/services/ptc.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {ApiClient,
|
|
1
|
+
import {ApiClient, routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
3
|
import {isForkPostGloas} from "@lodestar/params";
|
|
4
4
|
import {Slot, gloas} from "@lodestar/types";
|
|
@@ -69,9 +69,10 @@ export class PtcService {
|
|
|
69
69
|
);
|
|
70
70
|
|
|
71
71
|
try {
|
|
72
|
-
|
|
72
|
+
// No canonical block at slot resolves to `undefined`
|
|
73
|
+
const payloadAttestationData = (await this.api.validator.producePayloadAttestationData({slot})).value();
|
|
73
74
|
// If no beacon block was seen for the assigned slot, do not submit a payload attestation
|
|
74
|
-
if (payloadAttestationData
|
|
75
|
+
if (!payloadAttestationData) {
|
|
75
76
|
this.logger.debug("Skipping payload attestation, no beacon block seen for slot", {slot});
|
|
76
77
|
return;
|
|
77
78
|
}
|
|
@@ -81,14 +82,6 @@ export class PtcService {
|
|
|
81
82
|
}
|
|
82
83
|
};
|
|
83
84
|
|
|
84
|
-
private async producePayloadAttestationData(slot: Slot): Promise<gloas.PayloadAttestationData | null> {
|
|
85
|
-
const res = await this.api.validator.producePayloadAttestationData({slot});
|
|
86
|
-
if (!res.ok && res.status === HttpStatusCode.NOT_FOUND) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
return res.value();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
85
|
private async signAndPublishPayloadAttestations(
|
|
93
86
|
slot: Slot,
|
|
94
87
|
payloadAttestationData: gloas.PayloadAttestationData,
|