From 4af1c72f8abb90b036463e032dd1e2fda6cd35fc Mon Sep 17 00:00:00 2001
From: Jonas Kastberg Hinrichsen <jihgfee@gmail.com>
Date: Mon, 22 Jan 2024 07:16:44 +0100
Subject: [PATCH] Moved examples to other file. Added naive def of iProto_le

---
 theories/channel/multi_proto.v                | 322 ++----------------
 .../multi_proto_consistency_examples.v        | 293 ++++++++++++++++
 2 files changed, 317 insertions(+), 298 deletions(-)
 create mode 100644 theories/channel/multi_proto_consistency_examples.v

diff --git a/theories/channel/multi_proto.v b/theories/channel/multi_proto.v
index e5507e8..984b84c 100644
--- a/theories/channel/multi_proto.v
+++ b/theories/channel/multi_proto.v
@@ -556,302 +556,17 @@ Lemma iProto_consistent_unfold {Σ V} (ps : gmap nat (iProto Σ V)) :
 Proof.
   apply: (fixpoint_unfold iProto_consistent_pre').
 Qed.
-(* Definition iProto_le {Σ V} (p1 p2 : iProto Σ V) : iProp Σ := *)
-(*   ∀ p3, iProto_consistent p1 p3 -∗ iProto_consistent p2 p3. *)
-(* Arguments iProto_le {_ _} _%proto _%proto. *)
-(* Global Instance: Params (@iProto_le) 2 := {}. *)
-(* Notation "p ⊑ q" := (iProto_le p q) : bi_scope. *)
-
-(* Global Instance iProto_le_ne {Σ V} : NonExpansive2 (@iProto_le Σ V). *)
-(* Proof. solve_proper. Qed. *)
-(* Global Instance iProto_le_proper {Σ V} : Proper ((≡) ==> (≡) ==> (⊣⊢)) (@iProto_le Σ V). *)
-(* Proof. solve_proper. Qed. *)
-
-Definition iProto_example1 {Σ V} : gmap nat (iProto Σ V) :=
-  ∅.
-
-Lemma iProto_example1_consistent {Σ V} :
-  ⊢ iProto_consistent (@iProto_example1 Σ V).
-Proof.
-  rewrite iProto_consistent_unfold.
-  iIntros (i j m1 m2) "Hi Hj".
-  rewrite lookup_total_empty.
-  by rewrite iProto_end_message_equivI.
-Qed.
-
-Definition iProto_example2 `{!invGS Σ} (P : iProp Σ) : gmap nat (iProto Σ Z) :=
-  <[0 := (<(Send 1) @ (x:Z)> MSG x {{ P }} ; END)%proto ]>
-  (<[1 := (<(Recv 0) @ (x:Z)> MSG x {{ P }} ; END)%proto ]>
-   ∅).
-
-Lemma iProto_example2_consistent `{!invGS Σ} (P : iProp Σ) :
-  ⊢ iProto_consistent (@iProto_example2 _ Σ invGS0 P).
-Proof.
-  rewrite iProto_consistent_unfold.
-  rewrite /iProto_example2.
-  iIntros (i j m1 m2) "Hm1 Hm2".
-  destruct i, j.
-  - rewrite !lookup_total_insert.
-    rewrite !iProto_message_equivI.
-    iDestruct "Hm1" as (Hieq) "#Hm1".
-    iDestruct "Hm2" as (Hjeq) "#Hm2".
-    done.
-  - destruct j; last first.
-    { rewrite !lookup_total_insert.
-      rewrite !iProto_message_equivI.
-      iDestruct "Hm1" as (Hieq) "#Hm1". done. }
-    rewrite !lookup_total_insert.
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite !lookup_total_insert.
-    rewrite !iProto_message_equivI.
-    iDestruct "Hm1" as (Hieq) "#Hm1".
-    iDestruct "Hm2" as (Hjeq) "#Hm2".
-    iIntros (v p1) "Hm1'".
-    iSpecialize ("Hm1" $!v (Next p1)).
-    rewrite iMsg_base_eq. simpl.
-    rewrite iMsg_exist_eq. simpl.
-    iRewrite -"Hm1" in "Hm1'".
-    iExists END.
-    iSpecialize ("Hm2" $!v (Next END)).
-    iRewrite -"Hm2".
-    simpl.
-    iDestruct "Hm1'" as (x Heq) "[#Heq HP]".
-    iSplitL.
-    { iExists x. iSplit; [done|]. iFrame. done. }
-    iNext. iRewrite -"Heq".
-    rewrite insert_commute; [|done].
-    rewrite insert_insert.
-    rewrite insert_commute; [|done].
-    rewrite insert_insert.
-    rewrite iProto_consistent_unfold.
-    iIntros (i' j' m1' m2') "Hm1' Hm2'".
-    destruct i'.
-    { rewrite lookup_total_insert.
-      iDestruct (iProto_end_message_equivI with "Hm1'") as "H".
-      done. }
-    destruct i'.
-    { rewrite lookup_total_insert_ne; [|done].
-      rewrite lookup_total_insert.
-      iDestruct (iProto_end_message_equivI with "Hm1'") as "H".
-      done. }
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_alt. simpl.
-    iDestruct (iProto_end_message_equivI with "Hm1'") as "H".
-    done.
-  - destruct i; last first.
-    { rewrite lookup_total_insert_ne; [|done].
-      rewrite lookup_total_insert_ne; [|done].
-      rewrite lookup_total_alt. simpl.
-      iDestruct (iProto_end_message_equivI with "Hm1") as "H".
-      done. }
-    rewrite !lookup_total_insert.
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite !lookup_total_insert.
-    rewrite !iProto_message_equivI.
-    iDestruct "Hm1" as (Hieq) "#Hm1". done.
-  - destruct i.
-    { rewrite lookup_total_insert_ne; [|done].
-      rewrite lookup_total_insert.
-      rewrite !iProto_message_equivI.
-      iDestruct "Hm1" as (Hieq) "#Hm1". done. }
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_alt. simpl.
-    iDestruct (iProto_end_message_equivI with "Hm1") as "H".
-    done.
-Qed.
+Definition iProto_le {Σ V} (i:nat) (p1 p2 : iProto Σ V) : iProp Σ :=
+  ∀ ps, iProto_consistent (<[i:=p1]>ps) -∗ iProto_consistent (<[i:=p2]>ps).
+Arguments iProto_le {_ _} _ _%proto _%proto.
+Global Instance: Params (@iProto_le) 3 := {}.
+(* Notation "p ⊑ q" := (iProto_le i p q) : bi_scope. *)
 
-Definition iProto_example3 `{!invGS Σ}  : gmap nat (iProto Σ Z) :=
-  <[0 := <(Send 1) @ (x:Z)> MSG x ; <(Recv 2)> MSG x; END ]>
-  (<[1 := <(Recv 0) @ (x:Z)> MSG x ; <(Send 2)> MSG x; END ]>
-  (<[2 := <(Recv 1) @ (x:Z)> MSG x ; <(Send 0)> MSG x; END ]>
-    ∅)).
+Global Instance iProto_le_ne {Σ V} n : Proper ((=) ==> (dist n) ==> (dist n) ==> (dist n)) (@iProto_le Σ V).
+Proof. solve_proper. Qed.
+Global Instance iProto_le_proper {Σ V} : Proper ((=) ==> (≡) ==> (≡) ==> (⊣⊢)) (@iProto_le Σ V).
+Proof. solve_proper. Qed.
 
-Lemma iProto_example3_consistent `{!invGS Σ} :
-  ⊢ iProto_consistent (@iProto_example3 _ Σ invGS0).
-Proof.
-  rewrite iProto_consistent_unfold.
-  rewrite /iProto_example3.
-  iIntros (i j m1 m2) "Hm1 Hm2".
-  destruct i; last first.
-  { destruct i.
-    { rewrite lookup_total_insert_ne; [|done].
-      rewrite !lookup_total_insert.
-      rewrite !iProto_message_equivI.
-      by iDestruct "Hm1" as (Hieq) "#Hm1". }
-    destruct i.
-    { rewrite lookup_total_insert_ne; [|done].
-      rewrite lookup_total_insert_ne; [|done].
-      rewrite !iProto_message_equivI.
-      by iDestruct "Hm1" as (Hieq) "#Hm1". }
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_empty=> /=.
-    by rewrite iProto_end_message_equivI. }
-  destruct j.
-  { rewrite !lookup_total_insert.
-    rewrite !iProto_message_equivI.
-    by iDestruct "Hm2" as (Hjeq) "#Hm2". }
-  destruct j; last first.
-  { rewrite !lookup_total_insert.
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_insert_ne; [|done].
-    destruct j.
-    { rewrite !lookup_total_insert.
-      rewrite !iProto_message_equivI.
-      by iDestruct "Hm2" as (Hjeq) "#Hm2". }
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_empty=> /=.
-    by rewrite iProto_end_message_equivI. }
-  rewrite !lookup_total_insert.
-  rewrite lookup_total_insert_ne; [|done].
-  rewrite !lookup_total_insert.
-  rewrite !iProto_message_equivI.
-  iDestruct "Hm1" as (Hieq) "#Hm1".
-  iDestruct "Hm2" as (Hjeq) "#Hm2".
-  iIntros (v p1) "Hm1'".
-  iSpecialize ("Hm1" $!v (Next p1)).
-  rewrite !iMsg_base_eq.
-  rewrite !iMsg_exist_eq.
-  iRewrite -"Hm1" in "Hm1'".
-  iDestruct "Hm1'" as (x Heq) "[#Hm1' _]".
-  iSpecialize ("Hm2" $!v (Next (<Send 2> iMsg_base_def x True END))).
-  iExists (<Send 2> iMsg_base_def x True END).
-  iRewrite -"Hm2".
-  simpl.
-  iSplitL.
-  { iExists x. iSplit; [done|]. iFrame. done. }
-  iNext.
-  rewrite iProto_consistent_unfold.
-  rewrite insert_commute; [|done].
-  rewrite insert_insert.
-  rewrite insert_commute; [|done].
-  rewrite insert_insert.
-  iRewrite -"Hm1'".
-  iClear (m1 m2 Hieq Hjeq p1 v Heq) "Hm1 Hm2 Hm1'".
-  iIntros (i j m1 m2) "Hm1 Hm2".
-  destruct i.
-  { rewrite !lookup_total_insert.
-    rewrite !iProto_message_equivI.
-    by iDestruct "Hm1" as (Hieq) "#Hm1". }
-  rewrite lookup_total_insert_ne; [|done].
-  destruct i; last first.
-  { destruct i.
-    { rewrite lookup_total_insert_ne; [|done].
-      rewrite lookup_total_insert.
-      rewrite !iProto_message_equivI.
-      by iDestruct "Hm1" as (Hieq) "#Hm1". }
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_empty=> /=.
-    by rewrite iProto_end_message_equivI. }
-  rewrite lookup_total_insert.
-  destruct j.
-  { rewrite lookup_total_insert.
-    rewrite !iProto_message_equivI.
-    by iDestruct "Hm2" as (Hjeq) "#Hm2". }
-  rewrite lookup_total_insert_ne; [|done].
-  destruct j.
-  { rewrite lookup_total_insert.
-    rewrite !iProto_message_equivI.
-    by iDestruct "Hm2" as (Hjeq) "#Hm2". }
-  rewrite lookup_total_insert_ne; [|done].
-  destruct j; last first.
-  { rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_empty.
-    by rewrite iProto_end_message_equivI. }
-  rewrite lookup_total_insert.
-  rewrite !iProto_message_equivI.
-  iDestruct "Hm1" as (Hieq) "#Hm1".
-  iDestruct "Hm2" as (Hjeq) "#Hm2".
-  iIntros (v p1) "Hm1'".
-  iSpecialize ("Hm1" $!v (Next p1)).
-  iRewrite -"Hm1" in "Hm1'".
-  iDestruct "Hm1'" as (Heq) "[#Hm1' _]".
-  iSpecialize ("Hm2" $!v (Next (<Send 0> iMsg_base_def x True END))).
-  iExists (<Send 0> iMsg_base_def x True END).
-  iRewrite -"Hm2".
-  simpl.
-  iSplitL.
-  { iExists x. iSplit; [done|]. iFrame. done. }
-  iNext.
-  rewrite iProto_consistent_unfold.
-  rewrite (insert_commute _ 1 2); [|done].
-  rewrite (insert_commute _ 1 0); [|done].
-  rewrite insert_insert.
-  rewrite (insert_commute _ 2 0); [|done].
-  rewrite (insert_commute _ 2 1); [|done].
-  rewrite insert_insert.
-  iRewrite -"Hm1'".
-  iClear (m1 m2 Hieq Hjeq p1 v Heq) "Hm1 Hm2 Hm1'".
-  iIntros (i j m1 m2) "Hm1 Hm2".
-  destruct i.
-  { rewrite !lookup_total_insert.
-    rewrite !iProto_message_equivI.
-    by iDestruct "Hm1" as (Hieq) "#Hm1". }
-  rewrite lookup_total_insert_ne; [|done].
-  destruct i.
-  { rewrite lookup_total_insert.
-    by rewrite iProto_end_message_equivI. }
-  rewrite lookup_total_insert_ne; [|done].
-  destruct i; last first.
-  { rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_empty.
-    by rewrite iProto_end_message_equivI. }
-  rewrite lookup_total_insert.
-  destruct j; last first.
-  { rewrite lookup_total_insert_ne; [|done].
-    destruct j.
-    { rewrite lookup_total_insert.
-      by rewrite iProto_end_message_equivI. }
-    rewrite lookup_total_insert_ne; [|done].
-    destruct j.
-    { rewrite lookup_total_insert.
-      rewrite !iProto_message_equivI.
-      by iDestruct "Hm2" as (Hjeq) "#Hm2". }
-    rewrite lookup_total_insert_ne; [|done].
-    rewrite lookup_total_empty.
-    by rewrite iProto_end_message_equivI. }
-  rewrite lookup_total_insert.
-  rewrite !iProto_message_equivI.
-  iDestruct "Hm1" as (Hieq) "#Hm1".
-  iDestruct "Hm2" as (Hjeq) "#Hm2".
-  iIntros (v p1) "Hm1'".
-  iSpecialize ("Hm1" $!v (Next p1)).
-  iRewrite -"Hm1" in "Hm1'".
-  iDestruct "Hm1'" as (Heq) "[#Hm1' _]".
-  iSpecialize ("Hm2" $!v (Next END)).
-  iExists END.
-  iRewrite -"Hm2".
-  simpl.
-  iSplitL; [done|].
-  rewrite insert_insert.
-  rewrite insert_commute; [|done].
-  rewrite (insert_commute _ 2 1); [|done].
-  rewrite insert_insert.
-  iNext.
-  iRewrite -"Hm1'".
-  rewrite iProto_consistent_unfold.
-  iClear (m1 m2 Hieq Hjeq p1 v Heq) "Hm1 Hm2 Hm1'".
-  iIntros (i j m1 m2) "Hm1 Hm2".
-  destruct i.
-  { rewrite lookup_total_insert.
-    by rewrite !iProto_end_message_equivI. }
-  rewrite lookup_total_insert_ne; [|done].
-  destruct i.
-  { rewrite lookup_total_insert.
-    by rewrite !iProto_end_message_equivI. }
-  rewrite lookup_total_insert_ne; [|done].
-  destruct i.
-  { rewrite lookup_total_insert.
-    by rewrite !iProto_end_message_equivI. }
-  rewrite lookup_total_insert_ne; [|done].
-  rewrite lookup_total_empty.
-  by rewrite iProto_end_message_equivI.
-Qed.
-  
 Record proto_name := ProtName { proto_names : gmap nat gname }.
 Global Instance proto_name_inhabited : Inhabited proto_name :=
   populate (ProtName inhabitant).
@@ -898,6 +613,17 @@ Section proto.
   Implicit Types p pl pr : iProto Σ V.
   Implicit Types m : iMsg Σ V.
 
+  Lemma iProto_consistent_le ps i p1 p2 :
+    ps !! i = Some p1 →
+    iProto_le i p1 p2 -∗
+    iProto_consistent ps -∗
+    iProto_consistent (<[i := p2]>ps).
+  Proof.
+    iIntros (HSome) "Hle".
+    rewrite -{1}(insert_id ps i p1); [|done].
+    iApply "Hle".
+  Qed.
+
   Lemma iProto_consistent_step ps m1 m2 i j v p1 :
     iProto_consistent ps -∗
     ps !!! i ≡ (<(Send j)> m1) -∗
@@ -918,7 +644,7 @@ Section proto.
   Lemma iProto_own_auth_agree γ ps i p :
     iProto_own_auth γ ps -∗ iProto_own_frag γ i p -∗ ▷ (ps !!! i ≡ p).
   Proof.
-    iIntros "H● H◯". 
+    iIntros "H● H◯".
     iDestruct (own_valid_2 with "H● H◯") as "H✓".
     rewrite gmap_view_both_validI.
     iDestruct "H✓" as "[_ [H1 H2]]".
@@ -930,7 +656,7 @@ Section proto.
     rewrite !option_equivI excl_equivI.
     by iNext.
   Qed.
-  
+
   Lemma iProto_own_auth_update γ ps i p p' :
     iProto_own_auth γ ps -∗ iProto_own_frag γ i p ==∗
     iProto_own_auth γ (<[i := p']>ps) ∗ iProto_own_frag γ i p'.
@@ -965,7 +691,7 @@ Section proto.
     iFrame.
     iModIntro.
     rewrite -fmap_insert. iFrame.
-  Qed.      
+  Qed.
 
   Lemma iProto_init ps :
     ▷ iProto_consistent ps -∗
@@ -974,7 +700,7 @@ Section proto.
     iIntros "Hconsistnet".
     iMod iProto_own_auth_alloc as (γ) "[Hauth Hfrags]".
     iExists γ. iFrame. iExists _. iFrame. done.
-  Qed. 
+  Qed.
 
   Lemma iProto_step γ i j m1 m2 p1 v :
     iProto_ctx γ -∗
diff --git a/theories/channel/multi_proto_consistency_examples.v b/theories/channel/multi_proto_consistency_examples.v
new file mode 100644
index 0000000..4863f4a
--- /dev/null
+++ b/theories/channel/multi_proto_consistency_examples.v
@@ -0,0 +1,293 @@
+From iris.algebra Require Import gmap excl_auth gmap_view.
+From iris.proofmode Require Import proofmode.
+From iris.base_logic Require Export lib.iprop.
+From iris.base_logic Require Import lib.own.
+From iris.program_logic Require Import language.
+From actris.channel Require Import multi_proto_model multi_proto.
+Set Default Proof Using "Type".
+Export action.
+
+Definition iProto_example1 {Σ V} : gmap nat (iProto Σ V) :=
+  ∅.
+
+Lemma iProto_example1_consistent {Σ V} :
+  ⊢ iProto_consistent (@iProto_example1 Σ V).
+Proof.
+  rewrite iProto_consistent_unfold.
+  iIntros (i j m1 m2) "Hi Hj".
+  rewrite lookup_total_empty.
+  by rewrite iProto_end_message_equivI.
+Qed.
+
+Definition iProto_example2 `{!invGS Σ} (P : iProp Σ) : gmap nat (iProto Σ Z) :=
+  <[0 := (<(Send 1) @ (x:Z)> MSG x {{ P }} ; END)%proto ]>
+  (<[1 := (<(Recv 0) @ (x:Z)> MSG x {{ P }} ; END)%proto ]>
+   ∅).
+
+Lemma iProto_example2_consistent `{!invGS Σ} (P : iProp Σ) :
+  ⊢ iProto_consistent (@iProto_example2 _ Σ invGS0 P).
+Proof.
+  rewrite iProto_consistent_unfold.
+  rewrite /iProto_example2.
+  iIntros (i j m1 m2) "Hm1 Hm2".
+  destruct i, j.
+  - rewrite !lookup_total_insert.
+    rewrite !iProto_message_equivI.
+    iDestruct "Hm1" as (Hieq) "#Hm1".
+    iDestruct "Hm2" as (Hjeq) "#Hm2".
+    done.
+  - destruct j; last first.
+    { rewrite !lookup_total_insert.
+      rewrite !iProto_message_equivI.
+      iDestruct "Hm1" as (Hieq) "#Hm1". done. }
+    rewrite !lookup_total_insert.
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite !lookup_total_insert.
+    rewrite !iProto_message_equivI.
+    iDestruct "Hm1" as (Hieq) "#Hm1".
+    iDestruct "Hm2" as (Hjeq) "#Hm2".
+    iIntros (v p1) "Hm1'".
+    iSpecialize ("Hm1" $!v (Next p1)).
+    rewrite iMsg_base_eq. simpl.
+    rewrite iMsg_exist_eq. simpl.
+    iRewrite -"Hm1" in "Hm1'".
+    iExists END%proto.
+    iSpecialize ("Hm2" $!v (Next END%proto)).
+    iRewrite -"Hm2".
+    simpl.
+    iDestruct "Hm1'" as (x Heq) "[#Heq HP]".
+    iSplitL.
+    { iExists x. iSplit; [done|]. iFrame. done. }
+    iNext. iRewrite -"Heq".
+    rewrite insert_commute; [|done].
+    rewrite insert_insert.
+    rewrite insert_commute; [|done].
+    rewrite insert_insert.
+    rewrite iProto_consistent_unfold.
+    iIntros (i' j' m1' m2') "Hm1' Hm2'".
+    destruct i'.
+    { rewrite lookup_total_insert.
+      iDestruct (iProto_end_message_equivI with "Hm1'") as "H".
+      done. }
+    destruct i'.
+    { rewrite lookup_total_insert_ne; [|done].
+      rewrite lookup_total_insert.
+      iDestruct (iProto_end_message_equivI with "Hm1'") as "H".
+      done. }
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_alt. simpl.
+    iDestruct (iProto_end_message_equivI with "Hm1'") as "H".
+    done.
+  - destruct i; last first.
+    { rewrite lookup_total_insert_ne; [|done].
+      rewrite lookup_total_insert_ne; [|done].
+      rewrite lookup_total_alt. simpl.
+      iDestruct (iProto_end_message_equivI with "Hm1") as "H".
+      done. }
+    rewrite !lookup_total_insert.
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite !lookup_total_insert.
+    rewrite !iProto_message_equivI.
+    iDestruct "Hm1" as (Hieq) "#Hm1". done.
+  - destruct i.
+    { rewrite lookup_total_insert_ne; [|done].
+      rewrite lookup_total_insert.
+      rewrite !iProto_message_equivI.
+      iDestruct "Hm1" as (Hieq) "#Hm1". done. }
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_alt. simpl.
+    iDestruct (iProto_end_message_equivI with "Hm1") as "H".
+    done.
+Qed.
+
+Definition iProto_example3 `{!invGS Σ}  : gmap nat (iProto Σ Z) :=
+  <[0 := (<(Send 1) @ (x:Z)> MSG x ; <(Recv 2)> MSG x; END)%proto ]>
+  (<[1 := (<(Recv 0) @ (x:Z)> MSG x ; <(Send 2)> MSG x; END)%proto ]>
+  (<[2 := (<(Recv 1) @ (x:Z)> MSG x ; <(Send 0)> MSG x; END)%proto ]>
+    ∅)).
+
+Lemma iProto_example3_consistent `{!invGS Σ} :
+  ⊢ iProto_consistent (@iProto_example3 _ Σ invGS0).
+Proof.
+  rewrite iProto_consistent_unfold.
+  rewrite /iProto_example3.
+  iIntros (i j m1 m2) "Hm1 Hm2".
+  destruct i; last first.
+  { destruct i.
+    { rewrite lookup_total_insert_ne; [|done].
+      rewrite !lookup_total_insert.
+      rewrite !iProto_message_equivI.
+      by iDestruct "Hm1" as (Hieq) "#Hm1". }
+    destruct i.
+    { rewrite lookup_total_insert_ne; [|done].
+      rewrite lookup_total_insert_ne; [|done].
+      rewrite !iProto_message_equivI.
+      by iDestruct "Hm1" as (Hieq) "#Hm1". }
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_empty=> /=.
+    by rewrite iProto_end_message_equivI. }
+  destruct j.
+  { rewrite !lookup_total_insert.
+    rewrite !iProto_message_equivI.
+    by iDestruct "Hm2" as (Hjeq) "#Hm2". }
+  destruct j; last first.
+  { rewrite !lookup_total_insert.
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_insert_ne; [|done].
+    destruct j.
+    { rewrite !lookup_total_insert.
+      rewrite !iProto_message_equivI.
+      by iDestruct "Hm2" as (Hjeq) "#Hm2". }
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_empty=> /=.
+    by rewrite iProto_end_message_equivI. }
+  rewrite !lookup_total_insert.
+  rewrite lookup_total_insert_ne; [|done].
+  rewrite !lookup_total_insert.
+  rewrite !iProto_message_equivI.
+  iDestruct "Hm1" as (Hieq) "#Hm1".
+  iDestruct "Hm2" as (Hjeq) "#Hm2".
+  iIntros (v p1) "Hm1'".
+  iSpecialize ("Hm1" $!v (Next p1)).
+  rewrite !iMsg_base_eq.
+  rewrite !iMsg_exist_eq.
+  iRewrite -"Hm1" in "Hm1'".
+  iDestruct "Hm1'" as (x Heq) "[#Hm1' _]".
+  iSpecialize ("Hm2" $!v (Next (<Send 2> iMsg_base_def x True END)))%proto.
+  iExists (<Send 2> iMsg_base_def x True END)%proto.
+  iRewrite -"Hm2".
+  simpl.
+  iSplitL.
+  { iExists x. iSplit; [done|]. iFrame. done. }
+  iNext.
+  rewrite iProto_consistent_unfold.
+  rewrite insert_commute; [|done].
+  rewrite insert_insert.
+  rewrite insert_commute; [|done].
+  rewrite insert_insert.
+  iRewrite -"Hm1'".
+  iClear (m1 m2 Hieq Hjeq p1 v Heq) "Hm1 Hm2 Hm1'".
+  iIntros (i j m1 m2) "Hm1 Hm2".
+  destruct i.
+  { rewrite !lookup_total_insert.
+    rewrite !iProto_message_equivI.
+    by iDestruct "Hm1" as (Hieq) "#Hm1". }
+  rewrite lookup_total_insert_ne; [|done].
+  destruct i; last first.
+  { destruct i.
+    { rewrite lookup_total_insert_ne; [|done].
+      rewrite lookup_total_insert.
+      rewrite !iProto_message_equivI.
+      by iDestruct "Hm1" as (Hieq) "#Hm1". }
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_empty=> /=.
+    by rewrite iProto_end_message_equivI. }
+  rewrite lookup_total_insert.
+  destruct j.
+  { rewrite lookup_total_insert.
+    rewrite !iProto_message_equivI.
+    by iDestruct "Hm2" as (Hjeq) "#Hm2". }
+  rewrite lookup_total_insert_ne; [|done].
+  destruct j.
+  { rewrite lookup_total_insert.
+    rewrite !iProto_message_equivI.
+    by iDestruct "Hm2" as (Hjeq) "#Hm2". }
+  rewrite lookup_total_insert_ne; [|done].
+  destruct j; last first.
+  { rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_empty.
+    by rewrite iProto_end_message_equivI. }
+  rewrite lookup_total_insert.
+  rewrite !iProto_message_equivI.
+  iDestruct "Hm1" as (Hieq) "#Hm1".
+  iDestruct "Hm2" as (Hjeq) "#Hm2".
+  iIntros (v p1) "Hm1'".
+  iSpecialize ("Hm1" $!v (Next p1)).
+  iRewrite -"Hm1" in "Hm1'".
+  iDestruct "Hm1'" as (Heq) "[#Hm1' _]".
+  iSpecialize ("Hm2" $!v (Next (<Send 0> iMsg_base_def x True END)))%proto.
+  iExists (<Send 0> iMsg_base_def x True END)%proto.
+  iRewrite -"Hm2".
+  simpl.
+  iSplitL.
+  { iExists x. iSplit; [done|]. iFrame. done. }
+  iNext.
+  rewrite iProto_consistent_unfold.
+  rewrite (insert_commute _ 1 2); [|done].
+  rewrite (insert_commute _ 1 0); [|done].
+  rewrite insert_insert.
+  rewrite (insert_commute _ 2 0); [|done].
+  rewrite (insert_commute _ 2 1); [|done].
+  rewrite insert_insert.
+  iRewrite -"Hm1'".
+  iClear (m1 m2 Hieq Hjeq p1 v Heq) "Hm1 Hm2 Hm1'".
+  iIntros (i j m1 m2) "Hm1 Hm2".
+  destruct i.
+  { rewrite !lookup_total_insert.
+    rewrite !iProto_message_equivI.
+    by iDestruct "Hm1" as (Hieq) "#Hm1". }
+  rewrite lookup_total_insert_ne; [|done].
+  destruct i.
+  { rewrite lookup_total_insert.
+    by rewrite iProto_end_message_equivI. }
+  rewrite lookup_total_insert_ne; [|done].
+  destruct i; last first.
+  { rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_empty.
+    by rewrite iProto_end_message_equivI. }
+  rewrite lookup_total_insert.
+  destruct j; last first.
+  { rewrite lookup_total_insert_ne; [|done].
+    destruct j.
+    { rewrite lookup_total_insert.
+      by rewrite iProto_end_message_equivI. }
+    rewrite lookup_total_insert_ne; [|done].
+    destruct j.
+    { rewrite lookup_total_insert.
+      rewrite !iProto_message_equivI.
+      by iDestruct "Hm2" as (Hjeq) "#Hm2". }
+    rewrite lookup_total_insert_ne; [|done].
+    rewrite lookup_total_empty.
+    by rewrite iProto_end_message_equivI. }
+  rewrite lookup_total_insert.
+  rewrite !iProto_message_equivI.
+  iDestruct "Hm1" as (Hieq) "#Hm1".
+  iDestruct "Hm2" as (Hjeq) "#Hm2".
+  iIntros (v p1) "Hm1'".
+  iSpecialize ("Hm1" $!v (Next p1)).
+  iRewrite -"Hm1" in "Hm1'".
+  iDestruct "Hm1'" as (Heq) "[#Hm1' _]".
+  iSpecialize ("Hm2" $!v (Next END))%proto.
+  iExists END%proto.
+  iRewrite -"Hm2".
+  simpl.
+  iSplitL; [done|].
+  rewrite insert_insert.
+  rewrite insert_commute; [|done].
+  rewrite (insert_commute _ 2 1); [|done].
+  rewrite insert_insert.
+  iNext.
+  iRewrite -"Hm1'".
+  rewrite iProto_consistent_unfold.
+  iClear (m1 m2 Hieq Hjeq p1 v Heq) "Hm1 Hm2 Hm1'".
+  iIntros (i j m1 m2) "Hm1 Hm2".
+  destruct i.
+  { rewrite lookup_total_insert.
+    by rewrite !iProto_end_message_equivI. }
+  rewrite lookup_total_insert_ne; [|done].
+  destruct i.
+  { rewrite lookup_total_insert.
+    by rewrite !iProto_end_message_equivI. }
+  rewrite lookup_total_insert_ne; [|done].
+  destruct i.
+  { rewrite lookup_total_insert.
+    by rewrite !iProto_end_message_equivI. }
+  rewrite lookup_total_insert_ne; [|done].
+  rewrite lookup_total_empty.
+  by rewrite iProto_end_message_equivI.
+Qed.
-- 
GitLab