Skip to content

Commit

Permalink
add TLA+ specs for Disk Paxos
Browse files Browse the repository at this point in the history
  • Loading branch information
banhday committed Feb 18, 2019
1 parent b9505d6 commit 512db7e
Show file tree
Hide file tree
Showing 5 changed files with 311 additions and 5 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Do you have your own case study that you like to share with the community? Send
| 11 | bosco | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/bosco">One-Step Byzantine asynchronous consensus (Song & Renesse, 2008)</a> | Thanh Hai Tran, Igor Konnov, Josef Widder | | &#10004; | Nat, FinSet |
| 12 | Boulangerie | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/Bakery-Boulangerie">A variant of the bakery algorithm (Yoram & Patkin, 2015)</a> | Stephan Merz | &#10004; | &#10004; | Int |
| 13 | byihive | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/byihive">Based on RFC3506 - Requirements and Design for Voucher Trading System (Fujimura & Eastlake) </a> | Santhosh Raju | | &#10004; | default theories |
| 14 | byzpaxos | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/byzpaxos">Byzantizing Paxos by Refinement (Lamport, 2011)</a> | Leslie Lamport? | | &#10004; | Int, FinSet |
| 14 | byzpaxos | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/byzpaxos">Byzantizing Paxos by Refinement (Lamport, 2011)</a> | Leslie Lamport | | &#10004; | Int, FinSet |
| 15 | c1cs | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/c1cs">Consensus in one communication step (Brasileiro et al., 2001)</a> | Thanh Hai Tran, Igor Konnov, Josef Widder | | &#10004; | Int, FinSet |
| 16 | Caesar | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/Caesar">Multi-leader generalized consensus protocol (Arun et al., 2017)</a> | Giuliano Losa | | &#10004; | FinSet, Seq, Int |
| 17 | CarTalkPuzzle | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/CarTalkPuzzle">A TLA+ specification of the solution to a nice puzzle.</a> | | | &#10004; | Int |
Expand All @@ -37,7 +37,7 @@ Do you have your own case study that you like to share with the community? Send
| 23 | detector_chan96 | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/detector_chan96">Chandra and Toueg’s eventually perfect failure detector</a> | Thanh Hai Tran, Igor Konnov, Josef Widder | | &#10004; | Int, FinSet |
| 24 | DieHard | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/DieHard">A very elementary example based on a puzzle from a movie</a> | | | &#10004; | Nat |
| 25 | dijkstra-mutex | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/dijkstra-mutex">Mutual exclusion algorithm (Dijkstra, 1965)</a> | | | &#10004; | Int |
| 26 | diskpaxos | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/diskpaxos">Disk Paxos (Gafni & Lamport, 2003)</a> | Giuliano Losa | | &#10004; | Int |
| 26 | diskpaxos | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/diskpaxos">Disk Paxos (Gafni & Lamport, 2003)</a> | Leslie Lamport, Giuliano Losa | | &#10004; | Int |
| 27 | egalitarian-paxos | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/egalitarian-paxos">Leaderless replication protocol based on Paxos (Moraru et al., 2013)</a> | Iulian Moraru | | &#10004; | Nat, FinSet |
| 28 | ewd840 | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/ewd840">Termination detection in a ring (Dijkstra et al., 1986)</a> | Stephan Merz | &#10004; | &#10004; | Nat |
| 29 | fastpaxos | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/fastpaxos">An extension of the classic Paxos algorithm, only PDF files (Lamport, 2006)</a> | Heidi Howard | | | Nat, FinSet |
Expand All @@ -56,7 +56,7 @@ Do you have your own case study that you like to share with the community? Send
| 42 | nbacc_ray97 | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/nbacc_ray97">Asynchronous non-blocking atomic commit (Raynal, 1997)</a> | Thanh Hai Tran, Igor Konnov, Josef Widder | | &#10004; | Nat, FinSet |
| 43 | nbacg_guer01 | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/nbacg_guer01">On the hardness of failure-sensitive agreement problems (Guerraoui, 2001)</a> | Thanh Hai Tran, Igor Konnov, Josef Widder | | &#10004; | Nat, FinSet |
| 44 | nfc04 | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/nfc04">Non-functional properties of component-based software systems (Zschaler, 2010)</a> | Steffen Zschaler | | &#10004; | Real, Nat |
| 45 | Paxos | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/Paxos">Paxos consensus algorithm (Lamport, 1998)</a> | Leslie Lamport? | | &#10004; | Int, FinSet |
| 45 | Paxos | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/Paxos">Paxos consensus algorithm (Lamport, 1998)</a> | Leslie Lamport | | &#10004; | Int, FinSet |
| 46 | Prisoners | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/Prisoners">A puzzle was presented on an American radio program.</a> | | | &#10004; | Nat, FinSet |
| 47 | raft | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/raft">Raft consensus algorithm (Ongaro, 2014)</a> | Diego Ongaro | | &#10004; | FinSet, Nat, Seq |
| 48 | SnapshotIsolation | <a href="https://github.com/tlaplus/Examples/tree/master/specifications/SnapshotIsolation">Serializable snapshot isolation (Cahill et al., 2010)</a> | Michael J. Cahill, Uwe Röhm, Alan D. Fekete | | &#10004; | FinSet, Int, Seq |
Expand Down
132 changes: 132 additions & 0 deletions specifications/diskpaxos/DiskSynod.tla
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
----------------------------- MODULE DiskSynod -----------------------------

