From 8cd2308c8fb995d4b938505ffa59fc0c283e54c3 Mon Sep 17 00:00:00 2001
From: dsac <arnaud@dabyseesaram.info>
Date: Tue, 28 Jun 2022 14:26:35 +0200
Subject: [PATCH] model definition

---
 aneris/examples/crdt/statelib/spec/model.v    |  78 -----
 .../examples/crdt/statelib/user_model/model.v | 127 +++++++
 .../examples/crdt/statelib/user_model/spec.v  | 313 ++++++++++++++++++
 3 files changed, 440 insertions(+), 78 deletions(-)
 delete mode 100644 aneris/examples/crdt/statelib/spec/model.v
 create mode 100644 aneris/examples/crdt/statelib/user_model/model.v
 create mode 100644 aneris/examples/crdt/statelib/user_model/spec.v

diff --git a/aneris/examples/crdt/statelib/spec/model.v b/aneris/examples/crdt/statelib/spec/model.v
deleted file mode 100644
index 923929c..0000000
--- a/aneris/examples/crdt/statelib/spec/model.v
+++ /dev/null
@@ -1,78 +0,0 @@
-From stdpp Require Import base gmap.
-From aneris.examples.crdt.spec Require Import crdt_time crdt_events crdt_denot.
-
-(** * Models for state-based CRDTs **)
-
-(* The "state" in "state-based CRDTs" are join semilattices: i.e.
-   a poset with a lub operation. *)
-Section Lattices.
-
-  Class Lattice (E : Type) := {
-    lat_le : relation E;
-    lat_po :> PartialOrder lat_le;
-    lat_lub : E -> E -> E;
-    lat_lub_le : ∀ e1 e2 e3,
-        lat_le e1 e3 -> lat_le e2 e3 -> lat_le (lat_lub e1 e2) e3
-  }.
-
-End Lattices.
-
-Infix "≤_l" := lat_le (at level 80, no associativity).
-Infix "⊔_l" := lat_lub (at level 50, left associativity).
-
-Section ModelDef.
-
-  Context {Op : Type}.
-  Context `{!Lattice LatSt, !Log_Time, !EqDecision Op, !Countable Op, !CrdtDenot Op LatSt}.
-
-  (* A set of events is `dep_closed` if it contains every causal dependency of
-     every element of the set. *)
-  Definition dep_closed (s : gset (Event Op)) : Prop :=
-    ∀ e e' : Event Op, e ∈ s -> e' <_t e -> e' ∈ s.
-
-  Lemma dep_closed_union (s s' : gset (Event Op)) :
-    dep_closed s -> dep_closed s' -> dep_closed (s ∪ s').
-  Proof.
-    intros Hsc Hs'c e e' [Hl | Hr]%elem_of_union Hlt.
-    - apply elem_of_union_l.
-      eapply Hsc; eauto.
-    - apply elem_of_union_r.
-      eapply Hs'c; eauto.
-  Qed.
-
-  Class StateCrdtModel := {
-    (* The lub operation must be coherent with respect to denotations.
-       We can assume that s1 and s2 are dep_closed because that is an invariant
-       that is always preserved by state-based CRDTs. *)
-    st_crdtM_lub_coh : ∀ (s1 s2 : gset (Event Op)) (st1 st2 st3 : LatSt),
-      ⟦ s1 ⟧ ⇝ st1 ->
-      ⟦ s2 ⟧ ⇝ st2 ->
-      dep_closed s1 ->
-      dep_closed s2 ->
-      st1 ⊔_l st2 = st3 <-> ⟦ s1 ∪ s2 ⟧ ⇝ st3;
-
-    (* The mutator sends a state, an operation, and the replica id where the
-       mutation is taking place to a new state.  *)
-    st_crdtM_mut (st : LatSt) (op : Op) (repId : nat) : LatSt;
-
-    (* All mutations are monotone, so always end up higher up in the lattice.  *)
-    st_crdtM_mut_mon (st : LatSt) (op : Op) (repId : nat) :
-      st ≤_l (st_crdtM_mut st op repId);
-
-    (* Mutations are coherent with denotations. *)
-    st_crdtM_mut_coh (s : gset (Event Op)) (st st' : LatSt) (op : Op) (repId : nat) (ev : (Event Op)) :
-      ⟦ s ⟧ ⇝ st ->
-      ev.(EV_Op) = op ->
-      ev.(EV_Orig) = repId ->
-      ev ∉ s ->
-      is_maximum ev (s ∪ {[ ev ]}) ->
-      st' = st_crdtM_mut st op repId <-> ⟦ s ∪ {[ ev ]} ⟧ ⇝ st';
-
-    (* The initial CRDT state. *)
-    st_crdtM_init_st : LatSt;
-
-    (* The initial state is the denotation of the empty set of operations. *)
-    st_crdtM_init_st_coh : ⟦ ∅ ⟧ ⇝ st_crdtM_init_st
-  }.
-
-End ModelDef.
diff --git a/aneris/examples/crdt/statelib/user_model/model.v b/aneris/examples/crdt/statelib/user_model/model.v
new file mode 100644
index 0000000..a10e0e8
--- /dev/null
+++ b/aneris/examples/crdt/statelib/user_model/model.v
@@ -0,0 +1,127 @@
+From stdpp Require Import base gmap.
+From aneris.examples.crdt.spec Require Import crdt_denot crdt_events crdt_time.
+From aneris.examples.crdt.statelib.time Require Import time.
+From aneris.examples.crdt.statelib.proof Require Import events.
+
+(** * Models for state-based CRDTs **)
+
+(* The "state" in "state-based CRDTs" are join semilattices: i.e.
+   a poset with a lub operation. *)
+Section Lattices.
+
+  Class Lattice (E : Type) := {
+    lat_le : relation E;
+    lat_po :> PartialOrder lat_le;
+    lat_lub : E -> E -> E;
+    lat_lub_spec :
+      ∀ e1 e2,
+        lat_le e1 (lat_lub e1 e2)
+          ∧ lat_le e2 (lat_lub e1 e2)
+          ∧ ∀ e, lat_le e1 e → lat_le e2 e → lat_le (lat_lub e1 e2) e;
+  }.
+
+  (** Properties on the least upper bound *)
+  Lemma lat_lub_idem {E: Type} (L: Lattice E) (e: E) :
+    lat_lub e e = e.
+  Proof.
+    destruct lat_po as [[_ _] Ha].
+    destruct (lat_lub_spec e e) as (Hle1 & Hle2 & Hsp).
+    apply Ha; last assumption.
+    by apply Hsp.
+  Qed.
+  Lemma lat_lub_comm {E: Type} (L: Lattice E) (e e': E) :
+    lat_lub e e' = lat_lub e' e.
+  Proof.
+    destruct lat_po as [[_ _] Ha].
+    destruct (lat_lub_spec e e') as (Hle1 & Hle2 & Hsp).
+    destruct (lat_lub_spec e' e) as (Hle1' & Hle2' & Hsp').
+    apply Ha.
+    - by apply Hsp.
+    - by apply Hsp'.
+  Qed.
+
+  Lemma lat_lub_le_l {E: Type} (L: Lattice E) (e e' e'': E):
+    lat_le e'' e → lat_le e'' (lat_lub e e').
+  Proof.
+    destruct lat_po as [[_ Rt] _].
+    destruct (lat_lub_spec e e') as (A & B & C).
+    intros Hle.
+    by apply (Rt e'' e (lat_lub e e')).
+  Qed.
+  Lemma lat_lub_le_r {E: Type} (L: Lattice E) (e e' e'': E):
+    lat_le e'' e' → lat_le e'' (lat_lub e e').
+  Proof.
+    destruct lat_po as [[_ Rt] _].
+    destruct (lat_lub_spec e e') as (A & B & C).
+    intros Hle.
+    by apply (Rt e'' e' (lat_lub e e')).
+  Qed.
+
+  Lemma lat_lub_assoc {E: Type} (L: Lattice E) (e e' e'': E) :
+    lat_lub e (lat_lub e' e'') = lat_lub (lat_lub e e') e''.
+  Proof.
+    destruct lat_po as [[_ _] Ha].
+    apply Ha.
+    - destruct (lat_lub_spec e (lat_lub e' e'')) as (Hubl & Hubr & Hleast).
+      apply Hleast.
+      + by do 2 apply lat_lub_le_l.
+      + destruct (lat_lub_spec e' e'') as (Hubl' & Hubr' & Hleast').
+        apply (Hleast' (lat_lub (lat_lub e e') e'')).
+        * by apply lat_lub_le_l, lat_lub_le_r.
+        * by apply lat_lub_le_r.
+    - destruct (lat_lub_spec (lat_lub e e') e'') as (Hubl & Hubr & Hleast).
+      apply Hleast.
+      + destruct (lat_lub_spec e e') as (Hubl' & Hubr' & Hleast').
+        apply Hleast'.
+        * by apply lat_lub_le_l.
+        * by apply lat_lub_le_r, lat_lub_le_l.
+      + by do 2 apply lat_lub_le_r.
+  Qed.
+End Lattices.
+
+Infix "≤_l" := lat_le (at level 80, no associativity).
+Infix "⊔_l" := lat_lub (at level 50, left associativity).
+
+Section ModelDef.
+
+  Context {Op : Type} {LatSt: Type}.
+  Context `{!Lattice LatSt, !EqDecision Op, !Countable Op, !CrdtDenot Op LatSt}.
+
+  Class StateCrdtModel := {
+    (* The lub operation must be coherent with respect to denotations.
+       We can assume that s1 and s2 are dep_closed because that is an invariant
+       that is always preserved by state-based CRDTs. *)
+    st_crdtM_lub_coh : ∀ (s1 s2 : gset (Event Op)) (st1 st2 st3 : LatSt),
+      ⟦ s1 ⟧ ⇝ st1 ->
+      ⟦ s2 ⟧ ⇝ st2 ->
+      event_set_valid s1 ->
+      event_set_valid s2 ->
+      st1 ⊔_l st2 = st3 <-> ⟦ s1 ∪ s2 ⟧ ⇝ st3;
+
+    (* The mutator sends a state, an operation, and the replica id where the
+       mutation is taking place to a new state.  *)
+    st_crdtM_mut: LatSt → Event Op → LatSt → Prop;
+
+    (* All mutations are monotone, so always end up higher up in the lattice.  *)
+    st_crdtM_mut_mon (st : LatSt) (e: Event Op) (st': LatSt) :
+      st_crdtM_mut st e st' → st ≤_l st';
+
+    (* Mutations are coherent with denotations. *)
+    st_crdtM_mut_coh (s : gset (Event Op)) (st st' : LatSt) (ev: Event Op) :
+      ⟦ s ⟧ ⇝ st ->
+      event_set_valid s ->
+      ev ∉ s ->
+      is_maximum ev (s ∪ {[ ev ]}) ->
+      st_crdtM_mut st ev st' <->
+      ⟦ s ∪ {[ ev ]} ⟧ ⇝ st';
+
+    (* The initial CRDT state. *)
+    st_crdtM_init_st : LatSt;
+
+    (* The initial state is the denotation of the empty set of operations. *)
+    st_crdtM_init_st_coh : ⟦ ∅ ⟧ ⇝ st_crdtM_init_st
+  }.
+
+End ModelDef.
+Arguments StateCrdtModel (Op LatSt) {_ _ _ _}.
+
diff --git a/aneris/examples/crdt/statelib/user_model/spec.v b/aneris/examples/crdt/statelib/user_model/spec.v
new file mode 100644
index 0000000..84cbe1b
--- /dev/null
+++ b/aneris/examples/crdt/statelib/user_model/spec.v
@@ -0,0 +1,313 @@
+From iris.algebra Require Import auth gmap excl csum.
+From aneris.algebra Require Import monotone.
+From aneris.aneris_lang Require Import network resources proofmode.
+From aneris.prelude Require Import time.
+From aneris.aneris_lang.lib Require Import list_proof lock_proof vector_clock_proof serialization_proof.
+From aneris.aneris_lang.program_logic Require Import lightweight_atomic.
+From aneris.examples.crdt.spec Require Import crdt_spec.
+From aneris.examples.crdt.statelib.user_model Require Import model.
+From aneris.examples.crdt.statelib.proof Require Import events.
+
+(** * Specification of the op-based CRDT library *)
+
+Section Params.
+  Context {LogOp LogSt : Type}.
+  Context `{!anerisG Mdl Σ, !EqDecision LogOp, !Countable LogOp}.
+  Context `{!Lattice LogSt}.
+
+  (* User-supplied parameters when using the library. *)
+  Class StLib_Params := {
+    (* Serialization of operations. *)
+    StLib_Serialization : serialization;
+
+    (* CRDT model *)
+    StLib_Denot :> CrdtDenot LogOp LogSt;
+    StLib_Model :> StateCrdtModel LogOp LogSt;
+
+    (* Coherence between logical and physical state: for
+       states, operations, and events (event = operation + timestamp).
+
+       For example, for a counter CRDT the logical state is
+       (morally) an integer, while the physical state is an
+       AnerisLang `val` (containing the integer).
+       The correspondence is trivial in that case, but can
+       be more complicated for other CRDTs. *)
+    StLib_State_Coh : LogSt -> val -> Prop;
+    StLib_Op_Coh : LogOp -> val -> Prop;
+    StLib_Op_Coh_Inj o1 o2 v : StLib_Op_Coh o1 v -> StLib_Op_Coh o2 v -> o1 = o2;
+    StLib_St_Coh : LogSt -> val -> Prop;
+    StLib_St_Coh_Inj o1 o2 v : StLib_St_Coh o1 v -> StLib_St_Coh o2 v -> o1 = o2;
+    StLib_Coh_Ser op v : StLib_Op_Coh op v -> Serializable StLib_Serialization v;
+  }.
+
+  Definition StLib_Event_Coh `{!StLib_Params} (e : Event LogOp) (v : val) : Prop :=
+    ∃ valOp valTime valOrig,
+      v = ((valOp, valTime), valOrig)%V ∧
+      StLib_Op_Coh e.(EV_Op) valOp ∧
+      True ∧ (*is_list (elements e.(EV_Time)) valTime ∧ TODO: deal with the time representation *)
+      valOrig = #(e.(EV_Orig)).
+
+  Class StLib_Res `{!CRDT_Params} := {
+    StLib_CRDT_Res :> CRDT_Res_Mixin Mdl Σ LogOp;
+    StLib_InitToken : nat -> iProp Σ;
+    StLib_SocketProto : nat -> socket_interp Σ;
+  }.
+
+End Params.
+
+Global Arguments StLib_Params (LogOp LogSt) {_ _ _}.
+Global Arguments StLib_Res (LogOp) {_ _ _ _ _ _}.
+
+Section Specification.
+
+  (* The following resources are all needed to _state_ the specifications of library
+     functions, but they should _not_ all be provided by the user of the library
+     (e.g. the user provides StLib_UserParams, but not StLib_SysParams).
+
+     To use the library, the user should refer to class StLibSetup below.
+   *)
+  Context `{!anerisG Mdl Σ,
+            !EqDecision LogOp,
+            !Countable LogOp,
+            !Lattice LogSt,
+            !StLib_Params LogOp LogSt,
+            !StLib_SysParams Σ,
+            !CRDT_Params,
+            !StLib_Res LogOp}.
+
+  Definition get_state_spec (get_state : val) (repId : nat) (addr : socket_address) : iProp Σ :=
+    ⌜CRDT_Addresses !! repId = Some addr⌝ -∗
+     <<< ∀∀ (s1 s2 : gset (Event LogOp)), LocState repId s1 s2 >>>
+       get_state #() @[ip_of_address addr] ↑CRDT_InvName
+     <<<▷ ∃∃ (s2' : gset (Event LogOp)) (phys_st : val) (log_st : LogSt), RET phys_st;
+             ⌜s2 ⊆ s2'⌝ ∗
+             LocState repId s1 s2' ∗
+             ⌜StLib_State_Coh log_st phys_st⌝ ∗
+             ⌜⟦s1 ∪ s2'⟧ ⇝ log_st⌝ >>>.
+
+  Definition mutator_spec (mutator : val) (repId : nat) (addr : socket_address) : iProp Σ :=
+    ∀ (op : val) (log_op : LogOp),
+    ⌜CRDT_Addresses !! repId = Some addr⌝ -∗
+    ⌜StLib_Op_Coh log_op op⌝ -∗
+    <<< ∀∀ (h s1 s2 : gset (Event LogOp)),
+           GlobState h ∗
+           LocState repId s1 s2 >>>
+      mutator op @[ip_of_address addr] ↑CRDT_InvName
+    <<<▷ ∃∃ (e : Event LogOp) (h' s1' s2' : gset (Event LogOp)), RET #();
+           ⌜e.(EV_Op) = log_op⌝ ∗
+           ⌜e.(EV_Orig) = repId⌝ ∗
+           ⌜h' = h ∪ {[ e ]}⌝ ∗
+           ⌜s1' = s1 ∪ {[ e ]}⌝ ∗
+           ⌜s2 ⊆ s2'⌝ ∗
+           ⌜e ∉ h⌝ ∗
+           ⌜e ∉ s1⌝ ∗
+           ⌜e ∈ Maximals h'⌝ ∗
+           ⌜Maximum (s1' ∪ s2') = Some e⌝ ∗
+           GlobState h' ∗
+           LocState repId s1' s2' >>>.
+
+  Definition effect_spec (effect_fn : val) : iProp Σ :=
+    ∀ (addr : socket_address) (ev st : val) (s : (event_set LogOp))
+      (log_ev : Event LogOp) (log_st : LogSt),
+    {{{ ⌜StLib_Event_Coh log_ev ev⌝ ∗
+        ⌜StLib_State_Coh log_st st⌝ ∗
+        ⌜⟦ s ⟧ ⇝ log_st⌝ ∗
+        ⌜log_ev ∉ s⌝ ∗
+        ⌜maximal log_ev (s ∪ {[ log_ev ]})⌝ ∗
+        ⌜events_ext (s ∪ {[ log_ev ]})⌝ ∗
+        ⌜events_total_order (s ∪ {[ log_ev ]})⌝
+    }}}
+      effect_fn ev st @[ip_of_address addr]
+    {{{ st', RET st';
+        ∃ (log_st' : LogSt),
+          ⌜StLib_State_Coh log_st' st'⌝ ∗
+          ⌜st_crdtM_mut log_st log_ev log_st'⌝
+    }}}.
+
+  Definition merge_spec (merge_fn : val) : iProp Σ :=
+    ∀ (addr : socket_address) (st st' : val) (s s' : (event_set LogOp))
+      (log_st log_st' : LogSt),
+    {{{ ⌜StLib_State_Coh log_st st⌝ ∗
+        ⌜StLib_State_Coh log_st' st'⌝ ∗
+        ⌜⟦ s ⟧ ⇝ log_st⌝ ∗
+        ⌜⟦ s' ⟧ ⇝ log_st'⌝
+    }}}
+      merge_fn st st' @[ip_of_address addr]
+    {{{ st'', RET st'';
+        ∃ (log_st'' : LogSt),
+          ⌜StLib_State_Coh log_st'' st''⌝ ∗
+          ⌜lat_lub log_st log_st' = log_st''⌝
+    }}}.
+
+  Definition init_st_fn_spec (init_st_fun : val) : iProp Σ :=
+    ∀ addr,
+      {{{ True }}}
+        init_st_fun #() @[ip_of_address addr]
+      {{{ v, RET v; ⌜StLib_State_Coh st_crdtM_init_st v⌝ }}}.
+
+  Definition crdt_triplet_spec (crdt_triplet : val) : iProp Σ :=
+    ∃ (init_st_fn effect_fn merge_fn : val),
+      ⌜crdt_triplet = PairV (PairV init_st_fn effect_fn) merge_fn⌝ ∗
+      init_st_fn_spec init_st_fn  ∗
+      effect_spec effect_fn ∗
+      merge_spec merge_fn.
+
+  Definition crdt_fun_spec (crdt_fun : val) : iProp Σ :=
+    ∀ addr,
+      {{{ True }}}
+        crdt_fun #() @[ip_of_address addr]
+      {{{ v, RET v; crdt_triplet_spec v }}}.
+
+  Definition init_spec_for_specific_crdt (init : val)  : iProp Σ :=
+    ∀ (repId : nat) (addr : socket_address) (fixedAddrs : gset socket_address)
+      (addrs_val : val),
+        {{{ ⌜is_list CRDT_Addresses addrs_val⌝ ∗
+            ⌜CRDT_Addresses !! repId = Some addr⌝ ∗
+            ⌜addr ∈ fixedAddrs⌝ ∗
+            fixed fixedAddrs ∗
+            ([∗ list] i ↦ z ∈ CRDT_Addresses, z ⤇ StLib_SocketProto i) ∗
+            addr ⤳ (∅, ∅) ∗
+            free_ports (ip_of_address addr) {[port_of_address addr]} ∗
+            StLib_InitToken repId
+        }}}
+          init addrs_val #repId @[ip_of_address addr]
+        {{{ get_state_val mutator_val, RET (get_state_val, mutator_val);
+            LocState repId ∅ ∅ ∗
+            get_state_spec get_state_val repId addr ∗
+            mutator_spec mutator_val repId addr
+        }}}.
+
+    Definition init_spec (init : val) : iProp Σ :=
+    ∀ (repId : nat) (addr : socket_address) (fixedAddrs : gset socket_address)
+      (addrs_val crdt_val : val),
+        {{{ ⌜is_list CRDT_Addresses addrs_val⌝ ∗
+            ⌜CRDT_Addresses !! repId = Some addr⌝ ∗
+            ⌜addr ∈ fixedAddrs⌝ ∗
+            fixed fixedAddrs ∗
+            ([∗ list] i ↦ z ∈ CRDT_Addresses, z ⤇ StLib_SocketProto i) ∗
+            addr ⤳ (∅, ∅) ∗
+            free_ports (ip_of_address addr) {[port_of_address addr]} ∗
+            StLib_InitToken repId ∗
+            crdt_fun_spec crdt_val
+        }}}
+          init addrs_val #repId crdt_val @[ip_of_address addr]
+        {{{ get_state_val mutator_val, RET (get_state_val, mutator_val);
+            LocState repId ∅ ∅ ∗
+            get_state_spec get_state_val repId addr ∗
+            mutator_spec mutator_val repId addr
+        }}}.
+
+  (** * Simplified specs for when we have full ownership *)
+
+  Definition simplified_get_state_spec (get_state : val) (repId : nat) (addr : socket_address) : iProp Σ :=
+    ∀ (s1 s2 : event_set LogOp),
+      ⌜CRDT_Addresses !! repId = Some addr⌝ -∗
+      {{{ LocState repId s1 s2 }}}
+        get_state #() @[ip_of_address addr]
+      {{{ phys_st log_st, RET phys_st; ∃ s2',
+          ⌜s2 ⊆ s2'⌝ ∗
+          LocState repId s1 s2' ∗
+          ⌜StLib_State_Coh log_st phys_st⌝ ∗
+          ⌜⟦ s1 ∪ s2' ⟧ ⇝ log_st⌝
+      }}}.
+
+  Lemma read_spec_implies_simplified_spec get_state repId addr :
+    get_state_spec get_state repId addr ⊢ simplified_get_state_spec get_state repId addr.
+  Proof.
+    iIntros "#Hgetstate".
+    rewrite /simplified_get_state_spec.
+    iIntros (s1 s2) "#Haddr !>". iIntros (Φ) "Hloc HΦ".
+    iApply ("Hgetstate" with "[//]").
+    iExists s1, s2; iFrame.
+    iApply fupd_mask_intro; [set_solver |].
+    iIntros "Hcl !>".
+    iIntros (? ? ?) "(? & ? & ?)". iMod "Hcl". iModIntro.
+    iApply "HΦ".
+    eauto with iFrame.
+  Qed.
+
+  Definition simplified_mutator_spec (mutator : val) repId addr : iProp Σ :=
+    ∀ (op : val) (log_op : LogOp) (h s1 s2 : event_set LogOp),
+     ⌜CRDT_Addresses !! repId = Some addr⌝ -∗
+     ⌜StLib_Op_Coh log_op op⌝ -∗
+     {{{ GlobState h ∗
+         LocState repId s1 s2
+     }}}
+        mutator op @[ip_of_address addr]
+     {{{ RET #();
+         ∃ (e : Event LogOp) (h' s1' s2' : gset (Event LogOp)),
+           ⌜e.(EV_Op) = log_op⌝ ∗
+           ⌜e.(EV_Orig) = repId⌝ ∗
+           ⌜h' = h ∪ {[ e ]}⌝ ∗
+           ⌜s1' = s1 ∪ {[ e ]}⌝ ∗
+           ⌜s2 ⊆ s2'⌝ ∗
+           ⌜e ∉ h⌝ ∗
+           ⌜e ∉ s1⌝ ∗
+           ⌜e ∈ Maximals h'⌝ ∗
+           ⌜Maximum (s1' ∪ s2') = Some e⌝ ∗
+           GlobState h' ∗
+           LocState repId s1' s2' }}}.
+
+  Lemma mutator_spec_implies_simplified_mutator mutator repId addr :
+    mutator_spec mutator repId addr ⊢ simplified_mutator_spec mutator repId addr.
+  Proof.
+    iIntros "#Hmutator" (op log_op h s1 s2) "#Haddr %Hcoh".
+    iModIntro.
+    iIntros (Φ) "[Hglob Hloc] HΦ".
+    iApply ("Hmutator" with "[//]"); [done |].
+    iApply fupd_mask_intro; [set_solver |].
+    iIntros "Hcl". iExists h, s1, s2. iFrame.
+    iModIntro.
+    iIntros (e h' s1' s2') "(? & ? & ? & ? & ? & ? & ? & ? & ?)".
+    iMod "Hcl". iModIntro.
+    iApply "HΦ". eauto with iFrame.
+  Qed.
+
+End Specification.
+
+(** * Library interface **)
+Section StLibSetup.
+
+  Class StLib_Init_Function := { init : val }.
+
+  Context {LogOp LogSt : Type}.
+  Context `{!anerisG Mdl Σ, !EqDecision LogOp, !Countable LogOp,
+            !CRDT_Params, !Lattice LogSt, !StLib_Params LogOp LogSt, !StLib_Init_Function}.
+
+  Class StLibSetup :=
+      StLibSetup_Init E :
+      True ⊢ |={E}=> ∃ (Res : StLib_Res LogOp),
+        GlobInv ∗
+        GlobState ∅ ∗
+        ([∗ list] i ↦ _ ∈ CRDT_Addresses, StLib_InitToken i) ∗
+        init_spec init.
+
+End StLibSetup.
+
+Section RAs.
+
+  Context {LogOp LogSt : Type}.
+  Context `{!EqDecision LogOp, !Countable LogOp}.
+
+  Definition oneShotR := csumR (exclR unitO) (agreeR unitO).
+
+  Class StLibG Σ := {
+      StLibG_auth_gset_ev :> inG Σ (authUR (gsetUR (Event LogOp)));
+      StLibG_frac_agree :> inG Σ (prodR fracR (agreeR (gsetO (Event LogOp))));
+      StLibG_mono :> inG Σ (authUR (monotoneUR (@cc_subseteq LogOp _ _)));
+      StLibG_lockG :> lockG Σ;
+      StLibG_oneshot :> inG Σ oneShotR;
+  }.
+
+  Definition OPLIBΣ  : gFunctors :=
+    #[GFunctor (authUR (gsetUR (Event LogOp)));
+      GFunctor (prodR fracR (agreeR (gsetO (Event LogOp))));
+      GFunctor (authUR (monotoneUR (@cc_subseteq LogOp _ _)));
+      lockΣ;
+      GFunctor oneShotR].
+
+  Global Instance subG_OPLIBΣ {Σ} : subG OPLIBΣ Σ → StLibG Σ.
+  Proof. constructor; solve_inG. Qed.
+
+End RAs.
+
-- 
GitLab