|
| 1 | +---------------------- MODULE UpdateSystemWallet ------------------------ |
| 2 | + |
| 3 | +EXTENDS TLC, Integers, Sequences |
| 4 | + |
| 5 | +CONSTANTS launcher_state_depth \* How many state depth we want to check? |
| 6 | + |
| 7 | +(*--algorithm launcher |
| 8 | + variables |
| 9 | + current_launcher_state_depth = launcher_state_depth, |
| 10 | + current_wallet_exit_code = 0, |
| 11 | + update_exists \in {TRUE, FALSE}, |
| 12 | + |
| 13 | + next_state = "update_mode", |
| 14 | + |
| 15 | + wallet_exit_codes = <<>>, |
| 16 | + updater_exit_codes = <<>>, |
| 17 | + |
| 18 | + \* Tracking global state changes |
| 19 | + update_running = FALSE, |
| 20 | + wallet_running = FALSE |
| 21 | + |
| 22 | +define |
| 23 | + IsElementInSeq(el,seq)==\E i \in DOMAIN seq:seq[i]=el |
| 24 | +end define; |
| 25 | + |
| 26 | + |
| 27 | +\* Simply defining the update to be non-deterministic. |
| 28 | +macro update_arrived() begin |
| 29 | + |
| 30 | + either |
| 31 | + update_exists := TRUE; |
| 32 | + or |
| 33 | + update_exists := FALSE; |
| 34 | + end either; |
| 35 | + |
| 36 | +end macro; |
| 37 | + |
| 38 | +macro check_end_state(wallet_exit_codes) begin |
| 39 | + |
| 40 | + (* We always must pass through at least two labels before we end the proceess. *) |
| 41 | + assert Len(wallet_exit_codes) >= 2; |
| 42 | + |
| 43 | + (* We must pass through the "wallet_normal_mode" when running the spec. *) |
| 44 | + assert IsElementInSeq("update_mode", wallet_exit_codes); |
| 45 | + assert IsElementInSeq("wallet_normal_mode", wallet_exit_codes); |
| 46 | + |
| 47 | + goto Done; |
| 48 | + |
| 49 | +end macro; |
| 50 | + |
| 51 | +(* The Wallet process *) |
| 52 | +fair process Wallet = "Wallet" |
| 53 | +begin |
| 54 | + WalletRun: |
| 55 | + await wallet_running /\ next_state \in {"normal_mode", "safe_mode"}; |
| 56 | + |
| 57 | + current_launcher_state_depth := current_launcher_state_depth - 1; |
| 58 | +
|
| 59 | + \* This is before the actual "wallet run", so we can see with which "mode" |
| 60 | + \* was run with. |
| 61 | + if next_state = "normal_mode" then |
| 62 | + wallet_exit_codes := Append(wallet_exit_codes, "wallet_normal_mode"); |
| 63 | + elsif next_state = "safe_mode" then |
| 64 | + wallet_exit_codes := Append(wallet_exit_codes, "wallet_safe_mode"); |
| 65 | + end if; |
| 66 | + |
| 67 | + |
| 68 | + if current_launcher_state_depth <= 0 then |
| 69 | + goto Done; |
| 70 | + else |
| 71 | + either |
| 72 | + current_wallet_exit_code := 0; \* Success |
| 73 | + next_state := "success"; |
| 74 | + |
| 75 | + \* Check the end state |
| 76 | + check_end_state(wallet_exit_codes); |
| 77 | + |
| 78 | + or |
| 79 | + current_wallet_exit_code := 1; \* Failure |
| 80 | + next_state := "failure"; |
| 81 | + |
| 82 | + \* Check the end state |
| 83 | + check_end_state(wallet_exit_codes); |
| 84 | + |
| 85 | + or |
| 86 | + current_wallet_exit_code := 20; \* Update |
| 87 | + next_state := "update_mode"; |
| 88 | + |
| 89 | + goto WalletRun; |
| 90 | + or |
| 91 | + current_wallet_exit_code := 21; \* Safe mode |
| 92 | + next_state := "safe_mode"; |
| 93 | + \* Each time we go into safe mode, we can simulate an update. |
| 94 | + update_arrived(); |
| 95 | + |
| 96 | + goto WalletRun; |
| 97 | + or |
| 98 | + current_wallet_exit_code := 22; \* Normal mode |
| 99 | + next_state := "normal_mode"; |
| 100 | + |
| 101 | + \* Each time we go into safe mode, we can simulate an update. |
| 102 | + update_arrived(); |
| 103 | + |
| 104 | + goto WalletRun; |
| 105 | + end either; |
| 106 | + end if; |
| 107 | +
|
| 108 | +end process; |
| 109 | + |
| 110 | + |
| 111 | +(* The Launcher process *) |
| 112 | +fair process Launcher = "Launcher" |
| 113 | + |
| 114 | +begin |
| 115 | + Update: |
| 116 | + await next_state = "update_mode"; |
| 117 | + |
| 118 | + update_running := TRUE; |
| 119 | + wallet_running := FALSE; |
| 120 | + |
| 121 | + wallet_exit_codes := Append(wallet_exit_codes, "update_mode"); |
| 122 | +
|
| 123 | + if update_exists then |
| 124 | + updater_exit_codes := Append(updater_exit_codes, "updater_success"); |
| 125 | + update_exists := FALSE; |
| 126 | + else |
| 127 | + updater_exit_codes := Append(updater_exit_codes, "updater_failure"); |
| 128 | + end if; |
| 129 | + |
| 130 | + next_state := "normal_mode"; |
| 131 | + \* We have to run the wallet after the update |
| 132 | + |
| 133 | + |
| 134 | + |
| 135 | + Launching: |
| 136 | + |
| 137 | + update_running := FALSE; |
| 138 | + wallet_running := TRUE; |
| 139 | + |
| 140 | + \* The wallet is dictating the states the launcher has to handle. |
| 141 | + if next_state = "success" \/ next_state = "failure" \/ current_launcher_state_depth <= 0 then |
| 142 | + goto Done; |
| 143 | + elsif next_state = "update_mode" then |
| 144 | + goto Update; |
| 145 | + else |
| 146 | + goto Launching; |
| 147 | + end if; |
| 148 | +
|
| 149 | +end process; |
| 150 | + |
| 151 | + |
| 152 | +end algorithm;*) |
| 153 | +\* BEGIN TRANSLATION |
| 154 | +VARIABLES current_launcher_state_depth, current_wallet_exit_code, |
| 155 | + update_exists, next_state, wallet_exit_codes, updater_exit_codes, |
| 156 | + update_running, wallet_running, pc |
| 157 | + |
| 158 | +(* define statement *) |
| 159 | +IsElementInSeq(el,seq)==\E i \in DOMAIN seq:seq[i]=el |
| 160 | + |
| 161 | + |
| 162 | +vars == << current_launcher_state_depth, current_wallet_exit_code, |
| 163 | + update_exists, next_state, wallet_exit_codes, updater_exit_codes, |
| 164 | + update_running, wallet_running, pc >> |
| 165 | + |
| 166 | +ProcSet == {"Wallet"} \cup {"Launcher"} |
| 167 | + |
| 168 | +Init == (* Global variables *) |
| 169 | + /\ current_launcher_state_depth = launcher_state_depth |
| 170 | + /\ current_wallet_exit_code = 0 |
| 171 | + /\ update_exists \in {TRUE, FALSE} |
| 172 | + /\ next_state = "update_mode" |
| 173 | + /\ wallet_exit_codes = <<>> |
| 174 | + /\ updater_exit_codes = <<>> |
| 175 | + /\ update_running = FALSE |
| 176 | + /\ wallet_running = FALSE |
| 177 | + /\ pc = [self \in ProcSet |-> CASE self = "Wallet" -> "WalletRun" |
| 178 | + [] self = "Launcher" -> "Update"] |
| 179 | + |
| 180 | +WalletRun == /\ pc["Wallet"] = "WalletRun" |
| 181 | + /\ wallet_running /\ next_state \in {"normal_mode", "safe_mode"} |
| 182 | + /\ current_launcher_state_depth' = current_launcher_state_depth - 1 |
| 183 | + /\ IF next_state = "normal_mode" |
| 184 | + THEN /\ wallet_exit_codes' = Append(wallet_exit_codes, "wallet_normal_mode") |
| 185 | + ELSE /\ IF next_state = "safe_mode" |
| 186 | + THEN /\ wallet_exit_codes' = Append(wallet_exit_codes, "wallet_safe_mode") |
| 187 | + ELSE /\ TRUE |
| 188 | + /\ UNCHANGED wallet_exit_codes |
| 189 | + /\ IF current_launcher_state_depth' <= 0 |
| 190 | + THEN /\ pc' = [pc EXCEPT !["Wallet"] = "Done"] |
| 191 | + /\ UNCHANGED << current_wallet_exit_code, |
| 192 | + update_exists, next_state >> |
| 193 | + ELSE /\ \/ /\ current_wallet_exit_code' = 0 |
| 194 | + /\ next_state' = "success" |
| 195 | + /\ Assert(Len(wallet_exit_codes') >= 2, |
| 196 | + "Failure of assertion at line 41, column 5 of macro called at line 76, column 17.") |
| 197 | + /\ Assert(IsElementInSeq("update_mode", wallet_exit_codes'), |
| 198 | + "Failure of assertion at line 44, column 5 of macro called at line 76, column 17.") |
| 199 | + /\ Assert(IsElementInSeq("wallet_normal_mode", wallet_exit_codes'), |
| 200 | + "Failure of assertion at line 45, column 5 of macro called at line 76, column 17.") |
| 201 | + /\ pc' = [pc EXCEPT !["Wallet"] = "Done"] |
| 202 | + /\ UNCHANGED update_exists |
| 203 | + \/ /\ current_wallet_exit_code' = 1 |
| 204 | + /\ next_state' = "failure" |
| 205 | + /\ Assert(Len(wallet_exit_codes') >= 2, |
| 206 | + "Failure of assertion at line 41, column 5 of macro called at line 83, column 17.") |
| 207 | + /\ Assert(IsElementInSeq("update_mode", wallet_exit_codes'), |
| 208 | + "Failure of assertion at line 44, column 5 of macro called at line 83, column 17.") |
| 209 | + /\ Assert(IsElementInSeq("wallet_normal_mode", wallet_exit_codes'), |
| 210 | + "Failure of assertion at line 45, column 5 of macro called at line 83, column 17.") |
| 211 | + /\ pc' = [pc EXCEPT !["Wallet"] = "Done"] |
| 212 | + /\ UNCHANGED update_exists |
| 213 | + \/ /\ current_wallet_exit_code' = 20 |
| 214 | + /\ next_state' = "update_mode" |
| 215 | + /\ pc' = [pc EXCEPT !["Wallet"] = "WalletRun"] |
| 216 | + /\ UNCHANGED update_exists |
| 217 | + \/ /\ current_wallet_exit_code' = 21 |
| 218 | + /\ next_state' = "safe_mode" |
| 219 | + /\ \/ /\ update_exists' = TRUE |
| 220 | + \/ /\ update_exists' = FALSE |
| 221 | + /\ pc' = [pc EXCEPT !["Wallet"] = "WalletRun"] |
| 222 | + \/ /\ current_wallet_exit_code' = 22 |
| 223 | + /\ next_state' = "normal_mode" |
| 224 | + /\ \/ /\ update_exists' = TRUE |
| 225 | + \/ /\ update_exists' = FALSE |
| 226 | + /\ pc' = [pc EXCEPT !["Wallet"] = "WalletRun"] |
| 227 | + /\ UNCHANGED << updater_exit_codes, update_running, |
| 228 | + wallet_running >> |
| 229 | + |
| 230 | +Wallet == WalletRun |
| 231 | + |
| 232 | +Update == /\ pc["Launcher"] = "Update" |
| 233 | + /\ next_state = "update_mode" |
| 234 | + /\ update_running' = TRUE |
| 235 | + /\ wallet_running' = FALSE |
| 236 | + /\ wallet_exit_codes' = Append(wallet_exit_codes, "update_mode") |
| 237 | + /\ IF update_exists |
| 238 | + THEN /\ updater_exit_codes' = Append(updater_exit_codes, "updater_success") |
| 239 | + /\ update_exists' = FALSE |
| 240 | + ELSE /\ updater_exit_codes' = Append(updater_exit_codes, "updater_failure") |
| 241 | + /\ UNCHANGED update_exists |
| 242 | + /\ next_state' = "normal_mode" |
| 243 | + /\ pc' = [pc EXCEPT !["Launcher"] = "Launching"] |
| 244 | + /\ UNCHANGED << current_launcher_state_depth, |
| 245 | + current_wallet_exit_code >> |
| 246 | + |
| 247 | +Launching == /\ pc["Launcher"] = "Launching" |
| 248 | + /\ update_running' = FALSE |
| 249 | + /\ wallet_running' = TRUE |
| 250 | + /\ IF next_state = "success" \/ next_state = "failure" \/ current_launcher_state_depth <= 0 |
| 251 | + THEN /\ pc' = [pc EXCEPT !["Launcher"] = "Done"] |
| 252 | + ELSE /\ IF next_state = "update_mode" |
| 253 | + THEN /\ pc' = [pc EXCEPT !["Launcher"] = "Update"] |
| 254 | + ELSE /\ pc' = [pc EXCEPT !["Launcher"] = "Launching"] |
| 255 | + /\ UNCHANGED << current_launcher_state_depth, |
| 256 | + current_wallet_exit_code, update_exists, |
| 257 | + next_state, wallet_exit_codes, updater_exit_codes >> |
| 258 | + |
| 259 | +Launcher == Update \/ Launching |
| 260 | + |
| 261 | +(* Allow infinite stuttering to prevent deadlock on termination. *) |
| 262 | +Terminating == /\ \A self \in ProcSet: pc[self] = "Done" |
| 263 | + /\ UNCHANGED vars |
| 264 | + |
| 265 | +Next == Wallet \/ Launcher |
| 266 | + \/ Terminating |
| 267 | + |
| 268 | +Spec == /\ Init /\ [][Next]_vars |
| 269 | + /\ WF_vars(Wallet) |
| 270 | + /\ WF_vars(Launcher) |
| 271 | + |
| 272 | +Termination == <>(\A self \in ProcSet: pc[self] = "Done") |
| 273 | + |
| 274 | +\* END TRANSLATION |
| 275 | + |
| 276 | +=========================================================================== |
0 commit comments