EXTENDS Synod, FiniteSets

CONSTANTS Ballot(_), Disk, IsMajority(_)
ASSUME /\ \A p \in Proc : /\ Ballot(p) \subseteq {n \in Nat : n > 0}
/\ \A q \in Proc \ {p} : Ballot(p) \cap Ballot(q) = {}
/\ IsMajority(Disk)
/\ \A S, T \in SUBSET Disk :
IsMajority(S) /\ IsMajority(T) => (S \cup T # {})

DiskBlock == [mbal : (UNION {Ballot(p) : p \in Proc}) \cup {0},
bal : (UNION {Ballot(p) : p \in Proc}) \cup {0},
inp : Inputs \cup {NotAnInput}]

InitDB == [mbal |-> 0, bal |-> 0, inp |-> NotAnInput]

VARIABLES disk , dblock , phase, disksWritten, blocksRead

vars == <<input, output, disk , phase, dblock , disksWritten, blocksRead>>

Init == /\ input \in [Proc -> Inputs]
/\ output = [p \in Proc |-> NotAnInput]
/\ disk = [d \in Disk |-> [p \in Proc |-> InitDB ]]
/\ phase = [p \in Proc |-> 0]
/\ dblock = [p \in Proc |-> InitDB ]
/\ disksWritten = [p \in Proc |-> {}]
/\ blocksRead = [p \in Proc |-> [d \in Disk |-> {}]]

hasRead (p, d , q) == \E br \in blocksRead [p][d ] : br .proc = q

allBlocksRead(p) ==
LET allRdBlks == UNION {blocksRead [p][d ] : d \in Disk }
IN {br.block : br \in allRdBlks}

InitializePhase(p) ==
/\ disksWritten' = [disksWritten EXCEPT ![p] = {}]
/\ blocksRead' = [blocksRead EXCEPT ![p] = [d \in Disk |-> {}]]

StartBallot(p) ==
/\ phase[p] \in {1, 2}
/\ phase' = [phase EXCEPT ![p] = 1]
/\ \E b \in Ballot(p) : /\ b > dblock [p].mbal
/\ dblock' = [dblock EXCEPT ![p].mbal = b]
/\ InitializePhase(p)
/\ UNCHANGED <<input, output, disk>>

Phase1or2Write(p, d) ==
/\ phase[p] \in {1, 2}
/\ disk' = [disk EXCEPT ![d][p] = dblock[p]]
/\ disksWritten' = [disksWritten EXCEPT ![p] = @ \cup {d}]
/\ UNCHANGED <<input, output, phase, dblock , blocksRead>>

Phase1or2Read (p, d, q) ==
/\ d \in disksWritten[p]
/\ IF disk [d ][q].mbal < dblock [p].mbal
THEN /\ blocksRead' =
[blocksRead EXCEPT
![p][d ] = @ \cup {[block |-> disk [d ][q], proc |-> q]}]
/\ UNCHANGED <<input, output, disk , phase, dblock , disksWritten>>
ELSE StartBallot(p)

EndPhase1or2(p) ==
/\ IsMajority({d \in disksWritten[p] :
\A q \in Proc \ {p} : hasRead (p, d , q)})
/\ \/ /\ phase[p] = 1
/\ dblock' =
[dblock EXCEPT
![p].bal = dblock [p].mbal,
![p].inp =
LET blocksSeen == allBlocksRead(p) \cup {dblock [p]}
nonInitBlks ==
{bs \in blocksSeen : bs.inp # NotAnInput}
maxBlk ==
CHOOSE b \in nonInitBlks :
\A c \in nonInitBlks : b.bal >= c.bal
IN IF nonInitBlks = {} THEN input[p]
ELSE maxBlk .inp ]
/\ UNCHANGED output
\/ /\ phase[p] = 2
/\ output' = [output EXCEPT ![p] = dblock [p].inp]
/\ UNCHANGED dblock
/\ phase' = [phase EXCEPT ![p] = @ + 1]
/\ InitializePhase(p)
/\ UNCHANGED <<input, disk>>

Fail(p) ==
/\ \E ip \in Inputs : input' = [input EXCEPT ![p] = ip]
/\ phase' = [phase EXCEPT ![p] = 0]
/\ dblock' = [dblock EXCEPT ![p] = InitDB]
/\ output' = [output EXCEPT ![p] = NotAnInput]
/\ InitializePhase(p)
/\ UNCHANGED disk

Phase0Read(p, d) ==
/\ phase[p] = 0
/\ blocksRead' = [blocksRead EXCEPT
![p][d ] = @ \cup {[block |-> disk [d][p], proc |-> p]}]
/\ UNCHANGED <<input, output, disk , phase, dblock , disksWritten>>


EndPhase0(p) ==
/\ phase[p] = 0
/\ IsMajority({d \in Disk : hasRead (p, d, p)})
/\ \E b \in Ballot(p) :
/\ \A r \in allBlocksRead (p) : b > r.mbal
/\ dblock' = [dblock EXCEPT
![p] = [(CHOOSE r \in allBlocksRead (p) :
\A s \in allBlocksRead (p) : r .bal >= s.bal)
EXCEPT !.mbal = b]]
/\ InitializePhase(p)
/\ phase' = [phase EXCEPT ![p] = 1]
/\ UNCHANGED <<input, output, disk>>

