@lodestar/validator 1.43.0-dev.bc569affb9 → 1.43.0-dev.c98da75ec7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/lib/metrics.d.ts +10 -0
  2. package/lib/metrics.d.ts.map +1 -1
  3. package/lib/metrics.js +37 -0
  4. package/lib/metrics.js.map +1 -1
  5. package/lib/services/block.d.ts +2 -1
  6. package/lib/services/block.d.ts.map +1 -1
  7. package/lib/services/block.js +4 -3
  8. package/lib/services/block.js.map +1 -1
  9. package/lib/services/blockDuties.d.ts +20 -4
  10. package/lib/services/blockDuties.d.ts.map +1 -1
  11. package/lib/services/blockDuties.js +18 -3
  12. package/lib/services/blockDuties.js.map +1 -1
  13. package/lib/services/chainHeaderTracker.d.ts +8 -2
  14. package/lib/services/chainHeaderTracker.d.ts.map +1 -1
  15. package/lib/services/chainHeaderTracker.js +23 -8
  16. package/lib/services/chainHeaderTracker.js.map +1 -1
  17. package/lib/services/emitter.d.ts +14 -1
  18. package/lib/services/emitter.d.ts.map +1 -1
  19. package/lib/services/emitter.js +22 -0
  20. package/lib/services/emitter.js.map +1 -1
  21. package/lib/services/proposerPreferences.d.ts +25 -0
  22. package/lib/services/proposerPreferences.d.ts.map +1 -0
  23. package/lib/services/proposerPreferences.js +101 -0
  24. package/lib/services/proposerPreferences.js.map +1 -0
  25. package/lib/services/ptc.d.ts +28 -0
  26. package/lib/services/ptc.d.ts.map +1 -0
  27. package/lib/services/ptc.js +89 -0
  28. package/lib/services/ptc.js.map +1 -0
  29. package/lib/services/ptcDuties.d.ts +31 -0
  30. package/lib/services/ptcDuties.d.ts.map +1 -0
  31. package/lib/services/ptcDuties.js +201 -0
  32. package/lib/services/ptcDuties.js.map +1 -0
  33. package/lib/services/validatorStore.d.ts +3 -0
  34. package/lib/services/validatorStore.d.ts.map +1 -1
  35. package/lib/services/validatorStore.js +54 -1
  36. package/lib/services/validatorStore.js.map +1 -1
  37. package/lib/util/externalSignerClient.d.ts +9 -1
  38. package/lib/util/externalSignerClient.d.ts.map +1 -1
  39. package/lib/util/externalSignerClient.js +8 -0
  40. package/lib/util/externalSignerClient.js.map +1 -1
  41. package/lib/util/params.js +3 -0
  42. package/lib/util/params.js.map +1 -1
  43. package/lib/validator.d.ts +4 -1
  44. package/lib/validator.d.ts.map +1 -1
  45. package/lib/validator.js +13 -3
  46. package/lib/validator.js.map +1 -1
  47. package/package.json +12 -12
  48. package/src/metrics.ts +46 -0
  49. package/src/services/block.ts +3 -9
  50. package/src/services/blockDuties.ts +21 -6
  51. package/src/services/chainHeaderTracker.ts +31 -7
  52. package/src/services/emitter.ts +31 -0
  53. package/src/services/proposerPreferences.ts +124 -0
  54. package/src/services/ptc.ts +131 -0
  55. package/src/services/ptcDuties.ts +246 -0
  56. package/src/services/validatorStore.ts +79 -0
  57. package/src/util/externalSignerClient.ts +13 -1
  58. package/src/util/params.ts +3 -0
  59. package/src/validator.ts +39 -5
@@ -9,6 +9,8 @@ import {
9
9
  DOMAIN_BEACON_BUILDER,
10
10
  DOMAIN_BEACON_PROPOSER,
11
11
  DOMAIN_CONTRIBUTION_AND_PROOF,
12
+ DOMAIN_PROPOSER_PREFERENCES,
13
+ DOMAIN_PTC_ATTESTER,
12
14
  DOMAIN_RANDAO,
13
15
  DOMAIN_SELECTION_PROOF,
14
16
  DOMAIN_SYNC_COMMITTEE,
@@ -668,6 +670,77 @@ export class ValidatorStore {
668
670
  };
669
671
  }
670
672
 
