// lesson: leader-election

Leader Election

When a candidate starts an election it sends a RequestVote RPC to every other server in parallel. Figure 2 gives the arguments:

// RequestVote RPC (Figure 2)
// Arguments:
//   term          candidate's term
//   candidateId   candidate requesting vote
//   lastLogIndex  index of candidate's last log entry (§5.4)
//   lastLogTerm   term of candidate's last log entry (§5.4)
// Results:
//   term          currentTerm, for candidate to update itself
//   voteGranted   true means candidate received vote

The receiver's side is what you implement in this challenge. Figure 2's "RequestVote RPC, Receiver implementation" is only two lines, but every clause matters:

  1. Reply false if term < currentTerm (§5.1).
  2. If votedFor is null or candidateId, and candidate's log is at least as up-to-date as receiver's log, grant vote (§5.2, §5.4).

At most one vote per term

votedFor records who this server voted for in the current term. Each server gives out at most one vote per term, first-come-first-served, which is what makes two leaders in one term impossible: two candidates would each need a majority, and majorities overlap. Note the "or candidateId" clause — if the same candidate asks twice (a retransmitted RPC), the vote is granted again. Granting a vote is idempotent, not a second vote.

Whenever currentTerm changes (rule "All Servers" from lesson 1), votedFor resets to none: a new term is a fresh ballot.

In the paper currentTerm, votedFor, and the log are persistent state — a real server must fsync them before answering an RPC, or a reboot could let it vote twice in one term. Our in-memory structs stand in for that durable state.

The up-to-dateness check (§5.4.1)

The log check is Raft's election-time safety filter: a candidate cannot win unless its log is at least as up-to-date as a majority of voters, which guarantees the winner already holds every committed entry (the Leader Completeness Property). "Up-to-date" is defined precisely:

If the logs have last entries with different terms, then the log with the later term is more up-to-date. If the logs end with the same term, then whichever log is longer is more up-to-date.

Compare last log term first, then last log index. A short log ending in a high term beats a long log ending in a low term.

Indexing convention

The paper numbers log entries from 1. We keep that: Raft index i lives at Log[i-1], the last index is len(Log), and an empty log has last index 0 and last term 0. This convention holds for the rest of the course.

Handle RequestVote

30 pts

Implement HandleRequestVote exactly per Figure 2. It mutates the receiver's state in place and returns the reply.

Order of operations:

  1. If args.Term > s.CurrentTerm: set CurrentTerm = args.Term, become Follower, reset VotedFor = -1. This happens even if the vote is then refused for log reasons.
  2. Reply false if args.Term < s.CurrentTerm. The reply's Term is always the (possibly just-updated) CurrentTerm.
  3. Grant the vote only if VotedFor is -1 or already args.CandidateID, and the candidate's log is at least as up-to-date as ours: compare args.LastLogTerm against our last log term, breaking ties with args.LastLogIndex against our last log index (candidate wins ties).
  4. On granting, record VotedFor = args.CandidateID.

HandleRequestVote never modifies the log.

Log in to submit a solution and earn points.