Next == \E p \in Proc :
\/ StartBallot(p)
\/ \E d \in Disk : \/ Phase0Read (p, d)
\/ Phase1or2Write(p, d)
\/ \E q \in Proc \ {p} : Phase1or2Read (p, d, q)
\/ EndPhase1or2(p)
\/ Fail(p)
\/ EndPhase0(p)

DiskSynodSpec == Init /\ [][Next]_vars

THEOREM DiskSynodSpec => SynodSpec


=============================================================================
\* ModIFication History
\* Last modIFied Sat Jan 26 14:03:35 CET 2019 by tthai
\* Created Sat Jan 26 12:19:05 CET 2019 by tthai
119 changes: 119 additions & 0 deletions specifications/diskpaxos/HDiskSynod.tla
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
----------------------------- MODULE HDiskSynod -----------------------------

EXTENDS DiskSynod
VARIABLES allInput, chosen

HInit == /\ Init
/\ chosen = NotAnInput
/\ allInput = {input[p] : p \in Proc}

HNext == /\ Next
/\ chosen' = LET hasOutput(p) == output'[p] # NotAnInput
IN IF \/ chosen # NotAnInput
\/ \A p \in Proc : ~hasOutput(p)
THEN chosen
ELSE output'[CHOOSE p \in Proc : hasOutput(p)]
/\ allInput' = allInput \cup {input'[p] : p \in Proc}