673
+ async signPayloadAttestation(
674
+ duty: routes.validator.PtcDuty,
675
+ data: gloas.PayloadAttestationData,
676
+ currentSlot: Slot,
677
+ logger?: LoggerVc
678
+ ): Promise<gloas.PayloadAttestationMessage> {
679
+ if (data.slot > currentSlot) {
680
+ throw Error(`Not signing payload attestation with slot ${data.slot} greater than current slot ${currentSlot}`);
681
+ }
682
+
683
+ this.assertDoppelgangerSafe(duty.pubkey);
684
+ this.validatePtcDuty(duty, data);
685
+
686
+ const signingSlot = data.slot;
687
+ const domain = this.config.getDomain(signingSlot, DOMAIN_PTC_ATTESTER);
688
+ const signingRoot = computeSigningRoot(ssz.gloas.PayloadAttestationData, data, domain);
689
+
690
+ logger?.debug("Signing payload attestation message", {
691
+ slot: signingSlot,
692
+ beaconBlockRoot: toRootHex(data.beaconBlockRoot),
693
+ signingRoot: toRootHex(signingRoot),
694
+ });
695
+
696
+ const signableMessage: SignableMessage = {
697
+ type: SignableMessageType.PAYLOAD_ATTESTATION,
698
+ data,
699
+ };
700
+
701
+ return {
702
+ validatorIndex: duty.validatorIndex,
703
+ data,
704
+ signature: await this.getSignature(duty.pubkey, signingRoot, signingSlot, signableMessage),
705
+ };
706
+ }
707
+
708
+ async signProposerPreferences(
709
+ duty: routes.validator.ProposerDuty,
710
+ dependentRoot: Uint8Array,
711
+ feeRecipient: ExecutionAddress,
712
+ gasLimit: number,
713
+ currentSlot: Slot
714
+ ): Promise<gloas.SignedProposerPreferences> {
715
+ if (duty.slot <= currentSlot) {
716
+ throw Error(`Not signing proposer preferences for past slot ${duty.slot} (current ${currentSlot})`);
717
+ }
718
+
719
+ this.assertDoppelgangerSafe(duty.pubkey);
720
+
721
+ const message: gloas.ProposerPreferences = {
722
+ dependentRoot,
723
+ proposalSlot: duty.slot,
724
+ validatorIndex: duty.validatorIndex,
725
+ feeRecipient: fromHex(feeRecipient),
726
+ gasLimit,
727
+ };
728
+
729
+ const signingSlot = duty.slot;
730
+ const domain = this.config.getDomain(signingSlot, DOMAIN_PROPOSER_PREFERENCES);
731
+ const signingRoot = computeSigningRoot(ssz.gloas.ProposerPreferences, message, domain);
732
+
733
+ const signableMessage: SignableMessage = {
734
+ type: SignableMessageType.PROPOSER_PREFERENCES,
735
+ data: message,
736
+ };
737
+
738
+ return {
739
+ message,
740
+ signature: await this.getSignature(duty.pubkey, signingRoot, signingSlot, signableMessage),
741
+ };
742
+ }
743
+
671
744
  async signAttestationSelectionProof(pubkey: BLSPubkeyMaybeHex, slot: Slot): Promise<BLSSignature> {
672
745
  const signingSlot = slot;
673
746
  const domain = this.config.getDomain(slot, DOMAIN_SELECTION_PROOF);
@@ -852,6 +925,12 @@ export class ValidatorStore {
852
925
  }
853
926
  }
854
927
 
