@lodestar/validator 1.48.0-dev.67df6eac67 → 1.48.0-dev.68ce7b06a0

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.
@@ -18,6 +18,8 @@ export declare class AttestationByTargetRepository {
18
18
  private readonly maxKey;
19
19
  constructor(db: LodestarValidatorDatabaseController);
20
20
  getAll(pubkey: BLSPubkey, limit?: number): Promise<SlashingProtectionAttestation[]>;
21
+ /** Attestation with the highest target epoch recorded for `pubkey`, or null if none */
22
+ getLatest(pubkey: BLSPubkey): Promise<SlashingProtectionAttestation | null>;
21
23
  get(pubkey: BLSPubkey, targetEpoch: Epoch): Promise<SlashingProtectionAttestation | null>;
22
24
  set(pubkey: BLSPubkey, atts: SlashingProtectionAttestation[]): Promise<void>;
23
25
  listPubkeys(): Promise<BLSPubkey[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"attestationByTargetRepository.d.ts","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/attestationByTargetRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,IAAI,EAAC,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAC,SAAS,EAAE,KAAK,EAAM,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAC,MAAM,EAAuB,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAC,mCAAmC,EAAC,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAC,6BAA6B,EAAC,MAAM,aAAa,CAAC;AAG1D;;;;GAIG;AACH,qBAAa,6BAA6B;IAS5B,SAAS,CAAC,EAAE,EAAE,mCAAmC;IAR7D,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACpD,SAAS,CAAC,MAAM,SAAgD;IAEhE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwC;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IAEpC,YAAsB,EAAE,EAAE,mCAAmC,EAQ5D;IAEK,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,6BAA6B,EAAE,CAAC,CAQxF;IAEK,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,GAAG,OAAO,CAAC,6BAA6B,GAAG,IAAI,CAAC,CAG9F;IAEK,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,6BAA6B,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjF;IAEK,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAGxC;IAED,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,SAAS;CASlB"}
1
+ {"version":3,"file":"attestationByTargetRepository.d.ts","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/attestationByTargetRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,IAAI,EAAC,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAC,SAAS,EAAE,KAAK,EAAM,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAC,MAAM,EAAuB,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAC,mCAAmC,EAAC,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAC,6BAA6B,EAAC,MAAM,aAAa,CAAC;AAG1D;;;;GAIG;AACH,qBAAa,6BAA6B;IAS5B,SAAS,CAAC,EAAE,EAAE,mCAAmC;IAR7D,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACpD,SAAS,CAAC,MAAM,SAAgD;IAEhE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwC;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IAEpC,YAAsB,EAAE,EAAE,mCAAmC,EAQ5D;IAEK,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,6BAA6B,EAAE,CAAC,CAQxF;IAED,uFAAuF;IACjF,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,6BAA6B,GAAG,IAAI,CAAC,CAShF;IAEK,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,GAAG,OAAO,CAAC,6BAA6B,GAAG,IAAI,CAAC,CAG9F;IAEK,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,6BAA6B,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjF;IAEK,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAGxC;IAED,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,SAAS;CASlB"}
@@ -36,6 +36,17 @@ export class AttestationByTargetRepository {
36
36
  });
37
37
  return attestations.map((attestation) => this.type.deserialize(attestation));
38
38
  }
