diff --git a/packages/validator/src/slashingProtection/minMaxSurround/minMaxSurround.ts b/packages/validator/src/slashingProtection/minMaxSurround/minMaxSurround.ts index e3ef3b0d8184..446c3cd763e7 100644 --- a/packages/validator/src/slashingProtection/minMaxSurround/minMaxSurround.ts +++ b/packages/validator/src/slashingProtection/minMaxSurround/minMaxSurround.ts @@ -5,13 +5,29 @@ import {SurroundAttestationError, SurroundAttestationErrorCode} from "./errors.j // surround vote checking with min-max surround // https://github.com/protolambda/eth2-surround#min-max-surround +/** + * Number of epochs in the past to check for surrounding attestations. + * + * This value can be limited to a reasonable high amount as Lodestar does not solely rely on this strategy but also + * implements the minimal strategy which has been formally proven to be safe (https://github.com/michaelsproul/slashing-proofs). + * + * Limiting this value is required due to practical reasons as otherwise there would be a min-span DB read and write + * for each validator from current epoch until genesis which massively increases DB size and causes I/O lag, resulting in + * instability on first startup with an empty DB. See https://github.com/ChainSafe/lodestar/issues/5356 for more details. + * + * The value 4096 has been chosen as it is the default used by slashers (https://lighthouse-book.sigmaprime.io/slasher.html#history-length) + * and is generally higher than the weak subjectivity period. However, it would still be risky if we just relied on min-max surround + * for slashing protection, as slashers can be configured to collect slashable attestations over a longer period. + */ +const DEFAULT_MAX_EPOCH_LOOKBACK = 4096; + export class MinMaxSurround implements IMinMaxSurround { private store: IDistanceStore; private maxEpochLookback: number; constructor(store: IDistanceStore, options?: {maxEpochLookback?: number}) { this.store = store; - this.maxEpochLookback = options?.maxEpochLookback ?? Infinity; + this.maxEpochLookback = options?.maxEpochLookback ?? DEFAULT_MAX_EPOCH_LOOKBACK; } async assertNoSurround(pubKey: BLSPubkey, attestation: MinMaxSurroundAttestation): Promise {