aneris_examples.ccddb.examples.session_guarantees.ryw

From iris.algebra Require Import agree gmap auth.
From iris.proofmode Require Import tactics.
From aneris.aneris_lang Require Import
     lang network notation tactics proofmode lifting.
From aneris.aneris_lang.lib Require Import lock network_helpers.
From aneris.aneris_lang.lib.serialization Require Import serialization.
From aneris_examples.ccddb.spec Require Import spec resources.
From aneris_examples.ccddb.examples.session_guarantees
     Require Import res sm_code sm_proof.
From aneris_examples.ccddb Require Import spec_util.

Import Network.

Context `{!anerisG Σ, !lockG Σ}.
Context `{!DB_params}.
Context `{!DB_time, !DB_events}.
Context `{!DB_resources Σ}.
Context `{!Maximals_Computing}.
Context `{!inG Σ (authUR (gmapUR nat (agreeR (leibnizO log_req))))}.

Section ReadYourWrites.

  (* We assume that the set of db keys is non-empty and we know one of the keys *)
  Variable key : Key.
  Hypothesis Hkey_valid : key DB_keys.
  (* We assume a value that can be written to the db. *)
  Variable dbv : SerializableVal.

  (* Read Your Writes example *)
  Definition ryw_example : base_lang.val :=
    λ: "client_addr" "server_addr",
    let: "ops" := sm_setup "client_addr" in
    let: "init_fn" := Fst (Fst "ops") in
    let: "read_fn" := Snd (Fst "ops") in
    let: "write_fn" := Snd "ops" in
    "init_fn" "server_addr";;
    "write_fn" "server_addr" #key dbv;;
    "read_fn" "server_addr" #key.

  Theorem ryw_example_spec (A : gset socket_address) (ca sa : socket_address) (db_id : rep_id) :
    {{{ fixed A
         sa A
         sa (db_si db_id)
         ca A
         free_ports (ip_of_address ca) {[ port_of_address ca ]}
    }}}

      ryw_example #ca #sa @[ip_of_address ca]

   {{{ vo, RET vo;
        s e e' v, vo = SOMEV v
                  e.(AE_val) = v
                  e.(AE_key) = key
                  e'.(AE_val) = dbv
                  e'.(AE_key) = key
                  Seen db_id s
                  e s
                  e' s
                  ¬ (e <ₜe')
   }}}.
  Proof.
    iIntros (ϕ) "(#Hfixed & #Hsa & #Hsi & #Hca & Hfree) Hcont".
    wp_lam. wp_pures.
    wp_apply (sm_setup_spec with "[$Hfree $Hfixed $Hca]").
    iIntros (fns) "Hpre".
    iDestruct "Hpre" as (init_fn read_fn write_fn)
                          "(-> & #Hinit_spec & #Hread_spec & #Hwrite_spec)".
    wp_pures.
    (* Init *)
    wp_apply ("Hinit_spec" with "[$Hsi]").
    rewrite /init_post.
    iIntros "Hinit". iDestruct "Hinit" as (s) "(#Hseen & #Hkeys & _)".
    (* Get snapshot for the key we want to read *)
    iAssert ( h : gmem, OwnMemSnapshot key h)%I as "#Hsnap";
    first by iDestruct (big_sepS_delete _ _ _ Hkey_valid with "Hkeys") as "[Hkey _]".
    iDestruct "Hsnap" as (h) "#Hsnap".
    (* Write *)
    wp_apply ("Hwrite_spec" $! _ _ key dbv with "[$Hsi $Hseen $Hsnap]"); [by iPureIntro|].
    iIntros "Hwpost". rewrite /write_post.
    iDestruct "Hwpost" as (e' s' h') "(#Hek' & #Hev' & #Hss' & _ & #Hseen' & #Hsnap' & #Hes & #Hes' & #Hemaxh & #Hemaxs')".
    (* Read *)
    wp_apply ("Hread_spec" with "[$Hsi $Hseen' $Hsnap']"); [by iPureIntro|].
    iIntros (vo) "Hreadpost". iApply "Hcont".
    rewrite /read_post.
    iDestruct "Hreadpost" as (s'' h'') "(#Hss'' & _ & #Hseen'' & _ & [[-> #Hrestrict] | Hsome])".
    - (* Read returns none: a contradiction *)
      iDestruct "Hrestrict" as %Hrestrict.
      iDestruct "Hss''" as %Hss''.
      iDestruct "Hes'" as %Hes'.
      iDestruct "Hek'" as %Hek'.
      exfalso.
      assert (e' s'') as Hes'' by set_solver.
      assert (e' restrict_key key s'') as Hinrest; last by set_solver.
      apply (iffRL (elem_of_filter _ _ _)); auto.
    - (* Read returns some value *)
      iDestruct "Hsome" as (e'' v'') "(-> & #Hev'' & #Hek'' & #Hemax & #Herasure)".
      iExists s'', e'', e', _.
      iSplit; first by iPureIntro.
      iFrame "#".
      iDestruct "Hemax" as %Hemax.
      iDestruct "Hes'" as %Hes'.
      iDestruct "Hss''" as %Hss''.
      iDestruct "Hek'" as %Hek'.
      iDestruct "Hek''" as %Hek''.
      repeat iPureIntro.
      repeat split; auto.
      * assert (e'' restrict_key key s'') as Hin.
        { eapply Maximals_correct in Hemax.
          destruct Hemax as (? & _); auto.
        }
        set_solver.
      * eapply Maximals_correct in Hemax.
        destruct Hemax as (Hinres & Hforall).
        apply Hforall.
        assert (e' s'') as He'in by set_solver.
        eapply elem_of_filter; auto.
  Qed.

End ReadYourWrites.