▶<3>6Cardinality(Server) \in Nat BY <3>1, FS_CardinalityType3/3tlapm
#52L1053:41:1053:43provedsmtcached
#53L1053:44:1053:48trivialtlapm
#54L1053:50:1053:68trivialtlapm
▶<3>7Cardinality(Q1) \in Nat /\ Cardinality(Q2) \in Nat BY <3>4, FS_CardinalityType3/3tlapm
#55L1054:64:1054:66provedsmtcached
#56L1054:67:1054:71trivialtlapm
#57L1054:73:1054:91trivialtlapm
▶<3>8Cardinality(Q1) + Cardinality(Q2) > Cardinality(Server) BY <3>5, <3>6, <3>74/4tlapm
#58L1055:69:1055:71provedsmtcached
#59L1055:72:1055:76trivialtlapm
#60L1055:78:1055:82trivialtlapm
#61L1055:84:1055:88trivialtlapm
▶<3>.QED BY <3>1, <3>3, <3>8, FS_MajoritiesIntersect5/5tlapm
#38L1056:16:1056:18provedsmtcached
#39L1056:19:1056:23trivialtlapm
#40L1056:25:1056:29trivialtlapm
#41L1056:31:1056:35trivialtlapm
#42L1056:37:1056:59trivialtlapm
▶<2>.SUFFICES: show for any primary s in post-state, all committed entries with smaller terms are in log'[s]SUFFICES ASSUME NEW s \in Server, state'[s] = Primary,2/2smt
#62L1060:41:1060:43provedsmtcached
#63L1060:44:1060:48trivialtlapm
▶<2>6Case s # leader: s was already primary, use induction hypothesisCASE s # leader20/20tlapm
▶<3>1state[s] = Primary BY <2>6, <2>2, A74/4tlapm
#67L1063:32:1063:34provedsmtcached
#68L1063:35:1063:39trivialtlapm
#69L1063:41:1063:45trivialtlapm
#70L1063:47:1063:49trivialtlapm
▶<3>2s \notin voteQ BY <2>6, <2>2, <3>1, A75/5tlapm
#71L1064:28:1064:30provedsmtcached
#72L1064:31:1064:35trivialtlapm
#73L1064:37:1064:41trivialtlapm
#74L1064:43:1064:47trivialtlapm
#75L1064:49:1064:51trivialtlapm
▶<3>3currentTerm'[s] = currentTerm[s] BY <3>2, <2>33/3tlapm
#76L1065:46:1065:48provedsmtcached
#77L1065:49:1065:53trivialtlapm
#78L1065:55:1065:59trivialtlapm
▶<3>4c[2] < currentTerm[s] BY <3>32/2smt
#79L1066:35:1066:37provedsmtcached
#80L1066:38:1066:42trivialtlapm
▶<3>5InLog(<<c[1],c[2]>>, s) BY <3>1, <3>4 DEF H_LeaderCompleteness3/3tlapm
#81L1067:37:1067:39provedsmtcached
#82L1067:40:1067:44trivialtlapm
#83L1067:46:1067:50trivialtlapm
▶<3>.QED BY <3>5, <2>1 DEF InLog3/3tlapm
#64L1068:16:1068:18provedsmtcached
#65L1068:19:1068:23trivialtlapm
#66L1068:25:1068:29trivialtlapm
▶<2>7Case s = leader: the new primary must have all committed entriesCASE s = leader241/241tlapm
▶<3>0currentTerm'[leader] = currentTerm[leader]+1 since leader ∈ voteQcurrentTerm'[leader] = currentTerm[leader] + 1 BY <2>3, <2>43/3tlapm
▶<3>1c[2] < currentTerm[leader] + 1 BY <2>7, <3>03/3tlapm
#93L1076:44:1076:46provedsmtcached
#94L1076:47:1076:51trivialtlapm
#95L1076:53:1076:57trivialtlapm
▶<3>2From H_CommittedEntryIsOnQuorum, get quorum Qc where everyone has InLog(c, n)PICK Qc \in Quorums(Server) : \A n \in Qc : InLog(<<c[1],c[2]>>, n)1/1smt
#96L1079:9:1079:11provedsmtcached
▶<3>3Qc and voteQ intersectQc \cap voteQ # {} BY <2>qi2/2smt
#97L1081:32:1081:34provedsmtcached
#98L1081:35:1081:40trivialtlapm
▶<3>4PICK w \in Qc \cap voteQ : TRUE BY <3>32/2smt
#99L1082:45:1082:47provedsmtcached
#100L1082:48:1082:52trivialtlapm
▶<3>5InLog(<<c[1],c[2]>>, w) BY <3>4, <3>23/3tlapm
#101L1083:37:1083:39provedsmtcached
#102L1083:40:1083:44trivialtlapm
#103L1083:46:1083:50trivialtlapm
▶<3>6CanVoteForOplog(w, leader, currentTerm[leader] + 1) BY <3>4, <2>53/3tlapm
#104L1084:65:1084:67provedsmtcached
#105L1084:68:1084:72trivialtlapm
#106L1084:74:1084:78trivialtlapm
▶<3>7Expand InLog for wPICK xw \in DOMAIN log[w] : xw = c[1] /\ log[w][xw] = c[2] BY <3>5 DEF InLog2/2smt
#107L1086:72:1086:74provedsmtcached
#108L1086:75:1086:79trivialtlapm
▶<3>8c[1] \in DOMAIN log[w] /\ log[w][c[1]] = c[2] BY <3>72/2smt
#109L1087:59:1087:61provedsmtcached
#110L1087:62:1087:66trivialtlapm
▶<3>9w \in Server BY <3>4, A4 DEF Quorums3/3tlapm
#111L1088:26:1088:28provedsmtcached
#112L1088:29:1088:33trivialtlapm
#113L1088:35:1088:37trivialtlapm
▶<3>10CanVoteForOplog means: LastTerm(log[leader]) > LastTerm(log[w]) OR (equal and longer)LET logOk == \/ LastTerm(log[leader]) > LastTerm(log[w])2/2smt
▶<3>15Case B: equal last terms and leader's log at least as longCASE LastTerm(log[leader]) = LastTerm(log[w]) /\ Len(log[leader]) >= Len(log[w])158/158tlapm
▶<4>1Sub-case B1: LastTerm(log[w]) > c[2] - same as Case ACASE LastTerm(log[w]) > c[2]32/32tlapm
▶<5>1LastTerm(log[leader]) > c[2] BY <3>15, <4>13/3tlapm
#176L1134:46:1134:48provedsmtcached
#177L1134:49:1134:54trivialtlapm
#178L1134:56:1134:60trivialtlapm
▶<5>2~Empty(log[leader])5/5tlapm
▶<6>1Empty(log[leader]) => LastTerm(log[leader]) = 0 BY DEF LastTerm, Empty1/1smt
#183L1136:67:1136:69provedsmtcached
▶<6>.QED BY <6>1, <5>1, <3>ct4/4tlapm
#179L1137:22:1137:24provedsmtcached
#180L1137:25:1137:29trivialtlapm
#181L1137:31:1137:35trivialtlapm
#182L1137:37:1137:42trivialtlapm
▶<5>2aLen(log[leader]) > 0 BY <5>2 DEF Empty2/2smt
#184L1138:39:1138:41provedsmtcached
#185L1138:42:1138:46trivialtlapm
▶<5>3Len(log[leader]) \in DOMAIN log[leader] BY <5>2a DEF TypeOK2/2smt
#186L1139:57:1139:59provedsmtcached
#187L1139:60:1139:65trivialtlapm
▶<5>4log[leader][Len(log[leader])] > c[2] BY <5>1, <5>2 DEF LastTerm, Empty3/3tlapm
▶<3>6Cardinality(Server) \in Nat BY <3>1, FS_CardinalityType3/3tlapm
#346L1245:41:1245:43provedsmtcached
#347L1245:44:1245:48trivialtlapm
#348L1245:50:1245:68trivialtlapm
▶<3>7Cardinality(Q1) \in Nat /\ Cardinality(Q2) \in Nat BY <3>4, FS_CardinalityType3/3tlapm
#349L1246:64:1246:66provedsmtcached
#350L1246:67:1246:71trivialtlapm
#351L1246:73:1246:91trivialtlapm
▶<3>8Cardinality(Q1) + Cardinality(Q2) > Cardinality(Server) BY <3>5, <3>6, <3>74/4tlapm
#352L1247:69:1247:71provedsmtcached
#353L1247:72:1247:76trivialtlapm
#354L1247:78:1247:82trivialtlapm
#355L1247:84:1247:88trivialtlapm
▶<3>.QED BY <3>1, <3>3, <3>8, FS_MajoritiesIntersect5/5tlapm
#332L1248:16:1248:18provedsmtcached
#333L1248:19:1248:23trivialtlapm
#334L1248:25:1248:29trivialtlapm
#335L1248:31:1248:35trivialtlapm
#336L1248:37:1248:59trivialtlapm
▶<2>3The commit quorum all have term = currentTerm[p]ImmediatelyCommitted(<<Len(log[p]), currentTerm[p]>>, commitQ) BY DEF CommitEntry1/1smt
#356L1250:74:1250:76provedsmtcached
▶<2>4\A n \in commitQ : currentTerm[n] = currentTerm[p] BY <2>3 DEF ImmediatelyCommitted2/2smt
#357L1251:62:1251:64provedsmtcached
#358L1251:65:1251:69trivialtlapm
▶<2>5For any primary s with currentTerm[s] > currentTerm[p], contradiction via quorum intersection\A s \in Server : state[s] = Primary /\ currentTerm[s] > currentTerm[p] => FALSE16/16tlapm
▶<3>.SUFFICES ASSUME NEW s \in Server, state[s] = Primary, currentTerm[s] > currentTerm[p] PROVE FALSE OBVIOUS1/1smt
▶<2>.Main proof: for all primaries s, all committed entries in post-state with smaller terms are in logSUFFICES ASSUME NEW s \in Server, state'[s] = Primary,1/1smt