From 3b076d872cfc028d5047aef9fc1d02dc61b0e0f8 Mon Sep 17 00:00:00 2001
From: Robbert Krebbers <mail@robbertkrebbers.nl>
Date: Thu, 6 Oct 2016 10:58:36 +0200
Subject: [PATCH] Prove correctness of counter with contributions.

---
 heap_lang/lib/counter.v | 219 ++++++++++++++++++++++++++++------------
 1 file changed, 153 insertions(+), 66 deletions(-)

diff --git a/heap_lang/lib/counter.v b/heap_lang/lib/counter.v
index a6c91aa29..2b8c7575b 100644
--- a/heap_lang/lib/counter.v
+++ b/heap_lang/lib/counter.v
@@ -1,7 +1,7 @@
 From iris.program_logic Require Export weakestpre.
 From iris.heap_lang Require Export lang.
 From iris.proofmode Require Import tactics.
-From iris.algebra Require Import auth.
+From iris.algebra Require Import frac auth.
 From iris.heap_lang Require Import proofmode notation.
 
 Definition newcounter : val := λ: <>, ref #0.
@@ -12,73 +12,160 @@ Definition inc : val :=
 Definition read : val := λ: "l", !"l".
 Global Opaque newcounter inc get.
 
-(** The CMRA we need. *)
-Class counterG Σ := CounterG { counter_tokG :> inG Σ (authR mnatUR) }.
-Definition counterΣ : gFunctors := #[GFunctor (constRF (authR mnatUR))].
+(** Monotone counter *)
+Class mcounterG Σ := MCounterG { mcounter_inG :> inG Σ (authR mnatUR) }.
+Definition mcounterΣ : gFunctors := #[GFunctor (constRF (authR mnatUR))].
 
-Instance subG_counterΣ {Σ} : subG counterΣ Σ → counterG Σ.
+Instance subG_mcounterΣ {Σ} : subG mcounterΣ Σ → mcounterG Σ.
 Proof. intros [?%subG_inG _]%subG_inv. split; apply _. Qed.
 
