aneris_examples.ccddb.resources.resources_lhst

Realisation of the DB_resources interface
From iris.algebra Require Import agree auth excl gmap.
From iris_monotone Require Import monotone.
From iris.proofmode Require Import tactics.
From iris.base_logic Require Import invariants.
From aneris.aneris_lang Require Import lang resources.
From aneris_examples.ccddb.spec Require Import base.
From aneris.aneris_lang.lib.vector_clock Require Import time.
From aneris_examples.ccddb.model Require Import events model_spec.
From aneris_examples.ccddb.resources Require Import base.

Import Network.

Notation PrinSeen S := (principal seen_relation S).

Section Local_history.

  Context `{!anerisG Σ, !DB_params, !internal_DBG Σ}.

  Section Predicates.

    Context (γLs : list (gname * gname)).

    Definition local_history_Global_inv
               (γs : gname * gname) (S : gset apply_event) : iProp Σ :=
      own γs.1 ( (PrinSeen S)) own γs.2 ( S).

    Definition local_history_Local_inv
               (i : nat) (S : gset apply_event) : iProp Σ :=
       γs, γLs !! i = Some γs own γs.1 ( (PrinSeen S)) own γs.2 ( S).

    Definition local_history_seen (i : nat) (S : gset apply_event) : iProp Σ :=
       γs, γLs !! i = Some γs
        own γs.1 ( (PrinSeen S)) own γs.2 ( S).

    Instance local_history_seen_Persistent :
       i s, Persistent (local_history_seen i s).
    Proof. apply _. Qed.

    Lemma seen_lookup i γs s Ss :
      γLs !! i = Some γs
      ([∗ list] γs';S γLs;Ss, local_history_Global_inv γs' S)
      own γs.1 ( (PrinSeen s)) -∗
       s', seen_relation s s' Ss !! i = Some s'.
    Proof.
      iIntros (Hi) "HL Hs".
      iDestruct (big_sepL2_length with "HL") as %Hlen.
      destruct (lookup_lt_is_Some_2 Ss i) as [S HS].
      { rewrite -Hlen; apply lookup_lt_is_Some; eauto. }
      iDestruct (big_sepL2_lookup_acc _ _ _ i with "HL") as "[[HS1 HS2] Hrest]";
        eauto.
      iDestruct (own_valid_2 with "HS1 Hs") as %[Hv1 Hv2]%auth_both_valid.
      revert Hv1; rewrite principal_included; eauto.
    Qed.

    Lemma local_history_invs_agree i s Ss :
      ([∗ list] γs;S γLs;Ss, local_history_Global_inv γs S)
      local_history_Local_inv i s -∗ Ss !! i = Some s.
    Proof.
      iIntros "HL Hs".
      iDestruct "Hs" as (γs ?) "[Hs1 Hs2]".
      iDestruct (big_sepL2_length with "HL") as %Hlen.
      destruct (lookup_lt_is_Some_2 Ss i) as [s' Hs'].
      { rewrite -Hlen; apply lookup_lt_is_Some; eauto. }
      iDestruct (big_sepL2_lookup_acc _ _ _ i with "HL") as "[[HS1 HS2] Hrest]";
        eauto.
      iDestruct (own_valid_2 with "HS1 Hs1") as %[Hv1 Hv2]%auth_both_valid.
      revert Hv1; rewrite principal_included; intros [Hv11 Hv12].
      iDestruct (own_valid_2 with "Hs2 HS2") as %[Hv1' Hv2']%auth_both_valid.
      revert Hv1'; rewrite gset_included; intros Hv1'.
      iPureIntro.
      rewrite Hs'; f_equal.
      set_solver.
    Qed.

    Lemma global_local_history_agree i γs s s':
      γLs !! i = Some γs
      local_history_Global_inv γs s local_history_Local_inv i s' -∗ s = s'.
    Proof.
      iIntros (Hi) "[Hs1 Hs2]".
      iDestruct 1 as (γs' Hi') "[Hs'1 Hs'2]".
      simplify_eq.
      iDestruct (own_valid_2 with "Hs1 Hs'1") as %[Hv1 Hv2]%auth_both_valid.
      revert Hv1; rewrite principal_included; intros [Hv11 Hv12].
      iDestruct (own_valid_2 with "Hs'2 Hs2") as %[Hv'1 Hv'2]%auth_both_valid.
      apply gset_included in Hv'1.
      iPureIntro; set_solver.
    Qed.

    Lemma local_history_seen_included i s s':
      local_history_Local_inv i s' local_history_seen i s -∗ s s'.
    Proof.
      iDestruct 1 as (γs Hi) "[Hs1 Hs2]".
      iDestruct 1 as (γs' Hi') "[Hs'1 Hs'2]".
      simplify_eq.
      iDestruct (own_valid_2 with "Hs2 Hs'2") as %[Hv'1 Hv'2]%auth_both_valid.
      by apply gset_included in Hv'1.
    Qed.

    Lemma local_history_update i s Ss e:
      ( (e' : apply_event),
          e' s vector_clock_lt (ae_time e) (ae_time e') False)
      local_history_Local_inv i s
      ([∗ list] γs;S γLs;Ss, local_history_Global_inv γs S) ==∗
      ([∗ list] γs;S γLs; <[i := s {[e]} ]> Ss,
        local_history_Global_inv γs S)
      local_history_Local_inv i (s {[e]}).
    Proof.
      iIntros (He) "Hs HL".
      iDestruct "Hs" as (γs ?) "[Hs1 Hs2]".
      iDestruct (big_sepL2_length with "HL") as %Hlen.
      destruct (lookup_lt_is_Some_2 Ss i) as [s' Hs'].
      { rewrite -Hlen; apply lookup_lt_is_Some; eauto. }
      iDestruct (big_sepL2_insert_acc _ _ _ i with "HL") as "[HS Hback]";
        eauto.
      iDestruct (global_local_history_agree with "HS [Hs1 Hs2]") as %->;
        first done.
      { iExists _; iSplit; first done; iFrame. }
      iDestruct "HS" as "[HS1 HS2]".
      iMod (own_update_2 _ _ _ ( PrinSeen (s {[e]}) PrinSeen (s {[e]}))
              with "HS1 Hs1") as "[HS1 Hs1]".
      { apply auth_update.
        apply monotone_local_update_grow.
        split; set_solver. }
      iMod (own_update_2 _ _ _ ( (s {[e]}) (s {[e]}))
              with "Hs2 HS2") as "[Hs2 HS2]".
      { apply auth_update.
        apply gset_local_update.
        set_solver. }
      iSpecialize ("Hback" $! γs (s {[e]}) with "[$HS1 $HS2]").
      rewrite (list_insert_id γLs); last done.
      iModIntro; iFrame.
      iExists _; iSplit; first done; iFrame.
    Qed.

  End Predicates.

  Section init.

    Lemma alloc_lhst :
    True |==>
       γLs,
        length γLs = length DB_addresses
        ([∗ list] γs; S γLs; empty_lhsts, local_history_Global_inv γs S)
        ([∗ list] i _ DB_addresses, local_history_Local_inv γLs i ).
  Proof.
    iIntros (_).
    rewrite /empty_lhsts.
    iInduction DB_addresses as [|dba] "IHdba"; simpl.
    { by iModIntro; iExists []; rewrite !big_sepL2_nil. }
    iMod ("IHdba") as (γLs Hlen) "[H1 H2]".
    iMod (own_alloc ( PrinSeen PrinSeen )) as (γ1) "[H31 H32]".
    { by apply auth_both_valid. }
    iMod (own_alloc ( )) as (γ2) "[H41 H42]".
    { by apply auth_both_valid. }
    iModIntro.
    iExists ((γ1, γ2) :: γLs).
    rewrite -Hlen /=; iSplit; first done.
    iFrame.
    iExists (γ1, γ2); iSplit; first done.
    iFrame.
  Qed.

  End init.

End Local_history.