928
+ private validatePtcDuty(duty: routes.validator.PtcDuty, data: gloas.PayloadAttestationData): void {
929
+ if (duty.slot !== data.slot) {
930
+ throw Error(`Inconsistent PTC duties during signing: duty.slot ${duty.slot} != data.slot ${data.slot}`);
931
+ }
932
+ }
933
+
855
934
  private assertDoppelgangerSafe(pubKey: PubkeyHex | BLSPubkey): void {
856
935
  const pubkeyHex = typeof pubKey === "string" ? pubKey : toPubkeyHex(pubKey);
857
936
  if (!this.isDoppelgangerSafe(pubkeyHex)) {
@@ -34,6 +34,8 @@ export enum SignableMessageType {
34
34
  SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF = "SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF",
35
35
  VALIDATOR_REGISTRATION = "VALIDATOR_REGISTRATION",
36
36
  EXECUTION_PAYLOAD_ENVELOPE = "EXECUTION_PAYLOAD_ENVELOPE",
37
+ PAYLOAD_ATTESTATION = "PAYLOAD_ATTESTATION",
38
+ PROPOSER_PREFERENCES = "PROPOSER_PREFERENCES",
37
39
  }
38
40
 
39
41
  const AggregationSlotType = new ContainerType({
@@ -83,7 +85,9 @@ export type SignableMessage =
83
85
  | {type: SignableMessageType.SYNC_COMMITTEE_SELECTION_PROOF; data: ValueOf<typeof SyncAggregatorSelectionDataType>}
84
86
  | {type: SignableMessageType.SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF; data: altair.ContributionAndProof}
85
87
  | {type: SignableMessageType.VALIDATOR_REGISTRATION; data: ValidatorRegistrationV1}
86
- | {type: SignableMessageType.EXECUTION_PAYLOAD_ENVELOPE; data: gloas.ExecutionPayloadEnvelope};
88
+ | {type: SignableMessageType.EXECUTION_PAYLOAD_ENVELOPE; data: gloas.ExecutionPayloadEnvelope}
89
+ | {type: SignableMessageType.PAYLOAD_ATTESTATION; data: gloas.PayloadAttestationData}
90
+ | {type: SignableMessageType.PROPOSER_PREFERENCES; data: gloas.ProposerPreferences};
87
91
 
88
92
  const requiresForkInfo: Record<SignableMessageType, boolean> = {
89
93
  [SignableMessageType.AGGREGATION_SLOT]: true,
@@ -99,6 +103,8 @@ const requiresForkInfo: Record<SignableMessageType, boolean> = {
99
103
  [SignableMessageType.SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF]: true,
100
104
  [SignableMessageType.VALIDATOR_REGISTRATION]: false,
101
105
  [SignableMessageType.EXECUTION_PAYLOAD_ENVELOPE]: true,
106
+ [SignableMessageType.PAYLOAD_ATTESTATION]: true,
107
+ [SignableMessageType.PROPOSER_PREFERENCES]: true,
102
108
  };
103
109
 
104
110
  type Web3SignerSerializedRequest = {
@@ -273,6 +279,12 @@ function serializerSignableMessagePayload(config: BeaconConfig, payload: Signabl
273
279
 
274
280
  case SignableMessageType.EXECUTION_PAYLOAD_ENVELOPE:
275
281
  return {execution_payload_envelope: ssz.gloas.ExecutionPayloadEnvelope.toJson(payload.data)};
282
+
283
+ case SignableMessageType.PAYLOAD_ATTESTATION:
284
+ return {payload_attestation: ssz.gloas.PayloadAttestationData.toJson(payload.data)};
285
+
286
+ case SignableMessageType.PROPOSER_PREFERENCES:
287
+ return {proposer_preferences: ssz.gloas.ProposerPreferences.toJson(payload.data)};
276
288
  }
277
289
  }
278
290
 
@@ -327,5 +327,8 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record<keyof ConfigWit
327
327
  BUILDER_PENDING_WITHDRAWALS_LIMIT: gloasForkRelevant,
328
328
  MAX_BUILDERS_PER_WITHDRAWALS_SWEEP: gloasForkRelevant,
329
329
  MIN_BUILDER_WITHDRAWABILITY_DELAY: gloasForkRelevant,
330
+ CHURN_LIMIT_QUOTIENT_GLOAS: gloasForkRelevant,
331
+ CONSOLIDATION_CHURN_LIMIT_QUOTIENT: gloasForkRelevant,
332
+ MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS: gloasForkRelevant,
330
333
  };
331
334
  }
package/src/validator.ts CHANGED
@@ -9,12 +9,15 @@ import {Metrics} from "./metrics.js";
9
9
  import {MetaDataRepository} from "./repositories/metaDataRepository.js";
10
10
  import {AttestationService} from "./services/attestation.js";
11
11
  import {BlockProposingService} from "./services/block.js";
12
+ import {BlockDutiesService} from "./services/blockDuties.js";
12
13
  import {ChainHeaderTracker} from "./services/chainHeaderTracker.js";
13
14
  import {DoppelgangerService} from "./services/doppelgangerService.js";
14
15
  import {ValidatorEventEmitter} from "./services/emitter.js";
15
16
  import {ExternalSignerOptions, pollExternalSignerPubkeys} from "./services/externalSignerSync.js";
16
17
  import {IndicesService} from "./services/indices.js";
17
18
  import {pollBuilderValidatorRegistration, pollPrepareBeaconProposer} from "./services/prepareBeaconProposer.js";
19
+ import {ProposerPreferencesService} from "./services/proposerPreferences.js";
20
+ import {PtcService} from "./services/ptc.js";
18
21
  import {SyncCommitteeService} from "./services/syncCommittee.js";
19
22
  import {SyncingStatusTracker} from "./services/syncingStatusTracker.js";
20
23
  import {Signer, ValidatorProposerConfig, ValidatorStore, defaultOptions} from "./services/validatorStore.js";
@@ -30,6 +33,7 @@ export type ValidatorModules = {
30
33
  slashingProtection: ISlashingProtection;
31
34
  blockProposingService: BlockProposingService;
32
35
  attestationService: AttestationService;
36
+ ptcService: PtcService;
33
37
  syncCommitteeService: SyncCommitteeService;
34
38
  config: BeaconConfig;
35
39
  api: ApiClient;
@@ -84,6 +88,7 @@ export class Validator {
84
88
  private readonly slashingProtection: ISlashingProtection;
85
89
  private readonly blockProposingService: BlockProposingService;
86
90
  private readonly attestationService: AttestationService;
91
+ private readonly ptcService: PtcService;
87
92
  private readonly syncCommitteeService: SyncCommitteeService;
88
93
  private readonly config: BeaconConfig;
89
94
  private readonly api: ApiClient;
@@ -102,6 +107,7 @@ export class Validator {
102
107
  slashingProtection,
103
108
  blockProposingService,
104
109
  attestationService,
110
+ ptcService,
105
111
  syncCommitteeService,
106
112
  config,
107
113
  api,
@@ -118,6 +124,7 @@ export class Validator {
118
124
  this.slashingProtection = slashingProtection;
119
125
  this.blockProposingService = blockProposingService;
120
126
  this.attestationService = attestationService;
127
+ this.ptcService = ptcService;
121
128
  this.syncCommitteeService = syncCommitteeService;
122
129
  this.config = config;
123
130
  this.api = api;
@@ -225,13 +232,24 @@ export class Validator {
225
232
  // We set infinity to prevent MaxListenersExceededWarning which get logged when listeners > 10
226
233
  emitter.setMaxListeners(Infinity);
227
234
 
228
- const chainHeaderTracker = new ChainHeaderTracker(logger, api, emitter);
235
+ const chainHeaderTracker = new ChainHeaderTracker(config, logger, api, emitter);
229
236
  const syncingStatusTracker = new SyncingStatusTracker(logger, api, clock, metrics);
230
237
 
231
- const blockProposingService = new BlockProposingService(config, loggerVc, api, clock, validatorStore, metrics, {
232
- broadcastValidation: opts.broadcastValidation ?? defaultOptions.broadcastValidation,
233
- blindedLocal: opts.blindedLocal ?? defaultOptions.blindedLocal,
234
- });
238
+ const blockDutiesService = new BlockDutiesService(config, loggerVc, api, clock, validatorStore, metrics);
239
+
240
+ const blockProposingService = new BlockProposingService(
241
+ config,
242
+ loggerVc,
243
+ api,
244
+ clock,
245
+ validatorStore,
246
+ blockDutiesService,
247
+ metrics,
248
+ {
249
+ broadcastValidation: opts.broadcastValidation ?? defaultOptions.broadcastValidation,
250
+ blindedLocal: opts.blindedLocal ?? defaultOptions.blindedLocal,
251
+ }
252
+ );
235
253
 
236
254
  const attestationService = new AttestationService(
237
255
  loggerVc,
@@ -249,6 +267,18 @@ export class Validator {
249
267
  }
250
268
  );
251
269
 
270
+ const ptcService = new PtcService(
271
+ config,
272
+ loggerVc,
273
+ api,
274
+ clock,
275
+ validatorStore,
276
+ emitter,
277
+ chainHeaderTracker,
278
+ syncingStatusTracker,
279
+ metrics
280
+ );
281
+
252
282
  const syncCommitteeService = new SyncCommitteeService(
253
283
  config,
254
284
  loggerVc,
@@ -265,6 +295,8 @@ export class Validator {
265
295
  }
266
296
  );
267
297
 
298
+ new ProposerPreferencesService(config, loggerVc, api, clock, validatorStore, blockDutiesService, metrics);
299
+
268
300
  return new Validator({
269
301
  opts,
270
302
  genesis,
@@ -272,6 +304,7 @@ export class Validator {
272
304
  slashingProtection,
273
305
  blockProposingService,
274
306
  attestationService,
307
+ ptcService,
275
308
  syncCommitteeService,
276
309
  config,
277
310
  api,
@@ -338,6 +371,7 @@ export class Validator {
338
371
  removeDutiesForKey(pubkey: PubkeyHex): void {
339
372
  this.blockProposingService.removeDutiesForKey(pubkey);
340
373
  this.attestationService.removeDutiesForKey(pubkey);
374
+ this.ptcService.removeDutiesForKey(pubkey);
341
375
  this.syncCommitteeService.removeDutiesForKey(pubkey);
342
376
  }
343
377