Skip to content

Recovery implementation violates Invariants 8 + 1 #2

Description

@kewbish

(We're researchers from NJU/MSR/UIUC/UBC working on automating system specification in TLA+. We've been using our tool on SwiftPaxos and wanted to contribute our findings back, if the team finds this useful! We understand this is research code and just wanted to confirm if our reports are valid.)

Invariant 8 of the paper (pg 8) states: if a replica sends `Ack` at ballot `b` and `NewLeaderAck` at ballot `b' > b`, it sends `Ack` before `NewLeaderAck`.

The implementation does not seem to order acks in the channel during recovery. For example:

  1. Before recovery, replica enqueues an old-ballot Ack into batcher (e.g. here)
  2. Replica receives NewLeader(b') and enters recovery:
    • handleNewLeader immediately sends NewLeaderAckN here
  3. It seems batcher is not stopped/drained by recovery and continues running (e.g. goroutine loop here)
  4. batcher can still emit an old-ballot Ack afterwards, since there's no filtering of stale ballots in the sender channel itself.

Because producer goroutines race to enqueue into sender, there is no guarantee the old `Ack`s are enqueued before the new ones. It seems that flushing batcher might also be necessary.


Also, when merging the new ballots, there is no equality or conflict check before cmdIds are overwritten here. Because the map iteration orders are unstable per local replica, it is possible commands with different phases across replicas could be overridden.

This seems to violate Invariant 1 (pg 4), which states: any two replicas commit a command with the same set of dependencies. On recovery, two replicas could end up with different dependency phases.

Can you please confirm whether or not this is a valid bug in the system as it is currently implemented?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions