From 0fb52bbec44814d176a9796367c0da86e6c889ae Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Sat, 4 Jul 2026 21:43:10 +0100 Subject: [PATCH 1/2] fix: prune old proposer preferences submissions --- packages/validator/src/services/proposerPreferences.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/validator/src/services/proposerPreferences.ts b/packages/validator/src/services/proposerPreferences.ts index 29e161754156..7ccc645f0504 100644 --- a/packages/validator/src/services/proposerPreferences.ts +++ b/packages/validator/src/services/proposerPreferences.ts @@ -58,6 +58,11 @@ export class ProposerPreferencesService { } const currentEpoch = computeEpochAtSlot(slot); + + // Only currentEpoch and currentEpoch + 1 are ever processed, so drop the epoch that just fell + // behind. A no-op except on the first slot of a new epoch (epochs advance one at a time). + this.submitted.delete(currentEpoch - 1); + const batch: gloas.SignedProposerPreferences[] = []; // Track which `(submission, slot)` pairs are pending an API submission so we can mark // them only after the network call succeeds. Marking before would silently drop a From fb9455d53d774ed371362bb0c59c9b3b61ff1ce9 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Sat, 4 Jul 2026 22:00:53 +0100 Subject: [PATCH 2/2] refactor: prune proposer preferences on epoch tick --- .../validator/src/services/proposerPreferences.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/validator/src/services/proposerPreferences.ts b/packages/validator/src/services/proposerPreferences.ts index 7ccc645f0504..42ff1101bb5a 100644 --- a/packages/validator/src/services/proposerPreferences.ts +++ b/packages/validator/src/services/proposerPreferences.ts @@ -47,6 +47,7 @@ export class ProposerPreferencesService { _metrics: Metrics | null ) { clock.runEverySlot(this.runProposerPreferencesTask); + clock.runEveryEpoch(this.pruneSubmitted); } private runProposerPreferencesTask = async (slot: Slot): Promise => { @@ -58,11 +59,6 @@ export class ProposerPreferencesService { } const currentEpoch = computeEpochAtSlot(slot); - - // Only currentEpoch and currentEpoch + 1 are ever processed, so drop the epoch that just fell - // behind. A no-op except on the first slot of a new epoch (epochs advance one at a time). - this.submitted.delete(currentEpoch - 1); - const batch: gloas.SignedProposerPreferences[] = []; // Track which `(submission, slot)` pairs are pending an API submission so we can mark // them only after the network call succeeds. Marking before would silently drop a @@ -133,4 +129,13 @@ export class ProposerPreferencesService { this.logger.error("Error submitting signed proposer preferences", {count: batch.length}, e as Error); } }; + + /** Drop tracking for past epochs; only currentEpoch and currentEpoch + 1 are ever processed. */ + private pruneSubmitted = async (epoch: Epoch): Promise => { + for (const trackedEpoch of this.submitted.keys()) { + if (trackedEpoch < epoch) { + this.submitted.delete(trackedEpoch); + } + } + }; }