HInv1 ==
/\ input \in [Proc -> Inputs]
/\ output \in [Proc -> Inputs \cup {NotAnInput}]
/\ disk \in [Disk -> [Proc -> DiskBlock ]]
/\ phase \in [Proc -> 0..3]
/\ dblock \in [Proc -> DiskBlock ]
/\ output \in [Proc -> Inputs \cup {NotAnInput}]
/\ disksWritten \in [Proc -> SUBSET Disk ]
/\ blocksRead \in [Proc -> [Disk -> SUBSET [block : DiskBlock , proc : Proc]]]
/\ allInput \in SUBSET Inputs
/\ chosen \in Inputs \cup {NotAnInput}

MajoritySet == {D \in SUBSET Disk : IsMajority(D)}

blocksOf(p) ==
LET rdBy(q, d) == {br \in blocksRead[q][d] : br.proc = p}
IN {dblock[p]} \cup {disk[d][p] : d \in Disk }
\cup {br.block : br \in UNION{rdBy(q, d) : q \in Proc, d \in Disk}}

allBlocks == UNION {blocksOf(p) : p \in Proc}

HInv2 ==
/\ \A p \in Proc :
\A bk \in blocksOf (p) : /\ bk.mbal \in Ballot(p) \cup {0}
/\ bk.bal \in Ballot(p) \cup {0}
(*/\ (bk.bal = 0) ≡ (bk.inp = NotAnInput)*)
/\ (bk.bal = 0) <=> (bk.inp = NotAnInput)
/\ bk.mbal >= bk.bal
/\ bk.inp \in allInput \cup {NotAnInput}
/\ \A p \in Proc, d \in Disk :
/\ (d \in disksWritten[p]) => /\ phase[p] \in {1, 2}
/\ disk[d][p] = dblock[p]
/\ (phase[p] \in {1, 2}) => /\ (blocksRead [p][d ] # {}) =>
(d \in disksWritten[p])
/\ ~hasRead (p, d, p)
/\ \A p \in Proc :
/\ (phase[p] = 0) => /\ dblock[p] = InitDB
/\ disksWritten[p] = {}
/\ \A d \in Disk : \A br \in blocksRead[p][d] :
/\ br.proc = p
/\ br.block = disk [d ][p]
/\ (phase[p] # 0) => /\ dblock[p].mbal \in Ballot(p)
/\ dblock[p].bal \in Ballot(p) \cup {0}
/\ \A d \in Disk : \A br \in blocksRead [p][d ] :
br.block.mbal < dblock[p].mbal
/\ (phase[p] \in {2, 3}) => (dblock[p].bal = dblock[p].mbal)
/\ output[p] = IF phase[p] = 3 THEN dblock[p].inp ELSE NotAnInput
/\ chosen \in allInput \cup {NotAnInput}
/\ \A p \in Proc : /\ input[p] \in allInput
/\ (chosen = NotAnInput) => (output[p] = NotAnInput)

HInv3 == \A p, q \in Proc, d \in Disk :
/\ phase[p] \in {1, 2}
/\ phase[q] \in {1, 2}
/\ hasRead (p, d, q)
/\ hasRead (q, d, p)
=> \/ [block |-> dblock [q], proc |-> q] \in blocksRead[p][d]
\/ [block |-> dblock [p], proc |-> p] \in blocksRead[q][d]

HInv4 ==
\A p \in Proc :
/\ (phase[p] # 0) =>
/\ \A bk \in blocksOf(p) : dblock[p].mbal >= bk.bal
/\ \A D \in MajoritySet :
\E d \in D : /\ dblock[p].mbal >= disk[d][p].mbal
/\ dblock[p].bal >= disk[d][p].bal
/\ (phase[p] = 1) => (\A bk \in blocksOf(p) : dblock[p].mbal > bk.bal)
/\ (phase[p] \in {2, 3}) =>
(\E D \in MajoritySet : \A d \in D : disk[d][p].mbal = dblock[p].bal)
/\ \A bk \in blocksOf(p) :
\E D \in MajoritySet : \A d \in D : disk[d][p].mbal >= bk.bal

maxBalInp(b, v ) == \A bk \in allBlocks : (bk.bal >= b) => (bk.inp = v)

HInv5 ==
\A p \in Proc :
(phase[p] = 2) => \/ maxBalInp(dblock[p].bal , dblock[p].inp)
\/ \E D \in MajoritySet, q \in Proc :
\A d \in D : /\ disk[d][q].mbal > dblock [p].bal
/\ ~hasRead (p, d , q)

valueChosen(v) ==
\E b \in UNION {Ballot(p) : p \in Proc} :
/\ maxBalInp(b, v)
/\ \E p \in Proc, D \in MajoritySet :
\A d \in D : /\ disk[d][p].bal >= b
/\ \A q \in Proc :
/\ phase[q] = 1
/\ dblock[q].mbal >= b
/\ hasRead(q, d, p)
=> (\E br \in blocksRead[q][d] : br.block.bal >= b)

HInv6 == /\ (chosen # NotAnInput) => valueChosen(chosen)
/\ \A p \in Proc : output[p] \in {chosen, NotAnInput}



=============================================================================
\* Modification History
\* Last modified Sat Jan 26 15:52:41 CET 2019 by tthai
\* Created Sat Jan 26 15:23:57 CET 2019 by tthai
6 changes: 4 additions & 2 deletions specifications/diskpaxos/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#### <a href="https://github.com/nano-o/MultiPaxos/blob/master/DiskPaxos.tla">diskpaxos</a>
- Specification's authors: Giuliano Losa
- TLA<sup>+</sup> specification's authors: Leslie Lamport
- Pluscal specification's authors: Giuliano Losa
- <a href="https://github.com/nano-o/MultiPaxos/blob/master/DiskPaxos.tla">Pluscal files</a>
- First, Lamport wrote the TLA<sup>+</sup> specifications in his paper. Because we could not find Lamport's TLA files, we translated his writing in PDF format to TLA<sup>+</sup> and pushed them in this repository. Later, Losa wrote another specification for this algortihm in Pluscal.
- Original paper: <a href="https://lamport.azurewebsites.net/pubs/disk-paxos.pdf">Gafni, Eli, and Leslie Lamport. Disk paxos. Distributed Computing 16.1 (2003): 1-20.</a>
- Extended modules: Int
- Computation models: crashes, inaccessibility
- Some properties checked with TLC: SynodSpec
- <a href="https://github.com/nano-o/MultiPaxos/blob/master/DiskPaxos.tla">TLA<sup>+</sup> files</a>
53 changes: 53 additions & 0 deletions specifications/diskpaxos/Synod.tla
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
------------------------------- MODULE Synod -------------------------------

EXTENDS Naturals

CONSTANTS N , Inputs
ASSUME (N \in Nat) /\ (N > 0)

Proc == 1..N

NotAnInput == CHOOSE c : c \notin Inputs

VARIABLES input, output

------------------------------- MODULE Inner -------------------------------

VARIABLES allInput, chosen

IInit == /\ input \in [Proc -> Inputs]
/\ output = [p \in Proc |-> NotAnInput]
/\ chosen = NotAnInput
/\ allInput = {input[p] : p \in Proc}

IChoose(p) ==
/\ output[p] = NotAnInput
/\ IF chosen = NotAnInput
THEN \E ip \in allInput : /\ chosen' = ip
/\ output' = [output EXCEPT ![p] = ip]
ELSE /\ output' = [output EXCEPT ![p] = chosen]
/\ UNCHANGED chosen
/\ UNCHANGED <<input, allInput>>

IFail(p) ==
/\ output' = [output EXCEPT ![p] = NotAnInput]
/\ \E ip \in Inputs : /\ input' = [input EXCEPT ![p] = ip]
/\ allInput = allInput \cup {ip}
/\ UNCHANGED chosen

INext == \E p \in Proc : IChoose(p) \/ IFail (p)

ISpec == IInit /\ [][INext]_<<input, output, chosen, allInput>>

=============================================================================

IS(chosen, allInput) == INSTANCE Inner

SynodSpec == \EE chosen, allInput : IS(chosen, allInput)!ISpec



=============================================================================
\* ModIFication History
\* Last modIFied Sat Jan 26 14:27:38 CET 2019 by tthai
\* Created Sat Jan 26 14:17:53 CET 2019 by tthai

0 comments on commit 512db7e

Please sign in to comment.