-
Notifications
You must be signed in to change notification settings - Fork 4
/
MVDS.tla
125 lines (104 loc) · 5.36 KB
/
MVDS.tla
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
------------------------------- MODULE MVDS ---------------------------------
(***************************************************************************)
(* TLA+ specification of Minimum Viable Data Synchronization *)
(* https://specs.vac.dev/mvds.html *)
(***************************************************************************)
EXTENDS Naturals, Sequences
CONSTANTS N \* the set of all possible nodes
Node == 1 .. N \* the nodes participating
VARIABLES state, \* the state of every node
network \* the network with which nodes pass messages to each other
\* add retransmissions
\* retransmissions will require better usage of state
State == { "-", "offered", "delivered" }
(***************************************************************************)
(* Messages used in MVDS *)
(***************************************************************************)
OFFER == "offer"
REQUEST == "request"
MSG == "msg"
ACK == "ack"
OfferMessage(msg) == [type |-> OFFER, id |-> msg]
RequestMessage(msg) == [type |-> REQUEST, id |-> msg]
MsgMessage(msg) == [type |-> MSG, id |-> msg]
AckMessage(msg) == [type |-> ACK, id |-> msg]
Message ==
{OfferMessage(msg) : msg \in Node} \union
{RequestMessage(msg) : msg \in Node} \union
{MsgMessage(msg) : msg \in Node} \union
{AckMessage(msg) : msg \in Node}
(***************************************************************************)
(* The type correctness predicate. *)
(***************************************************************************)
TypeOK ==
/\ network \in [Node -> [Node -> Seq(Message)]]
/\ state \in [Node -> [Node -> State]]
(***************************************************************************)
(* The initial state predicate. *)
(***************************************************************************)
Init ==
/\ network = [s \in Node |-> [r \in Node |-> <<>> ]]
/\ state = [s \in Node |-> [r \in Node |-> "-" ]]
(***************************************************************************)
(* Node `n` sends an offer to `r` *)
(***************************************************************************)
Offer(n, r) ==
/\ state[n][r] = "-"
/\ network' = [network EXCEPT ![n][r] = Append(@, OfferMessage(n))]
/\ state' = [state EXCEPT ![n][r] = "offered"]
(***************************************************************************)
(* Node `n` receives an offer from `s` *)
(***************************************************************************)
ReceiveOffer(n, s) ==
/\ network[s][n] # << >>
/\ LET m == Head(network[s][n])
IN /\ m.type = OFFER
/\ network' = [network EXCEPT ![s][n] = Tail(@),
![n][s] = Append(@, RequestMessage(s))]
/\ UNCHANGED state
(***************************************************************************)
(* Node `n` receives a request from `s` *)
(***************************************************************************)
ReceiveRequest(n, s) ==
/\ network[s][n] # << >>
/\ LET m == Head(network[s][n])
IN /\ m.type = REQUEST
/\ network' = [network EXCEPT ![s][n] = Tail(@),
![n][s] = Append(@, MsgMessage(n))]
/\ UNCHANGED state
(***************************************************************************)
(* Node `n` receives a message from `s` *)
(***************************************************************************)
ReceiveMessage(n, s) ==
/\ network[s][n] # << >>
/\ LET m == Head(network[s][n])
IN /\ m.type = MSG
/\ network' = [network EXCEPT ![s][n] = Tail(@),
![n][s] = Append(@, AckMessage(s))]
/\ UNCHANGED state
(***************************************************************************)
(* Node `n` receives a ack from `s` *)
(***************************************************************************)
ReceiveAck(n, s) ==
/\ network[s][n] # << >>
/\ LET m == Head(network[s][n])
IN /\ m.type = ACK
/\ network' = [network EXCEPT ![s][n] = Tail(@)]
/\ state' = [state EXCEPT ![s][n] = "delivered"]
(***************************************************************************)
(* Next-state relation. *)
(***************************************************************************)
Next ==
\/ \E n \in Node : \E s \in Node \ {n} :
Offer(n, s) \/ ReceiveOffer(n, s) \/ ReceiveRequest(n, s) \/
ReceiveMessage(n, s) \/ ReceiveAck(n, s)
vars == <<network, state>>
Spec == Init /\ [][Next]_vars
-----------------------------------------------------------------------------
(***************************************************************************)
(* A state constraint useful for validating the specification, *)
(* asserts that all messages are delivered. *)
(***************************************************************************)
AllMessagesDelivered ==
/\ \A n \in Node : \A s \in Node \ {n} : state[n][s] # "delivered"
=============================================================================