@lodestar/validator 1.50.0 → 1.51.0-dev.15ecdb3b27
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/attestation.d.ts.map +1 -1
- package/lib/services/attestation.js +1 -2
- package/lib/services/attestation.js.map +1 -1
- package/lib/services/attestationDuties.d.ts.map +1 -1
- package/lib/services/attestationDuties.js +12 -4
- package/lib/services/attestationDuties.js.map +1 -1
- package/lib/services/block.d.ts.map +1 -1
- package/lib/services/block.js +1 -1
- package/lib/services/block.js.map +1 -1
- package/lib/services/blockDuties.d.ts.map +1 -1
- package/lib/services/blockDuties.js +3 -1
- package/lib/services/blockDuties.js.map +1 -1
- package/lib/services/chainHeaderTracker.d.ts.map +1 -1
- package/lib/services/chainHeaderTracker.js +6 -1
- package/lib/services/chainHeaderTracker.js.map +1 -1
- package/lib/services/emitter.d.ts +10 -1
- package/lib/services/emitter.d.ts.map +1 -1
- package/lib/services/emitter.js +4 -0
- package/lib/services/emitter.js.map +1 -1
- package/lib/services/inclusionList.d.ts +25 -0
- package/lib/services/inclusionList.d.ts.map +1 -0
- package/lib/services/inclusionList.js +101 -0
- package/lib/services/inclusionList.js.map +1 -0
- package/lib/services/inclusionListDuties.d.ts +59 -0
- package/lib/services/inclusionListDuties.d.ts.map +1 -0
- package/lib/services/inclusionListDuties.js +252 -0
- package/lib/services/inclusionListDuties.js.map +1 -0
- package/lib/services/ptc.d.ts.map +1 -1
- package/lib/services/ptc.js +3 -2
- package/lib/services/ptc.js.map +1 -1
- package/lib/services/syncCommittee.js +1 -1
- package/lib/services/syncCommittee.js.map +1 -1
- package/lib/services/syncCommitteeDuties.d.ts.map +1 -1
- package/lib/services/syncCommitteeDuties.js +10 -5
- package/lib/services/syncCommitteeDuties.js.map +1 -1
- package/lib/services/validatorStore.d.ts +7 -1
- package/lib/services/validatorStore.d.ts.map +1 -1
- package/lib/services/validatorStore.js +29 -3
- package/lib/services/validatorStore.js.map +1 -1
- package/lib/slashingProtection/attestation/index.d.ts +1 -0
- package/lib/slashingProtection/attestation/index.d.ts.map +1 -1
- package/lib/slashingProtection/attestation/index.js +77 -44
- package/lib/slashingProtection/attestation/index.js.map +1 -1
- package/lib/slashingProtection/index.d.ts +2 -0
- package/lib/slashingProtection/index.d.ts.map +1 -1
- package/lib/slashingProtection/index.js +48 -5
- package/lib/slashingProtection/index.js.map +1 -1
- package/lib/util/externalSignerClient.d.ts +7 -4
- 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/validator.d.ts +4 -1
- package/lib/validator.d.ts.map +1 -1
- package/lib/validator.js +11 -4
- package/lib/validator.js.map +1 -1
- package/package.json +12 -12
- package/src/services/attestation.ts +1 -2
- package/src/services/attestationDuties.ts +18 -4
- package/src/services/block.ts +6 -3
- package/src/services/blockDuties.ts +3 -1
- package/src/services/chainHeaderTracker.ts +8 -1
- package/src/services/emitter.ts +10 -0
- package/src/services/inclusionList.ts +140 -0
- package/src/services/inclusionListDuties.ts +306 -0
- package/src/services/ptc.ts +6 -2
- package/src/services/syncCommittee.ts +1 -1
- package/src/services/syncCommitteeDuties.ts +13 -5
- package/src/services/validatorStore.ts +43 -3
- package/src/slashingProtection/attestation/index.ts +81 -46
- package/src/slashingProtection/index.ts +50 -6
- package/src/util/externalSignerClient.ts +10 -3
- package/src/validator.ts +31 -3
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {GENESIS_EPOCH} from "@lodestar/params";
|
|
2
2
|
import {BLSPubkey, Epoch, Root} from "@lodestar/types";
|
|
3
|
-
import {Logger, toPubkeyHex} from "@lodestar/utils";
|
|
3
|
+
import {Logger, defer, toPubkeyHex} from "@lodestar/utils";
|
|
4
4
|
import {uniqueVectorArr} from "../slashingProtection/utils.js";
|
|
5
|
-
import {LodestarValidatorDatabaseController} from "../types.js";
|
|
5
|
+
import {LodestarValidatorDatabaseController, PubkeyHex} from "../types.js";
|
|
6
6
|
import {
|
|
7
7
|
AttestationByTargetRepository,
|
|
8
8
|
AttestationLowerBoundRepository,
|
|
@@ -34,6 +34,8 @@ export type {ISlashingProtection, InterchangeFormatVersion, SlashingProtectionBl
|
|
|
34
34
|
export class SlashingProtection implements ISlashingProtection {
|
|
35
35
|
private blockService: SlashingProtectionBlockService;
|
|
36
36
|
private attestationService: SlashingProtectionAttestationService;
|
|
37
|
+
private readonly importing = new Map<PubkeyHex, Promise<void>>();
|
|
38
|
+
private lastImport: Promise<void> | null = null;
|
|
37
39
|
|
|
38
40
|
constructor(protected db: LodestarValidatorDatabaseController) {
|
|
39
41
|
const blockBySlotRepository = new BlockBySlotRepository(db);
|
|
@@ -51,10 +53,26 @@ export class SlashingProtection implements ISlashingProtection {
|
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
async checkAndInsertBlockProposal(pubKey: BLSPubkey, block: SlashingProtectionBlock): Promise<void> {
|
|
56
|
+
if (this.importing.size !== 0) {
|
|
57
|
+
const pubkeyHex = toPubkeyHex(pubKey);
|
|
58
|
+
let importing = this.importing.get(pubkeyHex);
|
|
59
|
+
while (importing !== undefined) {
|
|
60
|
+
await importing;
|
|
61
|
+
importing = this.importing.get(pubkeyHex);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
54
64
|
await this.blockService.checkAndInsertBlockProposal(pubKey, block);
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
async checkAndInsertAttestation(pubKey: BLSPubkey, attestation: SlashingProtectionAttestation): Promise<void> {
|
|
68
|
+
if (this.importing.size !== 0) {
|
|
69
|
+
const pubkeyHex = toPubkeyHex(pubKey);
|
|
70
|
+
let importing = this.importing.get(pubkeyHex);
|
|
71
|
+
while (importing !== undefined) {
|
|
72
|
+
await importing;
|
|
73
|
+
importing = this.importing.get(pubkeyHex);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
58
76
|
await this.attestationService.checkAndInsertAttestation(pubKey, attestation);
|
|
59
77
|
}
|
|
60
78
|
|
|
@@ -84,10 +102,36 @@ export class SlashingProtection implements ISlashingProtection {
|
|
|
84
102
|
}
|
|
85
103
|
}
|
|
86
104
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
105
|
+
|
|
106
|
+
// Checks for keys in the file wait for the whole import, a key that is already signing must not sign against
|
|
107
|
+
// a history the import is still extending. Imports run one after another so a later one cannot release a key early.
|
|
108
|
+
const pubkeyHexes = data.map((validator) => toPubkeyHex(validator.pubkey));
|
|
109
|
+
const previous = this.lastImport;
|
|
110
|
+
const {promise, resolve} = defer<void>();
|
|
111
|
+
this.lastImport = promise;
|
|
112
|
+
for (const pubkeyHex of pubkeyHexes) {
|
|
113
|
+
this.importing.set(pubkeyHex, promise);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
if (previous !== null) {
|
|
118
|
+
await previous;
|
|
119
|
+
}
|
|
120
|
+
for (const validator of data) {
|
|
121
|
+
logger?.info("Importing slashing protection", {pubkey: toPubkeyHex(validator.pubkey)});
|
|
122
|
+
await this.blockService.importBlocks(validator.pubkey, validator.signedBlocks);
|
|
123
|
+
await this.attestationService.importAttestations(validator.pubkey, validator.signedAttestations);
|
|
124
|
+
}
|
|
125
|
+
} finally {
|
|
126
|
+
resolve();
|
|
127
|
+
if (this.lastImport === promise) {
|
|
128
|
+
this.lastImport = null;
|
|
129
|
+
}
|
|
130
|
+
for (const pubkeyHex of pubkeyHexes) {
|
|
131
|
+
if (this.importing.get(pubkeyHex) === promise) {
|
|
132
|
+
this.importing.delete(pubkeyHex);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
91
135
|
}
|
|
92
136
|
}
|
|
93
137
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ContainerType, ValueOf} from "@chainsafe/ssz";
|
|
2
2
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
|
-
import {ForkName, ForkPostGloas,
|
|
3
|
+
import {ForkName, ForkPostGloas, ForkSeq, isForkPostDeneb} from "@lodestar/params";
|
|
4
4
|
import {blindedOrFullBlockToHeader, computeEpochAtSlot} from "@lodestar/state-transition";
|
|
5
5
|
import {
|
|
6
6
|
AggregateAndProof,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
Slot,
|
|
13
13
|
altair,
|
|
14
14
|
gloas,
|
|
15
|
+
heze,
|
|
15
16
|
phase0,
|
|
16
17
|
ssz,
|
|
17
18
|
sszTypesFor,
|
|
@@ -37,6 +38,7 @@ export enum SignableMessageType {
|
|
|
37
38
|
PAYLOAD_ATTESTATION_MESSAGE = "PAYLOAD_ATTESTATION_MESSAGE",
|
|
38
39
|
PROPOSER_PREFERENCES = "PROPOSER_PREFERENCES",
|
|
39
40
|
BUILDER_REQUEST_AUTH = "BUILDER_REQUEST_AUTH",
|
|
41
|
+
INCLUSION_LIST = "INCLUSION_LIST",
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
const AggregationSlotType = new ContainerType({
|
|
@@ -78,7 +80,7 @@ export type SignableMessage =
|
|
|
78
80
|
| {type: SignableMessageType.AGGREGATE_AND_PROOF; data: phase0.AggregateAndProof}
|
|
79
81
|
| {type: SignableMessageType.AGGREGATE_AND_PROOF_V2; data: AggregateAndProof}
|
|
80
82
|
| {type: SignableMessageType.ATTESTATION; data: phase0.AttestationData}
|
|
81
|
-
| {type: SignableMessageType.BLOCK_V2; data: BeaconBlock
|
|
83
|
+
| {type: SignableMessageType.BLOCK_V2; data: BeaconBlock | BlindedBeaconBlock}
|
|
82
84
|
| {type: SignableMessageType.DEPOSIT; data: ValueOf<typeof DepositType>}
|
|
83
85
|
| {type: SignableMessageType.RANDAO_REVEAL; data: {epoch: Epoch}}
|
|
84
86
|
| {type: SignableMessageType.VOLUNTARY_EXIT; data: phase0.VoluntaryExit}
|
|
@@ -89,7 +91,8 @@ export type SignableMessage =
|
|
|
89
91
|
| {type: SignableMessageType.EXECUTION_PAYLOAD_ENVELOPE; data: gloas.ExecutionPayloadEnvelope}
|
|
90
92
|
| {type: SignableMessageType.PAYLOAD_ATTESTATION_MESSAGE; data: gloas.PayloadAttestationData}
|
|
91
93
|
| {type: SignableMessageType.PROPOSER_PREFERENCES; data: gloas.ProposerPreferences}
|
|
92
|
-
| {type: SignableMessageType.BUILDER_REQUEST_AUTH; data: gloas.BuilderRequestAuth}
|
|
94
|
+
| {type: SignableMessageType.BUILDER_REQUEST_AUTH; data: gloas.BuilderRequestAuth}
|
|
95
|
+
| {type: SignableMessageType.INCLUSION_LIST; data: heze.InclusionList};
|
|
93
96
|
|
|
94
97
|
const requiresForkInfo: Record<SignableMessageType, boolean> = {
|
|
95
98
|
[SignableMessageType.AGGREGATION_SLOT]: true,
|
|
@@ -108,6 +111,7 @@ const requiresForkInfo: Record<SignableMessageType, boolean> = {
|
|
|
108
111
|
[SignableMessageType.PAYLOAD_ATTESTATION_MESSAGE]: true,
|
|
109
112
|
[SignableMessageType.PROPOSER_PREFERENCES]: true,
|
|
110
113
|
[SignableMessageType.BUILDER_REQUEST_AUTH]: false,
|
|
114
|
+
[SignableMessageType.INCLUSION_LIST]: true,
|
|
111
115
|
};
|
|
112
116
|
|
|
113
117
|
type Web3SignerSerializedRequest = {
|
|
@@ -319,6 +323,9 @@ function serializerSignableMessagePayload(config: BeaconConfig, payload: Signabl
|
|
|
319
323
|
},
|
|
320
324
|
};
|
|
321
325
|
}
|
|
326
|
+
|
|
327
|
+
case SignableMessageType.INCLUSION_LIST:
|
|
328
|
+
return {inclusion_list: ssz.heze.InclusionList.toJson(payload.data)};
|
|
322
329
|
}
|
|
323
330
|
}
|
|
324
331
|
|
package/src/validator.ts
CHANGED
|
@@ -6,7 +6,14 @@ import {
|
|
|
6
6
|
assertEqualParams,
|
|
7
7
|
createBeaconConfig,
|
|
8
8
|
} from "@lodestar/config";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Clock,
|
|
11
|
+
ClockOptions,
|
|
12
|
+
IClock,
|
|
13
|
+
computeEpochAtSlot,
|
|
14
|
+
getCurrentSlot,
|
|
15
|
+
getSlotDurations,
|
|
16
|
+
} from "@lodestar/state-transition";
|
|
10
17
|
import {BLSPubkey, phase0, ssz} from "@lodestar/types";
|
|
11
18
|
import {Genesis} from "@lodestar/types/phase0";
|
|
12
19
|
import {Logger, prettyGweiToEth, toPrintableUrl, toRootHex} from "@lodestar/utils";
|
|
@@ -20,6 +27,7 @@ import {ChainHeaderTracker} from "./services/chainHeaderTracker.js";
|
|
|
20
27
|
import {DoppelgangerService} from "./services/doppelgangerService.js";
|
|
21
28
|
import {ValidatorEventEmitter} from "./services/emitter.js";
|
|
22
29
|
import {ExternalSignerOptions, pollExternalSignerPubkeys} from "./services/externalSignerSync.js";
|
|
30
|
+
import {InclusionListService} from "./services/inclusionList.js";
|
|
23
31
|
import {IndicesService} from "./services/indices.js";
|
|
24
32
|
import {pollBuilderValidatorRegistration, pollPrepareBeaconProposer} from "./services/prepareBeaconProposer.js";
|
|
25
33
|
import {ProposalPreferencesService} from "./services/proposalPreferences.js";
|
|
@@ -46,6 +54,7 @@ export type ValidatorModules = {
|
|
|
46
54
|
blockProposingService: BlockProposingService;
|
|
47
55
|
attestationService: AttestationService;
|
|
48
56
|
ptcService: PtcService;
|
|
57
|
+
inclusionListService: InclusionListService;
|
|
49
58
|
syncCommitteeService: SyncCommitteeService;
|
|
50
59
|
config: BeaconConfig;
|
|
51
60
|
api: ApiClient;
|
|
@@ -102,6 +111,7 @@ export class Validator {
|
|
|
102
111
|
private readonly blockProposingService: BlockProposingService;
|
|
103
112
|
private readonly attestationService: AttestationService;
|
|
104
113
|
private readonly ptcService: PtcService;
|
|
114
|
+
private readonly inclusionListService: InclusionListService;
|
|
105
115
|
private readonly syncCommitteeService: SyncCommitteeService;
|
|
106
116
|
private readonly config: BeaconConfig;
|
|
107
117
|
private readonly api: ApiClient;
|
|
@@ -121,6 +131,7 @@ export class Validator {
|
|
|
121
131
|
blockProposingService,
|
|
122
132
|
attestationService,
|
|
123
133
|
ptcService,
|
|
134
|
+
inclusionListService,
|
|
124
135
|
syncCommitteeService,
|
|
125
136
|
config,
|
|
126
137
|
api,
|
|
@@ -138,6 +149,7 @@ export class Validator {
|
|
|
138
149
|
this.blockProposingService = blockProposingService;
|
|
139
150
|
this.attestationService = attestationService;
|
|
140
151
|
this.ptcService = ptcService;
|
|
152
|
+
this.inclusionListService = inclusionListService;
|
|
141
153
|
this.syncCommitteeService = syncCommitteeService;
|
|
142
154
|
this.config = config;
|
|
143
155
|
this.api = api;
|
|
@@ -202,7 +214,9 @@ export class Validator {
|
|
|
202
214
|
globalInit: {
|
|
203
215
|
signal: controller.signal,
|
|
204
216
|
...globalInit,
|
|
205
|
-
timeoutMs:
|
|
217
|
+
timeoutMs:
|
|
218
|
+
globalInit?.timeoutMs ??
|
|
219
|
+
Math.min(...getSlotDurations(config).map(([, slotDurationMs]) => slotDurationMs)),
|
|
206
220
|
},
|
|
207
221
|
},
|
|
208
222
|
{config, logger, metrics: metrics?.restApiClient}
|
|
@@ -303,6 +317,17 @@ export class Validator {
|
|
|
303
317
|
metrics
|
|
304
318
|
);
|
|
305
319
|
|
|
320
|
+
const inclusionListService = new InclusionListService(
|
|
321
|
+
config,
|
|
322
|
+
loggerVc,
|
|
323
|
+
api,
|
|
324
|
+
clock,
|
|
325
|
+
validatorStore,
|
|
326
|
+
chainHeaderTracker,
|
|
327
|
+
syncingStatusTracker,
|
|
328
|
+
emitter
|
|
329
|
+
);
|
|
330
|
+
|
|
306
331
|
const syncCommitteeService = new SyncCommitteeService(
|
|
307
332
|
config,
|
|
308
333
|
loggerVc,
|
|
@@ -338,6 +363,7 @@ export class Validator {
|
|
|
338
363
|
blockProposingService,
|
|
339
364
|
attestationService,
|
|
340
365
|
ptcService,
|
|
366
|
+
inclusionListService,
|
|
341
367
|
syncCommitteeService,
|
|
342
368
|
config,
|
|
343
369
|
api,
|
|
@@ -366,7 +392,8 @@ export class Validator {
|
|
|
366
392
|
urls: urls.map(toPrintableUrl).toString(),
|
|
367
393
|
requestWireFormat: globalInit?.requestWireFormat ?? defaultInit.requestWireFormat,
|
|
368
394
|
responseWireFormat: globalInit?.responseWireFormat ?? defaultInit.responseWireFormat,
|
|
369
|
-
requestTimeoutMs:
|
|
395
|
+
requestTimeoutMs:
|
|
396
|
+
globalInit?.timeoutMs ?? Math.min(...getSlotDurations(config).map(([, slotDurationMs]) => slotDurationMs)),
|
|
370
397
|
});
|
|
371
398
|
} else {
|
|
372
399
|
api = clientOrUrls;
|
|
@@ -423,6 +450,7 @@ export class Validator {
|
|
|
423
450
|
this.blockProposingService.removeDutiesForKey(pubkey);
|
|
424
451
|
this.attestationService.removeDutiesForKey(pubkey);
|
|
425
452
|
this.ptcService.removeDutiesForKey(pubkey);
|
|
453
|
+
this.inclusionListService.removeDutiesForKey(pubkey);
|
|
426
454
|
this.syncCommitteeService.removeDutiesForKey(pubkey);
|
|
427
455
|
}
|
|
428
456
|
|