-Section proof.
-Context `{!heapG Σ, !counterG Σ} (N : namespace).
-
-Definition counter_inv (γ : gname) (l : loc) : iProp Σ :=
-  (∃ n, own γ (● (n : mnat)) ★ l ↦ #n)%I.
-
-Definition counter (l : loc) (n : nat) : iProp Σ :=
-  (∃ γ, heapN ⊥ N ∧ heap_ctx ∧
-        inv N (counter_inv γ l) ∧ own γ (◯ (n : mnat)))%I.
-
-(** The main proofs. *)
-Global Instance counter_persistent l n : PersistentP (counter l n).
-Proof. apply _. Qed.
-
-Lemma newcounter_spec (R : iProp Σ) Φ :
-  heapN ⊥ N →
-  heap_ctx ★ (∀ l, counter l 0 -★ Φ #l) ⊢ WP newcounter #() {{ Φ }}.
-Proof.
-  iIntros (?) "[#Hh HΦ]". rewrite /newcounter /=. wp_seq. wp_alloc l as "Hl".
-  iVs (own_alloc (● (O:mnat) ⋅ ◯ (O:mnat))) as (γ) "[Hγ Hγ']"; first done.
-  iVs (inv_alloc N _ (counter_inv γ l) with "[Hl Hγ]").
-  { iNext. iExists 0%nat. by iFrame. }
-  iVsIntro. iApply "HΦ". rewrite /counter; eauto 10.
-Qed.
-
-Lemma inc_spec l n (Φ : val → iProp Σ) :
-  counter l n ★ (counter l (S n) -★ Φ #()) ⊢ WP inc #l {{ Φ }}.
-Proof.
-  iIntros "[Hl HΦ]". iLöb as "IH". wp_rec.
-  iDestruct "Hl" as (γ) "(% & #? & #Hinv & Hγf)".
-  wp_bind (! _)%E. iInv N as (c) ">[Hγ Hl]" "Hclose".
-  wp_load. iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c; by iFrame|].
-  iVsIntro. wp_let. wp_op.
-  wp_bind (CAS _ _ _). iInv N as (c') ">[Hγ Hl]" "Hclose".
-  destruct (decide (c' = c)) as [->|].
-  - iDestruct (own_valid_2 with "[$Hγ $Hγf]")
+Section mono_proof.
+  Context `{!heapG Σ, !mcounterG Σ} (N : namespace).
+
+  Definition mcounter_inv (γ : gname) (l : loc) : iProp Σ :=
+    (∃ n, own γ (● (n : mnat)) ★ l ↦ #n)%I.
+
+  Definition mcounter (l : loc) (n : nat) : iProp Σ :=
+    (∃ γ, heapN ⊥ N ∧ heap_ctx ∧
+          inv N (mcounter_inv γ l) ∧ own γ (◯ (n : mnat)))%I.
+
+  (** The main proofs. *)
+  Global Instance mcounter_persistent l n : PersistentP (mcounter l n).
+  Proof. apply _. Qed.
+
+  Lemma newcounter_mono_spec (R : iProp Σ) Φ :
+    heapN ⊥ N →
+    heap_ctx ★ (∀ l, mcounter l 0 -★ Φ #l) ⊢ WP newcounter #() {{ Φ }}.
+  Proof.
+    iIntros (?) "[#Hh HΦ]". rewrite /newcounter /=. wp_seq. wp_alloc l as "Hl".
+    iVs (own_alloc (● (O:mnat) ⋅ ◯ (O:mnat))) as (γ) "[Hγ Hγ']"; first done.
+    iVs (inv_alloc N _ (mcounter_inv γ l) with "[Hl Hγ]").
+    { iNext. iExists 0%nat. by iFrame. }
+    iVsIntro. iApply "HΦ". rewrite /mcounter; eauto 10.
+  Qed.
+
+  Lemma inc_mono_spec l n (Φ : val → iProp Σ) :
+    mcounter l n ★ (mcounter l (S n) -★ Φ #()) ⊢ WP inc #l {{ Φ }}.
+  Proof.
+    iIntros "[Hl HΦ]". iLöb as "IH". wp_rec.
+    iDestruct "Hl" as (γ) "(% & #? & #Hinv & Hγf)".
+    wp_bind (! _)%E. iInv N as (c) ">[Hγ Hl]" "Hclose".
+    wp_load. iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c; by iFrame|].
+    iVsIntro. wp_let. wp_op.
+    wp_bind (CAS _ _ _). iInv N as (c') ">[Hγ Hl]" "Hclose".
+    destruct (decide (c' = c)) as [->|].
+    - iDestruct (own_valid_2 with "[$Hγ $Hγf]")
+        as %[?%mnat_included _]%auth_valid_discrete_2.
+      iVs (own_update_2 with "[$Hγ $Hγf]") as "[Hγ Hγf]".
+      { apply auth_update, (mnat_local_update _ _ (S c)); auto. } 
+      wp_cas_suc. iVs ("Hclose" with "[Hl Hγ]") as "_".
+      { iNext. iExists (S c). rewrite Nat2Z.inj_succ Z.add_1_l. by iFrame. }
+      iVsIntro. wp_if. iApply "HΦ"; iExists γ; repeat iSplit; eauto.
+      iApply (own_mono with "Hγf"). apply: auth_frag_mono.
+      by apply mnat_included, le_n_S.
+    - wp_cas_fail; first (by intros [= ?%Nat2Z.inj]).
+      iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c'; by iFrame|].
+      iVsIntro. wp_if. iApply ("IH" with "[Hγf] HΦ").
+      rewrite {3}/mcounter; eauto 10.
+  Qed.
+
+  Lemma read_mono_spec l j (Φ : val → iProp Σ) :
+    mcounter l j ★ (∀ i, ■ (j ≤ i)%nat → mcounter l i -★ Φ #i)
+    ⊢ WP read #l {{ Φ }}.
+  Proof.
+    iIntros "[Hc HΦ]". iDestruct "Hc" as (γ) "(% & #? & #Hinv & Hγf)".
+    rewrite /read /=. wp_let. iInv N as (c) ">[Hγ Hl]" "Hclose". wp_load.
+    iDestruct (own_valid_2 with "[$Hγ $Hγf]")
       as %[?%mnat_included _]%auth_valid_discrete_2.
     iVs (own_update_2 with "[$Hγ $Hγf]") as "[Hγ Hγf]".
-    { apply auth_update, (mnat_local_update _ _ (S c)); auto. } 
-    wp_cas_suc. iVs ("Hclose" with "[Hl Hγ]") as "_".
-    { iNext. iExists (S c). rewrite Nat2Z.inj_succ Z.add_1_l. by iFrame. }
-    iVsIntro. wp_if. iApply "HΦ"; iExists γ; repeat iSplit; eauto.
-    iApply (own_mono with "Hγf"). apply: auth_frag_mono.
-    by apply mnat_included, le_n_S.
-  - wp_cas_fail; first (by intros [= ?%Nat2Z.inj]).
-    iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c'; by iFrame|].
-    iVsIntro. wp_if. iApply ("IH" with "[Hγf] HΦ"). rewrite {3}/counter; eauto 10.
-Qed.
-
-Lemma read_spec l j (Φ : val → iProp Σ) :
-  counter l j ★ (∀ i, ■ (j ≤ i)%nat → counter l i -★ Φ #i)
-  ⊢ WP read #l {{ Φ }}.
-Proof.
-  iIntros "[Hc HΦ]". iDestruct "Hc" as (γ) "(% & #? & #Hinv & Hγf)".
-  rewrite /read /=. wp_let. iInv N as (c) ">[Hγ Hl]" "Hclose". wp_load.
-  iDestruct (own_valid_2 with "[$Hγ $Hγf]")
-    as %[?%mnat_included _]%auth_valid_discrete_2.
-  iVs (own_update_2 with "[$Hγ $Hγf]") as "[Hγ Hγf]".
-  { apply auth_update, (mnat_local_update _ _ c); auto. }
-  iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c; by iFrame|].
-  iApply ("HΦ" with "[%]"); rewrite /counter; eauto 10.
-Qed.
-End proof.
+    { apply auth_update, (mnat_local_update _ _ c); auto. }
+    iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c; by iFrame|].
+    iApply ("HΦ" with "[%]"); rewrite /mcounter; eauto 10.
+  Qed.
+End mono_proof.
+
+(** Counter with contributions *)
+Class ccounterG Σ :=
+  CCounterG { ccounter_inG :> inG Σ (authR (optionUR (prodR fracR natR))) }.
+Definition ccounterΣ : gFunctors :=
+  #[GFunctor (constRF (authR (optionUR (prodR fracR natR))))].
+
+Instance subG_ccounterΣ {Σ} : subG ccounterΣ Σ → ccounterG Σ.
+Proof. intros [?%subG_inG _]%subG_inv. split; apply _. Qed.
+
+Section contrib_spec.
+  Context `{!heapG Σ, !ccounterG Σ} (N : namespace).
+
+  Definition ccounter_inv (γ : gname) (l : loc) : iProp Σ :=
+    (∃ n, own γ (● Some (1%Qp, n)) ★ l ↦ #n)%I.
+
+  Definition ccounter_ctx (γ : gname) (l : loc) : iProp Σ :=
+    (heapN ⊥ N ∧ heap_ctx ∧ inv N (ccounter_inv γ l))%I.
+
+  Definition ccounter (γ : gname) (q : frac) (n : nat) : iProp Σ :=
+    own γ (◯ Some (q, n)).
+
+  (** The main proofs. *)
+  Lemma ccounter_op γ q1 q2 n1 n2 :
+    ccounter γ (q1 + q2) (n1 + n2) ⊣⊢ ccounter γ q1 n1★ ccounter γ q2 n2.
+  Proof. by rewrite /ccounter -own_op -auth_frag_op. Qed.
+
+  Lemma newcounter_contrib_spec (R : iProp Σ) Φ :
+    heapN ⊥ N →
+    heap_ctx ★ (∀ γ l, ccounter_ctx γ l ★ ccounter γ 1 0 -★ Φ #l)
+    ⊢ WP newcounter #() {{ Φ }}.
+  Proof.
+    iIntros (?) "[#Hh HΦ]". rewrite /newcounter /=. wp_seq. wp_alloc l as "Hl".
+    iVs (own_alloc (● (Some (1%Qp, O%nat)) ⋅ ◯ (Some (1%Qp, 0%nat))))
+      as (γ) "[Hγ Hγ']"; first done.
+    iVs (inv_alloc N _ (ccounter_inv γ l) with "[Hl Hγ]").
+    { iNext. iExists 0%nat. by iFrame. }
+    iVsIntro. iApply "HΦ". rewrite /ccounter_ctx /ccounter; eauto 10.
+  Qed.
+
+  Lemma inc_contrib_spec γ l q n (Φ : val → iProp Σ) :
+    ccounter_ctx γ l ★ ccounter γ q n ★ (ccounter γ q (S n) -★ Φ #())
+    ⊢ WP inc #l {{ Φ }}.
+  Proof.
+    iIntros "(#(%&?&?) & Hγf & HΦ)". iLöb as "IH". wp_rec.
+    wp_bind (! _)%E. iInv N as (c) ">[Hγ Hl]" "Hclose".
+    wp_load. iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c; by iFrame|].
+    iVsIntro. wp_let. wp_op.
+    wp_bind (CAS _ _ _). iInv N as (c') ">[Hγ Hl]" "Hclose".
+    destruct (decide (c' = c)) as [->|].
+    - iVs (own_update_2 with "[$Hγ $Hγf]") as "[Hγ Hγf]".
+      { apply auth_update, option_local_update, prod_local_update_2.
+        apply (nat_local_update _ _ (S c) (S n)); omega. }
+      wp_cas_suc. iVs ("Hclose" with "[Hl Hγ]") as "_".
+      { iNext. iExists (S c). rewrite Nat2Z.inj_succ Z.add_1_l. by iFrame. }
+      iVsIntro. wp_if. by iApply "HΦ".
+    - wp_cas_fail; first (by intros [= ?%Nat2Z.inj]).
+      iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c'; by iFrame|].
+      iVsIntro. wp_if. by iApply ("IH" with "[Hγf] HΦ").
+  Qed.
+
+  Lemma read_contrib_spec γ l q n (Φ : val → iProp Σ) :
+    ccounter_ctx γ l ★ ccounter γ q n ★
+      (∀ c, ■ (n ≤ c)%nat → ccounter γ q n -★ Φ #c)
+    ⊢ WP read #l {{ Φ }}.
+  Proof.
+    iIntros "(#(%&?&?) & Hγf & HΦ)".
+    rewrite /read /=. wp_let. iInv N as (c) ">[Hγ Hl]" "Hclose". wp_load.
+    iDestruct (own_valid_2 with "[$Hγ $Hγf]")
+      as %[[? ?%nat_included]%Some_pair_included_total_2 _]%auth_valid_discrete_2.
+    iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c; by iFrame|].
+    iApply ("HΦ" with "[%]"); rewrite /ccounter; eauto 10.
+  Qed.
+
+  Lemma read_contrib_spec_1 γ l n (Φ : val → iProp Σ) :
+    ccounter_ctx γ l ★ ccounter γ 1 n ★ (ccounter γ 1 n -★ Φ #n)
+    ⊢ WP read #l {{ Φ }}.
+  Proof.
+    iIntros "(#(%&?&?) & Hγf & HΦ)".
+    rewrite /read /=. wp_let. iInv N as (c) ">[Hγ Hl]" "Hclose". wp_load.
+    iDestruct (own_valid_2 with "[$Hγ $Hγf]") as %[Hn _]%auth_valid_discrete_2.
+    apply (Some_included_exclusive _) in Hn as [= ->]%leibniz_equiv; last done.
+    iVs ("Hclose" with "[Hl Hγ]") as "_"; [iNext; iExists c; by iFrame|].
+    by iApply "HΦ".
+  Qed.
+End contrib_spec.
-- 
GitLab