39
+ /** Attestation with the highest target epoch recorded for `pubkey`, or null if none */
40
+ async getLatest(pubkey) {
41
+ const [att] = await this.db.values({
42
+ gte: this.encodeKey(pubkey, 0),
43
+ lt: this.encodeKey(pubkey, Number.MAX_SAFE_INTEGER),
44
+ reverse: true,
45
+ limit: 1,
46
+ bucketId: this.bucketId,
47
+ });
48
+ return att ? this.type.deserialize(att) : null;
49
+ }
39
50
  async get(pubkey, targetEpoch) {
40
51
  const att = await this.db.get(this.encodeKey(pubkey, targetEpoch), this.dbReqOpts);
41
52
  return att && this.type.deserialize(att);
@@ -1 +1 @@
1
- {"version":3,"file":"attestationByTargetRepository.js","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/attestationByTargetRepository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"attestationByTargetRepository.js","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/attestationByTargetRepository.ts"],"names":[],"mappings":"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"}
@@ -27,7 +27,12 @@ export declare enum InvalidAttestationErrorCode {
27
27
  * The attestation is invalid because its target epoch is less than or equal to the lower
28
28
  * bound on target epochs for this validator.
29
29
  */
30
- TARGET_LESS_THAN_OR_EQ_LOWER_BOUND = "ERR_INVALID_ATTESTATION_TARGET_LESS_THAN_OR_EQ_LOWER_BOUND"
30
+ TARGET_LESS_THAN_OR_EQ_LOWER_BOUND = "ERR_INVALID_ATTESTATION_TARGET_LESS_THAN_OR_EQ_LOWER_BOUND",
31
+ /**
32
+ * The attestation is invalid because its source epoch is below the min-max span lookback window of the
33
+ * latest attestation of this validator, where a surround vote could not be detected.
34
+ */
35
+ SOURCE_BELOW_MIN_SPAN_LOOKBACK = "ERR_INVALID_ATTESTATION_SOURCE_BELOW_MIN_SPAN_LOOKBACK"
31
36
  }
32
37
  type InvalidAttestationErrorType = {
33
38
  code: InvalidAttestationErrorCode.DOUBLE_VOTE;
@@ -51,6 +56,10 @@ type InvalidAttestationErrorType = {
51
56
  code: InvalidAttestationErrorCode.TARGET_LESS_THAN_OR_EQ_LOWER_BOUND;
52
57
  targetEpoch: Epoch;
53
58
  minTargetEpoch: Epoch;
59
+ } | {
60
+ code: InvalidAttestationErrorCode.SOURCE_BELOW_MIN_SPAN_LOOKBACK;
61
+ sourceEpoch: Epoch;
62
+ minSourceEpoch: Epoch;
54
63
  };
55
64
  export declare class InvalidAttestationError extends LodestarError<InvalidAttestationErrorType> {
56
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAC,6BAA6B,EAAC,MAAM,aAAa,CAAC;AAE1D,oBAAY,2BAA2B;IACrC;;OAEG;IACH,WAAW,wCAAwC;IACnD;;OAEG;IACH,kBAAkB,+CAA+C;IACjE;;OAEG;IACH,kBAAkB,+CAA+C;IACjE;;OAEG;IACH,qBAAqB,kDAAkD;IACvE;;;OAGG;IACH,4BAA4B,yDAAyD;IACrF;;;OAGG;IACH,kCAAkC,+DAA+D;CAClG;AAED,KAAK,2BAA2B,GAC5B;IACE,IAAI,EAAE,2BAA2B,CAAC,WAAW,CAAC;IAC9C,WAAW,EAAE,6BAA6B,CAAC;IAC3C,IAAI,EAAE,6BAA6B,CAAC;CACrC,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,kBAAkB,CAAC;IACrD,WAAW,EAAE,6BAA6B,CAAC;IAE3C,IAAI,EAAE,6BAA6B,GAAG,IAAI,CAAC;CAC5C,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,kBAAkB,CAAC;IACrD,WAAW,EAAE,6BAA6B,CAAC;IAE3C,IAAI,EAAE,6BAA6B,GAAG,IAAI,CAAC;CAC5C,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,qBAAqB,CAAC;CACzD,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,4BAA4B,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC;IACnB,cAAc,EAAE,KAAK,CAAC;CACvB,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,kCAAkC,CAAC;IACrE,WAAW,EAAE,KAAK,CAAC;IACnB,cAAc,EAAE,KAAK,CAAC;CACvB,CAAC;AAEN,qBAAa,uBAAwB,SAAQ,aAAa,CAAC,2BAA2B,CAAC;CAAG"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAC,6BAA6B,EAAC,MAAM,aAAa,CAAC;AAE1D,oBAAY,2BAA2B;IACrC;;OAEG;IACH,WAAW,wCAAwC;IACnD;;OAEG;IACH,kBAAkB,+CAA+C;IACjE;;OAEG;IACH,kBAAkB,+CAA+C;IACjE;;OAEG;IACH,qBAAqB,kDAAkD;IACvE;;;OAGG;IACH,4BAA4B,yDAAyD;IACrF;;;OAGG;IACH,kCAAkC,+DAA+D;IACjG;;;OAGG;IACH,8BAA8B,2DAA2D;CAC1F;AAED,KAAK,2BAA2B,GAC5B;IACE,IAAI,EAAE,2BAA2B,CAAC,WAAW,CAAC;IAC9C,WAAW,EAAE,6BAA6B,CAAC;IAC3C,IAAI,EAAE,6BAA6B,CAAC;CACrC,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,kBAAkB,CAAC;IACrD,WAAW,EAAE,6BAA6B,CAAC;IAE3C,IAAI,EAAE,6BAA6B,GAAG,IAAI,CAAC;CAC5C,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,kBAAkB,CAAC;IACrD,WAAW,EAAE,6BAA6B,CAAC;IAE3C,IAAI,EAAE,6BAA6B,GAAG,IAAI,CAAC;CAC5C,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,qBAAqB,CAAC;CACzD,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,4BAA4B,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC;IACnB,cAAc,EAAE,KAAK,CAAC;CACvB,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,kCAAkC,CAAC;IACrE,WAAW,EAAE,KAAK,CAAC;IACnB,cAAc,EAAE,KAAK,CAAC;CACvB,GACD;IACE,IAAI,EAAE,2BAA2B,CAAC,8BAA8B,CAAC;IACjE,WAAW,EAAE,KAAK,CAAC;IACnB,cAAc,EAAE,KAAK,CAAC;CACvB,CAAC;AAEN,qBAAa,uBAAwB,SAAQ,aAAa,CAAC,2BAA2B,CAAC;CAAG"}
@@ -27,6 +27,11 @@ export var InvalidAttestationErrorCode;
27
27
  * bound on target epochs for this validator.
28
28
  */
29
29
  InvalidAttestationErrorCode["TARGET_LESS_THAN_OR_EQ_LOWER_BOUND"] = "ERR_INVALID_ATTESTATION_TARGET_LESS_THAN_OR_EQ_LOWER_BOUND";
30
+ /**
31
+ * The attestation is invalid because its source epoch is below the min-max span lookback window of the
32
+ * latest attestation of this validator, where a surround vote could not be detected.
33
+ */
34
+ InvalidAttestationErrorCode["SOURCE_BELOW_MIN_SPAN_LOOKBACK"] = "ERR_INVALID_ATTESTATION_SOURCE_BELOW_MIN_SPAN_LOOKBACK";
30
35
  })(InvalidAttestationErrorCode || (InvalidAttestationErrorCode = {}));
31
36
  export class InvalidAttestationError extends LodestarError {
32
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAG9C,MAAM,CAAN,IAAY,2BA2BX;AA3BD,WAAY,2BAA2B;IACrC;;OAEG;IACH,kFAAmD,CAAA;IACnD;;OAEG;IACH,gGAAiE,CAAA;IACjE;;OAEG;IACH,gGAAiE,CAAA;IACjE;;OAEG;IACH,sGAAuE,CAAA;IACvE;;;OAGG;IACH,oHAAqF,CAAA;IACrF;;;OAGG;IACH,gIAAiG,CAAA;AACnG,CAAC,EA3BW,2BAA2B,KAA3B,2BAA2B,QA2BtC;AAkCD,MAAM,OAAO,uBAAwB,SAAQ,aAA0C;CAAG"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAG9C,MAAM,CAAN,IAAY,2BAgCX;AAhCD,WAAY,2BAA2B;IACrC;;OAEG;IACH,kFAAmD,CAAA;IACnD;;OAEG;IACH,gGAAiE,CAAA;IACjE;;OAEG;IACH,gGAAiE,CAAA;IACjE;;OAEG;IACH,sGAAuE,CAAA;IACvE;;;OAGG;IACH,oHAAqF,CAAA;IACrF;;;OAGG;IACH,gIAAiG,CAAA;IACjG;;;OAGG;IACH,wHAAyF,CAAA;AAC3F,CAAC,EAhCW,2BAA2B,KAA3B,2BAA2B,QAgCtC;AAuCD,MAAM,OAAO,uBAAwB,SAAQ,aAA0C;CAAG"}
@@ -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,CAuEzG;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,CAcxG;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;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,CAkCxG;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"}
@@ -38,9 +38,16 @@ export class SlashingProtectionAttestationService {
38
38
  if (attestation.sourceEpoch > attestation.targetEpoch) {
39
39
  throw new InvalidAttestationError({ code: InvalidAttestationErrorCode.SOURCE_EXCEEDS_TARGET });
40
40
  }
41
+ const latestAtt = await this.attestationByTarget.getLatest(pubKey);
41
42
  // Check for a double vote. Namely, an existing attestation with the same target epoch,
42
- // and a different signing root.
43
- const sameTargetAtt = await this.attestationByTarget.get(pubKey, attestation.targetEpoch);
43
+ // and a different signing root. No db read needed if the latest attestation has a lower target epoch.
44
+ let sameTargetAtt = null;
45
+ if (latestAtt && latestAtt.targetEpoch === attestation.targetEpoch) {
46
+ sameTargetAtt = latestAtt;
47
+ }
48
+ else if (latestAtt && latestAtt.targetEpoch > attestation.targetEpoch) {
49
+ sameTargetAtt = await this.attestationByTarget.get(pubKey, attestation.targetEpoch);
50
+ }
44
51
  if (sameTargetAtt) {
45
52
  // Interchange format allows for attestations without signing_root, then assume root is equal
46
53
  if (isEqualNonZeroRoot(sameTargetAtt.signingRoot, attestation.signingRoot)) {
@@ -52,6 +59,19 @@ export class SlashingProtectionAttestationService {
52
59
  prev: sameTargetAtt,
53
60
  });
54
61
  }
62
+ // Min-span entries only exist within the lookback window below each recorded source epoch, a surround vote
63
+ // with an older source epoch is undetectable by min-max surround and must be rejected outright. Recorded
64
+ // attestations are surround-free, so the latest one has the highest source epoch and the widest window.
65
+ if (latestAtt) {
66
+ const minSourceEpoch = this.minMaxSurround.minSpanCoverageStart(latestAtt.sourceEpoch);
67
+ if (attestation.sourceEpoch < minSourceEpoch) {
68
+ throw new InvalidAttestationError({
69
+ code: InvalidAttestationErrorCode.SOURCE_BELOW_MIN_SPAN_LOOKBACK,
70
+ sourceEpoch: attestation.sourceEpoch,
71
+ minSourceEpoch,
72
+ });
73
+ }
74
+ }
55
75
  // Check for a surround vote
56
76
  try {
57
77
  await this.minMaxSurround.assertNoSurround(pubKey, attestation);
@@ -119,6 +139,25 @@ export class SlashingProtectionAttestationService {
119
139
  * Interchange import / export functionality
120
140
  */
121
141
  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;
152
+ }
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
+ }
122
161
  await this.attestationByTarget.set(pubkey, attestations);
123
162
  // Pre-compute spans for all attestations
124
163
  for (const attestation of attestations) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,wBAAwB,EAAE,4BAA4B,EAAC,MAAM,4BAA4B,CAAC;AAElH,OAAO,EAAC,kBAAkB,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AACzD,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,IAAK,UAGJ;AAHD,WAAK,UAAU;IACb,iDAAmC,CAAA;IACnC,mCAAqB,CAAA;AACvB,CAAC,EAHI,UAAU,KAAV,UAAU,QAGd;AAED,MAAM,OAAO,oCAAoC;IACvC,mBAAmB,CAAgC;IACnD,qBAAqB,CAAkC;IACvD,cAAc,CAAiB;IAEvC,YACE,mBAAkD,EAClD,qBAAsD,EACtD,cAA8B;QAE9B,IAAI,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;QAC/C,IAAI,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;QACnD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,yBAAyB,CAAC,MAAiB,EAAE,WAA0C;QAC3F,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAEpE,IAAI,UAAU,KAAK,UAAU,CAAC,SAAS,EAAE,CAAC;YACxC,MAAM,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACpD,CAAC;QAED,uDAAuD;IACzD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,MAAiB,EAAE,WAA0C;QAClF,yEAAyE;QACzE,sFAAsF;QACtF,IAAI,WAAW,CAAC,WAAW,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;YACtD,MAAM,IAAI,uBAAuB,CAAC,EAAC,IAAI,EAAE,2BAA2B,CAAC,qBAAqB,EAAC,CAAC,CAAC;QAC/F,CAAC;QAED,uFAAuF;QACvF,gCAAgC;QAChC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;QAC1F,IAAI,aAAa,EAAE,CAAC;YAClB,6FAA6F;YAC7F,IAAI,kBAAkB,CAAC,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3E,OAAO,UAAU,CAAC,SAAS,CAAC;YAC9B,CAAC;YACD,MAAM,IAAI,uBAAuB,CAAC;gBAChC,IAAI,EAAE,2BAA2B,CAAC,WAAW;gBAC7C,WAAW,EAAE,WAAW;gBACxB,IAAI,EAAE,aAAa;aACpB,CAAC,CAAC;QACL,CAAC;QAED,4BAA4B;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,wBAAwB,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;gBACrG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACpB,KAAK,4BAA4B,CAAC,cAAc;wBAC9C,MAAM,IAAI,uBAAuB,CAAC;4BAChC,IAAI,EAAE,2BAA2B,CAAC,kBAAkB;4BACpD,WAAW;4BACX,IAAI;yBACL,CAAC,CAAC;oBACL,KAAK,4BAA4B,CAAC,aAAa;wBAC7C,MAAM,IAAI,uBAAuB,CAAC;4BAChC,IAAI,EAAE,2BAA2B,CAAC,kBAAkB;4BACpD,WAAW;4BACX,IAAI;yBACL,CAAC,CAAC;gBACP,CAAC;YACH,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;QAED,uCAAuC;QACvC,kHAAkH;QAClH,+GAA+G;QAC/G,6DAA6D;QAC7D,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3E,IAAI,qBAAqB,EAAE,CAAC;YAC1B,MAAM,EAAC,cAAc,EAAE,cAAc,EAAC,GAAG,qBAAqB,CAAC;YAC/D,IAAI,WAAW,CAAC,WAAW,GAAG,cAAc,EAAE,CAAC;gBAC7C,MAAM,IAAI,uBAAuB,CAAC;oBAChC,IAAI,EAAE,2BAA2B,CAAC,4BAA4B;oBAC9D,WAAW,EAAE,WAAW,CAAC,WAAW;oBACpC,cAAc;iBACf,CAAC,CAAC;YACL,CAAC;YAED,IAAI,WAAW,CAAC,WAAW,IAAI,cAAc,EAAE,CAAC;gBAC9C,MAAM,IAAI,uBAAuB,CAAC;oBAChC,IAAI,EAAE,2BAA2B,CAAC,kCAAkC;oBACpE,WAAW,EAAE,WAAW,CAAC,WAAW;oBACpC,cAAc;iBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC,EAAE,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,iBAAiB,CAAC,MAAiB,EAAE,WAA0C;QACnF,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,sBAAsB,CAAC,MAAiB,EAAE,KAAY;QAC1D,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,MAAiB,EAAE,YAA6C;QACvF,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAEzD,yCAAyC;QACzC,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACnE,CAAC;QAED,oCAAoC;QACpC,MAAM,cAAc,GAAG,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;QAC5F,MAAM,cAAc,GAAG,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;QAC5F,IAAI,cAAc,IAAI,IAAI,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;YACrD,MAAM,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAC,cAAc,EAAE,cAAc,EAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,MAAiB;QACxC,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,CAAC;IAChD,CAAC;CACF"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/slashingProtection/attestation/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { BLSPubkey } from "@lodestar/types";
1
+ import { BLSPubkey, Epoch } from "@lodestar/types";
2
2
  import { IDistanceStore, IMinMaxSurround, MinMaxSurroundAttestation } from "./interface.js";
3
3
  export declare class MinMaxSurround implements IMinMaxSurround {
4
4
  private store;
@@ -6,6 +6,8 @@ export declare class MinMaxSurround implements IMinMaxSurround {
6
6
  constructor(store: IDistanceStore, options?: {
7
7
  maxEpochLookback?: number;
8
8
  });
9
+ /** Lowest epoch with a min-span entry after inserting an attestation with `sourceEpoch` */
10
+ minSpanCoverageStart(sourceEpoch: Epoch): Epoch;
9
11
  assertNoSurround(pubKey: BLSPubkey, attestation: MinMaxSurroundAttestation): Promise<void>;
10
12
  insertAttestation(pubKey: BLSPubkey, attestation: MinMaxSurroundAttestation): Promise<void>;
11
13
  private updateMinSpan;
@@ -1 +1 @@
1
- {"version":3,"file":"minMaxSurround.d.ts","sourceRoot":"","sources":["../../../src/slashingProtection/minMaxSurround/minMaxSurround.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAgB,cAAc,EAAE,eAAe,EAAE,yBAAyB,EAAC,MAAM,gBAAgB,CAAC;AAqBzG,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IAEjC,YAAY,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAC,EAGvE;IAEK,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/F;IAEK,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;YAIa,aAAa;YAkBb,oBAAoB;YAcpB,aAAa;YAgBb,mBAAmB;CAWlC"}
1
+ {"version":3,"file":"minMaxSurround.d.ts","sourceRoot":"","sources":["../../../src/slashingProtection/minMaxSurround/minMaxSurround.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAgB,cAAc,EAAE,eAAe,EAAE,yBAAyB,EAAC,MAAM,gBAAgB,CAAC;AAsBzG,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IAEjC,YAAY,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAC,EAGvE;IAED,2FAA2F;IAC3F,oBAAoB,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAE9C;IAEK,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/F;IAEK,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;YAIa,aAAa;YAkBb,oBAAoB;YAcpB,aAAa;YAgBb,mBAAmB;CAWlC"}
@@ -5,7 +5,8 @@ import { SurroundAttestationError, SurroundAttestationErrorCode } from "./errors
5
5
  * Number of epochs in the past to check for surrounding attestations.
6
6
  *
7
7
  * This value can be limited to a reasonable high amount as Lodestar does not solely rely on this strategy but also
8
- * implements the minimal strategy which has been formally proven to be safe (https://github.com/michaelsproul/slashing-proofs).
8
+ * rejects any source epoch below `minSpanCoverageStart` of the latest recorded attestation, which is the minimal
9
+ * strategy (formally proven safe, https://github.com/michaelsproul/slashing-proofs) relaxed by this lookback.
9
10
  *
10
11
  * Limiting this value is required due to practical reasons as otherwise there would be a min-span DB read and write
11
12
  * for each validator from current epoch until genesis which massively increases DB size and causes I/O lag, resulting in
@@ -23,6 +24,10 @@ export class MinMaxSurround {
23
24
  this.store = store;
24
25
  this.maxEpochLookback = options?.maxEpochLookback ?? DEFAULT_MAX_EPOCH_LOOKBACK;
25
26
  }
27
+ /** Lowest epoch with a min-span entry after inserting an attestation with `sourceEpoch` */
28
+ minSpanCoverageStart(sourceEpoch) {
29
+ return Math.max(0, sourceEpoch - 1 - this.maxEpochLookback);
30
+ }
26
31
  async assertNoSurround(pubKey, attestation) {
27
32
  await this.assertNotSurrounding(pubKey, attestation);
28
33
  await this.assertNotSurrounded(pubKey, attestation);
@@ -34,7 +39,7 @@ export class MinMaxSurround {
34
39
  // min span
35
40
  async updateMinSpan(pubKey, attestation) {
36
41
  await this.assertNotSurrounding(pubKey, attestation);
37
- const untilEpoch = Math.max(0, attestation.sourceEpoch - 1 - this.maxEpochLookback);
42
+ const untilEpoch = this.minSpanCoverageStart(attestation.sourceEpoch);
38
43
  const values = [];
39
44
  for (let epoch = attestation.sourceEpoch - 1; epoch >= untilEpoch; epoch--) {
40
45
  const minSpan = await this.store.minSpan.get(pubKey, epoch);
@@ -1 +1 @@
1
- {"version":3,"file":"minMaxSurround.js","sourceRoot":"","sources":["../../../src/slashingProtection/minMaxSurround/minMaxSurround.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"minMaxSurround.js","sourceRoot":"","sources":["../../../src/slashingProtection/minMaxSurround/minMaxSurround.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.48.0-dev.67df6eac67",
3
+ "version": "1.48.0-dev.68ce7b06a0",
4
4
  "description": "A Typescript implementation of the validator client",
5
5
  "author": "ChainSafe Systems",
6
6
  "license": "Apache-2.0",
@@ -49,22 +49,22 @@
49
49
  ],
50
50
  "dependencies": {
51
51
  "@chainsafe/lodestar-z": "catalog:",
52
- "@chainsafe/ssz": "^1.6.3",
53
- "@lodestar/api": "^1.48.0-dev.67df6eac67",
54
- "@lodestar/config": "^1.48.0-dev.67df6eac67",
55
- "@lodestar/db": "^1.48.0-dev.67df6eac67",
56
- "@lodestar/params": "^1.48.0-dev.67df6eac67",
57
- "@lodestar/state-transition": "^1.48.0-dev.67df6eac67",
58
- "@lodestar/types": "^1.48.0-dev.67df6eac67",
59
- "@lodestar/utils": "^1.48.0-dev.67df6eac67",
52
+ "@chainsafe/ssz": "^1.7.0",
53
+ "@lodestar/api": "^1.48.0-dev.68ce7b06a0",
54
+ "@lodestar/config": "^1.48.0-dev.68ce7b06a0",
55
+ "@lodestar/db": "^1.48.0-dev.68ce7b06a0",
56
+ "@lodestar/params": "^1.48.0-dev.68ce7b06a0",
57
+ "@lodestar/state-transition": "^1.48.0-dev.68ce7b06a0",
58
+ "@lodestar/types": "^1.48.0-dev.68ce7b06a0",
59
+ "@lodestar/utils": "^1.48.0-dev.68ce7b06a0",
60
60
  "strict-event-emitter-types": "^2.0.0"
61
61
  },
62
62
  "devDependencies": {
63
- "@lodestar/logger": "^1.48.0-dev.67df6eac67",
64
- "@lodestar/spec-test-util": "^1.48.0-dev.67df6eac67",
65
- "@lodestar/test-utils": "^1.48.0-dev.67df6eac67",
63
+ "@lodestar/logger": "^1.48.0-dev.68ce7b06a0",
64
+ "@lodestar/spec-test-util": "^1.48.0-dev.68ce7b06a0",
65
+ "@lodestar/test-utils": "^1.48.0-dev.68ce7b06a0",
66
66
  "@vekexasia/bigint-buffer2": "^1.1.1",
67
67
  "rimraf": "^4.4.1"
68
68
  },
69
- "gitHead": "0a0f60834c045d1d10e2015857ca89347b5b5dbd"
69
+ "gitHead": "e51a4f2cd35c7a1922ec955a3acd0e7fa343538e"
70
70
  }
@@ -41,6 +41,18 @@ export class AttestationByTargetRepository {
41
41
  return attestations.map((attestation) => this.type.deserialize(attestation));
42
42
  }
43
43
 
44
+ /** Attestation with the highest target epoch recorded for `pubkey`, or null if none */
45
+ async getLatest(pubkey: BLSPubkey): Promise<SlashingProtectionAttestation | null> {
46
+ const [att] = await this.db.values({
47
+ gte: this.encodeKey(pubkey, 0),
48
+ lt: this.encodeKey(pubkey, Number.MAX_SAFE_INTEGER),
49
+ reverse: true,
50
+ limit: 1,
51
+ bucketId: this.bucketId,
52
+ });
53
+ return att ? this.type.deserialize(att) : null;
54
+ }
55
+
44
56
  async get(pubkey: BLSPubkey, targetEpoch: Epoch): Promise<SlashingProtectionAttestation | null> {
45
57
  const att = await this.db.get(this.encodeKey(pubkey, targetEpoch), this.dbReqOpts);
46
58
  return att && this.type.deserialize(att);
@@ -29,6 +29,11 @@ export enum InvalidAttestationErrorCode {
29
29
  * bound on target epochs for this validator.
30
30
  */
31
31
  TARGET_LESS_THAN_OR_EQ_LOWER_BOUND = "ERR_INVALID_ATTESTATION_TARGET_LESS_THAN_OR_EQ_LOWER_BOUND",
32
+ /**
33
+ * The attestation is invalid because its source epoch is below the min-max span lookback window of the
34
+ * latest attestation of this validator, where a surround vote could not be detected.
35
+ */
36
+ SOURCE_BELOW_MIN_SPAN_LOOKBACK = "ERR_INVALID_ATTESTATION_SOURCE_BELOW_MIN_SPAN_LOOKBACK",
32
37
  }
33
38
 
34
39
  type InvalidAttestationErrorType =
@@ -61,6 +66,11 @@ type InvalidAttestationErrorType =
61
66
  code: InvalidAttestationErrorCode.TARGET_LESS_THAN_OR_EQ_LOWER_BOUND;
62
67
  targetEpoch: Epoch;
63
68
  minTargetEpoch: Epoch;
69
+ }
70
+ | {
71
+ code: InvalidAttestationErrorCode.SOURCE_BELOW_MIN_SPAN_LOOKBACK;
72
+ sourceEpoch: Epoch;
73
+ minSourceEpoch: Epoch;
64
74
  };
65
75
 
66
76
  export class InvalidAttestationError extends LodestarError<InvalidAttestationErrorType> {}
@@ -56,9 +56,16 @@ export class SlashingProtectionAttestationService {
56
56
  throw new InvalidAttestationError({code: InvalidAttestationErrorCode.SOURCE_EXCEEDS_TARGET});
57
57
  }
58
58
 
59
+ const latestAtt = await this.attestationByTarget.getLatest(pubKey);
60
+
59
61
  // Check for a double vote. Namely, an existing attestation with the same target epoch,
60
- // and a different signing root.
61
- const sameTargetAtt = await this.attestationByTarget.get(pubKey, attestation.targetEpoch);
62
+ // and a different signing root. No db read needed if the latest attestation has a lower target epoch.
63
+ let sameTargetAtt: SlashingProtectionAttestation | null = null;
64
+ if (latestAtt && latestAtt.targetEpoch === attestation.targetEpoch) {
65
+ sameTargetAtt = latestAtt;
66
+ } else if (latestAtt && latestAtt.targetEpoch > attestation.targetEpoch) {
67
+ sameTargetAtt = await this.attestationByTarget.get(pubKey, attestation.targetEpoch);
68
+ }
62
69
  if (sameTargetAtt) {
63
70
  // Interchange format allows for attestations without signing_root, then assume root is equal
64
71
  if (isEqualNonZeroRoot(sameTargetAtt.signingRoot, attestation.signingRoot)) {
@@ -71,6 +78,20 @@ export class SlashingProtectionAttestationService {
71
78
  });
72
79
  }
73
80
 
81
+ // Min-span entries only exist within the lookback window below each recorded source epoch, a surround vote
82
+ // with an older source epoch is undetectable by min-max surround and must be rejected outright. Recorded
83
+ // attestations are surround-free, so the latest one has the highest source epoch and the widest window.
84
+ if (latestAtt) {
85
+ const minSourceEpoch = this.minMaxSurround.minSpanCoverageStart(latestAtt.sourceEpoch);
86
+ if (attestation.sourceEpoch < minSourceEpoch) {
87
+ throw new InvalidAttestationError({
88
+ code: InvalidAttestationErrorCode.SOURCE_BELOW_MIN_SPAN_LOOKBACK,
89
+ sourceEpoch: attestation.sourceEpoch,
90
+ minSourceEpoch,
91
+ });
92
+ }
93
+ }
94
+
74
95
  // Check for a surround vote
75
96
  try {
76
97
  await this.minMaxSurround.assertNoSurround(pubKey, attestation);
@@ -143,6 +164,26 @@ export class SlashingProtectionAttestationService {
143
164
  * Interchange import / export functionality
144
165
  */
145
166
  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;
174
+ }
175
+ if (maxSourceAtt === null || attestation.sourceEpoch > maxSourceAtt.sourceEpoch) {
176
+ maxSourceAtt = attestation;
177
+ }
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
+
146
187
  await this.attestationByTarget.set(pubkey, attestations);
147
188
 
148
189
  // Pre-compute spans for all attestations
@@ -1,4 +1,4 @@
1
- import {BLSPubkey} from "@lodestar/types";
1
+ import {BLSPubkey, Epoch} from "@lodestar/types";
2
2
  import {SurroundAttestationError, SurroundAttestationErrorCode} from "./errors.js";
3
3
  import {DistanceEntry, IDistanceStore, IMinMaxSurround, MinMaxSurroundAttestation} from "./interface.js";
4
4
 
@@ -9,7 +9,8 @@ import {DistanceEntry, IDistanceStore, IMinMaxSurround, MinMaxSurroundAttestatio
9
9
  * Number of epochs in the past to check for surrounding attestations.
10
10
  *
11
11
  * This value can be limited to a reasonable high amount as Lodestar does not solely rely on this strategy but also
12
- * implements the minimal strategy which has been formally proven to be safe (https://github.com/michaelsproul/slashing-proofs).
12
+ * rejects any source epoch below `minSpanCoverageStart` of the latest recorded attestation, which is the minimal
13
+ * strategy (formally proven safe, https://github.com/michaelsproul/slashing-proofs) relaxed by this lookback.
13
14
  *
14
15
  * Limiting this value is required due to practical reasons as otherwise there would be a min-span DB read and write
15
16
  * for each validator from current epoch until genesis which massively increases DB size and causes I/O lag, resulting in
@@ -30,6 +31,11 @@ export class MinMaxSurround implements IMinMaxSurround {
30
31
  this.maxEpochLookback = options?.maxEpochLookback ?? DEFAULT_MAX_EPOCH_LOOKBACK;
31
32
  }
32
33
 
34
+ /** Lowest epoch with a min-span entry after inserting an attestation with `sourceEpoch` */
35
+ minSpanCoverageStart(sourceEpoch: Epoch): Epoch {
36
+ return Math.max(0, sourceEpoch - 1 - this.maxEpochLookback);
37
+ }
38
+
33
39
  async assertNoSurround(pubKey: BLSPubkey, attestation: MinMaxSurroundAttestation): Promise<void> {
34
40
  await this.assertNotSurrounding(pubKey, attestation);
35
41
  await this.assertNotSurrounded(pubKey, attestation);
@@ -45,7 +51,7 @@ export class MinMaxSurround implements IMinMaxSurround {
45
51
  private async updateMinSpan(pubKey: BLSPubkey, attestation: MinMaxSurroundAttestation): Promise<void> {
46
52
  await this.assertNotSurrounding(pubKey, attestation);
47
53
 
48
- const untilEpoch = Math.max(0, attestation.sourceEpoch - 1 - this.maxEpochLookback);
54
+ const untilEpoch = this.minSpanCoverageStart(attestation.sourceEpoch);
49
55
 
50
56
  const values: DistanceEntry[] = [];
51
57
  for (let epoch = attestation.sourceEpoch - 1; epoch >= untilEpoch; epoch--) {