Skip to content

Preserve votes when term does not change#8094

Open
cjen1-msft wants to merge 4 commits into
mainfrom
cjen1-msft/raft-prevote-double-leader
Open

Preserve votes when term does not change#8094
cjen1-msft wants to merge 4 commits into
mainfrom
cjen1-msft/raft-prevote-double-leader

Conversation

@cjen1-msft

@cjen1-msft cjen1-msft commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • fix same-term step-down so voted_for is only cleared when the observed term actually changes
  • add a deterministic three-node Raft scenario covering the pre-vote double-leader path
  • assert that the delayed second election is rejected, then converge the network for driver liveness

Why this fixes the violation

Pre-vote does not write voted_for, but it preserves any regular vote already cast in the current term. Previously, a same-term unmatched AppendEntries called become_aware_of_new_term() and erased that regular vote even though the term had not changed. This let the same node vote for two different candidates in term 3. Same term is not a new term, so the vote is now preserved; higher-term handling still clears it.

Validation

  • old two-leader assertion goes red with Candidate != Leader and already voted for n[0]
  • fixed scenario passed 20/20 repeated runs
  • all Raft scenarios passed
  • fixed scenario trace validation passed
  • scripts/ci-checks.sh passed

Cjen1 and others added 2 commits July 23, 2026 11:45
Reproduce the same-term election-safety violation where a node retains a peer vote while becoming a pre-vote candidate, then clears and reuses that vote after rejecting an unmatched AppendEntries.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use a three-node network where the single follower is the overlapping voter for both term-3 leaders.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cjen1-msft
cjen1-msft force-pushed the cjen1-msft/raft-prevote-double-leader branch from 2a9ce1a to 18cb608 Compare July 23, 2026 11:45
@cjen1-msft cjen1-msft changed the title Add pre-vote double-leader Raft scenario Add three-node pre-vote double-leader Raft scenario Jul 23, 2026
@cjen1-msft
cjen1-msft changed the base branch from achamayou-test-former-candidate-vote to main July 23, 2026 11:47
@cjen1-msft cjen1-msft changed the title Add three-node pre-vote double-leader Raft scenario Preserve votes when term does not change Jul 23, 2026
Copilot AI review requested due to automatic review settings July 23, 2026 12:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Raft election-safety bug in CCF’s AFT consensus implementation by ensuring voted_for is only cleared when the observed term actually changes (preventing double-voting within a single term). It also adds a deterministic Raft scenario to reproduce the prior double-leader path under pre-vote and assert the corrected behavior.

Changes:

  • Preserve voted_for across same-term step-downs by conditionally clearing it only when current_view changes.
  • Add a new 3-node deterministic Raft scenario that exercises the pre-vote double-leader path and asserts the delayed second election is rejected.
  • Ensure the scenario converges back to liveness after the safety assertion by dropping pending messages and syncing.

Custom instructions used:

  • .github/copilot-instructions.md
  • .github/instructions/reviewing.instructions.md

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/consensus/aft/raft.h Prevents clearing voted_for on same-term transitions by resetting it only when the term actually changes.
tests/raft_scenarios/pre_vote_double_leader Adds a deterministic regression scenario to cover the pre-vote/delayed election path and assert single-leader safety in-term.

Comment thread tests/raft_scenarios/pre_vote_double_leader Outdated
Comment thread src/consensus/aft/raft.h
@eddyashton eddyashton added the run-long-verification Run Long Verification jobs label Jul 23, 2026
@cjen1-msft
cjen1-msft force-pushed the cjen1-msft/raft-prevote-double-leader branch from 5cfd8e2 to 81909b7 Compare July 23, 2026 13:11
Only clear voted_for when become_aware_of_new_term observes an actual term change, and update the pre-vote double-leader scenario to assert the second election is rejected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cjen1-msft
cjen1-msft force-pushed the cjen1-msft/raft-prevote-double-leader branch from 81909b7 to 353fdeb Compare July 23, 2026 13:16
@cjen1-msft
cjen1-msft enabled auto-merge (squash) July 23, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-long-verification Run Long Verification jobs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants