@lodestar/validator 1.51.0-dev.32db66b396 → 1.51.0-dev.38410b466e

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.
@@ -13,6 +13,7 @@ export declare class SlashingProtectionAttestationService {
13
13
  private attestationByTarget;
14
14
  private attestationLowerBound;
15
15
  private minMaxSurround;
16
+ private readonly pendingAttestations;
16
17
  constructor(signedAttestationDb: AttestationByTargetRepository, attestationLowerBound: AttestationLowerBoundRepository, minMaxSurround: MinMaxSurround);
17
18
  /**
18
19
  * Check an attestation for slash safety, and if it is safe, record it in the database
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAC,cAAc,EAAyD,MAAM,4BAA4B,CAAC;AAClH,OAAO,EAAC,6BAA6B,EAAC,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAC,6BAA6B,EAAC,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAC,+BAA+B,EAAC,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAC,uBAAuB,EAAE,2BAA2B,EAAC,MAAM,aAAa,CAAC;AACjF,OAAO,EACL,6BAA6B,EAC7B,+BAA+B,EAC/B,uBAAuB,EACvB,2BAA2B,GAC5B,CAAC;AAEF,aAAK,UAAU;IACb,SAAS,0BAA0B;IACnC,EAAE,mBAAmB;CACtB;AAED,qBAAa,oCAAoC;IAC/C,OAAO,CAAC,mBAAmB,CAAgC;IAC3D,OAAO,CAAC,qBAAqB,CAAkC;IAC/D,OAAO,CAAC,cAAc,CAAiB;IAEvC,YACE,mBAAmB,EAAE,6BAA6B,EAClD,qBAAqB,EAAE,+BAA+B,EACtD,cAAc,EAAE,cAAc,EAK/B;IAED;;;OAGG;IACG,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5G;IAED;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,GAAG,OAAO,CAAC,UAAU,CAAC,CA4FzG;IAED;;;;OAIG;IACG,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAGpG;IAED;;OAEG;IACG,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,6BAA6B,GAAG,IAAI,CAAC,CAE3G;IAED;;OAEG;IACG,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,6BAA6B,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDxG;IAED;;OAEG;IACG,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,6BAA6B,EAAE,CAAC,CAEpF;IAEK,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAExC;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAC,cAAc,EAAyD,MAAM,4BAA4B,CAAC;AAClH,OAAO,EAAC,6BAA6B,EAAC,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAC,6BAA6B,EAAC,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAC,+BAA+B,EAAC,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAC,uBAAuB,EAAE,2BAA2B,EAAC,MAAM,aAAa,CAAC;AACjF,OAAO,EACL,6BAA6B,EAC7B,+BAA+B,EAC/B,uBAAuB,EACvB,2BAA2B,GAC5B,CAAC;AAEF,aAAK,UAAU;IACb,SAAS,0BAA0B;IACnC,EAAE,mBAAmB;CACtB;AAED,qBAAa,oCAAoC;IAC/C,OAAO,CAAC,mBAAmB,CAAgC;IAC3D,OAAO,CAAC,qBAAqB,CAAkC;IAC/D,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAoC;IAExE,YACE,mBAAmB,EAAE,6BAA6B,EAClD,qBAAqB,EAAE,+BAA+B,EACtD,cAAc,EAAE,cAAc,EAK/B;IAED;;;OAGG;IACG,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB5G;IAED;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,GAAG,OAAO,CAAC,UAAU,CAAC,CA4FzG;IAED;;;;OAIG;IACG,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAGpG;IAED;;OAEG;IACG,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,6BAA6B,GAAG,IAAI,CAAC,CAE3G;IAED;;OAEG;IACG,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,6BAA6B,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqExG;IAED;;OAEG;IACG,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,6BAA6B,EAAE,CAAC,CAEpF;IAEK,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAExC;CACF"}
@@ -1,3 +1,4 @@
1
+ import { defer, toPubkeyHex } from "@lodestar/utils";
1
2
  import { SurroundAttestationError, SurroundAttestationErrorCode } from "../minMaxSurround/index.js";
2
3
  import { ZERO_ROOT, isEqualNonZeroRoot, isEqualRoot, minEpoch } from "../utils.js";
3
4
  import { AttestationByTargetRepository } from "./attestationByTargetRepository.js";
@@ -13,6 +14,7 @@ export class SlashingProtectionAttestationService {
13
14
  attestationByTarget;
14
15
  attestationLowerBound;
15
16
  minMaxSurround;
17
+ pendingAttestations = new Map();
16
18
  constructor(signedAttestationDb, attestationLowerBound, minMaxSurround) {
17
19
  this.attestationByTarget = signedAttestationDb;
18
20
  this.attestationLowerBound = attestationLowerBound;
@@ -23,9 +25,24 @@ export class SlashingProtectionAttestationService {
23
25
  * This is the safe, externally-callable interface for checking attestations
24
26
  */
25
27
  async checkAndInsertAttestation(pubKey, attestation) {
26
- const safeStatus = await this.checkAttestation(pubKey, attestation);
27
- if (safeStatus !== SafeStatus.SAME_DATA) {
28
- await this.insertAttestation(pubKey, attestation);
28
+ const pubkeyHex = toPubkeyHex(pubKey);
29
+ const previous = this.pendingAttestations.get(pubkeyHex);
30
+ const { promise, resolve } = defer();
31
+ this.pendingAttestations.set(pubkeyHex, promise);
32
+ try {
33
+ if (previous !== undefined) {
34
+ await previous;
35
+ }
36
+ const safeStatus = await this.checkAttestation(pubKey, attestation);
37
+ if (safeStatus !== SafeStatus.SAME_DATA) {
38
+ await this.insertAttestation(pubKey, attestation);
39
+ }
40
+ }
41
+ finally {
42
+ resolve();
43
+ if (this.pendingAttestations.get(pubkeyHex) === promise) {
44
+ this.pendingAttestations.delete(pubkeyHex);
45
+ }
29
46
  }
30
47
  // TODO: Implement safe clean-up of stored attestations
31
48
  }
@@ -139,52 +156,68 @@ export class SlashingProtectionAttestationService {
139
156
  * Interchange import / export functionality
140
157
  */
141
158
  async importAttestations(pubkey, attestations) {
142
- // Min-max surround misses a surround vote beyond its lookback, require the highest target attestation to
143
- // have the highest source epoch as `checkAttestation` relies on it
144
- let latestAtt = await this.attestationByTarget.getLatest(pubkey);
145
- let maxSourceAtt = latestAtt;
146
- for (const attestation of attestations) {
147
- if (latestAtt === null || attestation.targetEpoch >= latestAtt.targetEpoch) {
148
- latestAtt = attestation;
149
- }
150
- if (maxSourceAtt === null || attestation.sourceEpoch > maxSourceAtt.sourceEpoch) {
151
- maxSourceAtt = attestation;
159
+ const pubkeyHex = toPubkeyHex(pubkey);
160
+ const previous = this.pendingAttestations.get(pubkeyHex);
161
+ const { promise, resolve } = defer();
162
+ this.pendingAttestations.set(pubkeyHex, promise);
163
+ try {
164
+ if (previous !== undefined) {
165
+ await previous;
152
166
  }
153
- }
154
- if (latestAtt && maxSourceAtt && latestAtt.sourceEpoch < maxSourceAtt.sourceEpoch) {
155
- throw new InvalidAttestationError({
156
- code: InvalidAttestationErrorCode.NEW_SURROUNDS_PREV,
157
- attestation: latestAtt,
158
- prev: maxSourceAtt,
159
- });
160
- }
161
- // Never replace a recorded attestation with a different source or signing root, a zero root refuses any attestation
162
- // with that target. The highest source epoch is kept as the latest attestation must have it, see above.
163
- const attestationsByTarget = new Map();
164
- for (const attestation of attestations) {
165
- const { sourceEpoch, targetEpoch, signingRoot } = attestation;
166
- const prevAtt = attestationsByTarget.get(targetEpoch) ?? (await this.attestationByTarget.get(pubkey, targetEpoch));
167
- if (prevAtt === null || (prevAtt.sourceEpoch === sourceEpoch && isEqualRoot(prevAtt.signingRoot, signingRoot))) {
168
- attestationsByTarget.set(targetEpoch, attestation);
167
+ // Min-max surround misses a surround vote beyond its lookback, require the highest target attestation to
168
+ // have the highest source epoch as `checkAttestation` relies on it
169
+ let latestAtt = await this.attestationByTarget.getLatest(pubkey);
170
+ let maxSourceAtt = latestAtt;
171
+ for (const attestation of attestations) {
172
+ if (latestAtt === null || attestation.targetEpoch >= latestAtt.targetEpoch) {
173
+ latestAtt = attestation;
174
+ }
175
+ if (maxSourceAtt === null || attestation.sourceEpoch > maxSourceAtt.sourceEpoch) {
176
+ maxSourceAtt = attestation;
177
+ }
169
178
  }
170
- else {
171
- attestationsByTarget.set(targetEpoch, {
172
- sourceEpoch: Math.max(prevAtt.sourceEpoch, sourceEpoch),
173
- targetEpoch,
174
- signingRoot: ZERO_ROOT,
179
+ if (latestAtt && maxSourceAtt && latestAtt.sourceEpoch < maxSourceAtt.sourceEpoch) {
180
+ throw new InvalidAttestationError({
181
+ code: InvalidAttestationErrorCode.NEW_SURROUNDS_PREV,
182
+ attestation: latestAtt,
183
+ prev: maxSourceAtt,
175
184
  });
176
185
  }
186
+ // Never replace a recorded attestation with a different source or signing root, a zero root refuses any attestation
187
+ // with that target. The highest source epoch is kept as the latest attestation must have it, see above.
188
+ const attestationsByTarget = new Map();
189
+ for (const attestation of attestations) {
190
+ const { sourceEpoch, targetEpoch, signingRoot } = attestation;
191
+ const prevAtt = attestationsByTarget.get(targetEpoch) ?? (await this.attestationByTarget.get(pubkey, targetEpoch));
192
+ if (prevAtt === null ||
193
+ (prevAtt.sourceEpoch === sourceEpoch && isEqualRoot(prevAtt.signingRoot, signingRoot))) {
194
+ attestationsByTarget.set(targetEpoch, attestation);
195
+ }
196
+ else {
197
+ attestationsByTarget.set(targetEpoch, {
198
+ sourceEpoch: Math.max(prevAtt.sourceEpoch, sourceEpoch),
199
+ targetEpoch,
200
+ signingRoot: ZERO_ROOT,
201
+ });
202
+ }
203
+ }
204
+ await this.attestationByTarget.set(pubkey, Array.from(attestationsByTarget.values()));
205
+ // Pre-compute spans for all attestations
206
+ for (const attestation of attestations) {
207
+ await this.minMaxSurround.insertAttestation(pubkey, attestation);
208
+ }
209
+ // Pre-compute and store lower-bound
210
+ const minSourceEpoch = minEpoch(attestations.map((attestation) => attestation.sourceEpoch));
211
+ const minTargetEpoch = minEpoch(attestations.map((attestation) => attestation.targetEpoch));
212
+ if (minSourceEpoch != null && minTargetEpoch != null) {
213
+ await this.attestationLowerBound.set(pubkey, { minSourceEpoch, minTargetEpoch });
214
+ }
177
215
  }
178
- await this.attestationByTarget.set(pubkey, Array.from(attestationsByTarget.values()));
179
- // Pre-compute spans for all attestations
180
- for (const attestation of attestations) {
181
- await this.minMaxSurround.insertAttestation(pubkey, attestation);
182
- }
183
- // Pre-compute and store lower-bound
184
- const minSourceEpoch = minEpoch(attestations.map((attestation) => attestation.sourceEpoch));
185
- const minTargetEpoch = minEpoch(attestations.map((attestation) => attestation.targetEpoch));
186
- if (minSourceEpoch != null && minTargetEpoch != null) {
187
- await this.attestationLowerBound.set(pubkey, { minSourceEpoch, minTargetEpoch });
216
+ finally {
217
+ resolve();
218
+ if (this.pendingAttestations.get(pubkeyHex) === promise) {
219
+ this.pendingAttestations.delete(pubkeyHex);
220
+ }
188
221
  }
189
222
  }
190
223
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/index.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,8 @@ export declare class SlashingProtection implements ISlashingProtection {
17
17
  protected db: LodestarValidatorDatabaseController;
18
18
  private blockService;
19
19
  private attestationService;
20
+ private readonly importing;
21
+ private lastImport;
20
22
  constructor(db: LodestarValidatorDatabaseController);
21
23
  checkAndInsertBlockProposal(pubKey: BLSPubkey, block: SlashingProtectionBlock): Promise<void>;
22
24
  checkAndInsertAttestation(pubKey: BLSPubkey, attestation: SlashingProtectionAttestation): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/slashingProtection/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAC,MAAM,EAAc,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAC,mCAAmC,EAAC,MAAM,aAAa,CAAC;AAOhE,OAAO,EACL,WAAW,EAGX,wBAAwB,EAIzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAC,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAC,6BAA6B,EAAE,uBAAuB,EAAC,MAAM,YAAY,CAAC;AAElF,OAAO,EAAC,uBAAuB,EAAE,2BAA2B,EAAC,MAAM,wBAAwB,CAAC;AAC5F,OAAO,EAAC,iBAAiB,EAAE,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAC1E,YAAY,EAAC,WAAW,EAAE,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAC,gBAAgB,EAAE,yBAAyB,EAAC,MAAM,wBAAwB,CAAC;AACnF,YAAY,EAAC,mBAAmB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,6BAA6B,EAAC,CAAC;AACpH;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,mBAAmB;IAIhD,SAAS,CAAC,EAAE,EAAE,mCAAmC;IAH7D,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,kBAAkB,CAAuC;IAEjE,YAAsB,EAAE,EAAE,mCAAmC,EAa5D;IAEK,2BAA2B,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAElG;IAEK,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5G;IAEK,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAE1E;IAEK,iBAAiB,CACrB,WAAW,EAAE,WAAW,EACxB,qBAAqB,EAAE,IAAI,EAC3B,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,KAAK,GACnB,OAAO,CAAC,IAAI,CAAC,CAsBf;IAEK,iBAAiB,CACrB,qBAAqB,EAAE,IAAI,EAC3B,OAAO,EAAE,SAAS,EAAE,EACpB,aAAa,EAAE,wBAAwB,EACvC,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAYtB;IAEK,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAIxC;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/slashingProtection/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAC,MAAM,EAAqB,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAC,mCAAmC,EAAY,MAAM,aAAa,CAAC;AAO3E,OAAO,EACL,WAAW,EAGX,wBAAwB,EAIzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAC,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAC,6BAA6B,EAAE,uBAAuB,EAAC,MAAM,YAAY,CAAC;AAElF,OAAO,EAAC,uBAAuB,EAAE,2BAA2B,EAAC,MAAM,wBAAwB,CAAC;AAC5F,OAAO,EAAC,iBAAiB,EAAE,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAC1E,YAAY,EAAC,WAAW,EAAE,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAC,gBAAgB,EAAE,yBAAyB,EAAC,MAAM,wBAAwB,CAAC;AACnF,YAAY,EAAC,mBAAmB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,6BAA6B,EAAC,CAAC;AACpH;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,mBAAmB;IAMhD,SAAS,CAAC,EAAE,EAAE,mCAAmC;IAL7D,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,kBAAkB,CAAuC;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,UAAU,CAA8B;IAEhD,YAAsB,EAAE,EAAE,mCAAmC,EAa5D;IAEK,2BAA2B,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUlG;IAEK,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5G;IAEK,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAE1E;IAEK,iBAAiB,CACrB,WAAW,EAAE,WAAW,EACxB,qBAAqB,EAAE,IAAI,EAC3B,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,KAAK,GACnB,OAAO,CAAC,IAAI,CAAC,CAgDf;IAEK,iBAAiB,CACrB,qBAAqB,EAAE,IAAI,EAC3B,OAAO,EAAE,SAAS,EAAE,EACpB,aAAa,EAAE,wBAAwB,EACvC,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAYtB;IAEK,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAIxC;CACF"}
@@ -1,5 +1,5 @@
1
1
  import { GENESIS_EPOCH } from "@lodestar/params";
2
- import { toPubkeyHex } from "@lodestar/utils";
2
+ import { defer, toPubkeyHex } from "@lodestar/utils";
3
3
  import { uniqueVectorArr } from "../slashingProtection/utils.js";
4
4
  import { AttestationByTargetRepository, AttestationLowerBoundRepository, SlashingProtectionAttestationService, } from "./attestation/index.js";
5
5
  import { BlockBySlotRepository, SlashingProtectionBlockService } from "./block/index.js";
@@ -16,6 +16,8 @@ export class SlashingProtection {
16
16
  db;
17
17
  blockService;
18
18
  attestationService;
19
+ importing = new Map();
20
+ lastImport = null;
19
21
  constructor(db) {
20
22
  this.db = db;
21
23
  const blockBySlotRepository = new BlockBySlotRepository(db);
@@ -27,9 +29,25 @@ export class SlashingProtection {
27
29
  this.attestationService = new SlashingProtectionAttestationService(attestationByTargetRepository, attestationLowerBoundRepository, minMaxSurround);
28
30
  }
29
31
  async checkAndInsertBlockProposal(pubKey, block) {
32
+ if (this.importing.size !== 0) {
33
+ const pubkeyHex = toPubkeyHex(pubKey);
34
+ let importing = this.importing.get(pubkeyHex);
35
+ while (importing !== undefined) {
36
+ await importing;
37
+ importing = this.importing.get(pubkeyHex);
38
+ }
39
+ }
30
40
  await this.blockService.checkAndInsertBlockProposal(pubKey, block);
31
41
  }
32
42
  async checkAndInsertAttestation(pubKey, attestation) {
43
+ if (this.importing.size !== 0) {
44
+ const pubkeyHex = toPubkeyHex(pubKey);
45
+ let importing = this.importing.get(pubkeyHex);
46
+ while (importing !== undefined) {
47
+ await importing;
48
+ importing = this.importing.get(pubkeyHex);
49
+ }
50
+ }
33
51
  await this.attestationService.checkAndInsertAttestation(pubKey, attestation);
34
52
  }
35
53
  async hasAttestedInEpoch(pubKey, epoch) {
@@ -52,10 +70,35 @@ export class SlashingProtection {
52
70
  }
53
71
  }
54
72
  }
55
- for (const validator of data) {
56
- logger?.info("Importing slashing protection", { pubkey: toPubkeyHex(validator.pubkey) });
57
- await this.blockService.importBlocks(validator.pubkey, validator.signedBlocks);
58
- await this.attestationService.importAttestations(validator.pubkey, validator.signedAttestations);
73
+ // Checks for keys in the file wait for the whole import, a key that is already signing must not sign against
74
+ // a history the import is still extending. Imports run one after another so a later one cannot release a key early.
75
+ const pubkeyHexes = data.map((validator) => toPubkeyHex(validator.pubkey));
76
+ const previous = this.lastImport;
77
+ const { promise, resolve } = defer();
78
+ this.lastImport = promise;
79
+ for (const pubkeyHex of pubkeyHexes) {
80
+ this.importing.set(pubkeyHex, promise);
81
+ }
82
+ try {
83
+ if (previous !== null) {
84
+ await previous;
85
+ }
86
+ for (const validator of data) {
87
+ logger?.info("Importing slashing protection", { pubkey: toPubkeyHex(validator.pubkey) });
88
+ await this.blockService.importBlocks(validator.pubkey, validator.signedBlocks);
89
+ await this.attestationService.importAttestations(validator.pubkey, validator.signedAttestations);
90
+ }
91
+ }
92
+ finally {
93
+ resolve();
94
+ if (this.lastImport === promise) {
95
+ this.lastImport = null;
96
+ }
97
+ for (const pubkeyHex of pubkeyHexes) {
98
+ if (this.importing.get(pubkeyHex) === promise) {
99
+ this.importing.delete(pubkeyHex);
100
+ }
101
+ }
59
102
  }
60
103
  }
61
104
  async exportInterchange(genesisValidatorsRoot, pubkeys, formatVersion, logger) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/slashingProtection/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/slashingProtection/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAS,KAAK,EAAE,WAAW,EAAC,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAC,eAAe,EAAC,MAAM,gCAAgC,CAAC;AAE/D,OAAO,EACL,6BAA6B,EAC7B,+BAA+B,EAC/B,oCAAoC,GACrC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAC,qBAAqB,EAAE,8BAA8B,EAAC,MAAM,kBAAkB,CAAC;AACvF,OAAO,EAEL,gBAAgB,EAChB,yBAAyB,EAGzB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAC,uBAAuB,EAAE,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAGlF,OAAO,EAAC,uBAAuB,EAAE,2BAA2B,EAAC,MAAM,wBAAwB,CAAC;AAC5F,OAAO,EAAC,iBAAiB,EAAE,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAE1E,OAAO,EAAC,gBAAgB,EAAE,yBAAyB,EAAC,MAAM,wBAAwB,CAAC;AAEnF;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAMP,EAAE;IALhB,YAAY,CAAiC;IAC7C,kBAAkB,CAAuC;IAChD,SAAS,GAAG,IAAI,GAAG,EAA4B,CAAC;IACzD,UAAU,GAAyB,IAAI,CAAC;IAEhD,YAAsB,EAAuC;kBAAvC,EAAE;QACtB,MAAM,qBAAqB,GAAG,IAAI,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAC5D,MAAM,6BAA6B,GAAG,IAAI,6BAA6B,CAAC,EAAE,CAAC,CAAC;QAC5E,MAAM,+BAA+B,GAAG,IAAI,+BAA+B,CAAC,EAAE,CAAC,CAAC;QAChF,MAAM,uBAAuB,GAAG,IAAI,uBAAuB,CAAC,EAAE,CAAC,CAAC;QAChE,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,uBAAuB,CAAC,CAAC;QAEnE,IAAI,CAAC,YAAY,GAAG,IAAI,8BAA8B,CAAC,qBAAqB,CAAC,CAAC;QAC9E,IAAI,CAAC,kBAAkB,GAAG,IAAI,oCAAoC,CAChE,6BAA6B,EAC7B,+BAA+B,EAC/B,cAAc,CACf,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,2BAA2B,CAAC,MAAiB,EAAE,KAA8B;QACjF,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC9C,OAAO,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,SAAS,CAAC;gBAChB,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QACD,MAAM,IAAI,CAAC,YAAY,CAAC,2BAA2B,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,MAAiB,EAAE,WAA0C;QAC3F,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC9C,OAAO,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,SAAS,CAAC;gBAChB,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QACD,MAAM,IAAI,CAAC,kBAAkB,CAAC,yBAAyB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,MAAiB,EAAE,KAAY;QACtD,OAAO,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC;IACxF,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,WAAwB,EACxB,qBAA2B,EAC3B,MAAe,EACf,YAAoB;QAEpB,MAAM,EAAC,IAAI,EAAC,GAAG,gBAAgB,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;QACpE,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,gHAAgH;YAChH,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;YACjE,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;gBAC7B,KAAK,MAAM,EAAC,WAAW,EAAC,IAAI,SAAS,CAAC,kBAAkB,EAAE,CAAC;oBACzD,IAAI,WAAW,GAAG,cAAc,EAAE,CAAC;wBACjC,MAAM,IAAI,gBAAgB,CAAC;4BACzB,IAAI,EAAE,yBAAyB,CAAC,mBAAmB;4BACnD,WAAW;4BACX,YAAY;yBACb,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,6GAA6G;QAC7G,oHAAoH;QACpH,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;QACjC,MAAM,EAAC,OAAO,EAAE,OAAO,EAAC,GAAG,KAAK,EAAQ,CAAC;QACzC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC;QAC1B,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;YACpC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,CAAC;YACH,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACtB,MAAM,QAAQ,CAAC;YACjB,CAAC;YACD,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;gBAC7B,MAAM,EAAE,IAAI,CAAC,+BAA+B,EAAE,EAAC,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC;gBACvF,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;gBAC/E,MAAM,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,kBAAkB,CAAC,CAAC;YACnG,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAC;YACV,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBAChC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACzB,CAAC;YACD,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;gBACpC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,OAAO,EAAE,CAAC;oBAC9C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,qBAA2B,EAC3B,OAAoB,EACpB,aAAuC,EACvC,MAAe;QAEf,MAAM,aAAa,GAAgC,EAAE,CAAC;QACtD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,EAAE,IAAI,CAAC,+BAA+B,EAAE,EAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC;YAC7E,aAAa,CAAC,IAAI,CAAC;gBACjB,MAAM;gBACN,YAAY,EAAE,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC;gBAC1D,kBAAkB,EAAE,MAAM,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,MAAM,CAAC;aAC7E,CAAC,CAAC;QACL,CAAC;QACD,MAAM,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAC3C,OAAO,oBAAoB,CAAC,EAAC,IAAI,EAAE,aAAa,EAAE,qBAAqB,EAAC,EAAE,aAAa,CAAC,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC;QAC/D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;QACzD,OAAO,eAAe,CAAC,CAAC,GAAG,UAAU,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;IACzD,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodestar/validator",
3
- "version": "1.51.0-dev.32db66b396",
3
+ "version": "1.51.0-dev.38410b466e",
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/lodestar-z": "catalog:",
52
52
  "@chainsafe/ssz": "^1.8.1",
53
- "@lodestar/api": "^1.51.0-dev.32db66b396",
54
- "@lodestar/config": "^1.51.0-dev.32db66b396",
55
- "@lodestar/db": "^1.51.0-dev.32db66b396",
56
- "@lodestar/params": "^1.51.0-dev.32db66b396",
57
- "@lodestar/state-transition": "^1.51.0-dev.32db66b396",
58
- "@lodestar/types": "^1.51.0-dev.32db66b396",
59
- "@lodestar/utils": "^1.51.0-dev.32db66b396",
53
+ "@lodestar/api": "^1.51.0-dev.38410b466e",
54
+ "@lodestar/config": "^1.51.0-dev.38410b466e",
55
+ "@lodestar/db": "^1.51.0-dev.38410b466e",
56
+ "@lodestar/params": "^1.51.0-dev.38410b466e",
57
+ "@lodestar/state-transition": "^1.51.0-dev.38410b466e",
58
+ "@lodestar/types": "^1.51.0-dev.38410b466e",
59
+ "@lodestar/utils": "^1.51.0-dev.38410b466e",
60
60
  "strict-event-emitter-types": "^2.0.0"
61
61
  },
62
62
  "devDependencies": {
63
- "@lodestar/logger": "^1.51.0-dev.32db66b396",
64
- "@lodestar/spec-test-util": "^1.51.0-dev.32db66b396",
65
- "@lodestar/test-utils": "^1.51.0-dev.32db66b396",
63
+ "@lodestar/logger": "^1.51.0-dev.38410b466e",
64
+ "@lodestar/spec-test-util": "^1.51.0-dev.38410b466e",
65
+ "@lodestar/test-utils": "^1.51.0-dev.38410b466e",
66
66
  "@vekexasia/bigint-buffer2": "^1.1.1",
67
67
  "rimraf": "^4.4.1"
68
68
  },
69
- "gitHead": "a1a1b3d55eae68131b79f1b40de95d9b61ae9c5d"
69
+ "gitHead": "27c04066e245afb8b5d71eb3127f64bcc32f764a"
70
70
  }
@@ -1,4 +1,5 @@
1
1
  import {BLSPubkey, Epoch} from "@lodestar/types";
2
+ import {defer, toPubkeyHex} from "@lodestar/utils";
2
3
  import {MinMaxSurround, SurroundAttestationError, SurroundAttestationErrorCode} from "../minMaxSurround/index.js";
3
4
  import {SlashingProtectionAttestation} from "../types.js";
4
5
  import {ZERO_ROOT, isEqualNonZeroRoot, isEqualRoot, minEpoch} from "../utils.js";
@@ -21,6 +22,7 @@ export class SlashingProtectionAttestationService {
21
22
  private attestationByTarget: AttestationByTargetRepository;
22
23
  private attestationLowerBound: AttestationLowerBoundRepository;
23
24
  private minMaxSurround: MinMaxSurround;
25
+ private readonly pendingAttestations = new Map<string, Promise<void>>();
24
26
 
25
27
  constructor(
26
28
  signedAttestationDb: AttestationByTargetRepository,
@@ -37,10 +39,25 @@ export class SlashingProtectionAttestationService {
37
39
  * This is the safe, externally-callable interface for checking attestations
38
40
  */
39
41
  async checkAndInsertAttestation(pubKey: BLSPubkey, attestation: SlashingProtectionAttestation): Promise<void> {
40
- const safeStatus = await this.checkAttestation(pubKey, attestation);
42
+ const pubkeyHex = toPubkeyHex(pubKey);
43
+ const previous = this.pendingAttestations.get(pubkeyHex);
44
+ const {promise, resolve} = defer<void>();
45
+ this.pendingAttestations.set(pubkeyHex, promise);
41
46
 
42
- if (safeStatus !== SafeStatus.SAME_DATA) {
43
- await this.insertAttestation(pubKey, attestation);
47
+ try {
48
+ if (previous !== undefined) {
49
+ await previous;
50
+ }
51
+ const safeStatus = await this.checkAttestation(pubKey, attestation);
52
+
53
+ if (safeStatus !== SafeStatus.SAME_DATA) {
54
+ await this.insertAttestation(pubKey, attestation);
55
+ }
56
+ } finally {
57
+ resolve();
58
+ if (this.pendingAttestations.get(pubkeyHex) === promise) {
59
+ this.pendingAttestations.delete(pubkeyHex);
60
+ }
44
61
  }
45
62
 
46
63
  // TODO: Implement safe clean-up of stored attestations
@@ -164,55 +181,73 @@ export class SlashingProtectionAttestationService {
164
181
  * Interchange import / export functionality
165
182
  */
166
183
  async importAttestations(pubkey: BLSPubkey, attestations: SlashingProtectionAttestation[]): Promise<void> {
167
- // Min-max surround misses a surround vote beyond its lookback, require the highest target attestation to
168
- // have the highest source epoch as `checkAttestation` relies on it
169
- let latestAtt = await this.attestationByTarget.getLatest(pubkey);
170
- let maxSourceAtt = latestAtt;
171
- for (const attestation of attestations) {
172
- if (latestAtt === null || attestation.targetEpoch >= latestAtt.targetEpoch) {
173
- latestAtt = attestation;
184
+ const pubkeyHex = toPubkeyHex(pubkey);
185
+ const previous = this.pendingAttestations.get(pubkeyHex);
186
+ const {promise, resolve} = defer<void>();
187
+ this.pendingAttestations.set(pubkeyHex, promise);
188
+
189
+ try {
190
+ if (previous !== undefined) {
191
+ await previous;
174
192
  }
175
- if (maxSourceAtt === null || attestation.sourceEpoch > maxSourceAtt.sourceEpoch) {
176
- maxSourceAtt = attestation;
193
+ // Min-max surround misses a surround vote beyond its lookback, require the highest target attestation to
194
+ // have the highest source epoch as `checkAttestation` relies on it
195
+ let latestAtt = await this.attestationByTarget.getLatest(pubkey);
196
+ let maxSourceAtt = latestAtt;
197
+ for (const attestation of attestations) {
198
+ if (latestAtt === null || attestation.targetEpoch >= latestAtt.targetEpoch) {
199
+ latestAtt = attestation;
200
+ }
201
+ if (maxSourceAtt === null || attestation.sourceEpoch > maxSourceAtt.sourceEpoch) {
202
+ maxSourceAtt = attestation;
203
+ }
177
204
  }
178
- }
179
- if (latestAtt && maxSourceAtt && latestAtt.sourceEpoch < maxSourceAtt.sourceEpoch) {
180
- throw new InvalidAttestationError({
181
- code: InvalidAttestationErrorCode.NEW_SURROUNDS_PREV,
182
- attestation: latestAtt,
183
- prev: maxSourceAtt,
184
- });
185
- }
186
-
187
- // Never replace a recorded attestation with a different source or signing root, a zero root refuses any attestation
188
- // with that target. The highest source epoch is kept as the latest attestation must have it, see above.
189
- const attestationsByTarget = new Map<Epoch, SlashingProtectionAttestation>();
190
- for (const attestation of attestations) {
191
- const {sourceEpoch, targetEpoch, signingRoot} = attestation;
192
- const prevAtt =
193
- attestationsByTarget.get(targetEpoch) ?? (await this.attestationByTarget.get(pubkey, targetEpoch));
194
- if (prevAtt === null || (prevAtt.sourceEpoch === sourceEpoch && isEqualRoot(prevAtt.signingRoot, signingRoot))) {
195
- attestationsByTarget.set(targetEpoch, attestation);
196
- } else {
197
- attestationsByTarget.set(targetEpoch, {
198
- sourceEpoch: Math.max(prevAtt.sourceEpoch, sourceEpoch),
199
- targetEpoch,
200
- signingRoot: ZERO_ROOT,
205
+ if (latestAtt && maxSourceAtt && latestAtt.sourceEpoch < maxSourceAtt.sourceEpoch) {
206
+ throw new InvalidAttestationError({
207
+ code: InvalidAttestationErrorCode.NEW_SURROUNDS_PREV,
208
+ attestation: latestAtt,
209
+ prev: maxSourceAtt,
201
210
  });
202
211
  }
203
- }
204
- await this.attestationByTarget.set(pubkey, Array.from(attestationsByTarget.values()));
205
212
 
206
- // Pre-compute spans for all attestations
207
- for (const attestation of attestations) {
208
- await this.minMaxSurround.insertAttestation(pubkey, attestation);
209
- }
213
+ // Never replace a recorded attestation with a different source or signing root, a zero root refuses any attestation
214
+ // with that target. The highest source epoch is kept as the latest attestation must have it, see above.
215
+ const attestationsByTarget = new Map<Epoch, SlashingProtectionAttestation>();
216
+ for (const attestation of attestations) {
217
+ const {sourceEpoch, targetEpoch, signingRoot} = attestation;
218
+ const prevAtt =
219
+ attestationsByTarget.get(targetEpoch) ?? (await this.attestationByTarget.get(pubkey, targetEpoch));
220
+ if (
221
+ prevAtt === null ||
222
+ (prevAtt.sourceEpoch === sourceEpoch && isEqualRoot(prevAtt.signingRoot, signingRoot))
223
+ ) {
224
+ attestationsByTarget.set(targetEpoch, attestation);
225
+ } else {
226
+ attestationsByTarget.set(targetEpoch, {
227
+ sourceEpoch: Math.max(prevAtt.sourceEpoch, sourceEpoch),
228
+ targetEpoch,
229
+ signingRoot: ZERO_ROOT,
230
+ });
231
+ }
232
+ }
233
+ await this.attestationByTarget.set(pubkey, Array.from(attestationsByTarget.values()));
234
+
235
+ // Pre-compute spans for all attestations
236
+ for (const attestation of attestations) {
237
+ await this.minMaxSurround.insertAttestation(pubkey, attestation);
238
+ }
210
239
 
211
- // Pre-compute and store lower-bound
212
- const minSourceEpoch = minEpoch(attestations.map((attestation) => attestation.sourceEpoch));
213
- const minTargetEpoch = minEpoch(attestations.map((attestation) => attestation.targetEpoch));
214
- if (minSourceEpoch != null && minTargetEpoch != null) {
215
- await this.attestationLowerBound.set(pubkey, {minSourceEpoch, minTargetEpoch});
240
+ // Pre-compute and store lower-bound
241
+ const minSourceEpoch = minEpoch(attestations.map((attestation) => attestation.sourceEpoch));
242
+ const minTargetEpoch = minEpoch(attestations.map((attestation) => attestation.targetEpoch));
243
+ if (minSourceEpoch != null && minTargetEpoch != null) {
244
+ await this.attestationLowerBound.set(pubkey, {minSourceEpoch, minTargetEpoch});
245
+ }
246
+ } finally {
247
+ resolve();
248
+ if (this.pendingAttestations.get(pubkeyHex) === promise) {
249
+ this.pendingAttestations.delete(pubkeyHex);
250
+ }
216
251
  }
217
252
  }
218
253
 
@@ -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
- for (const validator of data) {
88
- logger?.info("Importing slashing protection", {pubkey: toPubkeyHex(validator.pubkey)});
89
- await this.blockService.importBlocks(validator.pubkey, validator.signedBlocks);
90
- await this.attestationService.importAttestations(validator.pubkey, validator.signedAttestations);
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