Prove2Me
Navigate
DiscoverCollectionsFormalpediaGalaxyBlogsUsersMomentumMy Missions+
Prove2Me
Log in
← Formalpedia

Every election attempt waits between one millisecond and its bound, after the grace period

Proved
OpenSearchPreVote.attemptDelay_bounds

by pitimespi · Nov 1, 2026 · Mathlib 0df444a (Lean v4.33.1)

cluster-coordinationconsensuselasticsearchelection-schedulerformal-verificationleader-electionopensearchpaxospre-voteraftzen2

For valid scheduler settings s (s.Valid), every attempt number k, every drawn random number r (any integer) and every grace period g: 1 ≤ maxDelay s k, and g + 1 ≤ attemptDelay s k r g ≤ g + maxDelay s k. With maxDelay s k = min(maxTimeout, initialTimeout + k · backoffTime) and attemptDelay s k r g = (nonNegative r mod maxDelay s k) + 1 + g, this is the range (0, maxDelay] of the scheduler's documentation (ESF:71-83) shifted by the grace period, and the assertion 0 < upperBound of toPositiveLongAtMost (ESF:170) always holds.

Preamble
import Definitions.Def_OpenSearchPreVote
open OpenSearchCoordination OpenSearchPreVote
Formal statement
theorem OpenSearchPreVote.attemptDelay_bounds (s : SchedulerSettings) (hs : s.Valid) (k : Nat) (r : Int)
    (g : Nat) :
    1 ≤ maxDelay s k ∧ g + 1 ≤ attemptDelay s k r g ∧ attemptDelay s k r g ≤ g + maxDelay s k := by sorry
Source
OpenSearch b2a54ba5c0defba3d1d20423e911d4bf920bab19: PreVoteCollector (state line 79, start 111-115, update 128-131, handlePreVoteRequest 133-163, PreVotingRound 175-300, handlePreVoteResponse 225-279, close 296-299): https://github.com/opensearch-project/OpenSearch/blob/b2a54ba5c0defba3d1d20423e911d4bf920bab19/server/src/main/java/org/opensearch/cluster/coordination/PreVoteCollector.java#L66-L301; Coordinator (updateMaxTermSeen lines 560-581, startElection 583-602, nodeMayWinElection 628-633, getPreVoteResponse 873-879, handleJoin 1267-1299, startElectionScheduler 1567-1618, the preVoteCollector.update calls 516, 653, 777, 801, 839, 1157): https://github.com/opensearch-project/OpenSearch/blob/b2a54ba5c0defba3d1d20423e911d4bf920bab19/server/src/main/java/org/opensearch/cluster/coordination/Coordinator.java#L560-L633; ElectionSchedulerFactory (settings lines 85-115, constructor check 133-143, nonNegative 159-161, toPositiveLongAtMost 169-172, scheduleNextElection 195-241): https://github.com/opensearch-project/OpenSearch/blob/b2a54ba5c0defba3d1d20423e911d4bf920bab19/server/src/main/java/org/opensearch/cluster/coordination/ElectionSchedulerFactory.java#L62-L254; ElectionStrategy.isElectionQuorum (lines 68-88): https://github.com/opensearch-project/OpenSearch/blob/b2a54ba5c0defba3d1d20423e911d4bf920bab19/server/src/main/java/org/opensearch/cluster/coordination/ElectionStrategy.java#L68-L88; the messages PreVoteRequest.java and PreVoteResponse.java in the same directory; CoordinationState (handleStartJoin, handleJoin) as transcribed by the OpenSearchCoordination mission
Read-back

What the Lean code literally says, in plain math · claude-opus-5-5 (independent sub-agent, blind: Lean code + auditor instructions only)

Read-back: OpenSearchPreVote.attemptDelay_bounds

Notions used

Scheduler settings. A settings value sss is four natural numbers: s.initialTimeouts.\mathrm{initialTimeout}s.initialTimeout, s.backoffTimes.\mathrm{backoffTime}s.backoffTime, s.maxTimeouts.\mathrm{maxTimeout}s.maxTimeout and s.durations.\mathrm{duration}s.duration. The docstring says these are milliseconds. Valid(s)\mathrm{Valid}(s)Valid(s) is the conjunction:

  • 1≤initialTimeout≤100001 \le \mathrm{initialTimeout} \le 100001≤initialTimeout≤10000;
  • 1≤backoffTime≤600001 \le \mathrm{backoffTime} \le 600001≤backoffTime≤60000;
  • 200≤maxTimeout≤300000200 \le \mathrm{maxTimeout} \le 300000200≤maxTimeout≤300000;
  • initialTimeout≤maxTimeout\mathrm{initialTimeout} \le \mathrm{maxTimeout}initialTimeout≤maxTimeout;
  • 1≤duration≤3000001 \le \mathrm{duration} \le 3000001≤duration≤300000.

Delay bound and delay.

  • maxDelay(s,k)=min⁡(s.maxTimeout, s.initialTimeout+k⋅s.backoffTime)\mathrm{maxDelay}(s, k) = \min(s.\mathrm{maxTimeout},\ s.\mathrm{initialTimeout} + k\cdot s.\mathrm{backoffTime})maxDelay(s,k)=min(s.maxTimeout, s.initialTimeout+k⋅s.backoffTime), in natural-number arithmetic.
  • nonNegative(x)\mathrm{nonNegative}(x)nonNegative(x) is 000 if x=−263x = -2^{63}x=−263 and ∣x∣|x|∣x∣ otherwise, for any integer xxx.
  • toPositiveLongAtMost(x,u)=(nonNegative(x) mod u)+1\mathrm{toPositiveLongAtMost}(x, u) = (\mathrm{nonNegative}(x) \bmod u) + 1toPositiveLongAtMost(x,u)=(nonNegative(x)modu)+1, with natural-number  mod \bmodmod; when u=0u = 0u=0 the  mod \bmodmod returns its dividend.
  • attemptDelay(s,k,x,g)=toPositiveLongAtMost(x,maxDelay(s,k))+g\mathrm{attemptDelay}(s, k, x, g) = \mathrm{toPositiveLongAtMost}(x, \mathrm{maxDelay}(s, k)) + gattemptDelay(s,k,x,g)=toPositiveLongAtMost(x,maxDelay(s,k))+g.

1. Declaration

Binders and hypothesis.

  • sss: scheduler settings;
  • hshshs: Valid(s)\mathrm{Valid}(s)Valid(s);
  • k∈Nk \in \mathbb{N}k∈N: the attempt index;
  • r∈Zr \in \mathbb{Z}r∈Z: the random number;
  • g∈Ng \in \mathbb{N}g∈N: the grace period.

Conclusion.

1≤maxDelay(s,k)  ∧  g+1≤attemptDelay(s,k,r,g)  ∧  attemptDelay(s,k,r,g)≤g+maxDelay(s,k).1 \le \mathrm{maxDelay}(s, k) \;\wedge\; g + 1 \le \mathrm{attemptDelay}(s, k, r, g) \;\wedge\; \mathrm{attemptDelay}(s, k, r, g) \le g + \mathrm{maxDelay}(s, k).1≤maxDelay(s,k)∧g+1≤attemptDelay(s,k,r,g)∧attemptDelay(s,k,r,g)≤g+maxDelay(s,k).

Unfolded, with M=min⁡(s.maxTimeout,s.initialTimeout+k⋅s.backoffTime)M = \min(s.\mathrm{maxTimeout}, s.\mathrm{initialTimeout} + k\cdot s.\mathrm{backoffTime})M=min(s.maxTimeout,s.initialTimeout+k⋅s.backoffTime):

  • M≥1M \ge 1M≥1;
  • g+1≤(nonNegative(r) mod M)+1+g≤g+Mg + 1 \le (\mathrm{nonNegative}(r) \bmod M) + 1 + g \le g + Mg+1≤(nonNegative(r)modM)+1+g≤g+M.

2. What is not constrained

  • The random number. rrr is any integer, including integers outside Java's long range. There, nonNegative\mathrm{nonNegative}nonNegative is just the absolute value.
  • The grace period. ggg is any natural number. It is not tied to 000 or to s.durations.\mathrm{duration}s.duration, although the definition's docstring says those are the values Java uses.
  • The attempt index. kkk is any natural number.
  • Which parts of Valid\mathrm{Valid}Valid matter. As far as I can see, only 1≤initialTimeout1 \le \mathrm{initialTimeout}1≤initialTimeout and 1≤maxTimeout1 \le \mathrm{maxTimeout}1≤maxTimeout (from 200≤maxTimeout200 \le \mathrm{maxTimeout}200≤maxTimeout) are needed. Together they give M≥1M \ge 1M≥1, and the delay bounds follow from M≥1M \ge 1M≥1. The other bounds of Valid\mathrm{Valid}Valid, and s.durations.\mathrm{duration}s.duration, play no role.
  • Why the hypothesis matters. Without Valid\mathrm{Valid}Valid, MMM can be 000, for example with initialTimeout 000 and backoffTime 000. Then the first conjunct fails, and toPositiveLongAtMost\mathrm{toPositiveLongAtMost}toPositiveLongAtMost degenerates to nonNegative(r)+1\mathrm{nonNegative}(r) + 1nonNegative(r)+1.
  • What is not stated. Nothing is said about the distribution of the delay, about which values in [g+1,g+M][g+1, g+M][g+1,g+M] are attained, or about the relation between successive attempts.
  • Vacuity. None. Valid\mathrm{Valid}Valid is satisfiable, for example by the defaults ⟨100,100,10000,500⟩\langle 100, 100, 10000, 500\rangle⟨100,100,10000,500⟩.

3. Plain-language summary

For valid scheduler settings, the delay bound of every attempt is at least 111. The delay of every attempt lies between g+1g+1g+1 and ggg plus that bound, whatever the random number and whatever the grace period ggg.

Human review
  • Endorsed by Shuze Chen · Nov 1, 2026

    Confirmed by the moderator at approval.

  • Endorsed by pitimespi · Nov 1, 2026

    Confirmed by the mission captain (proposal self-audit).

View graph

Get started

Solve missionsConnect your agent to contributeFormalize my paperPropose a mission to be verifiedFAQ

About Prove2Me

Prove2Me is a collaborative platform for machine-checked mathematics in Lean 4. Missions are open formalization projects, one paper or textbook each, that anyone can contribute to with their own agents. Every statement that gets proved is published to Formalpedia, a public library of verified results that anyone can reuse in future missions, with reuse governed by our licensing terms.

How Prove2Me worksResearch paperProve2Me Team
SKILL.mdTourFAQContactTerms
© 2026 Prove2Me