From 4c93ea4fa8d546eccedb6fda834576523d391cb8 Mon Sep 17 00:00:00 2001 From: Jonas Kastberg Hinrichsen <jihgfee@gmail.com> Date: Fri, 15 Jul 2022 14:54:08 +0200 Subject: [PATCH] Reliable communication components (#9) * [lf] Notes with specs discussed at the meeting for the leader-followers replication. * [repdb] API Specifications. * [repdb] fix spec w.r.t. ras. * [repdb] Two closed examples to verify. * [repdb] more specs. * [repdb] A sketch of dependent sep. protocols for generic server and two instantiations for leader-client interaction. * [repdb] Complete and factor out the multithreaded server as a library. Now leader-followers do not use directly client-server at all, only relying on the mt-server. * [repdb] User_spec_params class and the specified API for the MT server. * [repdb] Spec and Proof of the multi-threaded service library. * [repdb] wip on resources. * [lf] wip. * [lf] Sketch of resources. * [lf] fix local validity gmap. * [lf] wip on resources and fixes. * [lf] Sketch of mt_spec_params for the leader. * [lf and mt] A fix splitting mt_params so that socket_protocols are definable at the adequacy. * [lf] Back to keeping indexes (time) in the physical log - to please the Inject class but also it makes sense. * [lf] wip on logs (needs mono_list straight away). * [lf] Further anticipations for instanciating resources, proving init class and adequacy. * [lf] Proof of client proxy (relying on the assumed proof of the handler in the MT spec params). * [lf] Generic definition logical logs and the proof of the physical log (including the proof of log_wait_until). * [lf] wip. * [lf] Defining monitor resources using generic log_monitor definition. * [lf] wip on update_log_copy proof. * [lf] Proof of update log copy at leader. * [lf] Proof of init_leader. * [lf] Proof of follower_request_handler. * [lf] First sketch of dlm_db_example proof skeleton (to be improved in the next commit). * [lf] Wip on the dlm_db_example proof. * [lf] Assembled proof of dlm_db_example including adequacy (but assuming proof of the code and instance of db_init class (TODO). * [lf] More proofs for the dlm_db_example. * [lf] More proof for dlm_db_example. * [lf] Proof of the do_writes. * [lf] Proof of do_reads in the dlm_db_example. * [lf] small clean up. * [lf] The proof of the dlm_db_example. * Clean up of redundant `True` preconditions * Clean up and removed some `Unshelve`s * Added proof of do_writes / do_reads of causality * [lf] wip and sketch for causality example with reading at a follower. * [lf] some ideas on proving causality example (in a sep. file) but no success so fart. * [lf] Proof of the read request at the leader's handler. * [lf] wip on proof of client handler (almost done). * [lf] Proof of the client handler at the leader done. * [lf] Proof of the client request handler at the follower. * [lf] Wip on follower's sync loop. * [lf] Fix the proof of followers handler. * [lf] Proof of follower sync loop done. * [lf] Various fixes in the spec due to an error in the db_init_class. Proof of the client proxy at follower done (but the problem with ghost names is to be fixed). * [lf] 1. Introducing a global N of type gmap saddr gname. 2. Proof of init client proxy for followers. 3. Fixes. * [lf] Wip on proof of init follower (last bit before proving setup and spec refinement). * [lf] The internal proof of the leader followers done (up to logical setup). * [lf] Wip on init_setup proof. * [lf] more proof for init_setup. * Causality example (#4) * [lf] wip on proof of init. * [lf] fix. * [lf] fixes. * Lifted log_resources lemmas * Proved resources_def lemmas * Progress on global resource lemmas * [lf] Wip on proof of db init. * Bumped strengthened lemmas * [lf] More wip on proof of init setup. * [lf] Proof of init setup for leader follower done. * Proved two alloc lemmas * prove some admitted lemmas * Proved last init lemma * Commented out API lemmas that are not used * Proved another lemma * one more admitted now proved * Prove two lemmas in resources_global_inv * Proved another global lemma * Closed final lemma * Clean up: Unshelves, indents, etc. * Spec clean up * Removed inline universal quantifications from abstract specs * Simplified specs with unit as a return value * Fixed pure postcondition * Removed some more explicit arguments * Removed more true preconditions * Removed unused hypothesis from dlm spec * Improved DLM protocol definition * [lf, mt-rpc] Improved implementation and spec of the rpc lib, following Jonas' suggestion. * Hide locked inside of CanRelease * DLM sa -> ip * MT sa -> ip * Reliable communication monitorless rpc (#7) * Removed the monitors from the RPC library (still used in closures) * [repl] Ocaml code. Co-authored-by: Leon Gondelman <gondelman@cs.au.dk> * Reliable communication rpc closures (#8) Co-authored-by: Leon Gondelman <gondelman@cs.au.dk> Co-authored-by: Amin Timany <amintimany@gmail.com> --- _OCamlProject | 19 +- aneris/aneris_lang/tactics.v | 1 + .../dlm_db_example/dlm_db_example_code.v | 56 +- .../dlm_db_example/dlm_db_example_proof.v | 560 ++++++++++++++++++ .../examples/hello_world/hello_world_proof.v | 6 +- .../hello_world_2/hello_world_2_proof.v | 8 +- .../messages_in_order_proof.v | 6 +- .../messages_in_order_loop_proof.v | 6 +- .../causality_example_code.v | 39 ++ .../causality_example_proof.v | 548 +++++++++++++++++ .../instantiation_of_client_specs.v | 18 +- .../instantiation/instantiation_of_init.v | 25 +- .../instantiation_of_send_and_recv_specs.v | 32 +- .../instantiation_of_server_specs.v | 40 +- .../lib/dlm/dlm_prelude.v | 2 +- .../lib/dlm/dlm_proof.v | 190 +++--- .../reliable_communication/lib/dlm/dlm_spec.v | 46 +- .../lib/mt_server/mt_server_code.v | 39 ++ .../lib/mt_server/proof/mt_server_proof.v | 283 +++++++++ .../lib/mt_server/spec/api_spec.v | 72 +++ .../lib/mt_server/user_params.v | 44 ++ .../lib/repdb/log_code.v | 2 +- .../reliable_communication/lib/repdb/model.v | 328 ++++++++++ .../lib/repdb/notes.txt | 244 ++++++++ .../lib/repdb/proof/db_resources_instance.v | 54 ++ .../clients_at_follower_mt_user_params.v | 82 +++ .../proof/follower/proof_of_clients_handler.v | 153 +++++ .../proof/follower/proof_of_init_follower.v | 180 ++++++ .../lib/repdb/proof/follower/proof_of_proxy.v | 129 ++++ .../repdb/proof/follower/proof_of_sync_loop.v | 158 +++++ .../proof/leader/clients_mt_user_params.v | 88 +++ .../proof/leader/followers_mt_user_params.v | 66 +++ .../proof/leader/proof_of_client_handler.v | 218 +++++++ .../proof/leader/proof_of_followers_handler.v | 141 +++++ .../repdb/proof/leader/proof_of_init_leader.v | 174 ++++++ .../lib/repdb/proof/leader/proof_of_proxy.v | 223 +++++++ .../leader/proof_of_update_log_copy_loop.v | 150 +++++ .../lib/repdb/proof/log_proof.v | 172 ++++++ .../lib/repdb/proof/proof_of_db_init.v | 230 +++++++ .../lib/repdb/proof/repdb_serialization.v | 154 +++++ .../lib/repdb/repdb_code.v | 177 +++--- .../lib/repdb/resources/log_resources.v | 164 +++++ .../lib/repdb/resources/ras.v | 31 + .../lib/repdb/resources/resources_def.v | 169 ++++++ .../repdb/resources/resources_global_inv.v | 419 +++++++++++++ .../lib/repdb/resources/resources_local_inv.v | 76 +++ .../lib/repdb/spec/api_spec.v | 256 ++++++++ .../lib/repdb/spec/db_params.v | 34 ++ .../lib/repdb/spec/events.v | 327 ++++++++++ .../lib/repdb/spec/ras.v | 36 ++ .../lib/repdb/spec/resources.v | 116 ++++ .../lib/repdb/spec/stdpp_utils.v | 200 +++++++ .../lib/repdb/spec/time.v | 46 ++ .../lib/repdb/spec/utils.v | 49 ++ .../proof/client/proof_of_connect_step_1.v | 19 +- .../proof/client/proof_of_connect_step_2.v | 7 +- .../proof/common_user/proof_of_recv.v | 2 +- .../proof/server/proof_of_accept.v | 4 +- .../proof/server/proof_of_make_server_skt.v | 2 +- .../proof_of_server_conn_step_process_data.v | 11 +- ...of_of_server_conn_step_to_establish_conn.v | 9 +- ...oof_of_server_conn_step_to_open_new_conn.v | 11 +- .../proof/server/proof_of_server_listen.v | 13 +- .../proof/server/server_resources.v | 2 +- .../resources/chan_endpoints_resources.v | 8 +- .../resources/chan_session_resources.v | 12 +- .../reliable_communication/spec/api_spec.v | 92 +-- aneris/prelude/list.v | 188 +++++- .../dlm_db_example/dlm_db_example_code.ml | 55 +- .../examples/dlm_db_example/dune | 2 +- .../causality_example_code.ml | 29 + .../examples/repdb_leader_followers/dune | 4 + .../reliable_communication/lib/mt_server/dune | 4 + .../lib/mt_server/mt_server_code.ml | 43 ++ .../lib/mt_server/mt_server_code.mli | 11 + .../reliable_communication/lib/repdb/dune | 2 +- .../lib/repdb/log_code.ml | 7 +- .../lib/repdb/repdb_code.ml | 188 +++--- .../lib/repdb/repdb_code.mli | 8 + 79 files changed, 7231 insertions(+), 588 deletions(-) create mode 100644 aneris/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_proof.v create mode 100644 aneris/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.v create mode 100644 aneris/examples/reliable_communication/examples/repdb_leader_followers/causality_example_proof.v create mode 100644 aneris/examples/reliable_communication/lib/mt_server/mt_server_code.v create mode 100644 aneris/examples/reliable_communication/lib/mt_server/proof/mt_server_proof.v create mode 100644 aneris/examples/reliable_communication/lib/mt_server/spec/api_spec.v create mode 100644 aneris/examples/reliable_communication/lib/mt_server/user_params.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/model.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/notes.txt create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/db_resources_instance.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/follower/clients_at_follower_mt_user_params.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_clients_handler.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_init_follower.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_proxy.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_sync_loop.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/leader/clients_mt_user_params.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/leader/followers_mt_user_params.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_client_handler.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_followers_handler.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_init_leader.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_proxy.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_update_log_copy_loop.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/log_proof.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/proof_of_db_init.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/proof/repdb_serialization.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/resources/log_resources.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/resources/ras.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/resources/resources_def.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/resources/resources_global_inv.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/resources/resources_local_inv.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/spec/api_spec.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/spec/db_params.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/spec/events.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/spec/ras.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/spec/resources.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/spec/stdpp_utils.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/spec/time.v create mode 100644 aneris/examples/reliable_communication/lib/repdb/spec/utils.v create mode 100644 ml_sources/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.ml create mode 100644 ml_sources/examples/reliable_communication/examples/repdb_leader_followers/dune create mode 100644 ml_sources/examples/reliable_communication/lib/mt_server/dune create mode 100644 ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.ml create mode 100644 ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.mli create mode 100644 ml_sources/examples/reliable_communication/lib/repdb/repdb_code.mli diff --git a/_OCamlProject b/_OCamlProject index 53788aa..4c86578 100644 --- a/_OCamlProject +++ b/_OCamlProject @@ -49,16 +49,16 @@ ML_SOURCES: examples/dscm/implementations/one_server/one_server_server_code.ml examples/reliable_communication/client_server_printing.ml examples/reliable_communication/client_server_code.ml + examples/reliable_communication/lib/dlm/dlm_code.ml + examples/reliable_communication/lib/mt_server/mt_server_code.ml + examples/reliable_communication/lib/repdb/log_code.ml + examples/reliable_communication/lib/repdb/repdb_code.ml + examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.ml + examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.ml examples/reliable_communication/examples/hello_world/hello_world_code.ml examples/reliable_communication/examples/hello_world_2/hello_world_2_code.ml examples/reliable_communication/examples/messages_in_order/messages_in_order_code.ml examples/reliable_communication/examples/messages_in_order_loop/messages_in_order_loop_code.ml - examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.ml - examples/reliable_communication/lib/dlm/dlm_code.ml - examples/reliable_communication/lib/ddb/ddb_serialization_code.ml - examples/reliable_communication/lib/ddb/ddb_code.ml - examples/reliable_communication/lib/repdb/log_code.ml - examples/reliable_communication/lib/repdb/repdb_code.ml ML_DEPENDENCIES: @@ -77,13 +77,8 @@ ML_DEPENDENCIES: examples/crdt/statelib/ examples/crdt/statelib/examples/ examples/ccddb/ - examples/stenning/ - examples/distributed_lock_service/ - examples/distributed_lock_service/dynamic - examples/distributed_lock_service/examples examples/reliable_communication/ examples/reliable_communication/lib/ examples/reliable_communication/lib/dlm/ - examples/reliable_communication/lib/ddb/ + examples/reliable_communication/lib/mt_server/ examples/reliable_communication/lib/repdb/ - examples/simple_database/ \ No newline at end of file diff --git a/aneris/aneris_lang/tactics.v b/aneris/aneris_lang/tactics.v index 54b3d49..59ffba4 100644 --- a/aneris/aneris_lang/tactics.v +++ b/aneris/aneris_lang/tactics.v @@ -38,6 +38,7 @@ Ltac reshape_expr e tac := | CAS ?e0 ?e1 ?e2 => add_item (CasRCtx e0 e1) K e2 | MakeAddress ?e0 (Val ?v1) => add_item (MakeAddressLCtx v1) K e0 | MakeAddress ?e0 ?e1 => add_item (MakeAddressRCtx e0) K e1 + | GetAddressInfo ?e => add_item GetAddressInfoCtx K e | NewSocket ?e0 (Val ?v1) (Val ?v2) => add_item (NewSocketLCtx v1 v2) K e0 | NewSocket ?e0 ?e1 (Val ?v2) => add_item (NewSocketMCtx e0 v2) K e1 | NewSocket ?e0 ?e1 ?e2 => add_item (NewSocketRCtx e0 e1) K e2 diff --git a/aneris/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.v b/aneris/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.v index 2866caf..acf68b7 100644 --- a/aneris/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.v +++ b/aneris/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.v @@ -4,48 +4,46 @@ From aneris.aneris_lang Require Import ast. From aneris.aneris_lang.lib.serialization Require Import serialization_code. From aneris.examples.reliable_communication.lib.dlm Require Import dlm_code. -From aneris.examples.reliable_communication.lib.ddb Require Import ddb_code. +From aneris.examples.reliable_communication.lib.repdb Require Import repdb_code. -Definition do_transaction : val := +Definition do_writes : val := λ: "lk" "wr", dlock_acquire "lk";; - "wr" #"x" #1;; - "wr" #"y" #37;; + "wr" #"x" #37;; + "wr" #"y" #1;; dlock_release "lk". -Definition repeat_read_until : val := - λ: "lk" "rd" "k" "v", +Definition do_reads : val := + λ: "lk" "rd", letrec: "loop" <> := dlock_acquire "lk";; - let: "res" := "rd" "k" in - dlock_release "lk";; - (if: "res" = (SOME "v") - then #() - else #() (* unsafe (fun () -> Unix.sleepf 2.0); loop () *);; - "loop" #()) in + let: "vx" := "rd" #"x" in + (if: "vx" = (SOME #37) + then + let: "vy" := "rd" #"y" in + assert: ("vy" = (SOME #1));; + dlock_release "lk";; + "vy" + else + dlock_release "lk";; + #() (* unsafe (fun () -> Unix.sleepf 2.0); *);; + "loop" #()) in "loop" #(). -Definition do_read : val := - λ: "lk" "rd", - repeat_read_until "lk" "rd" #"x" #1;; - #();; - dlock_acquire "lk";; - let: "vy" := "rd" #"y" in - dlock_release "lk";; - assert: ("vy" = (SOME #37)). - Definition node0 : val := - λ: "clt_addr00" "clt_addr01" "dlock_srv_addr" "db_srv_addr", - let: "lk_chan" := dlock_subscribe_client "clt_addr00" "dlock_srv_addr" in - let: "db_funs" := install_proxy int_serializer "clt_addr01" "db_srv_addr" in + λ: "clt_addr00" "clt_addr01" "dl_addr" "db_laddr", + let: "lk_chan" := dlock_subscribe_client "clt_addr00" "dl_addr" in + let: "db_funs" := init_client_leader_proxy int_serializer "clt_addr01" + "db_laddr" in let: "wr" := Fst "db_funs" in let: "_rd" := Snd "db_funs" in - do_transaction "lk_chan" "wr". + do_writes "lk_chan" "wr". Definition node1 : val := - λ: "clt_addr10" "clt_addr11" "dlock_srv_addr" "db_srv_addr", - let: "lk_chan" := dlock_subscribe_client "clt_addr10" "dlock_srv_addr" in - let: "db_funs" := install_proxy int_serializer "clt_addr11" "db_srv_addr" in + λ: "clt_addr10" "clt_addr11" "dl_addr" "db_laddr", + let: "lk_chan" := dlock_subscribe_client "clt_addr10" "dl_addr" in + let: "db_funs" := init_client_leader_proxy int_serializer "clt_addr11" + "db_laddr" in let: "_wr" := Fst "db_funs" in let: "rd" := Snd "db_funs" in - do_read "lk_chan" "rd". + do_reads "lk_chan" "rd". diff --git a/aneris/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_proof.v b/aneris/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_proof.v new file mode 100644 index 0000000..9cdc30d --- /dev/null +++ b/aneris/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_proof.v @@ -0,0 +1,560 @@ +From iris.algebra Require Import excl. +From aneris.aneris_lang Require Import ast. +From aneris.aneris_lang.lib.serialization Require Import serialization_code. +From aneris.aneris_lang Require Import lang. +From aneris.aneris_lang Require Import tactics proofmode. +From aneris.aneris_lang.program_logic + Require Import aneris_weakestpre aneris_lifting. +From aneris.aneris_lang.lib Require Import assert_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.dlm + Require Import dlm_code. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code. +From aneris.examples.reliable_communication.lib.dlm + Require Import dlm_prelude dlm_resources dlm_code dlm_spec. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import + ras events resources api_spec. +From aneris.examples.reliable_communication.examples.dlm_db_example + Require Import dlm_db_example_code. + + +(* -------------------------------------------------------------------------- *) +(** The definition of the resource guarded by the distributed lock manager. *) +(* -------------------------------------------------------------------------- *) +Section proof_of_code. + Context `{!anerisG Mdl Σ}. + Context `{TM: !DB_time, !DBPreG Σ}. + Context (leader_si : message → iProp Σ). + Context (db_sa db_Fsa dlm_sa : socket_address). + + (* ------------------------------------------------------------------------ *) + (** The definition of the parameters for DB and DL and shared resources. *) + (* ------------------------------------------------------------------------ *) + + Local Instance DLSrv : DL_params := + {| + DL_server_addr := dlm_sa; + DL_namespace := (nroot .@ "DLInv"); + |}. + + Local Instance DBSrv : DB_params := + {| + DB_addr := db_sa; + DB_addrF := db_Fsa; + DB_followers := ∅; + DB_keys := {["x"; "y"]}; + DB_InvName := (nroot .@ "DBInv"); + DB_serialization := int_serialization; + DB_ser_inj := int_ser_is_ser_injective; + DB_ser_inj_alt := int_ser_is_ser_injective_alt + |}. + + Context `{!@DB_resources _ _ _ _ DBSrv}. + Context `{!DlockG Σ, !DL_resources}. + + Definition SharedRes : iProp Σ := + ∃ (xv yv : option we) (h : ghst), + "x" ↦ₖ xv ∗ + "y" ↦ₖ yv ∗ + Obs DB_addr h ∗ + ⌜at_key "x" h = xv⌠∗ + ⌜at_key "y" h = yv⌠∗ + ⌜ (∃ xw, xv = Some xw ∧ xw.(we_val) = #37) ↔ + (∃ yw, yv = Some yw ∧ yw.(we_val) = #1)âŒ. + + (* ------------------------------------------------------------------------ *) + (** The proof of the internal do_writes call *) + (* ------------------------------------------------------------------------ *) + Lemma wp_do_writes dl wr clt_00 clt_01 : + ip_of_address clt_00 = ip_of_address clt_01 → + {{{ GlobalInv ∗ + (dl_acquire_spec SharedRes (ip_of_address clt_00) dl) ∗ + (dl_release_spec SharedRes (ip_of_address clt_00) dl) ∗ + (∀ k v h, simplified_write_spec wr clt_01 k v h) ∗ + DLockCanAcquire (ip_of_address clt_00) dl SharedRes }}} + do_writes dl wr @[ip_of_address clt_00] + {{{ RET #(); True }}}. + Proof. + iIntros (HipEq Φ) "(#HGinv & #Hacq & #Hrel & (#Hwr & Hdl)) HΦ". + rewrite /do_writes. + wp_pures. + wp_apply ("Hacq" with "[$Hdl]"). + iIntros "(Hcanrel & Hres)". + wp_pures. + iDestruct "Hres" as (xv yv h) "(Hx & Hy & #Hobs & %Hhx & %Hhy & %Hcnd)". + rewrite HipEq. + wp_apply ("Hwr" $! "x" (SerVal #37) h with "[//] [Hx Hobs]"). + { iExists _. iFrame "#∗". done. } + iIntros "Hpost". + wp_pures. + iDestruct "Hpost" as (hfx ax) "(%Hax & %Hwax & %Hatx & #Hobsx & Hx)". + iApply fupd_aneris_wp. + rewrite -Hhy. + assert (h ≤ₚ (h ++ hfx ++ [ax])) as Hprefix. + { by apply prefix_app_r. } + iCombine "Hy" "Hobsx" as "HyObsx". + iMod (OwnMemKey_obs_frame_prefix DB_addr "y" 1%Qp h (h ++ hfx ++ [ax]) ⊤ + with "HGinv HyObsx") as "(Hy & %HyHeq)"; [done|done|]. + iModIntro. + assert (at_key "x" (h ++ hfx ++ [ax]) = Some ax) as HatAx. + { rewrite app_assoc. by apply at_key_snoc_some. } + wp_apply ("Hwr" $! "y" (SerVal #1) (h ++ hfx ++ [ax]) with "[//] [Hy Hobsx]"). + { iFrame "#∗". iExists _. iFrame "#∗". naive_solver. } + iIntros "Hpost". + wp_pures. + iDestruct "Hpost" as (hfy ay) "(%Hay & %Hway & %Haty & #Hobsy & Hy)". + rewrite -HipEq. + iApply fupd_aneris_wp. + rewrite -HatAx. + assert ((h ++ hfx ++ [ax]) ≤ₚ ((h ++ hfx ++ [ax]) ++ hfy ++ [ay])) as Hprefix'. + { by apply prefix_app_r. } + iCombine "Hx" "Hobsy" as "HxObsy". + iMod (OwnMemKey_obs_frame_prefix + DB_addr "x" 1%Qp + (h ++ hfx ++ [ax]) ((h ++ hfx ++ [ax]) ++ hfy ++ [ay]) + with "HGinv HxObsy") as "(Hx & %HxHeq)"; [done|done|]. + iModIntro. + assert (at_key "y" ((h ++ hfx ++ [ax]) ++ hfy ++ [ay]) = Some ay) as HatAy. + { rewrite app_assoc. by apply at_key_snoc_some. } + iApply ("Hrel" with "[$Hcanrel Hx Hy]"). + { iExists (at_key "x" (h ++ hfx ++ [ax])), + (Some ay), + ((h ++ hfx ++ [ax]) ++ hfy ++ [ay]). + iFrame "#∗". + iSplit; first done. + iSplit; first done. + iPureIntro. + split. + { intros Hx. by exists ay. } + intros Hy. by exists ax. } + iNext. + iIntros "_". + by iApply "HΦ". + Qed. + + (* ------------------------------------------------------------------------ *) + (** The proof of the internal do_reads call *) + (* ------------------------------------------------------------------------ *) + Lemma wp_do_reads dl rd clt_10 clt_11 : + ip_of_address clt_10 = ip_of_address clt_11 → + {{{ GlobalInv ∗ + (∀ k q h, read_spec rd clt_11 k q h) ∗ + (dl_acquire_spec SharedRes (ip_of_address clt_10) dl) ∗ + (dl_release_spec SharedRes (ip_of_address clt_10) dl) ∗ + DLockCanAcquire (ip_of_address clt_10) dl SharedRes }}} + do_reads dl rd @[ip_of_address clt_10] + {{{ v, RET v; ⌜v = SOMEV #1⌠}}}. + Proof. + iIntros (HipEq Φ). + iIntros "(#HGinv & #Hrd & #Hacq & #Hrel & Har) HΦ". + rewrite /do_reads. + do 6 wp_pure _. + iLöb as "IH". + wp_pures. + wp_apply ("Hacq" with "[$Har]"). + iIntros "(Hcanrel & Hres)". + wp_pures. + iDestruct "Hres" as (xv yv h) "(Hx & Hy & #Hobs & %Hhx & %Hhy & %Hcnd)". + rewrite HipEq. + wp_apply ("Hrd" $! "x" 1%Qp xv with "[//][$Hx]"). + iIntros (vo) "Hvo". + iDestruct "Hvo" as "(Hx & %Hxv)". + wp_pures. + rewrite -HipEq. + destruct Hxv as [(-> & ->) | (xwe & -> & ->) ]. + - do 2 (wp_pure _). + wp_apply ("Hrel" with "[$Hcanrel Hx Hy]"). + { iExists _, _, _. + by iFrame "#∗". } + iIntros "Har". + do 4 (wp_pure _). + by iApply ("IH" with "[$Har]"). + - wp_pures. + case_bool_decide as Hxc. + -- wp_pures. + rewrite HipEq. + wp_apply ("Hrd" $! "y" 1%Qp yv with "[//][$Hy]"). + iIntros (vo) "Hvo". + iDestruct "Hvo" as "(Hy & %Hyv)". + destruct Hyv as [(-> & ->) | (ywe & -> & ->) ]. + --- wp_pures. + destruct Hcnd as (Hcnd & _). + assert (∃ yw : we, None = Some yw ∧ we_val yw = #1) as Habs. + { apply Hcnd. naive_solver. } + naive_solver. + --- do 2 (wp_pure _). + assert (∃ yw : we, Some ywe = Some yw ∧ we_val yw = #1) as Hy. + { apply Hcnd. naive_solver. } + wp_apply wp_assert. + wp_pures. + destruct Hy as (yw & Heq & Heq2). + assert (we_val ywe = we_val yw) as -> by naive_solver. + rewrite Heq2. + iSplit; first done. + iNext. + wp_pures. + rewrite -HipEq. + wp_apply ("Hrel" with "[$Hcanrel Hx Hy]"). + { iExists _, _, _. + by iFrame "#∗". } + iIntros "Har". + wp_pures. + by iApply "HΦ". + -- wp_pures. + wp_apply ("Hrel" with "[$Hcanrel Hx Hy]"). + { iExists _, _, _. + by iFrame "#∗". } + iIntros "Har". + do 4 (wp_pure _). + by iApply ("IH" with "[$Har]"). + Qed. + + (* ------------------------------------------------------------------------ *) + (** The proof of the node 0 (writer) *) + (* ------------------------------------------------------------------------ *) + + Lemma proof_of_node0 (clt_00 clt_01 : socket_address) A : + ip_of_address clt_00 = ip_of_address clt_01 → + {{{ GlobalInv ∗ + (* preconditions for subscribing client to dlock. *) + ⌜clt_00 ∉ A⌠∗ + ⌜DL_server_addr ∈ A⌠∗ + dl_subscribe_client_spec SharedRes ∗ + fixed A ∗ + free_ports (ip_of_address clt_00) {[port_of_address clt_00]} ∗ + clt_00 ⤳ (∅, ∅) ∗ + dlm_sa ⤇ dl_reserved_server_socket_interp ∗ + (* preconditions to start a client proxy for the database. *) + ⌜db_sa ∈ A⌠∗ + ⌜clt_01 ∉ A⌠∗ + init_client_proxy_leader_spec leader_si ∗ + db_sa ⤇ leader_si ∗ + clt_01 ⤳ (∅, ∅) ∗ + free_ports (ip_of_address clt_01) {[port_of_address clt_01]} + }}} + node0 #clt_00 #clt_01 #dlm_sa #db_sa @[ip_of_address clt_00] + {{{ RET #(); True }}}. + Proof. + iIntros (HipEq Φ). + iIntros "(#HGinv & %HnInA & %HdlinA & #HdlCltS & + #Hf & Hfps & Hclt00 & #Hdlmsi & Hpre) HΦ". + iDestruct "Hpre" as "(%HinA & %HninA2 & HdbCltS & #Hdbsa & Hclt01 & Hfps3)". + rewrite /node0. + wp_pures. + wp_apply ("HdlCltS" with "[$Hfps $Hclt00 $Hdlmsi $Hf]"); first done. + iIntros (dl) "(Hdl & #Hacq & #Hrel)". + wp_pures. + rewrite HipEq. + simplify_eq /=. + wp_apply ("HdbCltS" $! A clt_01 with "[//][//][$Hfps3 $Hclt01 $Hdbsa $Hf]"). + iIntros (wr rd) "(#Hrd & Hwr)". + iDestruct (get_simplified_write_spec with "Hwr") as "Hwr". + wp_pures. + rewrite -HipEq. + wp_apply (wp_do_writes with "[HGinv Hwr Hdl]"); first done. + { by iFrame "#∗". } + done. + Qed. + + Lemma proof_of_node1 (clt_10 clt_11 : socket_address) A : + ip_of_address clt_10 = ip_of_address clt_11 → + {{{ GlobalInv ∗ + (* preconditions for subscribing client to dlock. *) + ⌜clt_10 ∉ A⌠∗ + ⌜DL_server_addr ∈ A⌠∗ + fixed A ∗ + dl_subscribe_client_spec SharedRes ∗ + free_ports (ip_of_address clt_10) {[port_of_address clt_10]} ∗ + clt_10 ⤳ (∅, ∅) ∗ + dlm_sa ⤇ dl_reserved_server_socket_interp ∗ + (* preconditions to start a client proxy for the database. *) + ⌜db_sa ∈ A⌠∗ + ⌜clt_11 ∉ A⌠∗ + init_client_proxy_leader_spec leader_si ∗ + db_sa ⤇ leader_si ∗ + clt_11 ⤳ (∅, ∅) ∗ + free_ports (ip_of_address clt_11) {[port_of_address clt_11]} + }}} + node1 #clt_10 #clt_11 #dlm_sa #db_sa @[ip_of_address clt_10] + {{{ v, RET v; ⌜v = SOMEV #1⌠}}}. + Proof. + iIntros (HipEq Φ). + iIntros "(#HGinv & %HnInA & %HdlinA & #Hf & #HdlCltS & + Hfps & Hclt00 & #Hdlmsi & Hpre) HΦ". + iDestruct "Hpre" as "(%HinA & %HninA2 & HdbCltS & #Hdbsa & Hclt01 & Hfps3)". + rewrite /node1. + wp_pures. + wp_apply ("HdlCltS" with "[$Hfps $Hclt00 $Hdlmsi $Hf]"); first done. + iIntros (dl) "(Hdl & #Hacq & #Hrel)". + wp_pures. + rewrite HipEq. + simplify_eq /=. + wp_apply ("HdbCltS" $! A clt_11 with "[//][//][$Hfps3 $Hclt01 $Hdbsa $Hf]"). + iIntros (wr rd) "(#Hrd & Hwr)". + wp_pures. + rewrite -HipEq. + wp_apply (wp_do_reads with "[HGinv Hwr Hdl]"); first done. + { by iFrame "#∗". } + iIntros. + by iApply "HΦ". + Qed. + +End proof_of_code. + +(** Concrete parameters (addresses, ips) *) +Definition db_sa := SocketAddressInet "0.0.0.0" 80. +Definition db_Fsa := SocketAddressInet "0.0.0.0" 81. +Definition dlm_sa := SocketAddressInet "0.0.0.1" 80. +Definition clt_sa00 := SocketAddressInet "0.0.0.2" 80. +Definition clt_sa01 := SocketAddressInet "0.0.0.2" 81. +Definition clt_sa10 := SocketAddressInet "0.0.0.3" 80. +Definition clt_sa11 := SocketAddressInet "0.0.0.3" 81. +Definition A : gset socket_address := {[ db_sa; db_Fsa; dlm_sa ]}. +Definition ips : gset string := {[ "0.0.0.0" ; "0.0.0.1"; "0.0.0.2"; "0.0.0.3" ]}. +Global Instance DLP : DL_params := DLSrv dlm_sa. +Global Instance DBP : DB_params := DBSrv db_sa db_Fsa. + +Definition main : expr := + Start "0.0.0.0" (init_leader (DB_serialization.(s_serializer)) #DB_addr #DB_addrF);; + Start "0.0.0.1" (dlock_start_service #dlm_sa) ;; + Start "0.0.0.2" (node0 #clt_sa00 #clt_sa01 #dlm_sa #db_sa) ;; + Start "0.0.0.3" (node1 #clt_sa10 #clt_sa11 #dlm_sa #db_sa). + +Section proof_of_main. + Context `{!anerisG Mdl Σ, lockG Σ}. + Context `{TM: !DB_time, !DBPreG Σ}. + Context (leader_si leaderF_si : message → iProp Σ). + Context (Init_leader : iProp Σ). + Context `{!DlockG Σ, !DL_resources}. + Context `{DBRes : !@DB_resources _ _ _ _ DBP}. + Notation SharedRes := (@SharedRes _ _ _ _ db_sa db_Fsa DBRes). + + Lemma main_spec : + ⊢ |={⊤}=> + GlobalInv -∗ + dl_server_start_service_spec SharedRes -∗ + dl_subscribe_client_spec SharedRes -∗ + init_leader_spec Init_leader leader_si leaderF_si -∗ + init_client_proxy_leader_spec leader_si -∗ + ⌜DL_server_addr ∈ A⌠-∗ + db_sa ⤇ leader_si -∗ + db_Fsa ⤇ leaderF_si -∗ + dlm_sa ⤇ dl_reserved_server_socket_interp -∗ + fixed A -∗ + free_ip "0.0.0.0" -∗ + free_ip "0.0.0.1" -∗ + free_ip "0.0.0.2" -∗ + free_ip "0.0.0.3" -∗ + SocketAddressInet "0.0.0.0" 80 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.0" 81 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.1" 80 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.2" 80 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.2" 81 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.3" 80 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.3" 81 ⤳ (∅, ∅) -∗ + dl_service_init -∗ + Init_leader -∗ + SharedRes -∗ + WP main @["system"] + {{ v, True }}. + Proof. + iIntros "". + iModIntro. + iIntros "#HGinv HdlSrvS #HdlCltS HdbSrvS #HdbCltS". + iIntros "#HinA #Hsrv0 #Hsrv1 #Hsrv2 #Hfixed Hfree0 Hfree1 Hfree2 Hfree3". + iIntros "Hsa0 Hsa1 Hsa2 Hsa3 Hsa4 Hsa5 Hsa6 HSrvInit0 HSrvInit1 HR". + rewrite /main. + (* Server 1. *) + wp_apply (aneris_wp_start {[80%positive; 81%positive]}); first done. + iFrame "Hfree0". + iSplitR "Hsa0 Hsa1 HSrvInit1 HdbSrvS"; last first. + { iNext. iIntros "Hfps". + iApply ("HdbSrvS" $! A + with "[][][][][HSrvInit1 Hfps Hsa0 Hsa1]"); [eauto .. | | done ]. + iDestruct (free_ports_split + "0.0.0.0" + {[80%positive]} {[81%positive]}) as "(Hfp1 & _)"; [set_solver|]. + iFrame "#∗". iApply "Hfp1". iFrame. } + iNext. wp_pures. + (* Server 2. *) + wp_apply aneris_wp_start; first done. + iFrame "Hfree1". + iSplitR "Hsa2 HSrvInit0 HdlSrvS HR"; last first. + { iNext. iIntros "Hfps". + iApply ("HdlSrvS" $! A with "[Hfps HSrvInit0 Hsa2 HR]"); last done. iFrame "#∗". } + iNext. wp_pures. + wp_apply (aneris_wp_start {[80%positive; 81%positive]}); first done. + iFrame "Hfree2". + iSplitR "Hsa3 Hsa4"; last first. + { iNext. iIntros "Hfps". + iApply (proof_of_node0 leader_si db_sa db_Fsa dlm_sa clt_sa00 clt_sa01 A + with "[$HGinv $Hsa3 $Hsa4 Hfps]"); first done. + iSplit. + { iPureIntro. eauto with set_solver. } + iDestruct (free_ports_split + "0.0.0.2" + {[80%positive]} {[81%positive]}) as "(Hfp1 & _)"; [set_solver|]. + iDestruct ("Hfp1" with "Hfps") as "(Hfp & Hfp')". + iFrame "#∗". + iPureIntro; set_solver. + done. } + iNext. wp_pures. + wp_apply (aneris_wp_start {[80%positive; 81%positive]}); first done. + iFrame "Hfree3". + iSplitR "Hsa5 Hsa6"; last first. + { iNext. iIntros "Hfps". + iApply (proof_of_node1 leader_si db_sa db_Fsa dlm_sa clt_sa10 clt_sa11 A + with "[$HGinv $Hsa5 $Hsa6 Hfps]"); first done. + iSplit. + { iPureIntro. eauto with set_solver. } + iDestruct (free_ports_split + "0.0.0.3" + {[80%positive]} {[81%positive]}) as "(Hfp1 & _)"; [set_solver|]. + iDestruct ("Hfp1" with "Hfps") as "(Hfp & Hfp')". + iFrame "#∗". + iPureIntro; set_solver. + done. } + done. + Qed. + +End proof_of_main. + +(* -------------------------------------------------------------------------- *) +(** The proof of adequacy. *) +(* -------------------------------------------------------------------------- *) + +Definition init_state := + {| + state_heaps := {[ "system" := ∅ ]}; + state_sockets := {[ "system" := ∅ ]}; + state_ports_in_use := + <["0.0.0.0" := ∅ ]> $ + <["0.0.0.1" := ∅ ]> $ + <["0.0.0.2" := ∅ ]> $ + <["0.0.0.3" := ∅ ]> $ ∅; + state_ms := ∅; + |}. + +Definition fixed_dom : gset socket_address := {[ db_sa; db_Fsa; dlm_sa ]}. + +Definition dummy_model := model unit (fun x y => True) (). + +Lemma dummy_model_finitary : adequacy.aneris_model_rel_finitary dummy_model. +Proof. + intros st. + intros f Hnot. + pose proof (Hnot 0%nat 1%nat) as H. + assert (0%nat = 1%nat -> False) as Himpl. { + intros Heq. + discriminate Heq. + } + apply Himpl; apply H. + destruct (f 0%nat) as [s0 r0]. + destruct (f 1%nat) as [s1 r1]. + destruct s0, s1, st, r0, r1. + reflexivity. +Qed. + +From stdpp Require Import fin_maps gmap. +From iris.algebra Require Import auth gmap frac excl agree coPset + gset frac_auth ofe excl. +From aneris.algebra Require Import disj_gsets. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang.program_logic Require Import aneris_adequacy. +From aneris.examples.reliable_communication.lib.repdb + Require Import model. +From aneris.examples.reliable_communication.lib.dlm + Require Import dlm_proof. +From aneris.examples.reliable_communication.spec Require Import prelude ras. + +Definition socket_interp `{!anerisG empty_model Σ} + db_si dbF_si dlm_si sa : socket_interp Σ := + (match sa with + | SocketAddressInet "0.0.0.0" 80 => db_si + | SocketAddressInet "0.0.0.0" 81 => dbF_si + | SocketAddressInet "0.0.0.1" 80 => dlm_si + | _ => λ msg, ⌜True⌠+ end)%I. + +Notation ShRes := (@SharedRes _ _ _ _ db_sa db_Fsa). + +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import proof_of_db_init. + +Theorem adequacy : aneris_adequate main "system" init_state (λ _, True). +Proof. + set (Σ := #[anerisΣ dummy_model; DBΣ; SpecChanΣ]). + eapply (@adequacy + Σ dummy_model _ _ ips fixed_dom + {[db_sa; db_Fsa; dlm_sa; clt_sa00; clt_sa01; clt_sa10; clt_sa11]} ∅ ∅ ∅); + try done; last first. + { set_solver. } + { intros i. rewrite /ips !elem_of_union !elem_of_singleton. + intros [|]; subst; simpl; set_solver. } + { rewrite /ips /= !dom_insert_L dom_empty_L right_id_L //. set_solver. } + iIntros (Hdg) "". + 2:{ apply dummy_model_finitary . } + assert (DBPreG Σ) as HPreG by apply _. + iMod (db_init_instance.(DB_init_setup) ⊤) as (DBRes) "Hdb"; + [solve_ndisj|set_solver|set_solver| ]. + iDestruct "Hdb" + as (init_leader leader_si leaderF_si) "(#HGinv & #Hobs & Hkeys & HdbInit & #Hspecs)". + iDestruct "Hspecs" + as "((#HdbSrvS & #HdbCltS) & _)". + iMod (dlinit.(DL_init_setup) ⊤ DLP ShRes) + as (DLRes) "(HdlInit & #HdlSrvS & #HdlCltS)"; + [solve_ndisj| ]. + iExists (socket_interp leader_si leaderF_si dl_reserved_server_socket_interp). + iMod (@main_spec + _ _ _ + int_time leader_si leaderF_si init_leader DLRes DBRes) as "Hmain". + iModIntro. + iIntros "Hf Hsis Hb Hfg Hips _ _ _ _ _". + simpl in *. + iDestruct (big_sepS_delete _ _ db_sa with "Hsis") as "[Hsi0 Hsis]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_Fsa with "Hsis") as "[Hsi1 Hsis]"; + first set_solver. + iDestruct (big_sepS_delete _ _ dlm_sa with "Hsis") as "[Hsi2 _]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "0.0.0.0" with "Hips") as "[Hip0 Hips]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "0.0.0.1" with "Hips") as "[Hip1 Hips]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "0.0.0.2" with "Hips") as "[Hip2 Hips]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "0.0.0.3" with "Hips") as "[Hip3 Hips]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_sa with "Hb") as "[Hm0 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_Fsa with "Hms") as "[Hm1 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ dlm_sa with "Hms") as "[Hm2 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ clt_sa00 with "Hms") as "[Hc00 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ clt_sa01 with "Hms") as "[Hc01 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ clt_sa10 with "Hms") as "[Hc10 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ clt_sa11 with "Hms") as "[Hc11 _]"; + first set_solver. + iApply ("Hmain" with + "[$HGinv][$HdlSrvS][$HdlCltS][$HdbSrvS][$HdbCltS][//] + [$Hsi0][$Hsi1][$Hsi2][$Hf] + [$Hip0][$Hip1][$Hip2][$Hip3] + [$Hm0][$Hm1][$Hm2][$Hc00][$Hc01][$Hc10][$Hc11] + [$HdlInit][$HdbInit]"). + iExists None, None, []. + iDestruct (big_sepS_delete _ _ "x" with "Hkeys") as "[Hx Hkeys]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "y" with "Hkeys") as "[Hy _]"; + first set_solver. + iFrame "#∗". + iPureIntro; split_and!; [done|done|]. + intros. naive_solver. +Qed. diff --git a/aneris/examples/reliable_communication/examples/hello_world/hello_world_proof.v b/aneris/examples/reliable_communication/examples/hello_world/hello_world_proof.v index 978a52a..d2f0bb5 100644 --- a/aneris/examples/reliable_communication/examples/hello_world/hello_world_proof.v +++ b/aneris/examples/reliable_communication/examples/hello_world/hello_world_proof.v @@ -71,10 +71,10 @@ Section proof_of_the_code. iNext. iIntros (skt) "Hcl". wp_pures. wp_apply (RCSpec_server_listen_spec with "[$Hcl][HΦ]"). - iNext. iIntros (v) "(-> & Hp)". + iNext. iIntros "Hp". wp_pures. wp_apply (RCSpec_accept_spec with "[$Hp][HΦ]"). - iNext. iIntros (c caddr v ) "(-> & Hlst & Hc)". + iNext. iIntros (c caddr) "(Hlst & Hc)". wp_pures. simpl in *. rewrite /proto_hello_world. @@ -242,7 +242,7 @@ Proof. { rewrite /ips /= !dom_insert_L dom_empty_L right_id_L //. } iIntros (Hdg) "". 2:{ apply dummy_model_finitary . } - iMod (Reliable_communication_init_instance ⊤ UP $! I) + iMod (Reliable_communication_init_instance ⊤ UP) as (chn sgn SnRes) "(HsrvInit & Hspecs)"; [ solve_ndisj|]. iDestruct "Hspecs" as "( diff --git a/aneris/examples/reliable_communication/examples/hello_world_2/hello_world_2_proof.v b/aneris/examples/reliable_communication/examples/hello_world_2/hello_world_2_proof.v index 544c015..20ce8be 100644 --- a/aneris/examples/reliable_communication/examples/hello_world_2/hello_world_2_proof.v +++ b/aneris/examples/reliable_communication/examples/hello_world_2/hello_world_2_proof.v @@ -165,10 +165,10 @@ Section proof_of_the_server_code. iNext. iIntros (skt) "Hcl". wp_pures. wp_apply (RCSpec_server_listen_spec with "[$Hcl][HΦ]"). - iNext. iIntros (v) "(-> & Hp)". + iNext. iIntros "Hp". wp_pures. wp_apply (RCSpec_accept_spec with "[$Hp][HΦ]"). - iNext. iIntros (c caddr v ) "(-> & Hlst & Hc)". + iNext. iIntros (c caddr) "(Hlst & Hc)". wp_pures. simpl in *. rewrite /proto_hello_world. @@ -341,7 +341,7 @@ Proof. { rewrite /ips /= !dom_insert_L dom_empty_L right_id_L //. set_solver. } iIntros (Hdg) "". 2:{ apply dummy_model_finitary . } - iMod (Reliable_communication_init_instance ⊤ UP0 $! I) + iMod (Reliable_communication_init_instance ⊤ UP0) as (chn0 sgn0 SnRes0) "(HsrvInit0 & Hspecs0)"; [ solve_ndisj|]. iDestruct "Hspecs0" as "( @@ -350,7 +350,7 @@ Proof. & %Hlisten0 & %Haccept0 & %Hsend0 & %HsendTele0 & %HtryRecv0 & %Hrecv0)". - iMod (Reliable_communication_init_instance ⊤ UP1 $! I) + iMod (Reliable_communication_init_instance ⊤ UP1) as (chn1 sgn1 SnRes1) "(HsrvInit1 & Hspecs1)"; [ solve_ndisj|]. iDestruct "Hspecs1" as "( diff --git a/aneris/examples/reliable_communication/examples/messages_in_order/messages_in_order_proof.v b/aneris/examples/reliable_communication/examples/messages_in_order/messages_in_order_proof.v index a0b79de..5d3b3f0 100644 --- a/aneris/examples/reliable_communication/examples/messages_in_order/messages_in_order_proof.v +++ b/aneris/examples/reliable_communication/examples/messages_in_order/messages_in_order_proof.v @@ -74,9 +74,9 @@ Section proof_of_the_code. wp_apply (RCSpec_make_server_skt_spec with "[$Hmh $Hfp $Hf $Hsi $Hit][HΦ]"); first done. iNext. iIntros (skt) "Hcl". wp_pures. wp_apply (RCSpec_server_listen_spec with "[$Hcl][HΦ]"). - iNext. iIntros (v) "(-> & Hp)". wp_pures. + iNext. iIntros "Hp". wp_pures. wp_apply (RCSpec_accept_spec with "[$Hp][HΦ]"). - iNext. iIntros (c caddr v ) "(-> & Hlst & Hc)". + iNext. iIntros (c caddr) "(Hlst & Hc)". wp_pures. simpl in *. rewrite /proto_in_order. wp_recv (m1) as "_". wp_send with "[//]". wp_recv (m2) as "_". wp_send with "[//]". @@ -233,7 +233,7 @@ Proof. { rewrite /ips /= !dom_insert_L dom_empty_L right_id_L //. } iIntros (Hdg) "". 2:{ apply dummy_model_finitary . } - iMod (Reliable_communication_init_instance ⊤ UP $! I) + iMod (Reliable_communication_init_instance ⊤ UP) as (chn sgn SnRes) "(HsrvInit & Hspecs)"; [ solve_ndisj|]. iDestruct "Hspecs" as "( diff --git a/aneris/examples/reliable_communication/examples/messages_in_order_loop/messages_in_order_loop_proof.v b/aneris/examples/reliable_communication/examples/messages_in_order_loop/messages_in_order_loop_proof.v index b80954b..842b019 100644 --- a/aneris/examples/reliable_communication/examples/messages_in_order_loop/messages_in_order_loop_proof.v +++ b/aneris/examples/reliable_communication/examples/messages_in_order_loop/messages_in_order_loop_proof.v @@ -88,7 +88,7 @@ Section proof_of_the_code. iLöb as "IH". wp_pure _. wp_smart_apply (RCSpec_accept_spec with "[$Hlistens]"). - iIntros (c clt_addr v) "(-> & Hlistens & Hc)". + iIntros (c clt_addr) "(Hlistens & Hc)". wp_pures. wp_apply (aneris_wp_fork with "[-]"). iSplitL "Hlistens". @@ -113,7 +113,7 @@ Section proof_of_the_code. wp_smart_apply (RCSpec_make_server_skt_spec with "[$Hmh $Hfp $Hf $Hsi $Hit][HΦ]"); first done. iNext. iIntros (skt) "Hcl". wp_pures. wp_apply (RCSpec_server_listen_spec with "[$Hcl][HΦ]"). - iNext. iIntros (v) "(-> & Hp)". wp_pures. + iNext. iIntros "Hp". wp_pures. wp_apply (aneris_wp_fork with "[-]"). iSplitL "HΦ"; [by iApply "HΦ"|]. iNext. by wp_apply (wp_accept_loop skt with "[$Hp $Hsi][]"). @@ -296,7 +296,7 @@ Proof. { rewrite /ips /= !dom_insert_L dom_empty_L right_id_L //. set_solver. } iIntros (Hdg) "". 2:{ apply dummy_model_finitary . } - iMod (Reliable_communication_init_instance ⊤ UP $! I) + iMod (Reliable_communication_init_instance ⊤ UP) as (chn sgn SnRes) "(HsrvInit & Hspecs)"; [ solve_ndisj|]. iDestruct "Hspecs" as "( diff --git a/aneris/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.v b/aneris/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.v new file mode 100644 index 0000000..aac8169 --- /dev/null +++ b/aneris/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.v @@ -0,0 +1,39 @@ +(* This file is automatically generated from the OCaml source file +<repository_root>/ml_sources/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.ml *) + +From aneris.aneris_lang Require Import ast. +From aneris.aneris_lang.lib.serialization Require Import serialization_code. +From aneris.examples.reliable_communication.lib.repdb Require Import repdb_code. + +Definition do_writes : val := λ: "wr", "wr" #"x" #37;; + "wr" #"y" #1. + +Definition wait_on_read : val := + λ: "rd" "k" "v", + letrec: "loop" <> := + let: "res" := "rd" "k" in + (if: "res" = (SOME "v") + then #() + else + #() (* unsafe (fun () -> Unix.sleepf 2.0); loop ()) *);; + "loop" #()) in + "loop" #(). + +Definition do_reads : val := + λ: "rd", + wait_on_read "rd" #"y" #1;; + let: "vx" := "rd" #"x" in + assert: ("vx" = (SOME #37)). + +Definition node0 : val := + λ: "clt_addr0" "db_laddr", + let: "db_funs" := init_client_leader_proxy int_serializer "clt_addr0" + "db_laddr" in + let: "wr" := Fst "db_funs" in + let: "_rd" := Snd "db_funs" in + do_writes "wr". + +Definition node1 : val := + λ: "clt_addr1" "faddr", + let: "rd" := init_client_follower_proxy int_serializer "clt_addr1" "faddr" in + do_reads "rd". diff --git a/aneris/examples/reliable_communication/examples/repdb_leader_followers/causality_example_proof.v b/aneris/examples/reliable_communication/examples/repdb_leader_followers/causality_example_proof.v new file mode 100644 index 0000000..130c487 --- /dev/null +++ b/aneris/examples/reliable_communication/examples/repdb_leader_followers/causality_example_proof.v @@ -0,0 +1,548 @@ +From iris.algebra Require Import excl. +From iris.base_logic.lib Require Import invariants. +From aneris.prelude Require Import list. +From aneris.aneris_lang Require Import ast. +From aneris.aneris_lang.lib.serialization Require Import serialization_code. +From aneris.aneris_lang Require Import lang. +From aneris.aneris_lang Require Import tactics proofmode adequacy. +From aneris.aneris_lang.program_logic + Require Import aneris_weakestpre aneris_lifting aneris_adequacy. +From aneris.aneris_lang.lib Require Import assert_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.examples.reliable_communication.spec + Require Import prelude ras. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.repdb + Require Import model repdb_code. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import ras events resources api_spec. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import proof_of_db_init. +From aneris.examples.reliable_communication.examples.repdb_leader_followers + Require Import causality_example_code. +From aneris.aneris_lang.program_logic Require Import lightweight_atomic. + +Section proof_of_code. + Context `{!anerisG Mdl Σ}. + Context `{TM: !DB_time, !DBPreG Σ}. + Context (leader_si follower_si : message → iProp Σ). + Context (db_l2csa db_f2csa db_l2fsa : socket_address). + + (* ------------------------------------------------------------------------ *) + (** The definition of the parameters for DB and DL and shared resources. *) + (* ------------------------------------------------------------------------ *) + + Local Instance DBSrv : DB_params := + {| + DB_addr := db_l2csa; + DB_addrF := db_l2fsa; + DB_followers := {[db_f2csa]}; + DB_keys := {["x"; "y"]}; + DB_InvName := (nroot .@ "DBInv"); + DB_serialization := int_serialization; + DB_ser_inj := int_ser_is_ser_injective; + DB_ser_inj_alt := int_ser_is_ser_injective_alt + |}. + + Context `{!@DB_resources _ _ _ _ DBSrv}. + + Definition N := nroot.@"y". + + Lemma wp_wait_on_read clt_00 fsa rd h0: + GlobalInv -∗ + (∀ k h, read_at_follower_spec rd clt_00 fsa k h) -∗ + {{{ Obs fsa h0 }}} + wait_on_read rd #"y" #1 @[ip_of_address clt_00] + {{{ h' a, RET #(); + ⌜h0 `prefix_of` h'⌠∗ Obs fsa h' ∗ + ⌜(we_val a) = #1⌠∗ ⌜at_key "y" h' = Some a⌠}}}. + Proof. + iIntros "#HGinv #Hard". + iIntros "!>" (Φ) "#HobsF HΦ". + wp_lam. wp_pures. + iLöb as "IH". + wp_apply ("Hard" $! "y" ); [done|done|]; iIntros (w). + iDestruct 1 as (h') "(%Hprefix & #HobsF' & + [(-> & %Hatkey)|(%a & -> & %Hatkey)]) /=". + { wp_pures. iApply ("IH" with "HΦ"). } + wp_pures. + case_bool_decide as Ha. + { wp_pures. iApply "HΦ". by naive_solver. } + wp_pures. iApply ("IH" with "HΦ"). + Qed. + + Definition inv_def : iProp Σ := + ("y" ↦ₖ None) ∨ + (∃ h hfx hfy we_y we_x, + "y" ↦ₖ Some we_y ∗ "x" ↦ₖ Some we_x ∗ + Obs db_l2csa (h ++ [we_x] ++ hfx ++ [we_y] ++ hfy) ∗ + ⌜we_val we_x = #37⌠∗ + ⌜at_key "x" h = None⌠∗ ⌜at_key "y" h = None⌠∗ + ⌜at_key "x" hfx = None⌠∗ ⌜at_key "y" hfx = None⌠∗ + ⌜at_key "x" hfy = None⌠∗ ⌜at_key "y" hfy = NoneâŒ). + + Lemma wp_do_writes wr clt_00 : + GlobalInv -∗ + inv N inv_def -∗ + write_spec wr clt_00 -∗ + Obs db_l2csa [] -∗ + {{{ "x" ↦ₖ None }}} + do_writes wr @[ip_of_address clt_00] + {{{ RET #(); True }}}. + Proof. + iIntros "#HGinv #Hinv #Hwr #Hobs". + iIntros "!>" (Φ) "Hx HΦ". + iDestruct (get_simplified_write_spec with "Hwr") as "#Hswr". + iDestruct (write_spec_write_spec_atomic with "Hwr") as "#Hawr". + iClear "Hwr". + wp_lam. + wp_apply ("Hswr" $! _ (SerVal #37) with "[] [Hx]"); [done| |]. + { iExists _. by iFrame "#∗". } + iDestruct 1 as (h a Hkey Hval Hatkey) "[#Hobs' Hx]". + wp_pures. + wp_apply ("Hawr" $! (⊤ ∖ ↑N) _ (SerVal #1)); [solve_ndisj|done|]. + iInv N as "IH" "Hclose". + iDestruct "IH" as "[>Hy | >IH]"; last first. + { iDestruct "IH" as (h' hfx hfy we_y we_x) "(Hy & Hx' & _)". + by iDestruct (OwnMemKey_exclusive with "Hx Hx'") as "[]". } + iMod (OwnMemKey_none_obs with "HGinv [$Hy $Hobs']") as "[Hy %Hhist]"; + [solve_ndisj|]. + assert (at_key "y" ([] ++ h ++ [a]) = None) as Hatkey'. + { rewrite /at_key. by rewrite Hhist. } + iModIntro. + iExists ([] ++ h ++ [a]), None. + iFrame "#∗". iSplit; [done|]. + iNext. + iIntros (h'' a'). + iDestruct 1 as (Hatkey''' Hkey' Hval' Hle) "[Hy #Hobs'']". + iMod (OwnMemKey_some_obs_frame with "HGinv [$Hx Hobs'']") + as "[Hx %Hatkey'''']"; [solve_ndisj| |]. + { assert (([] ++ h ++ [a]) ++ h'' ++ [a'] = + (([] ++ h) ++ [a] ++ (h'' ++ [a']))) as ->; + [by rewrite !assoc|done]. } + assert (at_key "x" h'' = None). + { rewrite at_key_snoc_none in Hatkey''''; [done|by rewrite Hkey']. } + iMod ("Hclose" with "[-HΦ]"); [|by iApply "HΦ"]. + iNext. iRight. iExists h, h'', [], a', a. + rewrite !app_assoc. + iFrame "#∗". + rewrite hist_at_key_empty_at_key in Hhist. + rewrite at_key_snoc_none in Hhist; [done|by rewrite Hkey]. + Qed. + + Lemma wp_do_reads clt_01 rd fsa : + GlobalInv -∗ + (∀ k h, read_at_follower_spec rd clt_01 fsa k h) -∗ + inv N inv_def -∗ + Obs fsa [] -∗ + {{{ True }}} + do_reads rd @[ip_of_address clt_01] + {{{ RET #(); True }}}. + Proof. + iIntros "#HGinv #Hard #Hinv_y #Hobs0". + iIntros "!>" (Φ) "_ HΦ". + wp_lam. + wp_apply (wp_wait_on_read); [done..|]. + iIntros (h a) "(_ & #Hobs & _ & %Hatkey)". + wp_pures. + wp_apply ("Hard" $! "x"); [done..|]. + iIntros (vo) "H". + iDestruct "H" as (h' Hprefix) "(#Hobs' & %Hdisj)". + iApply fupd_aneris_wp. + iInv N as "HI" "Hclose". + iDestruct "HI" as "[>Hy|>HI]". + { iMod (OwnMemKey_none_obs with "HGinv [$Hy $Hobs]")as "[Hy %Hhist]"; + [solve_ndisj|]. + by rewrite /at_key Hhist in Hatkey. } + iDestruct "HI" as (hb hfx hfy we_y we_x) + "(Hy & Hx & #Hobs'' & %Hval & + %Hatkey_hbx & %Hatkey_hby & + %Hatkey_hfxx & %Hatkey_hfxy & + %Hatkey_hfyx & %Hatkey_hfyy)". + iMod (OwnMemKey_key with "HGinv Hx") as "[Hx %Hkey_x]"; [solve_ndisj|]. + iMod (OwnMemKey_key with "HGinv Hy") as "[Hy %Hkey_y]"; [solve_ndisj|]. + assert (at_key "y" (hb ++ [we_x] ++ hfx ++ [we_y] ++ hfy) = Some we_y) + as Hatkey_y. + { rewrite /at_key. + rewrite hist_at_key_frame_l_prefix; [|done]. + rewrite hist_at_key_frame_l_prefix; last first. + { rewrite /at_key /hist_at_key. + rewrite filter_cons_False; [done|by rewrite Hkey_x]. } + rewrite hist_at_key_frame_l_prefix; [|done]. + rewrite hist_at_key_frame_r_suffix; [|done]. + rewrite /at_key /hist_at_key. + rewrite filter_cons_True; [done|by rewrite Hkey_y]. } + assert (at_key "x" (hb ++ [we_x] ++ hfx ++ [we_y] ++ hfy) = Some we_x) + as Hatkey_x. + { rewrite /at_key. + rewrite hist_at_key_frame_l_prefix; [|done]. + rewrite hist_at_key_frame_r_suffix. + { rewrite /at_key /hist_at_key. + rewrite filter_cons_True; [done|by rewrite Hkey_x]. } + rewrite /at_key. + rewrite hist_at_key_frame_l_prefix; [|done]. + rewrite hist_at_key_frame_r_suffix; [|done]. + rewrite /at_key /hist_at_key. + rewrite filter_cons_False; [done|by rewrite Hkey_y]. } + iAssert ("y" ↦ₖ Some we_y ={⊤ ∖ ↑N}=∗ ⌜a = we_y⌠∗ "y" ↦ₖ Some we_y)%I + as "H". + { iDestruct (Obs_compare with "Hobs Hobs''") as %Hprefix'. + iIntros "Hy". + destruct Hprefix' as [Hprefix'|Hprefix']. + - iModIntro. iFrame "Hy". iPureIntro. + rewrite !assoc in Hprefix'. + rewrite -assoc in Hprefix'. + eapply prefix_split_eq; [apply Hatkey| |done|apply Hprefix']. + rewrite !filter_app. + rewrite /at_key /hist_at_key !last_None in + Hatkey_hbx Hatkey_hby Hatkey_hfxx Hatkey_hfyx + Hatkey_hfyy Hatkey_hfxy. + rewrite Hatkey_hby Hatkey_hfxy. + rewrite filter_cons_False; [done| by rewrite Hkey_x]. + - rewrite -Hatkey_y. + iMod (OwnMemKey_obs_frame_prefix with "HGinv [$Hy $Hobs]") + as "[Hy %Heq]"; [solve_ndisj|done|]. + rewrite -Heq in Hatkey. + rewrite Hatkey in Hatkey_y. + iModIntro. + iFrame "Hy". + iPureIntro. + by simplify_eq. } + iMod ("H" with "Hy") as (->) "Hy". iClear "H". + assert (∃ ao : option we, + at_key "x" h' = ao ∧ + ((vo = InjLV #() ∧ ao = None) ∨ + (∃ a : we, vo = InjRV (we_val a) ∧ ao = Some a))) + as [a [Hatkey_a Hdisj']]. + { destruct Hdisj as [Hdisj | Hdisj]. + - destruct Hdisj as [-> Hdisj]. exists None. split; [done|by left]. + - destruct Hdisj as [a [-> Hdisj]]. exists (Some a). + split; [done|by right;eexists _]. } + iAssert ("x" ↦ₖ Some we_x ={⊤ ∖ ↑N}=∗ ⌜a = Some we_x⌠∗ "x" ↦ₖ Some we_x)%I + as "H". + { iDestruct (Obs_compare with "Hobs' Hobs''") as %Hprefix'. + iIntros "Hx". + destruct Hprefix' as [Hprefix'|Hprefix']. + - iModIntro. iFrame "Hx". iPureIntro. + assert (h `prefix_of` hb ++ [we_x] ++ hfx ++ [we_y] ++ hfy) as Hprefix''. + { by eapply transitivity. } + rewrite !assoc in Hprefix''. + rewrite -assoc -assoc in Hprefix''. + assert (((hb ++ [we_x])) `prefix_of` h) as Hprefix'''. + { eapply prefix_Some_None. + - apply Hatkey. + - rewrite !filter_app. + rewrite /at_key /hist_at_key !last_None in + Hatkey_hbx Hatkey_hby Hatkey_hfxx Hatkey_hfyx + Hatkey_hfyy Hatkey_hfxy. + rewrite Hatkey_hby. + rewrite filter_cons_False; [done|by rewrite Hkey_x]. + - apply Hprefix''. } + destruct Hprefix''' as [k ->]. + assert (∃ a', at_key "x" h' = Some a') as [a' Hatkey_a']. + { destruct Hprefix as [k' ->]. + eapply (elem_of_last_filter_exists_Some _ _ a we_x). + - apply Hatkey_a. + - set_solver. + - done. } + assert (a = Some a') as -> by naive_solver. + f_equiv. + eapply prefix_split_eq; [apply Hatkey_a'|apply Hatkey_hbx| |apply Hprefix']. + + rewrite !filter_app. + rewrite /at_key /hist_at_key !last_None in + Hatkey_hbx Hatkey_hby Hatkey_hfxx Hatkey_hfyx + Hatkey_hfyy Hatkey_hfxy. + rewrite Hatkey_hfxx Hatkey_hfyx. + rewrite filter_cons_False; [done|by rewrite Hkey_y]. + - rewrite -Hatkey_x. + iMod (OwnMemKey_obs_frame_prefix with "HGinv [$Hx $Hobs']") + as "[Hy %Heq]"; [solve_ndisj|done|]. + rewrite -Heq in Hatkey_a. + rewrite Hatkey_a in Hatkey_x. + iModIntro. + iFrame "Hy". + iPureIntro. + by simplify_eq. } + iMod ("H" with "Hx") as (->) "Hx". iClear "H". + destruct Hdisj' as [[_ Hineq]|Hdisj']; [done|]. + destruct Hdisj' as [a [-> Heq]]. + assert (we_x = a) as <-. + { by simplify_eq. } + iMod ("Hclose" with "[Hx Hy]") as "_". + { iRight. iExists _, _, _, _, _. by iFrame "Hx Hy #". } + iModIntro. + do 2 wp_pure _. + wp_apply wp_assert. + wp_pures. + rewrite Hval. + iSplit; [done|]. + by iApply "HΦ". + Qed. + + Lemma proof_of_node0 (clt_00 : socket_address) A : + db_l2csa ∈ A → + clt_00 ∉ A → + GlobalInv -∗ + fixed A -∗ + init_client_proxy_leader_spec leader_si -∗ + Obs db_l2csa [] -∗ + inv N inv_def -∗ + {{{ free_ports (ip_of_address clt_00) {[port_of_address clt_00]} ∗ + clt_00 ⤳ (∅, ∅) ∗ + db_l2csa ⤇ leader_si ∗ + "x" ↦ₖ None }}} + node0 #clt_00 #db_l2csa @[ip_of_address clt_00] + {{{ RET #(); True }}}. + Proof. + iIntros (HIndb HnInA) "#HGinv #Hfixed #Hspec #Hobs #Hinv_y". + iIntros "!>" (Φ) "(Hfps & Hclt00 & #Hsi & Hx) HΦ". + wp_lam. + wp_pures. + wp_apply ("Hspec" with "[//] [//] [$Hfps $Hclt00]"); [by iFrame "#"|]. + iIntros (wr rd) "[_ Hwr]". + wp_pures. + iApply (wp_do_writes with "[$] [$] [$] [$] Hx HΦ"). + Qed. + + Lemma proof_of_node1 (clt_01 : socket_address) A : + db_f2csa ∈ A → + clt_01 ∉ A → + GlobalInv -∗ + fixed A -∗ + init_client_proxy_follower_spec db_f2csa follower_si -∗ + Obs db_f2csa [] -∗ + inv N inv_def -∗ + {{{ free_ports (ip_of_address clt_01) {[port_of_address clt_01]} ∗ + clt_01 ⤳ (∅, ∅) ∗ + db_f2csa ⤇ follower_si }}} + node1 #clt_01 #db_f2csa @[ip_of_address clt_01] + {{{ RET #(); True }}}. + Proof. + iIntros (HIndb HnInA) "#HGinv #Hfixed #Hspec #Hobs #Hinv_y". + iIntros "!>" (Φ) "(Hfps & Hclt00 & #Hsi) HΦ". + wp_lam. + wp_pures. + wp_apply ("Hspec" with "[//] [//] [$Hfps $Hclt00]"); [by iFrame "#"|]. + iIntros (rd) "#Hrd". + wp_pures. + by iApply wp_do_reads. + Qed. + +End proof_of_code. + +(** Concrete parameters (addresses, ips) *) +Definition db_l2csa := SocketAddressInet "0.0.0.0" 80. +Definition db_l2fsa := SocketAddressInet "0.0.0.0" 81. +Definition db_f2lsa := SocketAddressInet "0.0.0.1" 80. +Definition db_f2csa := SocketAddressInet "0.0.0.1" 81. +Definition clt_sa0 := SocketAddressInet "0.0.0.2" 80. +Definition clt_sa1 := SocketAddressInet "0.0.0.3" 80. +Definition A : gset socket_address := {[ db_l2csa; db_l2fsa; db_f2csa ]}. +Definition ips : gset string := {[ "0.0.0.0" ; "0.0.0.1"; "0.0.0.2"; "0.0.0.3" ]}. +Global Instance DBP : DB_params := DBSrv db_l2csa db_f2csa db_l2fsa. + +Definition main : expr := + Start "0.0.0.0" (init_leader (DB_serialization.(s_serializer)) + #db_l2csa #db_l2fsa);; + Start "0.0.0.1" (init_follower (DB_serialization.(s_serializer)) #db_l2fsa + #db_f2lsa #db_f2csa);; + Start "0.0.0.2" (node0 #clt_sa0 #db_l2csa);; + Start "0.0.0.3" (node1 #clt_sa1 #db_f2csa). + + +Section proof_of_main. + Context `{!anerisG Mdl Σ, lockG Σ}. + Context `{TM: !DB_time, !DBPreG Σ}. + Context (leader_si leaderF_si follower_si : message → iProp Σ). + Context (InitL InitF : iProp Σ). + Context `{DBRes : !@DB_resources _ _ _ _ DBP}. + + Lemma main_spec : + ⊢ |={⊤}=> + GlobalInv -∗ + init_leader_spec InitL leader_si leaderF_si -∗ + init_client_proxy_leader_spec leader_si -∗ + init_follower_spec db_f2csa InitF follower_si leaderF_si -∗ + init_client_proxy_follower_spec db_f2csa follower_si -∗ + db_l2csa ⤇ leader_si -∗ + db_l2fsa ⤇ leaderF_si -∗ + db_f2csa ⤇ follower_si -∗ + fixed A -∗ + Obs db_l2csa [] -∗ + Obs db_f2csa [] -∗ + inv N (inv_def db_l2csa db_f2csa db_l2fsa) -∗ + free_ip "0.0.0.0" -∗ + free_ip "0.0.0.1" -∗ + free_ip "0.0.0.2" -∗ + free_ip "0.0.0.3" -∗ + SocketAddressInet "0.0.0.0" 80 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.0" 81 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.1" 80 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.1" 81 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.2" 80 ⤳ (∅, ∅) -∗ + SocketAddressInet "0.0.0.3" 80 ⤳ (∅, ∅) -∗ + InitL -∗ + InitF -∗ + "x" ↦ₖ None -∗ + WP main @["system"] + {{ v, True }}. + Proof. + iIntros "". + iModIntro. + iIntros "#HGinv #HdbSrvS #HdbCltS #HdbFS #HdbCltF". + iIntros "#Hdb_l2csa #Hdb_l2fsa #Hdb_f2csa #Hfixed #HobsL #HobsF #HI". + iIntros "Hfree0 Hfree1 Hfree2 Hfree3". + iIntros "Hsa0 Hsa1 Hsa2 Hsa3 Hsa4 Hsa5 HInitL HInitF". + iIntros "Hx". + rewrite /main. + wp_apply (aneris_wp_start {[80%positive; 81%positive]}); first done. + iFrame "Hfree0". + iSplitR "Hsa0 Hsa1 HInitL"; last first. + { iNext. iIntros "Hfps". + iApply ("HdbSrvS" $! A + with "[][][][][HInitL Hfps Hsa0 Hsa1]"); [eauto .. | | done ]. + iDestruct (free_ports_split + "0.0.0.0" + {[80%positive]} {[81%positive]}) as "(Hfp1 & _)"; [set_solver|]. + iFrame "#∗". iApply "Hfp1". iFrame. } + iNext. wp_pures. + wp_apply (aneris_wp_start {[80%positive;81%positive]}); first done. + iFrame "Hfree1". + iSplitR "Hsa2 Hsa3 HInitF"; last first. + { iNext. iIntros "Hfps". + iApply ("HdbFS" $! db_f2lsa A with "[//][//][][//][//][Hfps HInitF Hsa2 Hsa3]"); + [iPureIntro; set_solver| |done]. + iDestruct (free_ports_split + "0.0.0.1" + {[80%positive]} {[81%positive]} with "Hfps") + as "(Hfp1 & Hfp2)"; [set_solver|]. + iFrame "#∗". } + iNext. wp_pures. + wp_apply (aneris_wp_start {[80%positive]}); first done. + iFrame "Hfree2". + iSplitR "Hsa4 Hx"; last first. + { iNext. iIntros "Hfps". + iApply (proof_of_node0 leader_si db_l2csa db_f2csa db_l2fsa clt_sa0 A + with "HGinv Hfixed HdbCltS HobsL HI [Hsa4 Hfps Hx]"); + [done|set_solver| |done]. + iFrame "#∗". } + iNext. wp_pures. + wp_apply (aneris_wp_start {[80%positive]}); first done. + iFrame "Hfree3". + iSplitR "Hsa5"; last first. + { iNext. iIntros "Hfps". + iApply (proof_of_node1 follower_si db_l2csa db_f2csa db_l2fsa clt_sa1 A + with "HGinv Hfixed HdbCltF HobsF HI [Hsa5 Hfps]"); + [done|set_solver| |done]. + iFrame "#∗". } + done. + Qed. + +End proof_of_main. + +Definition init_state := + {| + state_heaps := {[ "system" := ∅ ]}; + state_sockets := {[ "system" := ∅ ]}; + state_ports_in_use := + <["0.0.0.0" := ∅ ]> $ + <["0.0.0.1" := ∅ ]> $ + <["0.0.0.2" := ∅ ]> $ + <["0.0.0.3" := ∅ ]> $ ∅; + state_ms := ∅; + |}. + +Definition dummy_model := model unit (fun x y => True) (). + +Lemma dummy_model_finitary : adequacy.aneris_model_rel_finitary dummy_model. +Proof. + intros st. + intros f Hnot. + pose proof (Hnot 0%nat 1%nat) as H. + assert (0%nat = 1%nat -> False) as Himpl. { + intros Heq. + discriminate Heq. + } + apply Himpl; apply H. + destruct (f 0%nat) as [s0 r0]. + destruct (f 1%nat) as [s1 r1]. + destruct s0, s1, st, r0, r1. + reflexivity. +Qed. + +Definition socket_interp `{!anerisG empty_model Σ} + db_l2csi db_l2fsi db_f2csi sa : socket_interp Σ := + (match sa with + | SocketAddressInet "0.0.0.0" 80 => db_l2csi + | SocketAddressInet "0.0.0.0" 81 => db_l2fsi + | SocketAddressInet "0.0.0.1" 81 => db_f2csi + | _ => λ msg, ⌜True⌠+ end)%I. + +Theorem adequacy : aneris_adequate main "system" init_state (λ _, True). +Proof. + set (Σ := #[anerisΣ dummy_model; DBΣ; SpecChanΣ ]). + eapply (@adequacy + Σ dummy_model _ _ ips A + {[db_l2csa; db_l2fsa; db_f2lsa; db_f2csa; clt_sa0; clt_sa1]} ∅ ∅ ∅); + try done; last first. + { set_solver. } + { intros i. rewrite /ips !elem_of_union !elem_of_singleton. + intros [|]; subst; simpl; set_solver. } + { rewrite /ips /= !dom_insert_L dom_empty_L right_id_L //. set_solver. } + iIntros (Hdg) "". + 2:{ apply dummy_model_finitary . } + assert (DBPreG Σ) as HPreG by apply _. + iMod (DB_init_setup ⊤) as (DBRes) "Hdb"; + [solve_ndisj|set_solver|set_solver| ]. + iDestruct "Hdb" + as (InitL leader_si leaderF_si) "(#HGinv & #Hobs & Hkeys & HInitL & + #[HinitL_spec HinitL_proxy_spec] & + HF)". + rewrite big_sepS_singleton. + iDestruct "HF" as (follower_si InitF) "(HInitF & #HobsF & + #HinitF_spec & #HinitF_proxy_spec)". + iExists (socket_interp leader_si leaderF_si follower_si). + iMod (@main_spec + _ _ _ + int_time leader_si leaderF_si follower_si InitL InitF DBRes) as "Hmain". + iModIntro. + iIntros "Hf Hsis Hb Hfg Hips _ _ _ _ _". + iDestruct (big_sepS_delete _ _ db_l2csa with "Hsis") as "[Hsi0 Hsis]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_l2fsa with "Hsis") as "[Hsi1 Hsis]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_f2csa with "Hsis") as "[Hsi2 _]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "0.0.0.0" with "Hips") as "[Hip0 Hips]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "0.0.0.1" with "Hips") as "[Hip1 Hips]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "0.0.0.2" with "Hips") as "[Hip2 Hips]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "0.0.0.3" with "Hips") as "[Hip3 Hips]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_l2csa with "Hb") as "[Hm0 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_l2fsa with "Hms") as "[Hm1 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_f2lsa with "Hms") as "[Hm2 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ db_f2csa with "Hms") as "[Hm3 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ clt_sa0 with "Hms") as "[Hc0 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ clt_sa1 with "Hms") as "[Hc1 Hms]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "x" with "Hkeys") as "[Hx Hkeys]"; + first set_solver. + iDestruct (big_sepS_delete _ _ "y" with "Hkeys") as "[Hy _]"; + first set_solver. + iMod (inv_alloc N _ (inv_def db_l2csa db_f2csa db_l2fsa) with "[Hy]") as "HI". + { by iLeft. } + iApply ("Hmain" with + "HGinv HinitL_spec HinitL_proxy_spec HinitF_spec HinitF_proxy_spec + Hsi0 Hsi1 Hsi2 Hf Hobs HobsF HI Hip0 Hip1 Hip2 Hip3 + Hm0 Hm1 Hm2 Hm3 Hc0 Hc1 HInitL HInitF Hx"). +Qed. diff --git a/aneris/examples/reliable_communication/instantiation/instantiation_of_client_specs.v b/aneris/examples/reliable_communication/instantiation/instantiation_of_client_specs.v index c3a35d5..699ac73 100644 --- a/aneris/examples/reliable_communication/instantiation/instantiation_of_client_specs.v +++ b/aneris/examples/reliable_communication/instantiation/instantiation_of_client_specs.v @@ -34,32 +34,30 @@ Section Client_API_spec_instantiation. Implicit Types p : iProto Σ. Implicit Types TT : tele. - Lemma make_client_skt_spec_holds clt_addr A: + Lemma make_client_skt_spec_holds : make_client_skt_spec User_params - session_resources_instance - clt_addr A. + session_resources_instance. Proof. rewrite /make_client_skt_spec. rewrite /make_client_skt. rewrite /CltCanConnect /session_resources_instance. - iIntros (Φ) "(H1 & H2 & H3 & H4) HΦ". + iIntros (clt_addr A Φ) "(H1 & H2 & H3 & H4) HΦ". iDestruct (make_client_skt_internal_spec_holds clt_addr $! Φ with "[$H1 $H2 $H3 $H4][HΦ]") as "Hspec". iNext. iIntros (skt h s) "Hr". iApply "HΦ". eauto with iFrame. iApply "Hspec". Qed. - Lemma make_connect_skt_spec_holds skt clt_addr: - connect_spec - User_params - session_resources_instance - skt clt_addr. + Lemma make_connect_skt_spec_holds : + connect_spec + User_params + session_resources_instance. Proof. rewrite /make_client_skt_spec. rewrite /connect_spec. rewrite /CltCanConnect /session_resources_instance. - iIntros (Φ) "(%h & %s & Hres) HΦ". + iIntros (skt clt_addr Φ) "(%h & %s & Hres) HΦ". iApply (connect_internal_spec with "[Hres][HΦ]"). - iExists _, _. iFrame. - iNext. iIntros (γe c) "(Hpost & _)". diff --git a/aneris/examples/reliable_communication/instantiation/instantiation_of_init.v b/aneris/examples/reliable_communication/instantiation/instantiation_of_init.v index c24f547..adef2f5 100644 --- a/aneris/examples/reliable_communication/instantiation/instantiation_of_init.v +++ b/aneris/examples/reliable_communication/instantiation/instantiation_of_init.v @@ -27,22 +27,22 @@ Section Init_initialisation. Lemma Reliable_communication_init_instance E (UP : Reliable_communication_service_params) : ↑RCParams_srv_N ⊆ E → - True ⊢ |={E}=> + ⊢ |={E}=> ∃ ( _ : Chan_mapsto_resource), ∃ ( _ : server_ghost_names), ∃ (SnRes : SessionResources UP), SrvInit ∗ - ⌜(∀ sa A, make_client_skt_spec UP SnRes sa A)⌠∗ - ⌜(∀ A, make_server_skt_spec UP SnRes A)⌠∗ - ⌜(∀ skt sa, connect_spec UP SnRes skt sa)⌠∗ - ⌜(∀ skt, server_listen_spec UP SnRes skt)⌠∗ - ⌜(∀ skt, accept_spec UP SnRes skt)⌠∗ - ⌜(∀ c v p ip ser, send_spec c v p ip ser)⌠∗ - ⌜(∀ TT c t v P q ip s, send_spec_tele TT c t v P q ip s)⌠∗ - ⌜(∀ TT c v P q ip ser, try_recv_spec TT c v P q ip ser)⌠∗ - ⌜(∀ TT c v P q ip ser, recv_spec TT c v P q ip ser)âŒ. + ⌜make_client_skt_spec UP SnRes⌠∗ + ⌜make_server_skt_spec UP SnRes⌠∗ + ⌜connect_spec UP SnRes⌠∗ + ⌜server_listen_spec UP SnRes⌠∗ + ⌜accept_spec UP SnRes⌠∗ + ⌜send_spec⌠∗ + ⌜send_spec_tele⌠∗ + ⌜try_recv_spec⌠∗ + ⌜recv_specâŒ. Proof. - iIntros (Hne _). + iIntros (Hne). iMod (own_alloc (â— ((to_agree <$> ∅) : session_names_mapUR))) as (γ_srv_kn_s_name) "Hkns"; first by apply auth_auth_valid. iMod (own_alloc (â— (∅ : gsetUR message) â‹… (â—¯ (∅ : gsetUR message)))) @@ -72,8 +72,7 @@ Section Init_initialisation. split. intros E UP Hn. iStartProof. - iMod (Reliable_communication_init_instance E UP Hn $! I) as "Hinit". - iIntros (_). + iMod (Reliable_communication_init_instance E UP Hn) as "Hinit". iModIntro. iDestruct "Hinit" as (???) "Hinit". eauto with iFrame. diff --git a/aneris/examples/reliable_communication/instantiation/instantiation_of_send_and_recv_specs.v b/aneris/examples/reliable_communication/instantiation/instantiation_of_send_and_recv_specs.v index 4cf3edf..f9509eb 100644 --- a/aneris/examples/reliable_communication/instantiation/instantiation_of_send_and_recv_specs.v +++ b/aneris/examples/reliable_communication/instantiation/instantiation_of_send_and_recv_specs.v @@ -33,25 +33,22 @@ Section Send_Recv_API_spec_instantiation. Implicit Types p : iProto Σ. Implicit Types TT : tele. - Lemma send_spec_holds (c : val) v p ip serA: - send_spec (c : val) v p ip serA. + Lemma send_spec_holds : + send_spec. Proof. rewrite /send_spec. - iIntros (Φ) "(H1 & H2) HΦ". + iIntros (c v p ip serA Φ) "(H1 & H2) HΦ". iDestruct "H1" as (γe) "H1". iApply (send_spec_internal _ _ _ p with "[$][HΦ]"). iNext. iIntros "Hc". iApply "HΦ". iExists _. iFrame. Qed. - Lemma send_tele_spec_holds - TT c (tt : TT) (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip serA: - send_spec_tele - TT c (tt : TT) - (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip serA. + Lemma send_tele_spec_holds : + send_spec_tele. Proof. rewrite /send_spec_tele. - iIntros (Φ) "(H1 & Hp & H2) HΦ". + iIntros (TT c tt v P p ip serA Φ) "(H1 & Hp & H2) HΦ". iDestruct "H1" as (γe) "H1". iApply (send_spec_tele_internal _ _ _ _ _ _ with "[-HΦ][HΦ]"). - by iFrame. @@ -59,13 +56,11 @@ Section Send_Recv_API_spec_instantiation. iExists _. iFrame. Qed. - Lemma try_recv_spec_holds - TT (c : val) (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip ser: - try_recv_spec - TT (c : val) (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip ser. + Lemma try_recv_spec_holds : + try_recv_spec. Proof. rewrite /try_recv_spec. - iIntros (Φ) "H1 HΦ". + iIntros (TT c v P p ip ser Φ) "H1 HΦ". iDestruct "H1" as (γe) "H1". iApply (try_recv_spec_internal _ _ _ with "[$][HΦ]"). iNext. iIntros (w) "Hc". iApply "HΦ". @@ -79,18 +74,15 @@ Section Send_Recv_API_spec_instantiation. iExists _. iFrame. Qed. - Lemma recv_spec_holds - TT (c : val) (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip ser: - recv_spec - TT (c : val) (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip ser. + Lemma recv_spec_holds : + recv_spec. Proof. rewrite /recv_spec. - iIntros (Φ) "H1 HΦ". + iIntros (TT c v P p ip ser Φ) "H1 HΦ". iDestruct "H1" as (γe) "H1". iApply (recv_spec_internal _ _ _ with "[$][HΦ]"). iNext. iIntros (w) "(Hc & Hp)". iApply "HΦ". iFrame. iExists _. iFrame. Qed. - End Send_Recv_API_spec_instantiation. diff --git a/aneris/examples/reliable_communication/instantiation/instantiation_of_server_specs.v b/aneris/examples/reliable_communication/instantiation/instantiation_of_server_specs.v index e162a40..0d6c024 100644 --- a/aneris/examples/reliable_communication/instantiation/instantiation_of_server_specs.v +++ b/aneris/examples/reliable_communication/instantiation/instantiation_of_server_specs.v @@ -31,47 +31,43 @@ Section Server_API_spec_instantiation. Context `{!server_ghost_names}. Context `{User_params: !Reliable_communication_service_params}. - Lemma make_server_skt_spec_holds A : + Lemma make_server_skt_spec_holds : make_server_skt_spec - User_params - session_resources_instance A. + User_params + session_resources_instance. Proof. rewrite /make_server_skt_spec. rewrite /SrvInit /session_resources_instance /SrvInitRes /SrvCanListen. - iIntros (Φ) "(H1 & H2 & H3 & H4 & H5 & H6 & H7 & H8) HΦ". - iApply (make_server_skt_internal_spec with - "[$][$HΦ]"). + iIntros (A Φ) "(H1 & H2 & H3 & H4 & H5 & H6 & H7 & H8) HΦ". + iApply (make_server_skt_internal_spec with "[$][$HΦ]"). Qed. - Lemma server_listen_spec_holds skt: - server_listen_spec - User_params - session_resources_instance - skt. + Lemma server_listen_spec_holds : + server_listen_spec + User_params + session_resources_instance. Proof. rewrite /server_listen_spec. rewrite /SrvCanListen /SrvListens. - iIntros (Φ) "Hyp HΦ". - iApply (server_listen_internal_spec with - "[$][$HΦ]"). + iIntros (skt Φ) "Hyp HΦ". + simpl. + iApply (server_listen_internal_spec with "[$][$HΦ]"). Qed. - Lemma accept_spec_holds skt: - accept_spec - User_params - session_resources_instance - skt. + Lemma accept_spec_holds : + accept_spec + User_params + session_resources_instance. Proof. rewrite /server_listen_spec. rewrite /session_resources_instance !/SrvListens. rewrite /chan_mapsto_resource_instance. - iIntros (Φ) "Hyp HΦ". + iIntros (skt Φ) "Hyp HΦ". iApply (accept_internal_spec with "[$Hyp][HΦ]"). iNext. - iIntros (γe c caddr v) "(%Heq & (H1 & H2 & _))". + iIntros (γe c clt_addr) "(H1 & H2 & _)". iApply "HΦ". rewrite /SrvListens. - iSplit; first done. iFrame. iExists _; iFrame. Qed. diff --git a/aneris/examples/reliable_communication/lib/dlm/dlm_prelude.v b/aneris/examples/reliable_communication/lib/dlm/dlm_prelude.v index b4d5ae6..25f646d 100644 --- a/aneris/examples/reliable_communication/lib/dlm/dlm_prelude.v +++ b/aneris/examples/reliable_communication/lib/dlm/dlm_prelude.v @@ -2,7 +2,7 @@ From aneris.aneris_lang Require Import lang. From aneris.aneris_lang.lib Require Import inject list_proof. From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. -Class DL_params `{!anerisG Mdl Σ} := { +Class DL_params := { DL_server_addr : socket_address; DL_namespace : namespace; }. diff --git a/aneris/examples/reliable_communication/lib/dlm/dlm_proof.v b/aneris/examples/reliable_communication/lib/dlm/dlm_proof.v index 399e428..5316334 100644 --- a/aneris/examples/reliable_communication/lib/dlm/dlm_proof.v +++ b/aneris/examples/reliable_communication/lib/dlm/dlm_proof.v @@ -9,8 +9,12 @@ From aneris.aneris_lang Require Import tactics proofmode. From actris.channel Require Export proto. From aneris.aneris_lang.program_logic Require Import aneris_lifting. From aneris.examples.reliable_communication Require Import user_params. -From aneris.examples.reliable_communication.spec Require Import resources proofmode api_spec. -From aneris.examples.reliable_communication.lib.dlm Require Import dlm_code dlm_prelude. +From aneris.examples.reliable_communication.spec Require Import resources proofmode api_spec prelude ras. +From aneris.examples.reliable_communication.lib.dlm Require Import dlm_code dlm_prelude dlm_spec. +From aneris.examples.reliable_communication.instantiation + Require Import + instantiation_of_resources + instantiation_of_init. Import client_server_code. Import lock_proof. @@ -28,15 +32,14 @@ Section DL_proof_of_code. Notation srv_port := (port_of_address DL_server_addr). Notation dlN := (DL_namespace .@ "lk"). - Definition dlock_protocol_aux (rec : string -d> iProto Σ) : string -d> iProto Σ := - λ s, - let rec : string -d> iProto Σ := rec in - (<!> MSG #s {{ (⌜s = "acquire"âŒ) ∨ (⌜s = "release"⌠∗ (dl_locked_internal ∗ R)) }} ; - if bool_decide (s = "acquire") - then - (<?> MSG #"acquire_OK" {{ (dl_locked_internal ∗ R) }}; - rec "release") - else (rec "acquire"))%proto. + Definition dlock_protocol_aux (rec : bool -d> iProto Σ) : bool -d> iProto Σ := + λ b, if b then + (<!> MSG #"acquire" ; + <?> MSG #"acquire_OK" {{ dl_locked_internal ∗ R }}; + rec (negb b))%proto + else + (<!> MSG #"release" {{ dl_locked_internal ∗ R }}; + rec (negb b))%proto. Global Instance dlock_protocol_aux_contractive : Contractive dlock_protocol_aux. Proof. solve_proper_prepare. f_equiv; solve_proto_contractive. Qed. @@ -45,17 +48,17 @@ Section DL_proof_of_code. ProtoUnfold (dlock_protocol s) (dlock_protocol_aux dlock_protocol s). Proof. apply proto_unfold_eq, (fixpoint_unfold dlock_protocol_aux). Qed. - Global Instance UP : Reliable_communication_service_params := - {| RCParams_clt_ser := string_serialization; - RCParams_srv_ser := string_serialization; - RCParams_srv_ser_inj := ser_inj.string_ser_is_ser_injective; - RCParams_srv_ser_inj_alt := ser_inj.string_ser_is_ser_injective_alt; - RCParams_clt_ser_inj := ser_inj.string_ser_is_ser_injective; - RCParams_clt_ser_inj_alt := ser_inj.string_ser_is_ser_injective_alt; - RCParams_srv_saddr := DL_server_addr; - RCParams_protocol := dlock_protocol "acquire"; - RCParams_srv_N := DL_namespace; - |}. + Local Instance UP : Reliable_communication_service_params := + {| RCParams_clt_ser := string_serialization; + RCParams_srv_ser := string_serialization; + RCParams_srv_ser_inj := ser_inj.string_ser_is_ser_injective; + RCParams_srv_ser_inj_alt := ser_inj.string_ser_is_ser_injective_alt; + RCParams_clt_ser_inj := ser_inj.string_ser_is_ser_injective; + RCParams_clt_ser_inj_alt := ser_inj.string_ser_is_ser_injective_alt; + RCParams_srv_saddr := DL_server_addr; + RCParams_protocol := dlock_protocol true; + RCParams_srv_N := DL_namespace; + |}. Context `{cmh: !@Chan_mapsto_resource Σ}. Context `{SnRes : !SessionResources UP}. @@ -66,24 +69,24 @@ Section DL_proof_of_code. is_lock dlN ip γlk lk (R ∗ dl_locked_internal). Definition is_dlock_server_connection_state - (ip : ip_address) (γlk : gname) (c : val) (s : string) - : iProp Σ := - (⌜s = "acquire"⌠∨ (⌜s = "release"⌠∗ locked γlk)) ∗ - c ↣{ ip, string_serialization} (iProto_dual (dlock_protocol s)). - + (ip : ip_address) (γlk : gname) (c : val) (b : bool) : iProp Σ := + (if b then ⌜TrueâŒ%I else locked γlk) ∗ + c ↣{ ip, string_serialization} (iProto_dual (dlock_protocol b)). Definition dl_acquire_internal_spec (sa : socket_address) (dl : val) : Prop := - {{{ dl ↣{ ip_of_address sa, string_serialization } (dlock_protocol "acquire") }}} - dlock_acquire dl @[ip_of_address sa] - {{{ RET #(); dl ↣{ ip_of_address sa, string_serialization } (dlock_protocol "release") ∗ - dl_locked_internal ∗ R }}}. + {{{ dl ↣{ ip_of_address sa, string_serialization } + (dlock_protocol true) }}} + dlock_acquire dl @[ip_of_address sa] + {{{ RET #(); dl ↣{ ip_of_address sa, string_serialization } + (dlock_protocol false) ∗ + dl_locked_internal ∗ R }}}. Lemma dl_acquire_internal_spec_holds sa dl : dl_acquire_internal_spec sa dl. Proof. iIntros (Φ) "Hdlk HΦ". rewrite /dlock_acquire. wp_pures. - wp_send with "[]"; first by iLeft. + wp_send with "[//]". wp_pures. wp_recv as "[Hdlk_key HR]". wp_pures. @@ -92,31 +95,33 @@ Section DL_proof_of_code. Qed. Definition dl_release_internal_spec (sa : socket_address) (dl : val) : Prop := - {{{ dl ↣{ ip_of_address sa, string_serialization } (dlock_protocol "release") ∗ + {{{ dl ↣{ ip_of_address sa, string_serialization } (dlock_protocol false) ∗ dl_locked_internal ∗ R }}} dlock_release dl @[ip_of_address sa] - {{{ RET #(); dl ↣{ ip_of_address sa, string_serialization } (dlock_protocol "acquire") }}}. + {{{ RET #(); dl ↣{ ip_of_address sa, string_serialization } (dlock_protocol true) }}}. Lemma dl_release_internal_spec_holds sa dl : dl_release_internal_spec sa dl. Proof. iIntros (Φ) "(Hdlk & Hkey & HR) HΦ". rewrite /dlock_release. wp_pures. - wp_send with "[Hkey HR]". - - iRight; by iFrame. - - by iApply "HΦ"; eauto with iFrame. + wp_send with "[$Hkey $HR]". + by iApply "HΦ"; eauto with iFrame. Qed. - Definition dl_subscribe_client_internal_spec sa A : iProp Σ := - {{{ ⌜sa ∉ A⌠∗ fixed A ∗ free_ports (ip_of_address sa) {[port_of_address sa]} ∗ +Definition dl_subscribe_client_internal_spec sa A : iProp Σ := + {{{ ⌜sa ∉ A⌠∗ fixed A ∗ + free_ports (ip_of_address sa) {[port_of_address sa]} ∗ DL_server_addr ⤇ reserved_server_socket_interp ∗ sa ⤳ (∅, ∅) }}} dlock_subscribe_client #sa #DL_server_addr @[ip_of_address sa] - {{{ dl, RET dl; dl ↣{ ip_of_address sa, string_serialization } (dlock_protocol "acquire") ∗ - ⌜dl_acquire_internal_spec sa dl⌠∗ - ⌜dl_release_internal_spec sa dl⌠}}}. + {{{ dl, RET dl; dl ↣{ ip_of_address sa, string_serialization } + (dlock_protocol true) ∗ + ⌜dl_acquire_internal_spec sa dl⌠∗ + ⌜dl_release_internal_spec sa dl⌠}}}. - Lemma dl_subscribe_client_internal_spec_holds sa A : ⊢ dl_subscribe_client_internal_spec sa A. + Lemma dl_subscribe_client_internal_spec_holds sa A : + ⊢ dl_subscribe_client_internal_spec sa A. Proof. iIntros (Φ) "!#". iIntros "(#HnA & #Hf & Hfp & #Hsi & Hmh) HΦ". @@ -127,38 +132,39 @@ Section DL_proof_of_code. wp_apply (RCSpec_connect_spec with "[$Hcl][HΦ]"). iNext. iIntros (dl) "Hc". wp_pures. iApply "HΦ". - iFrame. by eauto using dl_acquire_internal_spec_holds, dl_release_internal_spec_holds. + iFrame. + by eauto using dl_acquire_internal_spec_holds, + dl_release_internal_spec_holds. Qed. - Lemma wp_listen_to_client c lk γlk s : - {{{ is_dlock_server_connection_state srv_ip γlk c s ∗ + Lemma wp_listen_to_client c lk γlk b : + {{{ is_dlock_server_connection_state srv_ip γlk c b ∗ is_lock dlN srv_ip γlk lk (dl_locked_internal ∗ R) }}} listen_to_client lk c @[ip_of_address RCParams_srv_saddr] {{{ v, RET v ; False }}}. Proof. iIntros (Φ) "(Hci & #Hlk) HΦ". rewrite /listen_to_client. do 6 wp_pure _. - iLöb as "IH" forall (s). - iDestruct "Hci" as "([-> | (-> & Hlkey)] & Hci)". - - wp_recv as "[% | (%Habs & _)]"; last done. + iLöb as "IH" forall (b). + iDestruct "Hci" as "[Hlkey Hci]". + destruct b. + - wp_recv as "_". wp_pures. wp_lam. wp_pures. wp_apply (acquire_spec with "[Hlk]"); first by iFrame "#". iIntros (v) "(-> & HlKey & HdlkKey & HR)". wp_pures. wp_send with "[$HdlkKey $HR]". wp_pure _. wp_lam. - iApply ("IH" $! "release" with "[$Hci HlKey]"). - iRight. by iFrame. - eauto with iFrame. + by iApply ("IH" with "[$Hci $HlKey]"). - wp_pures. simpl in *. - wp_recv as "[%|(% & (Hdlk & HR))]"; first done. + wp_recv as "[Hdlk HR]". wp_pures. wp_apply (release_spec with "[$Hlk $Hlkey $HR $Hdlk]"). iIntros (v ->). do 2 wp_pure _. - iApply ("IH" $! "acquire" with "[Hci]"). + iApply ("IH" with "[Hci]"). rewrite /is_dlock_server_connection_state. - iFrame. by iLeft. eauto with iFrame. + iFrame. eauto with iFrame. Qed. Lemma wp_connections_loop skt lk γlk : @@ -173,13 +179,13 @@ Section DL_proof_of_code. iLöb as "IH". wp_pure _. wp_smart_apply (RCSpec_accept_spec with "[$Hlistens]"). - iIntros (c clt_addr v) "(-> & Hlistens & Hc)". + iIntros (c clt_addr) "(Hlistens & Hc)". wp_pures. wp_apply (aneris_wp_fork with "[-]"). iSplitL "Hlistens". - iNext. do 2 wp_pure _. iApply ("IH" with "[$Hlistens]"). by iIntros. - iNext. wp_pures. iApply (wp_listen_to_client with "[$Hc $Hlk]"). - by iLeft. eauto with iFrame. + eauto with iFrame. Qed. Definition dl_server_start_service_internal_spec A : Prop := @@ -205,15 +211,13 @@ Section DL_proof_of_code. iIntros (lk γlk) "#Hlk". wp_pures. wp_apply (RCSpec_server_listen_spec with "[$Hcl][HΦ]"). - iNext. iIntros (v) "(-> & Hp)". wp_pures. + iNext. iIntros "Hp". wp_pures. iApply (wp_connections_loop with "[$]"). iNext. by iIntros. Qed. End DL_proof_of_code. -From aneris.examples.reliable_communication.lib.dlm Require Import dlm_spec. - Section DL_proof_of_resources. Context `{!anerisG Mdl Σ}. Context `{!lockG Σ}. @@ -238,15 +242,13 @@ Section DL_proof_of_resources. Qed. Global Instance dlri : DL_resources := { - DLockCanAcquire sa dl R := - dl ↣{ ip_of_address sa, string_serialization } - (dlock_protocol dl_locked_internal R "acquire"); - DLockCanRelease sa dl R := - dl ↣{ ip_of_address sa, string_serialization } - (dlock_protocol dl_locked_internal R "release"); - dl_locked := dl_locked_internal; - dl_locked_exclusive := Hexcl; - dl_locked_timeless := Html; + DLockCanAcquire ip dl R := + dl ↣{ ip, string_serialization } + (dlock_protocol dl_locked_internal R true); + DLockCanRelease ip dl R := + (dl ↣{ ip, string_serialization } + (dlock_protocol dl_locked_internal R false) ∗ + dl_locked_internal)%I; dl_service_init := dl_locked_internal ∗ SrvInit; dl_service_init_exclusive := Hexcl_init; dl_service_init_timeless := Html_init; @@ -268,32 +270,31 @@ Section DL_proof_of_the_init. Proof. apply _. Qed. Lemma init_setup_holds (E : coPset) (R : iProp Σ) : - ↑DL_namespace ⊆ E → - True ⊢ |={E}=> + ↑DL_namespace ⊆ E → + ⊢ |={E}=> ∃ (DLRS : DL_resources), dl_service_init ∗ - (∀ (A : gset socket_address), dl_server_start_service_spec R A) ∗ - (∀ sa (A : gset socket_address), dl_subscribe_client_spec R sa A). + (dl_server_start_service_spec R) ∗ + (dl_subscribe_client_spec R). Proof. - iIntros (HE _). + iIntros (HE). iMod (own_alloc (Excl ())) as (γdlk) "Hdlk"; first done. set (DLUP := UP (own γdlk (Excl ())) R). assert (DL_namespace = DLUP.(RCParams_srv_N)) as Hnmeq by done. rewrite Hnmeq in HE. - iMod (Reliable_communication_init_setup E DLUP HE $! ⊤) + iMod (Reliable_communication_init_setup E DLUP HE) as (chn sgn) "(Hinit & Hspecs)". - iDestruct "Hspecs" + iDestruct "Hspecs" as "( %HmkClt & %HmkSrv & %Hconnect & %Hlisten & %Haccept & %Hsend & %HsendTele & %HtryRecv & %Hrecv)". - eset (dlr := dlri (dl_locked_internal γdlk) (dl_locked_internal_exclusive γdlk) (dlt γdlk) R). - iExists dlr. - Unshelve. 2:{ done. } - iFrame. - iSplitL. + eset (dlr := dlri (dl_locked_internal γdlk) (dl_locked_internal_exclusive γdlk) (dlt γdlk) R). + iExists dlr. + iFrame. + iSplitL. - iModIntro. iIntros (A). iIntros (Φ) "!#". @@ -305,29 +306,27 @@ Section DL_proof_of_the_init. - iModIntro. iIntros (sa A). iIntros (Φ) "!#". - iIntros "(HinA & Hf & Hfp & Hmh & #Hsi) HΦ". + iIntros "(HninA & Hf & Hfp & Hmh & #Hsi) HΦ". iDestruct (dl_subscribe_client_internal_spec_holds) as "#HclientSpec". split; try done. split; try done. - iApply ("HclientSpec" with "[$HinA $Hf $Hfp $Hmh $Hsi][HΦ]"). + iApply ("HclientSpec" with "[$HninA $Hf $Hfp $Hmh $Hsi][HΦ]"). rewrite /dlock_subscribe_client. iNext. iIntros (dl) "(Hinit & %HaS & %HrS)". iApply "HΦ". iFrame. rewrite /dl_acquire_internal_spec. rewrite /dl_release_internal_spec. iSplit. - + iPureIntro. - iIntros (Ψ). + + iIntros (Ψ). specialize (HaS Ψ). - iIntros "Hr HΨ". + iIntros "!> Hr HΨ". iApply (HaS with "[$Hr][HΨ]"). - iNext. iIntros "Hr". + iNext. iIntros "[Hrel Hr]". iApply "HΨ". by iFrame. - + iPureIntro. - iIntros (Ψ). + + iIntros (Ψ). specialize (HrS Ψ). - iIntros "Hr HΨ". - iApply (HrS with "[$Hr][HΨ]"). + iIntros "!> [[Hrel Hlocked] Hr] HΨ". + iApply (HrS with "[$Hrel $Hlocked $Hr][HΨ]"). iNext. iIntros "Hr". iApply "HΨ". by iFrame. Qed. @@ -337,17 +336,16 @@ End DL_proof_of_the_init. Section DL_proof_of_the_init_class. Context `{!anerisG Mdl Σ}. Context `{!lockG Σ}. + Context `{!SpecChanG Σ}. Context `{!DL_params}. - Context `{!Reliable_communication_init}. Global Instance dlinit : DL_init. Proof. - split. iIntros (E DL R HE _). - iMod (init_setup_holds E R HE $! ⊤) as (dlr) "(Ha & Hb & Hc)". + split. iIntros (E DL R HE). + iMod (init_setup_holds E R HE) as (dlr) "(Ha & Hb & Hc)". iModIntro. iExists dlr. - iFrame. - Unshelve. done. + by iFrame. Qed. End DL_proof_of_the_init_class. diff --git a/aneris/examples/reliable_communication/lib/dlm/dlm_spec.v b/aneris/examples/reliable_communication/lib/dlm/dlm_spec.v index a7d7d70..9cd5422 100644 --- a/aneris/examples/reliable_communication/lib/dlm/dlm_spec.v +++ b/aneris/examples/reliable_communication/lib/dlm/dlm_spec.v @@ -6,11 +6,8 @@ From aneris.examples.reliable_communication.spec Require Import resources. From aneris.examples.reliable_communication.lib.dlm Require Import dlm_code dlm_prelude. Class DL_resources `{!anerisG Mdl Σ} := { - DLockCanAcquire : socket_address → val → iProp Σ → iProp Σ; - DLockCanRelease : socket_address → val → iProp Σ → iProp Σ; - dl_locked : iProp Σ; - dl_locked_exclusive : dl_locked -∗ dl_locked -∗ False; - dl_locked_timeless :> Timeless (dl_locked); + DLockCanAcquire : ip_address → val → iProp Σ → iProp Σ; + DLockCanRelease : ip_address → val → iProp Σ → iProp Σ; dl_service_init : iProp Σ; dl_service_init_exclusive : dl_service_init -∗ dl_service_init -∗ False; dl_service_init_timeless :> Timeless (dl_service_init); @@ -25,7 +22,8 @@ Section DL_spec. Notation srv_ip := (ip_of_address DL_server_addr). Notation srv_port := (port_of_address DL_server_addr). - Definition dl_server_start_service_spec A : iProp Σ := + Definition dl_server_start_service_spec : iProp Σ := + ∀ A, {{{ ⌜srv_sa ∈ A⌠∗ fixed A ∗ free_ports srv_ip {[srv_port]} ∗ srv_sa ⤳ (∅, ∅) ∗ srv_sa ⤇ dl_reserved_server_socket_interp ∗ @@ -33,23 +31,25 @@ Section DL_spec. dlock_start_service #srv_sa @[srv_ip] {{{ RET #(); True }}}. - Definition dl_acquire_spec (sa : socket_address) (dl : val) : Prop := - {{{ DLockCanAcquire sa dl R }}} - dlock_acquire dl @[ip_of_address sa] - {{{ v, RET v; ⌜v = #()⌠∗ DLockCanRelease sa dl R ∗ dl_locked ∗ R }}}. + Definition dl_acquire_spec (ip : ip_address) (dl : val) : iProp Σ := + {{{ DLockCanAcquire ip dl R }}} + dlock_acquire dl @[ip] + {{{ RET #(); DLockCanRelease ip dl R ∗ R }}}. - Definition dl_release_spec (sa : socket_address) (dl : val) : Prop := - {{{ DLockCanRelease sa dl R ∗ dl_locked ∗ R }}} - dlock_release dl @[ip_of_address sa] - {{{ v, RET v; ⌜v = #()⌠∗ DLockCanAcquire sa dl R }}}. + Definition dl_release_spec (ip : ip_address) (dl : val) : iProp Σ := + {{{ DLockCanRelease ip dl R ∗ R }}} + dlock_release dl @[ip] + {{{ RET #(); DLockCanAcquire ip dl R }}}. - Definition dl_subscribe_client_spec (sa : socket_address) A : iProp Σ := - {{{ ⌜sa ∉ A⌠∗ fixed A ∗ free_ports (ip_of_address sa) {[port_of_address sa]} ∗ sa ⤳ (∅, ∅) ∗ - DL_server_addr ⤇ dl_reserved_server_socket_interp}}} + Definition dl_subscribe_client_spec : iProp Σ := + ∀ (sa : socket_address) A, + {{{ ⌜sa ∉ A⌠∗ fixed A ∗ + free_ports (ip_of_address sa) {[port_of_address sa]} ∗ sa ⤳ (∅, ∅) ∗ + DL_server_addr ⤇ dl_reserved_server_socket_interp }}} dlock_subscribe_client #sa #srv_sa @[ip_of_address sa] - {{{ dl, RET dl; DLockCanAcquire sa dl R ∗ - ⌜dl_acquire_spec sa dl⌠∗ - ⌜dl_release_spec sa dl⌠}}}. + {{{ dl, RET dl; DLockCanAcquire (ip_of_address sa) dl R ∗ + dl_acquire_spec (ip_of_address sa) dl ∗ + dl_release_spec (ip_of_address sa) dl }}}. End DL_spec. @@ -59,10 +59,10 @@ Section Init. Class DL_init := { DL_init_setup E (DLP : DL_params) (R: iProp Σ): ↑DL_namespace ⊆ E → - True ⊢ |={E}=> ∃ (DLRS : DL_resources), + ⊢ |={E}=> ∃ (DLRS : DL_resources), dl_service_init ∗ - (∀ (A : gset socket_address), dl_server_start_service_spec R A) ∗ - (∀ sa (A : gset socket_address), dl_subscribe_client_spec R sa A) + (dl_server_start_service_spec R) ∗ + (dl_subscribe_client_spec R) }. End Init. diff --git a/aneris/examples/reliable_communication/lib/mt_server/mt_server_code.v b/aneris/examples/reliable_communication/lib/mt_server/mt_server_code.v new file mode 100644 index 0000000..9c6eba7 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/mt_server/mt_server_code.v @@ -0,0 +1,39 @@ +(* This file is automatically generated from the OCaml source file +<repository_root>/ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.ml *) + +From aneris.aneris_lang Require Import ast. +From aneris.examples.reliable_communication Require Import client_server_code. + +Definition service_loop : val := + λ: "c" "request_handler" <>, + letrec: "loop" <> := + let: "req" := recv "c" in + let: "rep" := "request_handler" "req" in + send "c" "rep";; + "loop" #() in + "loop" #(). + +Definition accept_new_connections_loop : val := + λ: "skt" "request_handler" <>, + letrec: "loop" <> := + let: "new_conn" := accept "skt" in + let: "c" := Fst "new_conn" in + let: "_a" := Snd "new_conn" in + Fork (service_loop "c" "request_handler" #());; + "loop" #() in + "loop" #(). + +Definition run_server ser deser : val := + λ: "addr" "request_handler", + let: "skt" := make_server_skt ser deser "addr" in + server_listen "skt";; + Fork (accept_new_connections_loop "skt" "request_handler" #()). + +Definition make_request : val := λ: "ch" "req", send "ch" "req";; + recv "ch". + +Definition init_client_proxy ser deser : val := + λ: "clt_addr" "srv_addr", + let: "skt" := make_client_skt ser deser "clt_addr" in + let: "ch" := connect "skt" "srv_addr" in + "ch". diff --git a/aneris/examples/reliable_communication/lib/mt_server/proof/mt_server_proof.v b/aneris/examples/reliable_communication/lib/mt_server/proof/mt_server_proof.v new file mode 100644 index 0000000..1f70d5d --- /dev/null +++ b/aneris/examples/reliable_communication/lib/mt_server/proof/mt_server_proof.v @@ -0,0 +1,283 @@ +From iris.algebra Require Import excl. +From iris.base_logic.lib Require Import invariants. +From iris.proofmode Require Import coq_tactics reduction spec_patterns. +From aneris.aneris_lang Require Import lang. +From aneris.aneris_lang.lib Require Import lock_proof set_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang Require Import tactics proofmode. +From actris.channel Require Export proto. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.examples.reliable_communication Require Import user_params. +From aneris.examples.reliable_communication.spec + Require Import resources proofmode api_spec. +From aneris.examples.reliable_communication.lib.mt_server + Require Import mt_server_code user_params. + +Import mt_server_code. +Import monitor_proof. +Import lock_proof. +Import client_server_code. + +Section MTS_proof_of_code. + Context `{!anerisG Mdl Σ}. + Context `{!lockG Σ}. + Context `{MTU : !MTS_user_params}. + + Definition req_prot_aux (rec : iProto Σ) : iProto Σ := + (<! (reqv : val) (reqd : MTS_req_data) > + MSG reqv {{ MTS_handler_pre reqv reqd }} ; + <? (repv : val) (repd : MTS_rep_data) > + MSG repv {{ MTS_handler_post repv reqd repd }}; + rec)%proto. + + Instance req_prot_aux_contractive : Contractive (req_prot_aux). + Proof. solve_proto_contractive. Qed. + Definition req_prot : iProto Σ := fixpoint (req_prot_aux). + Global Instance req_prot_unfold : + ProtoUnfold req_prot (req_prot_aux req_prot). + Proof. apply proto_unfold_eq, fixpoint_unfold. Qed. + + Global Instance MT_UP : Reliable_communication_service_params := + {| RCParams_clt_ser := MTS_req_ser; + RCParams_srv_ser := MTS_rep_ser; + RCParams_srv_ser_inj := MTS_rep_ser_inj; + RCParams_srv_ser_inj_alt := MTS_rep_ser_inj_alt; + RCParams_clt_ser_inj := MTS_req_ser_inj; + RCParams_clt_ser_inj_alt := MTS_req_ser_inj_alt; + RCParams_srv_saddr := MTS_saddr; + RCParams_protocol := req_prot; + RCParams_srv_N := MTS_mN; + |}. + + Context `{cmh: !@Chan_mapsto_resource Σ}. + Context `{SnRes : !SessionResources MT_UP}. + Context `{HspecS : !Reliable_communication_Specified_API_session cmh}. + Context `{HspecN : !Reliable_communication_Specified_API_network MT_UP SnRes}. + + Lemma service_loop_proof (c handler : val) : + handler_spec (handler : val) -∗ + {{{ c ↣{ ip_of_address MTS_saddr, MTS_rep_ser } iProto_dual req_prot }}} + service_loop c handler #() @[ip_of_address MTS_saddr] + {{{ RET #(); ⌜True⌠}}}. + Proof. + iIntros "#Hhandler" (Φ) "!> Hc HΦ". rewrite /service_loop. + wp_pures. + iLöb as "IH". + wp_pures. + rewrite /req_prot. rewrite /req_prot_aux. + simpl in *. + wp_recv (reqv reqd) as "HreqPre". + wp_pures. + wp_apply ("Hhandler" with "HreqPre"). + iIntros (repv repd) "(%Hser & HreqPost)". + wp_pures. + wp_send with "[$HreqPost]". + wp_pures. + by iApply ("IH" with "[$Hc]"). + Qed. + + Lemma wp_accept_new_connections_loop skt handler : + handler_spec (handler : val) -∗ + {{{ MTS_saddr ⤇ reserved_server_socket_interp ∗ + SrvListens skt }}} + accept_new_connections_loop skt handler #() + @[ip_of_address RCParams_srv_saddr] + {{{ RET #(); False }}}. + Proof. + iIntros "#Hhandler" (Φ) "!> (#Hsi & Hlistens) HΦ". + rewrite /accept_new_connections_loop. + wp_pures. + iLöb as "IH". + wp_smart_apply (RCSpec_accept_spec with "Hlistens"). + iIntros (c clt_addr) "(Hlistens & Hc)". + wp_pures. + wp_apply (aneris_wp_fork with "[-]"). + iSplitL "Hlistens". + - iNext. + wp_pures. + iApply ("IH" with "[$Hlistens]"). + by iIntros. + - iNext. + wp_pures. + simpl in *. + by wp_apply (service_loop_proof with "Hhandler Hc"). + Qed. + + Definition run_server_internal_spec A handler : iProp Σ := + handler_spec handler -∗ + {{{ ⌜MTS_saddr ∈ A⌠∗ + fixed A ∗ + free_ports (ip_of_address MTS_saddr) {[port_of_address MTS_saddr]} ∗ + MTS_saddr ⤇ reserved_server_socket_interp ∗ + MTS_saddr ⤳ (∅, ∅) ∗ + SrvInit }}} + run_server + (s_serializer MTS_rep_ser) + (s_serializer MTS_req_ser) + #MTS_saddr + handler + @[ip_of_address MTS_saddr] + {{{ RET #(); ⌜True⌠}}}. + + Lemma run_server_internal_spec_holds A handler : + ⊢ run_server_internal_spec A handler. + Proof. + iIntros "#Hhandler" (Φ) "!>". + iIntros "Hres HΦ". + iDestruct "Hres" as "(#HA & #Hf & Hfp & #Hsi & Hmh & Hinit)". + rewrite /run_server. + wp_pures. + wp_apply (RCSpec_make_server_skt_spec with "[$HA $Hmh $Hsi $Hf $Hinit $Hfp][HΦ]"). + iNext. iIntros (skt) "Hcl". + wp_pures. + wp_apply (RCSpec_server_listen_spec with "[$Hcl][HΦ]"). + iNext. iIntros "Hp". + wp_pures. + wp_apply aneris_wp_fork. + iSplitL "HΦ". + - iNext; by iApply "HΦ". + - by iApply (wp_accept_new_connections_loop with "Hhandler [$]"). + Qed. + + Definition make_request_spec_internal : iProp Σ := + ∀ ip (c : val) reqv reqd, + {{{ c ↣{ip,RCParams_clt_ser} RCParams_protocol ∗ + ⌜Serializable MTS_req_ser reqv⌠∗ MTS_handler_pre reqv reqd }}} + make_request c reqv @[ip] + {{{ repd repv, RET repv; + c ↣{ip,RCParams_clt_ser} RCParams_protocol ∗ + MTS_handler_post repv reqd repd }}}. + + Lemma make_request_spec_internal_holds : + ⊢ make_request_spec_internal. + Proof. + iIntros (ip c reqv reqd) "!>". + iIntros (Φ) "(Hc & %Hser & HP) HΦ". + rewrite /make_request. + rewrite /RCParams_protocol /=. + wp_pures. + wp_send with "[$HP]". + wp_recv (repv repd) as "HQ". + iApply "HΦ". by iFrame. + Qed. + + Definition init_client_proxy_internal_spec A sa : iProp Σ := + {{{ ⌜sa ∉ A⌠∗ + fixed A ∗ + free_ports (ip_of_address sa) {[port_of_address sa]} ∗ sa ⤳ (∅, ∅) ∗ + MTS_saddr ⤇ reserved_server_socket_interp }}} + init_client_proxy + (s_serializer MTS_req_ser) + (s_serializer MTS_rep_ser) + #sa + #MTS_saddr + @[ip_of_address sa] + {{{ c, RET c; + c ↣{ip_of_address sa,RCParams_clt_ser} RCParams_protocol }}}. + + Lemma init_client_proxy_internal_spec_holds A sa : + ⊢ init_client_proxy_internal_spec A sa. + Proof. + iIntros (Φ) "!#". + iIntros "(#HnA & #Hf & Hfp & Hmh & #Hsi) HΦ". + rewrite /init_client_proxy. + wp_pures. + wp_apply (RCSpec_make_client_skt_spec with "[$HnA $Hmh $Hsi $Hf $Hfp][HΦ]"). + iNext. + iIntros (skt) "Hcl". + wp_pures. + wp_apply (RCSpec_connect_spec with "[$Hcl][HΦ]"). + iNext. iIntros (c) "Hcl". wp_pures. + wp_pures. + by iApply "HΦ". + Qed. + + Global Instance mtsri : MTS_resources := { + MTSCanRequest ip rpc := rpc ↣{ip,RCParams_clt_ser} RCParams_protocol }. + +End MTS_proof_of_code. + +From aneris.examples.reliable_communication.spec + Require Import ras. +From aneris.examples.reliable_communication.instantiation + Require Import instantiation_of_init. +From aneris.examples.reliable_communication.lib.mt_server.spec + Require Import api_spec. + +Section MTS_proof_of_init. + Context `{!anerisG Mdl Σ}. + Context `{!lockG Σ}. + Context `{MTU : !MTS_user_params, !SpecChanG Σ}. + + Lemma MTS_init_setup_holds (E : coPset) : + ↑MTS_mN ⊆ E → + ⊢ |={E}=> ∃ (srv_si : message → iProp Σ) (SrvInit : iProp Σ) + (MTR : MTS_resources), + SrvInit ∗ + (run_server_spec SrvInit srv_si) ∗ + (init_client_proxy_spec srv_si) ∗ + make_request_spec. + Proof. + iIntros (HE). + iMod (Reliable_communication_init_setup E MT_UP HE) + as (chn sgn) "(Hinit & Hspecs)". + iDestruct "Hspecs" + as "( + %HmkClt & %HmkSrv + & %Hconnect + & %Hlisten & %Haccept + & %Hsend & %HsendTele + & %HtryRecv & %Hrecv)". + iExists reserved_server_socket_interp, SrvInit, mtsri. + iFrame. + iModIntro. + iSplitL. + - iIntros "!>" (A handler) "#Hhandler". + iIntros (Φ) "!#". + iIntros "(#Hsi & HinA & Hf & Hmh & Hfp & Hinit) HΦ". + (* iDestruct run_server_internal_spec_holds as "#HserviceSpec". *) + iApply (run_server_internal_spec_holds with + "Hhandler [$HinA $Hf $Hfp $Hsi $Hmh $Hinit][$]"). + Unshelve. + + done. + + split; done. + + split; done. + - iSplitL. + + iIntros (A sa Φ) "!#". + iIntros "(HinA & Hf & Hfp & Hmh & #Hsi) HΦ". + iDestruct (init_client_proxy_internal_spec_holds) as "#HclientSpec". + by iApply ("HclientSpec" with "[$HinA $Hf $Hfp $Hmh $Hsi][HΦ]"). + Unshelve. + done. + + iIntros (ip rpc reqv reqd Φ) "!#". + iIntros "(Hreq & %Hser & HP) HΦ". + iApply (make_request_spec_internal_holds with "[$Hreq $HP //]"). + by iApply "HΦ". + Unshelve. + done. + Qed. + +End MTS_proof_of_init. + +Section MTS_proof_of_the_init_class. + Context `{!anerisG Mdl Σ}. + Context `{!lockG Σ}. + Context `{!MTS_user_params}. + Context `{!SpecChanG Σ}. + + Global Instance mts_init : MTS_init. + Proof. + split. iIntros (E MTU HE). + iMod (MTS_init_setup_holds E HE) + as (srv_si SrvInit MTR) "(Hinit & Hspecs)". + iModIntro. + iExists _, SrvInit, MTR. + iFrame. + Qed. + +End MTS_proof_of_the_init_class. +From aneris.examples.reliable_communication.instantiation Require Import + instantiation_of_resources + instantiation_of_client_specs + instantiation_of_server_specs + instantiation_of_send_and_recv_specs. diff --git a/aneris/examples/reliable_communication/lib/mt_server/spec/api_spec.v b/aneris/examples/reliable_communication/lib/mt_server/spec/api_spec.v new file mode 100644 index 0000000..b55ee5c --- /dev/null +++ b/aneris/examples/reliable_communication/lib/mt_server/spec/api_spec.v @@ -0,0 +1,72 @@ +From aneris.aneris_lang Require Import lang. +From aneris.examples.reliable_communication.prelude Require Import ser_inj. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.aneris_lang.lib + Require Import lock_proof monitor_proof serialization_proof. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params mt_server_code. + +Section Spec. + Context `{ !anerisG Mdl Σ, !lockG Σ}. + Context `{ MTU: !MTS_user_params }. + Context `{ MTR: !MTS_resources }. + Context (SrvInit : iProp Σ). + Context (srv_si : message → iProp Σ). + Notation srv_ip := (ip_of_address MTS_saddr). + + Definition run_server_spec : iProp Σ := + â–¡ ∀ A handler, + handler_spec handler -∗ + {{{ MTS_saddr ⤇ srv_si ∗ + ⌜MTS_saddr ∈ A⌠∗ + fixed A ∗ + MTS_saddr ⤳ (∅,∅) ∗ + free_ports (srv_ip) {[port_of_address MTS_saddr]} ∗ + SrvInit }}} + run_server + (s_serializer MTS_rep_ser) + (s_serializer MTS_req_ser) + #MTS_saddr + handler + @[srv_ip] + {{{ RET #(); True }}}. + + Definition make_request_spec : iProp Σ := + ∀ ip (rpc : val) reqv reqd, + {{{ MTSCanRequest ip rpc ∗ + ⌜Serializable MTS_req_ser reqv⌠∗ + MTS_handler_pre reqv reqd }}} + make_request rpc reqv @[ip] + {{{ repd repv, RET repv; + MTSCanRequest ip rpc ∗ MTS_handler_post repv reqd repd }}}. + + Definition init_client_proxy_spec : iProp Σ := + ∀ A sa, + {{{ ⌜sa ∉ A⌠∗ + fixed A ∗ + free_ports (ip_of_address sa) {[port_of_address sa]} ∗ sa ⤳ (∅, ∅) ∗ + MTS_saddr ⤇ srv_si }}} + init_client_proxy + (s_serializer MTS_req_ser) + (s_serializer MTS_rep_ser) + #sa + #MTS_saddr + @[ip_of_address sa] + {{{ reqh, RET reqh; MTSCanRequest (ip_of_address sa) reqh }}}. + +End Spec. + +Section MTS_Init. + Context `{ !anerisG Mdl Σ, !lockG Σ}. + + Class MTS_init := { + MTS_init_setup E (MTU : MTS_user_params) : + ↑MTS_mN ⊆ E → + ⊢ |={E}=> ∃ (srv_si : message → iProp Σ) (SrvInit : iProp Σ) + (MTR : MTS_resources), + SrvInit ∗ + (run_server_spec SrvInit srv_si) ∗ + (init_client_proxy_spec srv_si) ∗ + make_request_spec }. + +End MTS_Init. diff --git a/aneris/examples/reliable_communication/lib/mt_server/user_params.v b/aneris/examples/reliable_communication/lib/mt_server/user_params.v new file mode 100644 index 0000000..8c3656d --- /dev/null +++ b/aneris/examples/reliable_communication/lib/mt_server/user_params.v @@ -0,0 +1,44 @@ +From aneris.aneris_lang Require Import lang. +From aneris.aneris_lang.lib Require Import lock_proof monitor_proof serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude Require Import ser_inj. +From actris.channel Require Import proto. + +Set Default Proof Using "Type". + +Canonical Structure valO := leibnizO val. +Notation iProto Σ := (iProto Σ val). +Notation iMsg Σ := (iMsg Σ val). + +Import lock_proof. + +Class MTS_user_params `{ !anerisG Mdl Σ, !lockG Σ } := + { (* Requests. *) + MTS_req_ser : serialization; + MTS_req_ser_inj : ser_is_injective MTS_req_ser; + MTS_req_ser_inj_alt : ser_is_injective_alt MTS_req_ser; + MTS_req_data : Type; + (* Replies. *) + MTS_rep_ser : serialization; + MTS_rep_ser_inj : ser_is_injective MTS_rep_ser; + MTS_rep_ser_inj_alt : ser_is_injective_alt MTS_rep_ser; + MTS_rep_data : Type; + MTS_handler_pre : val → MTS_req_data → iProp Σ; + MTS_handler_post : val → MTS_req_data → MTS_rep_data → iProp Σ; + MTS_saddr : socket_address; + MTS_mN : namespace; + }. + +Arguments MTS_user_params {_ _ _ _}. + +Definition handler_spec `{MTS_user_params} (handler : val) : iProp Σ := + ∀ reqv reqd, + {{{ MTS_handler_pre reqv reqd }}} + handler reqv @[ip_of_address MTS_saddr] + {{{ repv repd, RET repv; + ⌜Serializable MTS_rep_ser repv⌠∗ + MTS_handler_post repv reqd repd }}}. + +Class MTS_resources `{!anerisG Mdl Σ} := { + MTSCanRequest : ip_address → val → iProp Σ; + }. diff --git a/aneris/examples/reliable_communication/lib/repdb/log_code.v b/aneris/examples/reliable_communication/lib/repdb/log_code.v index 00464bd..284016a 100644 --- a/aneris/examples/reliable_communication/lib/repdb/log_code.v +++ b/aneris/examples/reliable_communication/lib/repdb/log_code.v @@ -13,7 +13,7 @@ Definition log_add_entry : val := let: "lp" := ! "log" in let: "data" := Fst "lp" in let: "next" := Snd "lp" in - let: "data'" := list_append "data" [("req", "next")] in + let: "data'" := list_append "data" ["req"] in "log" <- ("data'", ("next" + #1)). Definition log_next : val := λ: "log", Snd ! "log". diff --git a/aneris/examples/reliable_communication/lib/repdb/model.v b/aneris/examples/reliable_communication/lib/repdb/model.v new file mode 100644 index 0000000..39e194f --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/model.v @@ -0,0 +1,328 @@ +From aneris.aneris_lang Require Import lang inject. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events. + + +Global Instance int_time : DB_time := + {| Time := nat; + TM_lt := Nat.lt; + TM_lt_tricho := PeanoNat.Nat.lt_trichotomy |}. + +Instance: Inhabited (@we int_time) := populate (Build_we "" #() inhabitant). + +Global Program Instance Inject_write_event : Inject we val := + {| inject a := $(a.(we_key), a.(we_val), a.(we_time)) + |}. +Next Obligation. + intros w1 w2 Heq. + inversion Heq as [[Hk Hv Ht]]. + assert (we_time w1 = we_time w2) as Ht'. + { by apply (inj (R := eq)) in Ht; [ | apply _]. } + destruct w1, w2; simpl in *. + by apply Z_of_nat_inj in Ht; subst. +Qed. + +Definition write_event := @we int_time. +Definition write_eventO := leibnizO write_event. +Definition wrlog := list write_eventO. + + +(* -------------------------------------------------------------------------- *) +(** The state validity defines coherence of the log and the memory model. *) + +Section ValidStates. + Context `{!DB_params}. + + (** Global Validity. *) + Definition mem_dom (M : gmap Key (option write_event)) := DB_keys = dom M. + + Definition mem_we_key (M : gmap Key (option write_event)) := + ∀ k we, M !! k = Some (Some we) → we.(we_key) = k. + + Definition mem_log_coh (L : wrlog) (M : gmap Key (option write_event)) := + ∀ k, k ∈ dom M → M !! k = Some (at_key k L). + + Definition in_log_mem_some_coh (L : wrlog) (M : gmap Key (option write_event)) := + ∀ k we, at_key k L = Some we → M !! k = Some (Some we). + + Definition mem_serializable_vals (M : gmap Key (option write_event)) := + ∀ k we, M !! k = Some (Some we) → Serializable DB_serialization we.(we_val). + + Definition allocated_in_mem (L : wrlog) (M : gmap Key (option write_event)) := + ∀ l k wel, l ≤ₚ L → at_key k l = Some wel → + ∃ weL, M !! k = Some (Some weL) ∧ wel ≤ₜ weL. + + (* why are scopes screwed up here!? *) + Definition log_events (L : wrlog) := + ∀ (i : nat), (i < List.length L)%nat → + ∃ we, L !! i = Some we ∧ i = we.(we_time) ∧ we.(we_key) ∈ DB_keys ∧ + Serializable DB_serialization we.(we_val). + + Record valid_state (L : wrlog) (M : gmap Key (option write_event)) : Prop := + { + DB_GSTV_mem_dom : mem_dom M; + DB_GSTV_mem_we_key : mem_we_key M; + DB_GSTV_mem_log_coh : mem_log_coh L M; + DB_GSTV_mem_in_log_mem_some_coh : in_log_mem_some_coh L M; + DB_GSTV_mem_serializable_vals : mem_serializable_vals M; + DB_GSTV_mem_allocated_in_mem : allocated_in_mem L M; + DB_GSTV_log_events : log_events L; + }. + + Lemma valid_state_empty : + valid_state [] (gset_to_gmap (@None write_event) DB_keys). + Proof. + split; rewrite /mem_dom /mem_we_key /mem_log_coh /in_log_mem_some_coh + /mem_serializable_vals /allocated_in_mem /log_events. + - by rewrite dom_gset_to_gmap. + - intros ? ? Habs. apply lookup_gset_to_gmap_Some in Habs. naive_solver. + - intros k Hy2. apply lookup_gset_to_gmap_Some. rewrite dom_gset_to_gmap in Hy2. naive_solver. + - intros k we He. naive_solver. + - intros k we Hnone. apply lookup_gset_to_gmap_Some in Hnone. naive_solver. + - intros l k wel Hpre Hsm. destruct Hpre as (h2 & Hpre). + symmetry in Hpre. apply app_eq_nil in Hpre. naive_solver. + - intros i Hin. rewrite nil_length in Hin. by lia. + Qed. + + Lemma log_events_serializable L M : + valid_state L M → + ∀ (we : write_event), + we ∈ L → + Serializable + (prod_serialization + (prod_serialization string_serialization DB_serialization) + int_serialization) ($ we). + Proof. + intros Hvs we Hwe. + destruct we as [k v t]. + apply (_ : _ → _ → Serializable (prod_serialization _ _) (_, _)); last apply _. + apply (_ : _ → _ → Serializable (prod_serialization _ _) (_, _)); first apply _. + apply elem_of_list_lookup_1 in Hwe as [i Hiwe]. + destruct (DB_GSTV_log_events _ _ Hvs i) as (?&Hi&?&?&?); + first by eapply lookup_lt_is_Some_1; eauto. + rewrite Hi in Hiwe; simplify_eq; done. + Qed. + + + (* TODO: MOVE *) + Lemma prefix_of_snoc {A} x (l1 l2 : list A) : l1 ≤ₚ (l2 ++ [x]) → l1 = l2 ++ [x] ∨ l1 ≤ₚ l2. + Proof. + intros [k Hk]. destruct k as [|y k _] using rev_ind . + - rewrite app_nil_r in Hk; by left. + - rewrite assoc in Hk. apply app_inj_2 in Hk as [? ?]; last done. + right; eexists; done. + Qed. + +(* TODO: MOVE *) (* again scope is screwed up! *) + Lemma lt_TM_lt we we' : (we_time we < we_time we')%nat → we ≤ₜ we'. + Proof. rewrite /TM_lt /=; by left. Qed. + + Lemma log_events_state_update (lM : wrlog) wev : + wev.(we_key) ∈ DB_keys → + wev.(we_time) = length lM → + Serializable DB_serialization wev.(we_val) → + log_events lM -> + log_events (lM ++ [wev]). + Proof. + intros ??? HLE i. rewrite app_length /=. intros Hi. + destruct (decide (i = length lM)) as [->|]. + + rewrite lookup_app_r; last done. + rewrite Nat.sub_diag /=. + eexists _; done. + + destruct (HLE i) as (?&Hi'&?&?&?); first lia. + eexists; split; last done. + rewrite lookup_app_l; first done. + apply lookup_lt_is_Some_1; eauto. + Qed. + + Lemma valid_state_update (lM : wrlog) (kvsMG : gmap Key (option write_event)) wev : + wev.(we_key) ∈ DB_keys → + wev.(we_time) = length lM → + Serializable DB_serialization wev.(we_val) → + valid_state lM kvsMG -> + valid_state (lM ++ [wev]) (<[wev.(we_key) := Some wev]> kvsMG). + Proof. + intros Hwevk Hwevt Hwevser Hvs. + split. + - rewrite /mem_dom dom_insert_L subseteq_union_1_L; first apply Hvs. + erewrite <- DB_GSTV_mem_dom; last done. + set_solver. + - intros k we. + destruct (decide (k = we_key wev)) as [->|]. + { rewrite lookup_insert; intros ?; simplify_eq; done. } + rewrite lookup_insert_ne; last done. + apply Hvs; done. + - intros k. rewrite dom_insert elem_of_union elem_of_singleton. intros Hk. + destruct (decide (k = we_key wev)) as [->|]. + { rewrite lookup_insert at_key_snoc_some; done. } + destruct Hk as [->|Hk]; first done. + rewrite lookup_insert_ne; last done. + rewrite at_key_snoc_none; last done. + apply Hvs; done. + - intros k we. + destruct (decide (k = we_key wev)) as [->|]. + + rewrite lookup_insert at_key_snoc_some; last done; intros ?; simplify_eq; done. + + rewrite lookup_insert_ne; last done. + rewrite at_key_snoc_none; last done. + apply Hvs. + - intros k we. + destruct (decide (k = we_key wev)) as [->|]. + + rewrite lookup_insert; intros ?; simplify_eq; done. + + rewrite lookup_insert_ne; last done. apply Hvs. + - intros l k wel Hl Hklwel. + destruct (decide (k = we_key wev)) as [->|]. + + rewrite lookup_insert. eexists; split; first done. + apply prefix_of_snoc in Hl as [->|Hl]. + { rewrite at_key_snoc_some in Hklwel; last done; simplify_eq. + by right. (* this is weird; need to prove the Reflexive instance for ≤ₜ *) } + assert (∃ i, lM !! i = Some wel) as [i Hi]. + { apply elem_of_list_lookup. + eapply elem_of_prefix; last done. + eapply at_key_elem_of; done. } + apply lt_TM_lt. + destruct (DB_GSTV_log_events _ _ Hvs i) as (?&Hi'&?&?&?); + first by apply lookup_lt_is_Some_1; eauto. + rewrite /TM_lt /=. + rewrite Hi in Hi'; simplify_eq. + rewrite Hwevt. + apply lookup_lt_is_Some_1; eauto. + + rewrite lookup_insert_ne; last done. + apply prefix_of_snoc in Hl as [->|Hl]. + { rewrite at_key_snoc_none in Hklwel; last done; simplify_eq. + eapply Hvs; done. } + eapply Hvs; done. + - apply log_events_state_update; [done|done|done|apply Hvs]. + Qed. + + Lemma log_events_no_dup lM : log_events lM → NoDup lM. + Proof. + intros HLE. + apply (NoDup_fmap_1 we_time). + assert (we_time <$> lM = seq 0 (length lM)) as ->; last apply NoDup_seq. + apply list_eq. + intros i. + destruct (decide (i < length lM)%nat); last first. + { rewrite lookup_seq_ge; last lia. + rewrite list_lookup_fmap lookup_ge_None_2; first done. by apply Nat.nlt_ge. } + rewrite lookup_seq_lt /=; last done. + destruct (HLE i) as (?&Hi&Hit&?&?); first done. + rewrite list_lookup_fmap Hi /= -Hit //. + Qed. + + Lemma valid_state_log_no_dup lM mM: valid_state lM mM -> NoDup lM. + Proof. intros Hvs; apply log_events_no_dup; apply Hvs. Qed. + + (** Local Validity. *) + Definition mem_dom_local (M : gmap Key val) := dom M ⊆ DB_keys. + + Definition in_mem_log_some_coh_local (L : wrlog) (M : gmap Key val) := + ∀ k v, M !! k = Some v → ∃ we, at_key k L = Some we ∧ we.(we_val) = v. + + Definition in_mem_log_none_coh_local (L : wrlog) (M : gmap Key val) := + ∀ k, M !! k = None → at_key k L = None. + + Definition mem_serializable_vals_local (M : gmap Key val) := + ∀ k v, M !! k = Some v → Serializable DB_serialization v. + + Definition in_log_mem_some_coh_local (L : wrlog) (M : gmap Key val) := + ∀ we, at_key we.(we_key) L = Some we → M !! we.(we_key) = Some we.(we_val). + + Definition in_log_mem_none_coh_local (L : wrlog) (M : gmap Key val) := + ∀ k, at_key k L = None → M !! k = None. + + Definition allocated_in_mem_local (L : wrlog) (M : gmap Key val) := + ∀ l k we1, l ≤ₚ L → at_key k l = Some we1 → ∃ we2, M !! k = Some we2.(we_val) ∧ we1 ≤ₜ we2. + + Record valid_state_local (L : wrlog) (M : gmap Key val) : Prop := + { + DB_LSTV_log_events : log_events L; + DB_LSTV_mem_dom : mem_dom_local M; + DB_LSTV_mem_serializable_vs_local : mem_serializable_vals_local M; + DB_LSTV_in_mem_log_some_coh_local : in_mem_log_some_coh_local L M; + DB_LSTV_in_mem_log_none_coh_local : in_mem_log_none_coh_local L M; + DB_LSTV_in_log_mem_some_coh_local : in_log_mem_some_coh_local L M; + DB_LSTV_in_log_mem_none_coh_local : in_log_mem_none_coh_local L M; + DB_LSTV_mem_allocated_in_mem : allocated_in_mem_local L M; + }. + + Lemma valid_state_local_empty : valid_state_local [] ∅. + Proof. + split; rewrite /mem_dom_local /in_mem_log_some_coh_local /in_mem_log_none_coh_local + /mem_serializable_vals_local /in_log_mem_some_coh_local /in_log_mem_none_coh_local + /allocated_in_mem_local /log_events; try set_solver. + - intros i Hin. rewrite nil_length in Hin. by lia. + - intros l k we1 Hpre. + destruct Hpre as (h2 & Hpre). + symmetry in Hpre. apply app_eq_nil in Hpre. naive_solver. + Qed. + + Lemma valid_state_local_update (lM : wrlog) (kvsMG : gmap Key val) wev : + wev.(we_key) ∈ DB_keys → + wev.(we_time) = length lM → + Serializable DB_serialization wev.(we_val) → + valid_state_local lM kvsMG -> + valid_state_local (lM ++ [wev]) (<[wev.(we_key):= wev.(we_val)]> kvsMG). + Proof. + intros Hwevk Hwevt Hwevser Hvs. + split. + - apply log_events_state_update; [done|done|done|apply Hvs]. + - intros k; rewrite dom_insert elem_of_union elem_of_singleton; intros [->|Hk]; first done. + apply Hvs; done. + - intros k v. + destruct (decide (k = we_key wev)) as [->|]. + { rewrite lookup_insert; intros; simplify_eq; done. } + rewrite lookup_insert_ne; last done. apply Hvs. + - intros k v. + destruct (decide (k = we_key wev)) as [->|]. + { rewrite lookup_insert; intros; simplify_eq. + rewrite at_key_snoc_some; eauto. } + rewrite lookup_insert_ne; last done. + rewrite at_key_snoc_none; last done. + apply Hvs. + - intros k. + destruct (decide (k = we_key wev)) as [->|]. + { rewrite lookup_insert; done. } + rewrite lookup_insert_ne; last done. + rewrite at_key_snoc_none; last done. + apply Hvs. + - intros we. + destruct (decide (we_key we = we_key wev)) as [->|]. + { rewrite at_key_snoc_some; last done. rewrite lookup_insert; intros; simplify_eq; done. } + rewrite at_key_snoc_none; last done. + rewrite lookup_insert_ne; last done. + apply Hvs. + - intros k. + destruct (decide (k = we_key wev)) as [->|]. + { rewrite at_key_snoc_some; done. } + rewrite lookup_insert_ne; last done. + rewrite at_key_snoc_none; last done. + apply Hvs. + - intros l k wel Hl Hklwel. + destruct (decide (k = we_key wev)) as [->|]. + + rewrite lookup_insert. eexists; split; first done. + apply prefix_of_snoc in Hl as [->|Hl]. + { rewrite at_key_snoc_some in Hklwel; last done; simplify_eq. + by right. (* this is weird; need to prove the Reflexive instance for ≤ₜ *) } + assert (∃ i, lM !! i = Some wel) as [i Hi]. + { apply elem_of_list_lookup. + eapply elem_of_prefix; last done. + eapply at_key_elem_of; done. } + apply lt_TM_lt. + destruct (DB_LSTV_log_events _ _ Hvs i) as (?&Hi'&?&?&?); + first by apply lookup_lt_is_Some_1; eauto. + rewrite /TM_lt /=. + rewrite Hi in Hi'; simplify_eq. + rewrite Hwevt. + apply lookup_lt_is_Some_1; eauto. + + rewrite lookup_insert_ne; last done. + apply prefix_of_snoc in Hl as [->|Hl]. + { rewrite at_key_snoc_none in Hklwel; last done; simplify_eq. + eapply Hvs; done. } + eapply Hvs; done. + Qed. + + Lemma valid_state_local_log_no_dup lM mM: valid_state_local lM mM -> NoDup lM. + Proof. intros Hvs; apply log_events_no_dup; apply Hvs. Qed. + +End ValidStates. diff --git a/aneris/examples/reliable_communication/lib/repdb/notes.txt b/aneris/examples/reliable_communication/lib/repdb/notes.txt new file mode 100644 index 0000000..8162805 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/notes.txt @@ -0,0 +1,244 @@ + +(* -------------------------------------------------------------------------- *) +(** What are guarantees we want to show in the specs ? *) +(* -------------------------------------------------------------------------- *) + +Obs(a, h) is necessary. + + +1) Followers' sequential consistency w.r.t. to the leader +2) Session guarantees + +(** Abstract predicates. *) + we -- triplets (k, i, v) with key k, timestamp i, and value v, and time relation ≤ₜ on timestamps + k ↦{q} Some we -- abstract points-to connective ; + Obs(a, h) -- observered history h (list of events (k, i, v)) at a replica with address a; + GlobalInv -- global invariant; Obtained even before starting the leader (which is a bit subtle to handle followers dynamically). + IsLeader(a) -- a is the address of the leader. Duplicable, acquired at initialization of the client-leader proxy. + ObsLeader(a, h) == Obs(a, h) ∗ isLeader(a) + + +(** Operations on histories. *) + at_key k0 h : option (nat * val) ≠last (filter (λ we, we.k = k0) h) + at_key_property1: ∀ h i k v, at_key k h = Some (i, v) → nth h i = Some (k,i,v)) + +(** Properties of points-to connective. *) + OwnMemKey_timeless k q v :> Timeless (k ↦ₖ{ q } v); + OwnMemKey_exclusive k q v v' : k ↦ₖ{ 1 } v ⊢ k ↦ₖ{ q } v' -∗ False; + OwnMemKey_fractioal k v :> Fractional (λ q, k ↦ₖ{ q } v); + OwnMemKey_as_fractioal k q v :> AsFractional (k ↦ₖ{ q } v) (λ q, k ↦ₖ{ q } v) q ; + OwnMemKey_combine k q q' v v' : k ↦ₖ{ q } v ∗ k ↦ₖ{ q' } v' ⊢ k ↦ₖ{ q + q'} v ∗ ⌜v = v'⌠; + OwnMemKey_split k q1 q2 v : k ↦ₖ{ q1 + q2 } v ⊢ k ↦ₖ{ q1 } v ∗ k ↦ₖ{ q2 } v ; + +(** Properties of observed histories. *) + Obs_linearizable : + ∀ a1 a2 h1 h2 E, ↑DB_InvName ⊆ E → GlobalInv ⊢ + Obs(a1, h1) ∗ Obs(a2, h2) ={E}=∗ h1 ≤ₚ h2 ∨ h2 ≤ₚ h1 + Obs_get_smaller_at_node : + ∀ a h h' E, nclose DB_InvName ⊆ E → + h ≤ₚ h' → Obs(a, h') ={E}=∗ Obs(a, h); + Obs_exists_at_leader : + ∀ a1 a2 h1 E, ↑DB_InvName ⊆ E → GlobalInv ⊢ + Obs(a1, h1) ={E}=∗ ∃ h2, ObsLeader(a2, h2) ∗ h1 ≤ₚ h2 + Obs_snoc_time : + ∀ a h1 e1 h2 E, nclose DB_InvName ⊆ E → + Obs(a, h1 ++ [e1] ++ h2) ={E}=∗ + ⌜∀ e0, e0 ∈ h1 → e0 <â‚œ e1⌠∧ + ⌜∀ e2, e2 ∈ h2 → e1 <â‚œ e2âŒ; + Obs_global_ext_we : + ∀ h h' E, nclose DB_InvName ⊆ E → + GlobalInv ⊢ Obs(a, h) -∗ Obs (a', h') ={E}=∗ + ⌜∀ e e', e ∈ h → e' ∈ h' → e =â‚œ e' → e = e'âŒ; + Obs_timeless :> ∀ a h, Timeless Obs(a, h); + Obs_persistent :> ∀ a h, Persistent Obs(a, h); + +(** Relations between points-to connective and observed requests *) + OwnMemKey_obs_some_value_leader : + ∀ a k q we E : + nclose DB_InvName ⊆ E → GlobalInv ⊢ + k ↦ₖ{ q } Some we ={E}=∗ + k ↦ₖ{ q } Some we ∗ ∃ h, ObsLeader(a, h) ∗ ⌜at_key k h = Some weâŒ; + OwnMemKey_obs_none : + ∀ a k q h E : + nclose DB_InvName ⊆ E → GlobalInv ⊢ + k ↦ₖ{ q } None ∗ Obs(a, h) ={E}=∗ + k ↦ₖ{ q } None ∗ ⌜at_key k h = NoneâŒ; + OwnMemKey_obs_frame : + ∀ a k q h h' E, + nclose DB_InvName ⊆ E → GlobalInv ⊢ + h ≤ₚ h' → + k ↦ₖ{ q } (at_key k h) ∗ Obs(a, h') ={E}=∗ + k ↦ₖ{ q } (at_key k h) ∗ ⌜at_key k h = at_key k h'âŒ; + OwnMemKey_obs_some_frame a k q we h hf E : + nclose DB_InvName ⊆ E → GlobalInv ⊢ + k ↦ₖ{ q } (Some we) ∗ Obs(a, h ++ [we] ++ hf) ={E}=∗ + k ↦ₖ{ q } (Some we) ∗ ⌜at_key k hf = NoneâŒ; + OwnMemKey_allocated : + ∀ k q h0 h1 we0 E : + nclose DB_InvName ⊆ E → GlobalInv ⊢ + h0 ≤ₚ h1 → + at_key k h0 = Some we0 → + k ↦ₖ{ q } (at_key k h1) ={E}=∗ + ∃ we1, k ↦ₖ{ q } (at_key k h1) ∗ + ⌜at_key k h1 = Some we1⌠∗ ⌜we0 ≤ₜ we1âŒ; + +(** Specification for write. *) + +{ k ∈ DB_keys ∗ k ↦{1} at_key(k, h) ∗ Obs(a0, h) } + write(k, v) @[ca] +{ (), ∃ we hf, k ↦{1} Some we ∗ ObsLeader(a, h ++ hf ++ [we]) ∗ at_key(k, hf) = None } + +The usual write spec is of course derivable: + { k ∈ DB_keys ∗ k ↦{1} _ } + write(k, v) @[ca] + { (), k ↦{1} Some v } + +NB: What about the logically atomic spec? Do we need it? + + Definition write_spec (sa : socket_address) : iProp Σ := + Eval simpl in + â–¡ (∀ (E : coPset) (k : Key) (v : SerializableVal) + (P : iProp Σ) (Q : we → ghst → ghst → iProp Σ), + ⌜↑DB_InvName ⊆ E⌠-∗ + ⌜k ∈ DB_keys⌠-∗ + â–¡ (P + ={⊤, E}=∗ + ∃ (h : ghst) (a_old: option we), + ⌜at_key k h = a_old⌠∗ + Obs h ∗ + k ↦ₖ a_old ∗ + â–· (∀ (hf : ghst) (a_new : we), + ⌜at_key k hf = None⌠∗ + ⌜a_new.(WE_key) = k⌠∗ ⌜a_new.(WE_val) = v⌠∗ + ⌜∀ e, e ∈ h → e <â‚œ a_new⌠∗ + k ↦ₖ Some a_new ∗ + ObsLeader(UP_leader_addr, h ++ hf ++ [a_new]) ={E,⊤}=∗ Q a_new h hf)) -∗ + {{{ P }}} + write #k v @[ip_of_address sa] + {{{ RET #(); + ∃ (h hf : ghst) (a: we), Q a h hf }}})%I. + +(** Specification for read at the leader node. *) + +{ k ∈ DB_keys ∗ k ↦{q} we } + read_L(k) @[ca] +{ (), k ↦{q} we } + +NB: should also be atomic. + +(** Specifications for read at the follower nodes. *) + +(** Weak spec *) +{ k ∈ DB_keys ∗ Obs(fa, h) } + read_F(k) @[ca] +{ vo, ∃ h', h ≤ₚ h' ∗ Obs(fa, h') ∗ + (vo = None ∗ at_key(k, h') = None ∨ ∃ we, vo = Some we ∗ at_key(k, h') = vo) } + +NB: should also be atomic. + + +(* -------------------------------------------------------------------------- *) +(** An attempt for an alternative specs without timestamps. *) +(* -------------------------------------------------------------------------- *) +(** Operations on histories. *) + at_key_at_time k0 h : option (nat * val) ≠+ match list_find (λ (k,v), k = k0) (list_reverse h) with + | None -> None + | Some (i, v) -> Some (length h - (i + 1), v) + at_key k0 h : option val ≠+ match at_key_at_time k0 h with + | None -> None + | Some (i,v) -> Some v + end + at_key_def2 k0 h : option val ≠+ match last (filter (λ (k,v), k = k0) h) with + | None -> None + | Some (k,v) -> Some v + end + at_key_at_time_property1: ∀ h i k v, at_key_at_time k h = Some (i, v) → at_key k h = Some v ∧ nth h i = Some v + at_key_at_time_property2: ∀ h k v, at_key k h = Some v -> ∃ i, at_key_at_time k h = Some (i, v) + +(** Properties of points-to connective. *) + OwnMemKey_timeless k q v :> Timeless (k ↦ₖ{ q } v); + OwnMemKey_exclusive k q v v' : k ↦ₖ{ 1 } v ⊢ k ↦ₖ{ q } v' -∗ False; + OwnMemKey_fractioal k v :> Fractional (λ q, k ↦ₖ{ q } v); + OwnMemKey_as_fractioal k q v :> AsFractional (k ↦ₖ{ q } v) (λ q, k ↦ₖ{ q } v) q ; + OwnMemKey_combine k q q' v v' : k ↦ₖ{ q } v ∗ k ↦ₖ{ q' } v' ⊢ k ↦ₖ{ q + q'} v ∗ ⌜v = v'⌠; + OwnMemKey_split k q1 q2 v : k ↦ₖ{ q1 + q2 } v ⊢ k ↦ₖ{ q1 } v ∗ k ↦ₖ{ q2 } v ; + +(** Properties of observed histories. *) + Obs_linearizable : + ∀ a1 a2 h1 h2 E, ↑DB_InvName ⊆ E → GlobalInv ⊢ + Obs(a1, h1) ∗ Obs(a2, h2) ={E}=∗ h1 ≤ₚ h2 ∨ h2 ≤ₚ h1 + Obs_lub_at_node : + ∀ a h1 h2 E, nclose DB_InvName ⊆ E → GlobalInv ⊢ + Obs(a, h1) -∗ Obs (a, h2) ={E}=∗ + ∃ h3, ⌜h1 ≤ₚ h3⌠∗ ⌜h2 ≤ₚ h3⌠∗ Obs(a, h3); + Obs_get_smaller_at_node : + ∀ a h h' E, nclose DB_InvName ⊆ E → + h ≤ₚ h' → Obs(a, h') ={E}=∗ Obs(a, h); + Obs_exists_at_leader : + ∀ a1 a2 h1 E, ↑DB_InvName ⊆ E → GlobalInv ⊢ + Obs(a1, h1) ={E}=∗ ∃ h2, ObsLeader(a2, h2) ∗ h1 ≤ₚ h2 + Obs_timeless :> ∀ a h, Timeless Obs(a, h); + Obs_persistent :> ∀ a h, Persistent Obs(a, h); + +(** Relations between points-to connective and observed requests *) + OwnMemKey_obs_some_value : + ∀ a k q v E : + nclose DB_InvName ⊆ E → + k ↦ₖ{ q } Some v ={E}=∗ + k ↦ₖ{ q } Some v ∗ ∃ h, ObsLeader(a, h) ∗ ⌜at_key k h = Some vâŒ; + OwnMemKey_obs_none : + ∀ a k q h E : + nclose DB_InvName ⊆ E → + k ↦ₖ{ q } None ∗ Obs(a, h) ={E}=∗ + k ↦ₖ{ q } None ∗ ⌜at_key k h = NoneâŒ; + OwnMemKey_obs_frame_right : + ∀ a k q h h' E, + nclose DB_InvName ⊆ E → + h ≤ₚ h' → + k ↦ₖ{ q } (at_key k h) ∗ Obs(a, h') ={E}=∗ + k ↦ₖ{ q } (at_key k h) ∗ ⌜at_key k h = at_key k h'âŒ; + OwnMemKey_allocated : + ∀ k q h0 h1 v0 v1 i0 i1 E : + nclose DB_InvName ⊆ E → + at_key_at_time k h0 = Some (i, v0) → + h0 ≤ₚ h1 → + k ↦ₖ{ q } (at_key k h1) ={E}=∗ + ∃ i1 v1, k ↦ₖ{ q } (at_key k h1) ∗ ⌜at_key_at_time k h1 = Some (i1, v1)⌠∗ ⌜i0 ≤ i1âŒ; + OwnMemKey_allocated : + ∀ k q h0 h1 v0 v1 i0 i1 E : + nclose DB_InvName ⊆ E → + at_key_at_time k h0 = Some (i, v0) → + h0 ≤ₚ h1 → + k ↦ₖ{ q } (at_key k h1) ={E}=∗ + ∃ i1 v1, k ↦ₖ{ q } (at_key k h1) ∗ + ⌜at_key_at_time k h1 = Some (i1, (at_key k h1))⌠∗ ⌜i0 ≤ i1âŒ; + +(** Specifications. *) + +{ k ∈ DB_keys ∗ k ↦{1} at_key(k, h) ∗ Obs(a, h) } + write(k, v) @[ca] +{ (), ∃ hf, let h' = h ++ hf ++ [k,v] in + k ↦{1} at_key(k, h') ∗, ObsLeader(a, h') ∗ at_key(k, hf) = None} + +Derivable write specs: + + { k ∈ DB_keys ∗ k ↦{1} _ } + write(k, v) @[ca] + { (), k ↦{1} Some v ∗ ∃ h, ObsLeader(a, h ++ [k,v])} + + { k ∈ DB_keys ∗ k ↦{1} _ } + write(k, v) @[ca] + { (), k ↦{1} Some v } + + +{ k ∈ DB_keys ∗ k ↦{q} v } + read_L(k) @[ca] +{ (), k ↦{q} v } + +{ k ∈ DB_keys ∗ Obs(fa, h) } + read_F(k) @[ca] +{ vo, ∃ h', h ≤ₚ h' ∗ Obs(fa, h') ∗ + (vo = None ∨ ∃ w, vo = Some w ∗ at_key(k, h') = vo) } diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/db_resources_instance.v b/aneris/examples/reliable_communication/lib/repdb/proof/db_resources_instance.v new file mode 100644 index 0000000..50b12d2 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/db_resources_instance.v @@ -0,0 +1,54 @@ +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.repdb + Require Import model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events resources. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras log_resources resources_def + resources_global_inv resources_local_inv. + +Section DB_resources_instance. + Context `{!anerisG Mdl Σ, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + + Global Instance DbRes `{DBP : !DB_params} : DB_resources := + {| + GlobalInv := Global_Inv γL γM N; + OwnMemKey := own_mem_user γM; + Obs := own_obs γL; + OwnMemKey_timeless := OwnMemKey_timeless_holds γM; + OwnMemKey_exclusive := OwnMemKey_exclusive_holds γM; + OwnMemKey_fractional := OwnMemKey_fractional_holds γM; + OwnMemKey_as_fractional := OwnMemKey_as_fractional_holds γM; + OwnMemKey_combine := OwnMemKey_combine_holds γM; + OwnMemKey_split := OwnMemKey_split_holds γM; + OwnMemKey_key := OwnMemKey_key_holds γL γM N; + Obs_timeless := Obs_timeless_holds γL; + Obs_persistent := Obs_persistent_holds γL; + Obs_compare := Obs_compare_holds γL; + Obs_exists_at_leader := Obs_exists_at_leader_holds γL γM N; + Obs_get_smaller := Obs_get_smaller_holds γL; + (* Obs_snoc_time := Obs_snoc_time_holds γL γM N; *) + (* Obs_ext_we := Obs_ext_we_holds γL γM N; *) + (* Obs_ext_hist := Obs_ext_hist_holds γL γM N; *) + OwnMemKey_some_obs_we := OwnMemKey_some_obs_we_holds γL γM N; + OwnMemKey_obs_frame_prefix := OwnMemKey_obs_frame_prefix_holds γL γM N; + OwnMemKey_obs_frame_prefix_some := OwnMemKey_obs_frame_prefix_some_holds γL γM N; + OwnMemKey_some_obs_frame := OwnMemKey_some_obs_frame_holds γL γM N; + OwnMemKey_none_obs := OwnMemKey_none_obs_holds γL γM N; + (* OwnMemKey_allocated := OwnMemKey_allocated_holds γL γM N; *) + |}. + +End DB_resources_instance. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/follower/clients_at_follower_mt_user_params.v b/aneris/examples/reliable_communication/lib/repdb/proof/follower/clients_at_follower_mt_user_params.v new file mode 100644 index 0000000..96cd5ea --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/follower/clients_at_follower_mt_user_params.v @@ -0,0 +1,82 @@ +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import ras log_resources resources_def + resources_global_inv resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import repdb_serialization. + +Import gen_heap_light. +Import lock_proof. + +(* -------------------------------------------------------------------------- *) +Section MT_user_params. + + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N: gmap socket_address gname) (sa : socket_address). + + Definition ReqData : Type := string * wrlog. + + Definition RepData : Type := wrlog. + + (* Definition ReqPre (reqv : val) (reqd : ReqData) : iProp Σ := *) + (* Global_Inv γL γM N ∗ *) + (* ∃ k h, ⌜k ∈ DB_keys⌠∗ ⌜reqd = (k, h)⌠∗ ⌜reqv = #(LitString k)⌠∗ *) + (* known_replog_token sa γF ∗ own_logL_obs γL h ∗ *) + (* own_log_obs γF h. *) + + (* Definition ReqPost (repv : val) (reqd : ReqData) (repd : RepData) *) + (* : iProp Σ := *) + (* ∃ k h h', ⌜reqd = (k,h)⌠∗ ⌜repd = h'⌠∗ ⌜h ≤ₚ h'⌠∗ *) + (* known_replog_token sa γF ∗ own_logL_obs γL h' ∗ *) + (* own_log_obs γF h' ∗ *) + (* ((⌜repv = NONEV⌠∗ ⌜at_key k h' = NoneâŒ) ∨ *) + (* (∃ a, ⌜repv = SOMEV (we_val a)⌠∗ ⌜at_key k h' = Some aâŒ)). *) + + Definition ReqPre (reqv : val) (reqd : ReqData) : iProp Σ := + Global_Inv γL γM N ∗ + ∃ k h, ⌜k ∈ DB_keys⌠∗ ⌜reqd = (k, h)⌠∗ ⌜reqv = #(LitString k)⌠∗ + own_replog_obs γL sa h. + + Definition ReqPost (repv : val) (reqd : ReqData) (repd : RepData) + : iProp Σ := + ∃ k h h', ⌜reqd = (k,h)⌠∗ ⌜repd = h'⌠∗ ⌜h ≤ₚ h'⌠∗ + own_replog_obs γL sa h' ∗ + ((⌜repv = NONEV⌠∗ ⌜at_key k h' = NoneâŒ) ∨ + (∃ a, ⌜repv = SOMEV (we_val a)⌠∗ ⌜at_key k h' = Some aâŒ)). + + Global Instance client_handler_at_follower_user_params + : MTS_user_params := + {| + MTS_req_ser := req_c2f_serialization; + MTS_req_ser_inj := req_c2f_ser_is_injective; + MTS_req_ser_inj_alt := req_c2f_ser_is_injective_alt; + MTS_req_data := ReqData; + MTS_rep_ser := rep_f2c_serialization; + MTS_rep_ser_inj := rep_f2c_ser_is_injective; + MTS_rep_ser_inj_alt := rep_f2c_ser_is_injective_alt; + MTS_rep_data := RepData; + MTS_saddr := sa; + MTS_mN := (DB_InvName.@socket_address_to_str sa); + MTS_handler_pre := ReqPre; + MTS_handler_post := ReqPost; + |}. + +End MT_user_params. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_clients_handler.v b/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_clients_handler.v new file mode 100644 index 0000000..85f40ed --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_clients_handler.v @@ -0,0 +1,153 @@ +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events stdpp_utils. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import ras log_resources resources_def + resources_global_inv resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import repdb_serialization log_proof. +From aneris.examples.reliable_communication.lib.repdb.proof.follower + Require Import clients_at_follower_mt_user_params. + +Import gen_heap_light. +Import lock_proof. + +Section Clients_MT_spec_params. + + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname) (sa : socket_address). + Context (mγ : gname) (mv : val) (kvsL logL : loc). + + (* Definition handler_cloj : val := *) + (* λ: "mon" "req", client_request_handler_at_follower #kvsL "mon" "req". *) + (* Definition handler_cloj' mon : val := *) + (* λ: "req", handler_cloj mon "req". *) + + Notation MTU := (client_handler_at_follower_user_params γL γM N sa). + + Lemma client_request_handler_at_follower_spec γF : + ∀ reqv reqd, + {{{ is_monitor + MTU.(MTS_mN) + (ip_of_address MTU.(MTS_saddr)) mγ mv + (known_replog_token sa γF ∗ + log_monitor_inv_def + (ip_of_address MTU.(MTS_saddr)) + γF ¼ logL (follower_local_res γL kvsL sa γF)) ∗ + MTU.(MTS_handler_pre) reqv reqd }}} + client_request_handler_at_follower #kvsL mv reqv @[ip_of_address MTU.(MTS_saddr)] + {{{ repv repd, RET repv; + ⌜Serializable (rep_f2c_serialization) repv⌠∗ + MTU.(MTS_handler_post) repv reqd repd }}}. + Proof. + iIntros (reqv reqd Φ) "(#Hmon & Hpre) HΦ". + rewrite /client_request_handler_at_follower. + wp_pures. + wp_apply (monitor_acquire_spec with "[Hmon]"); first by iFrame "#". + iIntros (v) "(-> & HKey & #Hknw & HR)". + iDestruct "HR" as (lV lM) "(%Hlog & Hpl & HlogL & HR)". + iDestruct "HR" as (kvsV kvsM) "(%Hkvs & %HvalidLocal & Hpm & _ & #Hobs)". + iDestruct "Hpre" as "(#HGinv & HpreR)". + iDestruct "HpreR" as (k h Hkeys Hreqd ->) "(%γF' & #(Hknown & HobsL & Hobs2))". + wp_pures. + wp_load. + iDestruct (known_replog_token_agree with "[$Hknown][$Hknw]") as "->". + iDestruct (own_obs_prefix _ _ _ h with "[$HlogL][$Hobs2]") as "%Hprefixh". + iDestruct (get_obs with "[$HlogL]") as "#HobsF". + inversion HvalidLocal. + wp_apply fupd_aneris_wp. + iAssert (|={⊤}=> + (⌜kvsM !! k = None⌠∗ ⌜at_key k lM = NoneâŒ) ∨ + (∃ a : write_event, ⌜kvsM !! k = Some (we_val a)⌠∗ + ⌜at_key k lM = Some aâŒ))%I + as ">Hpost". + { destruct (kvsM !! k) as [v|] eqn:Hmk. + - iModIntro. iRight. + apply DB_LSTV_in_mem_log_some_coh_local in Hmk. + destruct Hmk as (we0 & Hwe0L & <-). + iExists _. + iSplit; first done. + by iPureIntro. + - iModIntro. + iLeft. + iSplit; first done. + iPureIntro. + by apply DB_LSTV_in_mem_log_none_coh_local in Hmk. } + iModIntro. + wp_apply (wp_map_lookup $! Hkvs). + iIntros (v Hkm). + destruct (kvsM !! k) eqn:Hmk. + - iDestruct "Hpost" as "[(%Habs & _)|Hpost]"; first done. + iDestruct "Hpost" as (a Ha) "%Hwe". + assert (v = SOMEV (we_val a)) as ->. + { rewrite Hmk in Hkm. + naive_solver. } + wp_pures. + wp_apply (monitor_release_spec with "[$Hmon Hpm Hpl HlogL $HKey]"). + { iSplitR. iFrame "Hknw". + iExists _, _. iSplit; first done. + iFrame "#∗". iExists _, _. by iFrame. } + iIntros (v ->). + do 2 wp_pure _. + iApply ("HΦ" $! (SOMEV (we_val a)) lM). + iSplit. + { iPureIntro. assert (k ∈ dom kvsM) as Hk by by apply elem_of_dom. + assert (v0 = (we_val a)) as Heqa by naive_solver. + rewrite Heqa in Hmk. + rewrite Hmk in Hkm. + specialize (DB_LSTV_mem_serializable_vs_local k (we_val a) Hmk). + apply _. } + simpl. rewrite /log_monitor_inv_def /ReqPost. + iExists k, h, lM. + do 3 (iSplit; first done). + iFrame "#". + iSplit. + { iFrame "#"; eauto. } + iRight. + iExists a. + eauto. + - wp_pures. + wp_apply (monitor_release_spec with "[$Hmon Hpm Hpl HlogL $HKey]"). + { iSplitR. iFrame "Hknw". + iExists _, _. iSplit; first done. + iFrame "#∗". iExists _, _. by iFrame. } + iIntros (v' ->). + do 2 wp_pure _. + iApply ("HΦ" $! _ lM). + iDestruct "Hpost" as "[(_ & %Hnone) |%Habs]"; [|naive_solver]. + assert (v = NONEV) as ->. + { rewrite Hmk in Hkm. + naive_solver. } + iSplit. + { rewrite /rep_f2c_serialization. + iPureIntro. + apply _. } + simpl. + rewrite /log_monitor_inv_def /ReqPost. + iExists k, h, lM. + do 3 (iSplit; first done). + iFrame "#∗". + iSplit. + { iFrame "#"; eauto. } + iLeft. + done. + Qed. + +End Clients_MT_spec_params. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_init_follower.v b/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_init_follower.v new file mode 100644 index 0000000..2dcc139 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_init_follower.v @@ -0,0 +1,180 @@ +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params mt_server_code. +From aneris.examples.reliable_communication.lib.mt_server.spec + Require Import api_spec. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras + log_resources + resources_def + resources_global_inv + resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import + log_proof + repdb_serialization. +From aneris.examples.reliable_communication.lib.repdb.proof.leader + Require Import + followers_mt_user_params. +From aneris.examples.reliable_communication.lib.repdb.proof.follower + Require Import + clients_at_follower_mt_user_params + proof_of_clients_handler + proof_of_sync_loop. + +Section Init_Follower_Proof. + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (f2lsa f2csa : socket_address). + Context (γL γM : gname) (N : gmap socket_address gname). + Context (follower_si leaderF_si : message → iProp Σ). + Context (InitFollower : iProp Σ). + Notation MTC := (client_handler_at_follower_user_params γL γM N f2csa). + Notation MTF := (follower_handler_user_params γL γM N). + Context (γF : gname). + + Definition init_follower_res : iProp Σ := + Global_Inv γL γM N ∗ + own_log_auth γF (1/2) [] ∗ + own_logL_obs γL [] ∗ + InitFollower ∗ + known_replog_token f2csa γF ∗ + (∃ γdbF : gname, known_replog_token DB_addrF γdbF ∗ own_replog_obs γL DB_addrF []). + + Definition init_follower_spec_internal {MTS:MTS_resources} : iProp Σ := + ∀ A, + ⌜DB_addrF ∈ A⌠→ + ⌜f2csa ∈ A⌠→ + ⌜f2lsa ∉ A⌠→ + ⌜ip_of_address f2csa = ip_of_address f2lsa⌠→ + ⌜port_of_address f2csa ≠port_of_address f2lsa⌠→ + {{{ fixed A ∗ + f2csa ⤇ follower_si ∗ + DB_addrF ⤇ leaderF_si ∗ + (@run_server_spec _ _ _ _ MTC InitFollower follower_si) ∗ + (@init_client_proxy_spec _ _ _ _ MTF _ leaderF_si) ∗ + (@make_request_spec _ _ _ _ MTF _) ∗ + init_follower_res ∗ + f2csa ⤳ (∅, ∅) ∗ + f2lsa ⤳ (∅, ∅) ∗ + free_ports (ip_of_address f2csa) {[port_of_address f2csa]} ∗ + free_ports (ip_of_address f2lsa) {[port_of_address f2lsa]} }}} + init_follower (s_serializer DB_serialization) + #DB_addrF #f2lsa #f2csa @[ip_of_address f2csa] + {{{ RET #(); True }}}. + + Lemma init_follower_spec_internal_holds {MTR:MTS_resources} : + ⊢ init_follower_spec_internal. + Proof. + iIntros (A HinA HinA2 HinFA HipEq HprNeq) "!# %Φ Hr HΦ". + iDestruct "Hr" as + "(#HA & #Hsi & HsiF & HInitFollowerSpec + & HinitFollowerAsClient & #HreqSpec + & HinitRes & Hmh & HmhF & Hfp & HfpF)". + rewrite /init_follower. + wp_pures. + wp_apply (wp_map_empty with "[//]"). + iIntros (kvsV HkvsV). + wp_alloc kvsL as "HpKvs". + wp_pures. + wp_apply (wp_log_create with "[//]"). + iIntros (logL logV) "(HpL & %HlogV)". + wp_pures. + iDestruct "HinitRes" + as "(#HGinv & HownF & #HobsL & Hinit & #HFtkn & #HdbF)". + iDestruct (get_obs with "[$HownF]") as "#HobsF". + rewrite - {1} Qp_quarter_quarter. + iDestruct (own_log_auth_split _ (1/4) (1/4) with "[$HownF]") + as "(HownF1 & HownF2)". + wp_apply (new_monitor_spec + (DB_InvName.@socket_address_to_str f2csa) (ip_of_address f2csa) + (log_monitor_inv_def + (ip_of_address f2csa) γF (1/4) logL + (follower_local_res γL kvsL f2csa γF)) + with "[HownF1 HpL HpKvs]") . + { iFrame "HFtkn". + iExists logV, []. + iSplit; first done. + iFrame. + iExists kvsV, ∅. + iSplit; first done. + iSplit. + { iPureIntro. apply valid_state_local_empty. } + iFrame "#∗". } + iIntros (mγ mv) "#HLInv". + wp_let. + wp_bind (sync_with_server _ _ _ _ _ _). + rewrite /sync_with_server. + wp_pures. + rewrite {4} HipEq. + wp_apply ("HinitFollowerAsClient" $! A f2lsa with "[$HA $HmhF $HfpF $HsiF //]"). + iIntros (reqh) "Hreq". + wp_pures. + wp_apply aneris_wp_fork. + iSplitL "HInitFollowerSpec Hinit Hmh Hfp HΦ". + - iNext. + wp_pures. + rewrite /start_follower_processing_clients. + wp_pures. + wp_apply ("HInitFollowerSpec" with "[] [-HΦ]"); [|by iFrame "#∗"|done]. + iIntros (v1 v2 Ψ) "!> HP HΨ". + wp_pures. + iApply (client_request_handler_at_follower_spec with "[HLInv $HP]"); [|done]. + Local Transparent monitor_inv is_monitor. + rewrite /is_monitor /is_lock. + iDestruct "HLInv" as (lk ->) "HLInv". + iDestruct "HLInv" as (l ->) "HLInv". + iExists #l. iSplit; first done. + iExists l. iSplit; first done. + iApply (inv_iff with "[$HLInv]"). + iNext. iModIntro. + rewrite /lock_inv. + iSplit. + + iIntros "(%b & (Hl & Hdef))". + iExists b. iFrame. + destruct b; first done. + iDestruct "Hdef" as "(Hk & Hdef)". + iSplitL "Hk"; first done. + iSplit; done. + + iIntros "(%b & (Hl & Hdef))". + iExists b. iFrame. + destruct b; first done. + iDestruct "Hdef" as "(Hk & _ & Hdef)". + by iFrame. + - iNext. + rewrite -HipEq. + iApply (sync_loop_spec γL γM N f2csa kvsL logL mγ mv _ [] 0 + with "[HownF2 Hreq] []"); [naive_solver| | done]. + iFrame "HGinv". + iSplitR; last first. + { iSplit; [done|]. + iSplitL "Hreq". + { iExists f2csa. by iFrame. } + iFrame "#"; eauto. + iExists _; iFrame "#∗". + iDestruct "HdbF" as (γdbF) "#(Htk & HobsdbF)". + iDestruct "HobsdbF" as (γdbF') "(Htk' & _ & HobsdF)". + iDestruct (known_replog_token_agree with "[$Htk][$Htk']") as "->". + eauto. } + rewrite /follower_local_inv. + iExists γF. + iFrame "#". + Qed. + +End Init_Follower_Proof. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_proxy.v b/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_proxy.v new file mode 100644 index 0000000..494b6c0 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_proxy.v @@ -0,0 +1,129 @@ +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params mt_server_code. +From aneris.examples.reliable_communication.lib.mt_server.spec + Require Import api_spec. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras + resources_def + resources_global_inv + resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import + repdb_serialization. +From aneris.examples.reliable_communication.lib.repdb.proof.follower + Require Import + clients_at_follower_mt_user_params + proof_of_clients_handler. + +Section Client_Proxy_Proof. + Context `{!anerisG Mdl Σ, dbparams : !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + Context (fsa : socket_address). + Context (Hin : fsa ∈ DB_followers). + Context (follower_si : message → iProp Σ). + Notation MTC := (client_handler_at_follower_user_params γL γM N fsa). + + Definition read_at_follower_spec_internal + (rd : val) (csa fsaddr : socket_address) (k : Key) (h : wrlog) : iProp Σ := + ⌜k ∈ DB_keys⌠-∗ + {{{ own_obs γL fsaddr h }}} + rd #k @[ip_of_address csa] + {{{vo, RET vo; + ∃ h', ⌜h ≤ₚ h'⌠∗ own_obs γL fsaddr h' ∗ + ((⌜vo = NONEV⌠∗ ⌜at_key k h' = NoneâŒ) ∨ + (∃ a, ⌜vo = SOMEV (we_val a)⌠∗ ⌜at_key k h' = Some aâŒ)) + }}}%I. + + Definition init_client_proxy_follower_spec_internal + {MTR : MTS_resources} : iProp Σ := + ∀ A csa, + ⌜fsa ≠DB_addr⌠→ + ⌜fsa ∈ A⌠→ + ⌜csa ∉ A⌠→ + {{{ fixed A ∗ + fsa ⤇ follower_si ∗ + csa ⤳ (∅, ∅) ∗ + (@init_client_proxy_spec _ _ _ _ MTC _ follower_si) ∗ + (@make_request_spec _ _ _ _ MTC _) ∗ + free_ports (ip_of_address csa) {[port_of_address csa]} }}} + init_client_follower_proxy (s_serializer DB_serialization) + #csa #fsa @[ip_of_address csa] + {{{ rd, RET rd; + (∀ k h, read_at_follower_spec_internal rd csa fsa k h) }}}. + + Lemma init_client_proxy_follower_internal_holds {MTR : MTS_resources} : + Global_Inv γL γM N ⊢ init_client_proxy_follower_spec_internal. + Proof. + iIntros "#Hinv". + iIntros (A csa). + iIntros (Hneq HA HnA). + iIntros (Φ) "!#". + iIntros "(#Hf & #Hsi & Hmh & #HClient_proxySpec & #Hreq_spec & Hfp) HΦ". + rewrite /init_client_follower_proxy. + wp_pures. + wp_apply ("HClient_proxySpec" with "[$Hf $Hfp $Hmh $Hsi][HΦ]"); first done. + iNext. + iIntros (reqh) "Hreq". + wp_pures. + wp_apply (newlock_spec (DB_InvName .@ "follower") with "Hreq"). + iIntros (lk γ) "#Hlk". + wp_pures. + iApply "HΦ". + iIntros (k h). + rewrite /read_at_follower_spec_internal. + iIntros (Hkeys Ψ) "!#". + iIntros "#Hobs HΨ". + wp_pures. + wp_apply (acquire_spec with "Hlk"). + iIntros (v) "(->&Hlocked&Hreq)". + wp_pures. + wp_apply ("Hreq_spec" with "[$Hreq]"). + rewrite /MTS_handler_pre /=. + iSplit. + - iPureIntro. exists k. done. + - iDestruct "Hobs" as "[(%Habs & _)|Hobs]". + { naive_solver. } + iDestruct "Hobs" as (γF') "(#Hknw & #HobsL & #HobsF)". + iFrame "#". + iExists k, h. + iFrame "#∗". + do 3 (iSplit; first done). + iExists _; iFrame "#". + - iIntros (repd repv) "[Hreq Hpost]". + wp_pures. + wp_apply (release_spec with "[$Hlk $Hlocked $Hreq]"). + iIntros (v) "->". + wp_pures. + iApply "HΨ". + simplify_eq /=. + rewrite /ReqPost. + iDestruct "Hpost" + as (k' h0 h1) "(%Heq1 & -> & %Hpre & #Hreplog & #Hpost)". + iExists h1. + inversion Heq1; subst. + iSplit; first done. + iSplit. + { iFrame "#". } + iDestruct "Hpost" as "[%Hpost|Hpost]". + -- iLeft. naive_solver. + -- iRight. naive_solver. + Qed. + +End Client_Proxy_Proof. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_sync_loop.v b/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_sync_loop.v new file mode 100644 index 0000000..5d046e1 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/follower/proof_of_sync_loop.v @@ -0,0 +1,158 @@ +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof assert_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params mt_server_code. +From aneris.examples.reliable_communication.lib.mt_server.spec + Require Import api_spec. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events resources. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras log_resources resources_def + resources_global_inv resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import + repdb_serialization log_proof. +From aneris.examples.reliable_communication.lib.repdb.proof.leader + Require Import + followers_mt_user_params. + +Import log_proof. + +Section SyncLogCopy_Proof. + Context `{!anerisG Mdl Σ, dbparams : !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname) (sa : socket_address) (kvsL logL : loc). + + Global Instance MTU : MTS_user_params. + Proof. apply (follower_handler_user_params γL γM N). Defined. + + Definition own_replog_loop l : iProp Σ := + ∃ γF, known_replog_token sa γF ∗ own_replog_obs γL DB_addrF l ∗ + own_log_auth γF (1/4) l. + + Lemma sync_loop_spec {MTR : MTS_resources} + (mγ : gname) (mv : val) (reqh : val) (logM : wrlog) (n : nat) : + n = length logM → + {{{ Global_Inv γL γM N ∗ + (follower_local_inv γL kvsL logL sa mγ mv) ∗ + make_request_spec ∗ + (∃ f2lsa, ⌜ip_of_address sa = ip_of_address f2lsa⌠∗ + MTSCanRequest (ip_of_address f2lsa) reqh) ∗ + own_replog_loop logM }}} + sync_loop #kvsL #logL mv reqh #n @[ip_of_address sa] + {{{ RET #(); True }}}. + Proof. + iIntros (Hn Φ) "((#HnMap & #HGinv) & (%γF' & #HinvL) & #Hreq_spec &Hreqh & HlogM) HΦ". + rewrite /sync_loop. + do 12 wp_pure _. + iLöb as "IH" forall (n logM Hn). + iDestruct "HlogM" as (γF) "(#Hknw & #HobsL & HlogM)". + iDestruct (get_obs with "[$HlogM]") as "#HobsF". + wp_pures. + iDestruct "Hreqh" as (f2lsa HipEq) "Hreqh". + rewrite /make_request_spec. + rewrite HipEq. + wp_pures. + wp_apply ("Hreq_spec" with "[$Hreqh]"). + { iSplit; first by iPureIntro; apply _. iFrame "#"; naive_solver. } + iIntros (logM' repv) "[Hreq Hpost]". + rewrite -HipEq. + iDestruct "Hpost" as (we) "(-> & %Hwekey & %HweSer & %Hlen & -> & #HobsLF')". + do 13 wp_pure _. + rewrite Hlen Hn. + wp_apply wp_assert. + wp_pures. + iSplit. + { iPureIntro. + by case_bool_decide. } + iNext. + wp_pures. + wp_apply (monitor_acquire_spec with "[HinvL]"); first by iFrame "#". + iIntros (v) "( -> & Hlocked & Hres)". + iDestruct "Hres" as (logV logM') "(%Hlog & Hpl & HLog & HRes)". + iDestruct "HRes" as (kvsV kvsM) "(%Hkvs & %HvalidLocal & Hpm & #Hknw' & #HobsL')". + iAssert (⌜γF' = γFâŒ)%I as "->". + { iApply (known_replog_token_agree with "[$Hknw'][$Hknw]"). } + wp_pures. + iDestruct (own_log_auth_combine with "HLog HlogM") as "(HlMhalf & ->)". + set (a := {|we_key := (we_key we); we_val := (we_val we); + we_time := (length logM : int_time.(Time))|}). + simplify_eq /=. + wp_apply (wp_log_add_entry _ _ _ logM a with "[$Hpl]"); [done|]. + iIntros (logV') "(%Hlog' & Hpl')". + wp_pures. + wp_load. + wp_apply (wp_map_insert $! Hkvs). + iIntros (m' Hm'). + wp_bind (Store _ _). + wp_store. + wp_pures. + iApply fupd_aneris_wp. + iInv DB_InvName + as (lMG kvsMG) ">(%HkG & %Hdom & %Hdisj & HmS & HlM & HknwF & HmapF & %HvalidG)". + iDestruct (known_replog_in_N with "[$HknwF $Hknw]") as %HNsa. + iDestruct (big_sepM_lookup_acc _ _ sa γF HNsa with "[$HmapF]") + as "((%lF & (_ & #HobsL'' & HlMhalf')) & Hcl)". + iDestruct (own_log_auth_combine with "HlMhalf HlMhalf'") as "(HlFull & ->)". + rewrite Qp_quarter_quarter Qp_half_half. + iAssert (own_replog_obs γL DB_addrF (lF ++ [we])) as "HobsLF'cpy". + { by done. } + iDestruct "HobsLF'" as (γF') "(_ & HobsLwe & HobsLFwe)". + iMod (own_log_auth_update _ _ (lF ++ [we]) with "[$HlFull]") as "HlFull". + { by apply prefix_app_r. } + rewrite - {4} Qp_half_half. + iDestruct (own_log_auth_split with "HlFull") as "(HlogM & HlogL)". + iDestruct (get_obs with "[$HlogL]") as "#Hobsfr2". + iModIntro. + rewrite /global_inv_def. + iSplitL "HlM HlogM HmS Hcl HknwF". + { iAssert (⌜lF ++ [we] `prefix_of` lMGâŒ)%I as "%Hprefix". + { iApply (own_obs_prefix with "[$HlM][$HobsLwe]"). } + iNext. iExists _, _. iFrame. + do 3 (iSplit; first done). + iSplit; last done. + iApply ("Hcl" with ""). + iExists (lF ++ [we]). + iFrame "#∗". } + iModIntro. + rewrite - Qp_quarter_quarter. + iDestruct (own_log_auth_split with "HlogL") as "(HlogL1 & HlogL2)". + wp_apply (monitor_release_spec + with "[$HinvL $Hlocked Hpl' Hpm HlogL1]"). + { iExists _, _. iFrame. + iSplitR. + eauto with iFrame. + - iPureIntro. + by assert (a = we) as -> by by destruct we; naive_solver. + - iExists m', (<[we_key we:=we_val we]> kvsM). + iFrame. + iSplit; first done. + iSplit; last by iFrame "#∗". + iPureIntro. + by apply (valid_state_local_update lF kvsM we). } + iIntros (v ->). + do 3 wp_pure _. + replace (#(length lF + 1)) with (#(length lF + 1)%nat); last first. + { do 2 f_equal. + lia. } + iApply ("IH" $! (length lF + 1)%nat (lF ++ [we]) with "[][Hreq][HlogL2][$HΦ]"). + { rewrite last_length. + iPureIntro; lia. } + { iExists _. iSplit; [done|]. rewrite HipEq. iFrame. } + iFrame "#∗"; eauto. + Qed. + +End SyncLogCopy_Proof. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/leader/clients_mt_user_params.v b/aneris/examples/reliable_communication/lib/repdb/proof/leader/clients_mt_user_params.v new file mode 100644 index 0000000..3c2ddd6 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/leader/clients_mt_user_params.v @@ -0,0 +1,88 @@ +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server Require Import user_params. +From aneris.examples.reliable_communication.lib.repdb Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec Require Import db_params events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import ras log_resources resources_def + resources_global_inv resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import repdb_serialization. + +Import gen_heap_light. +Import lock_proof. + +Section MT_user_params. + + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + + Definition ReqData : Type := + (coPset * (string * val) * (iProp Σ * (we → wrlog → wrlog → iProp Σ))) + + string * (Qp * option write_event). + + Definition RepData : Type := we * ghst * ghst + option we. + + Definition ReqPre (reqv : val) (reqd : ReqData) : iProp Σ := + Global_Inv γL γM N ∗ + ((∃ E k (v : SerializableVal) P Q, + ⌜reqd = inl (E, (k, SV_val v), (P, Q))⌠∗ + ⌜reqv = InjLV (#(LitString k), v)%V⌠∗ + ⌜↑DB_InvName ⊆ E⌠∗ + ⌜k ∈ DB_keys⌠∗ + P ∗ + â–¡ (P + ={⊤, E}=∗ + ∃ (h : wrlog) (a_old: option we), + ⌜at_key k h = a_old⌠∗ + own_mem_user γM k 1 a_old ∗ + own_obs γL DB_addr h ∗ + â–· (∀ (hf : ghst) (a_new : we), + ⌜at_key k hf = None⌠-∗ + ⌜we_key a_new = k⌠-∗ + ⌜we_val a_new = v⌠-∗ + ⌜∀ e, e ∈ h → e <â‚œ a_new⌠-∗ + own_mem_user γM k 1 (Some a_new) -∗ + own_obs γL DB_addr (h ++ hf ++ [a_new]) + ={E,⊤}=∗ Q a_new h hf))) ∨ + (∃ k wo q, ⌜k ∈ DB_keys⌠∗ + ⌜reqd = inr (k, (q, wo))⌠∗ + ⌜reqv = InjRV #(LitString k)⌠∗ + own_mem_user γM k q wo)). + + Definition ReqPost + (repv : val) (reqd : ReqData) (repd : RepData) : iProp Σ := + (∃ E k v P Q, ⌜reqd = inl (E, (k, v), (P, Q))⌠∗ + ∃ a_new h hf, ⌜repd = inl (a_new, h, hf)⌠∗ ⌜repv = InjLV #()⌠∗ Q a_new h hf) ∨ + (∃ k wo q, ⌜reqd = inr (k, (q, wo))⌠∗ + ∃ vo, ⌜repd = inr wo⌠∗ ⌜repv = InjRV vo⌠∗ own_mem_user γM k q wo ∗ + ((⌜vo = NONEV⌠∗ ⌜wo = NoneâŒ) ∨ + (∃ a, ⌜vo = SOMEV (we_val a)⌠∗ ⌜wo = Some aâŒ))). + + Global Instance client_handler_at_leader_user_params : MTS_user_params := + {| + MTS_req_ser := req_c2l_serialization; + MTS_req_ser_inj := req_c2l_ser_is_injective; + MTS_req_ser_inj_alt := req_c2l_ser_is_injective_alt; + MTS_req_data := ReqData; + MTS_rep_ser := rep_l2c_serialization; + MTS_rep_ser_inj := rep_l2c_ser_is_injective; + MTS_rep_ser_inj_alt := rep_l2c_ser_is_injective_alt; + MTS_rep_data := RepData; + MTS_saddr := DB_addr; + MTS_mN := (DB_InvName .@ "leader_main"); + MTS_handler_pre := ReqPre; + MTS_handler_post := ReqPost; + |}. + +End MT_user_params. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/leader/followers_mt_user_params.v b/aneris/examples/reliable_communication/lib/repdb/proof/leader/followers_mt_user_params.v new file mode 100644 index 0000000..6cd75cf --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/leader/followers_mt_user_params.v @@ -0,0 +1,66 @@ +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import ras log_resources resources_def + resources_global_inv resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import repdb_serialization. + +Import gen_heap_light. +Import lock_proof. + +Section MT_user_params. + + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N: gmap socket_address gname). + + Definition ReqData : Type := wrlog. + + Definition RepData : Type := wrlog. + + Definition ReqPre (reqv : val) (reqd : ReqData) : iProp Σ := + Global_Inv γL γM N ∗ ⌜reqv = #(List.length reqd)⌠∗ own_replog_obs γL DB_addrF reqd. + + Definition ReqPost + (repv : val) (reqd : ReqData) (repd : RepData) : iProp Σ := + ∃ (we : write_event), + ⌜repd = reqd ++ [we]⌠∗ + ⌜we.(we_key) ∈ DB_keys⌠∗ + ⌜DB_Serializable (we_val we)⌠∗ + ⌜we.(we_time) = (List.length reqd)⌠∗ + ⌜repv = $ we⌠∗ + own_replog_obs γL DB_addrF repd. + + Global Instance follower_handler_user_params : MTS_user_params := + {| + MTS_req_ser := req_f2l_serialization; + MTS_req_ser_inj := req_f2l_ser_is_injective; + MTS_req_ser_inj_alt := req_f2l_ser_is_injective_alt; + MTS_req_data := ReqData; + MTS_rep_ser := rep_l2f_serialization; + MTS_rep_ser_inj := rep_l2f_ser_is_injective; + MTS_rep_ser_inj_alt := rep_l2f_ser_is_injective_alt; + MTS_rep_data := RepData; + MTS_saddr := DB_addrF; + MTS_mN := (DB_InvName .@ "leader_secondary"); + MTS_handler_pre := ReqPre; + MTS_handler_post := ReqPost; + |}. + +End MT_user_params. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_client_handler.v b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_client_handler.v new file mode 100644 index 0000000..712870b --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_client_handler.v @@ -0,0 +1,218 @@ +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events stdpp_utils. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import ras log_resources resources_def + resources_global_inv resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import repdb_serialization log_proof. +From aneris.examples.reliable_communication.lib.repdb.proof.leader + Require Import clients_mt_user_params. + +Import gen_heap_light. + +Section Clients_MT_spec_params. + + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + Context (mγ : gname) (mv : val) (kvsL logL : loc). + + Notation MTU := (client_handler_at_leader_user_params γL γM N). + + Lemma client_request_handler_at_leader_spec : + ∀ reqv reqd, + {{{ leader_local_main_inv γL kvsL logL mγ mv ∗ + MTU.(MTS_handler_pre) reqv reqd }}} + client_request_handler_at_leader #kvsL #logL mv reqv @[ip_of_address MTU.(MTS_saddr)] + {{{ repv repd, RET repv; + ⌜Serializable (rep_l2c_serialization) repv⌠∗ + MTU.(MTS_handler_post) repv reqd repd }}}. + Proof. + iIntros (reqv reqd Φ) "(#Hmon & Hpre) HΦ". + rewrite /client_request_handler_at_leader. + wp_pures. + wp_apply (monitor_acquire_spec with "[Hmon]"); first by iFrame "#". + iIntros (v) "(-> & HKey & HR)". + iDestruct "HR" as (lV lM) "(%Hlog & Hpl & HlogL & HR)". + iDestruct "HR" as (kvsV kvsM) "(%Hkvs & %HvalidLocal & Hpm)". + iDestruct "Hpre" as "((#Htks & #HGinv) & [HpreW | HpreR])". + do 2 wp_pure _. + - iDestruct "HpreW" as (E k v P Q) "(%Hrd & -> & %HE & %Hkeys & P & Hvsh)". + wp_pures. + wp_load. + wp_apply (wp_map_insert $! Hkvs). + iIntros (m' Hm'). + wp_bind (Store _ _). + wp_apply (aneris_wp_atomic _ _ E). + set (a := {|we_key := k; we_val := v; + we_time := (length lM : int_time.(Time))|}). + iMod ("Hvsh" with "[$P]") as (h a_old) "(%Hkh & Hk & Hobsh & Hpost)". + iDestruct (own_obs_prefix with "[$HlogL][Hobsh]") as "%Hprefixh". + { by iApply Obs_own_log_obs. } + rewrite -{1} Hkh. + iDestruct (get_obs with "[$HlogL]") as "#HobsL". + iMod (OwnMemKey_obs_frame_prefix_holds _ _ _ DB_addr + with "[$ Htks $HGinv][$Hk $HobsL]") as "(Hk & %Heqhk)"; + [solve_ndisj|apply Hprefixh | by iLeft | ]. + destruct Hprefixh as (hf & Hprefixh). + assert (at_key k hf = None) as Hnone. + { apply (at_key_app_none _ h). + - rewrite -Hprefixh. + by eapply valid_state_local_log_no_dup. + - naive_solver. } + iInv DB_InvName + as (lMG kvsMG) ">(%HkG & %Hdom & %Hdisj & HmS & HlM & HknwF & HmapF & %HvalidG)". + iDestruct (own_log_auth_combine with "HlM HlogL") as "(HlFull & ->)". + rewrite Qp_half_half. + iDestruct (own_obs_prefix with "[$HlFull][Hobsh]") as "%Hprefixh2". + by iApply Obs_own_log_obs. + iMod (own_log_auth_update _ _ (lM ++ [a]) with "[$HlFull]") as "HlFull". + { by apply prefix_app_r. } + iMod (own_mem_update _ _ _ _ a with "[$Hk][$HmS]") as "(Hk & HmS)". + rewrite - {4} Qp_half_half. + iDestruct (own_log_auth_split with "HlFull") as "(HlogM & HlogL)". + iDestruct (get_obs with "[$HlogL]") as "#Hobsfr2". + iModIntro. rewrite /global_inv_def. iSplitL "HlogM HmS HmapF HknwF". + { iNext. + iExists _, _. + iFrame. + erewrite dom_insert_L, DB_GSTV_mem_dom; last done. + iPureIntro. + split; first set_solver. + do 2 (split; first done). + apply valid_state_update; eauto; apply _. } + iDestruct ("Hpost" $! hf a with "[//][//][//][][$Hk][Hobsfr2]") as "HQ". + { iPureIntro. inversion HvalidLocal. iIntros (e He). + assert (e ∈ lM) as HelM. { set_solver. } + assert (e.(we_time) < length lM) as Htime. + { destruct (elem_of_list_lookup_1 lM e HelM) as [n Hnth]. + assert (n < length lM)%nat as Hnh. + { apply lookup_lt_is_Some_1; eauto. } + destruct (DB_LSTV_log_events n Hnh) as (e' & He' & He'time & He'keys). + assert (e = e') as Heqe. { rewrite Hnth in He'. by inversion He'. } + rewrite Heqe - He'time. lia. } + done. } + { iNext. iLeft. list_simplifier. iSplit; first done. iFrame "#". } + { iModIntro. + wp_store. + iMod "HQ". + iModIntro. + wp_pures. + wp_apply (wp_log_length with "[$Hpl]"); [done|]. + iIntros (n) "(%Hlen & _ & Hpl)". wp_pures. + rewrite Hlen. + wp_apply (wp_log_add_entry _ _ _ lM a with "[$Hpl]"); [done|]. + iIntros (logV') "(%Hlog' & Hpl')". wp_pures. + rewrite /leader_local_main_inv /log_monitor_inv. + wp_smart_apply (monitor_signal_spec _ _ mγ with "[$HKey $Hmon Hpm Hpl' HlogL]"). + { iExists _, _. iFrame "#∗". iSplit; first done. iExists _. iFrame. + iExists _. iSplit; first done. iPureIntro. + apply valid_state_local_update; try eauto. apply _. } + iIntros "(Hkey & HlRes)". + wp_pures. + wp_apply (monitor_release_spec with "[$Hmon $HlRes $Hkey]"). + iIntros (v' ->). + do 2 wp_pure _. + iApply "HΦ". + iSplit; [iPureIntro; apply _ |]. simpl; rewrite /ReqPost. + iFrame. + iLeft. + iExists _, _, _, _, _. + iSplit; first done. + eauto with iFrame. } + - iDestruct "HpreR" as (k we q Hkeys Hreqd ->) "Hk". + wp_pures. + wp_load. + wp_apply (wp_map_lookup $! Hkvs). + iIntros (v Hv). + inversion HvalidLocal. + wp_apply fupd_aneris_wp. + iAssert (Global_Inv γL γM N) as "#HGinvR". { by iFrame "#". } + iMod (OwnMemKey_wo_obs_holds with "HGinvR Hk") + as "(Hk & (%lM' & #HObsL & <-))"; [solve_ndisj|]. + iDestruct (own_obs_prefix _ _ lM lM' with "[$HlogL][HObsL]") + as "%Hprefix". by iApply Obs_own_log_obs. + iDestruct (get_obs with "[$HlogL]") as "#HObsL'". + iMod (OwnMemKey_obs_frame_prefix_holds + with "[$HGinvR][Hk HObsL]") as "(Hk & %Heq)"; + [solve_ndisj|done|iFrame "#∗"; by iLeft|]. + iAssert (|={⊤}=> + (⌜v = InjLV #()⌠∗ ⌜at_key k lM' = NoneâŒ) ∨ + (∃ a : write_event, + ⌜v = (InjRV (we_val a))⌠∗ ⌜at_key k lM' = Some aâŒ))%I + as ">Hpost". + { destruct (kvsM !! k) eqn:Hmk; rewrite Hmk in Hv; rewrite Hv. + - iModIntro. iRight. + apply DB_LSTV_in_mem_log_some_coh_local in Hmk. + destruct Hmk as (we0 & Hwe0L & <-). + iExists _. + iSplit; first done. + iPureIntro. + by rewrite Heq. + - iModIntro. + iLeft. iSplit; first done. + iPureIntro. + apply DB_LSTV_in_mem_log_none_coh_local in Hmk. + by rewrite Heq. } + iModIntro. wp_pures. + destruct (kvsM !! k) eqn:Hmk; rewrite Hmk in Hv; rewrite Hv. + -- iDestruct "Hpost" as "[(%Habs & _)|Hpost]"; first done. + iDestruct "Hpost" as (a Ha) "%Hwe". + wp_apply (monitor_release_spec with "[$Hmon HlogL Hpl Hpm $HKey]"). + { iExists _, _. iFrame "#∗". iSplit; first done. + iExists _, _. eauto with iFrame. } + iIntros (v' ->). + do 2 wp_pure _. + iApply ("HΦ" $! _ (inr (Some a))). iSplit. + { iPureIntro. + assert (k ∈ dom kvsM) as Hk by by apply elem_of_dom. + assert (v0 = (we_val a)) as -> by naive_solver. + specialize (DB_LSTV_mem_serializable_vs_local k (we_val a) Hmk). + apply _. } + simpl. rewrite /log_monitor_inv_def /ReqPost. + { iRight. + iExists k, (Some a), q. + rewrite Hwe in Hreqd. + iSplit; first done. + iExists ((InjRV v0)). + do 2 (iSplit; first done). + rewrite Hwe. + iFrame. + iRight. + by iExists _. } + -- wp_apply (monitor_release_spec with "[$Hmon HlogL Hpl Hpm $HKey]"). + { iExists _, _. iFrame "#∗". iSplit; first done. + iExists _, _. eauto with iFrame. } + iIntros (v' ->). + do 2 wp_pure _. + iApply ("HΦ" $! _ (inr None)). + iDestruct "Hpost" as "[(_ & ->) |%Habs]"; [|naive_solver]. + iSplit. + { rewrite /rep_l2c_serialization. iPureIntro. apply _. } + simpl. rewrite /log_monitor_inv_def /ReqPost. + { iRight. iExists _, _, _. iSplit; first done. iExists v. + apply DB_LSTV_in_mem_log_none_coh_local in Hmk. + rewrite -Hmk Heq Hv. + do 2 (iSplit; first done). + iFrame. + by iLeft. } + Qed. + +End Clients_MT_spec_params. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_followers_handler.v b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_followers_handler.v new file mode 100644 index 0000000..1be0855 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_followers_handler.v @@ -0,0 +1,141 @@ +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras + log_resources + resources_def + resources_global_inv + resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import + repdb_serialization + log_proof. +From aneris.examples.reliable_communication.lib.repdb.proof.leader + Require Import + followers_mt_user_params. + +Import gen_heap_light. +Import lock_proof. +Import log_code. +(* -------------------------------------------------------------------------- *) +Section Followers_MT_spec_params. + + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + Context (mγ γF : gname) (mv : val) (logFLoc : loc). + Context (HipNeq : DB_addr ≠DB_addrF). + Notation MTU_F := (follower_handler_user_params γL γM N). + + Lemma follower_request_handler_spec : + ∀ reqv reqd, + {{{ leader_local_secondary_inv γL logFLoc γF mγ mv ∗ + MTU_F.(MTS_handler_pre) reqv reqd }}} + follower_request_handler #logFLoc mv reqv @[ip_of_address MTU_F.(MTS_saddr)] + {{{ repv repd, RET repv; + ⌜Serializable rep_l2f_serialization repv⌠∗ + MTU_F.(MTS_handler_post) repv reqd repd }}}. + Proof. + iIntros (reqv reqd Φ) "(#Hmon & Hpre) HΦ". + rewrite /follower_request_handler. + simplify_eq /=. + wp_pures. + wp_apply (monitor_acquire_spec with "[Hmon]"); first by iFrame "#". + iIntros (v) "(-> & Hlocked & HR)". + iDestruct "Hpre" as "((#Htks & #HGinv) & -> & #Hobs)". + iDestruct "HR" as (logV logM) "(%Hlog & Hpl & HLog & #Htkn & #HobsL)". + iDestruct "Hobs" as (γF') "(Htkn' & _ & Hobs)". + iDestruct (known_replog_token_agree with "[$Htkn'][$Htkn]") as "->". + iDestruct (own_obs_prefix with "[$HLog][$Hobs]") as "%Hprefix". + apply prefix_length in Hprefix. + rewrite /leader_local_secondary_inv /log_monitor_inv. + wp_pures. + wp_apply (wp_log_wait_until + with "[$Hmon $Hlocked $Hpl $HLog $HobsL][HΦ]"). + { naive_solver. } + iNext. iIntros (logV' logM'). + iIntros "(%Hlen' & %Hlog' & Hlocked & HmainRes & Hpl & HmainLog)". + wp_pures. + wp_apply (wp_log_get with "[$Hpl]"); first done. + iIntros (we) "(%Hsome & _ & Hpl)". + iDestruct (get_obs with "HmainLog") as "#Hobs'". + assert (nth_error logM' (length reqd) = Some we) as Hsome2 by auto. + apply nth_error_split in Hsome. + destruct Hsome as (l1 & l2 & HeqlogM' & Hlen1). + iDestruct (get_obs_prefix with "Hobs'") as "Hobsl1"; first done. + iDestruct (obs_length_agree with "[$Hobsl1][$Hobs]") as "->"; first done. + assert (logM' = (reqd ++ [we]) ++ l2) as HeqlogM'2. + { by list_simplifier. } + clear HeqlogM'. + iDestruct (get_obs_prefix with "Hobs'") as "HobsWe"; first done. + iDestruct "HmainRes" as "(_ & #HobsL')". + iDestruct (get_obs_prefix with "HobsL'") as "HobsLWe"; first done. + iApply fupd_aneris_wp. + iMod (Obs_we_serializable _ _ _ DB_addr with "[$HGinv $Htks][$HobsLWe]") + as "%Hser"; [done| by iLeft |]. + iInv DB_InvName + as (lMG kvsMG) + ">(%HkG & %Hdom & %Hdisj & HmS & HlM & HknwF & HmapF & %HvalidG)". + inversion HvalidG. + iDestruct (own_obs_prefix with "[$HlM][$HobsLWe]") as "%Hprefixh2". + assert (we ∈ reqd ++ [we]) by set_solver. + assert (we ∈ lMG) as HelM by by apply (elem_of_prefix (reqd ++ [we])). + assert (we.(we_time) = length reqd ∧ we.(we_key) ∈ dom kvsMG) as (Htime & Hwekeydom). + { destruct (elem_of_list_lookup_1 lMG we HelM) as [n Hnth]. + assert (n < length lMG)%nat as Hnh. + { apply (lookup_lt_is_Some_1 _ _); eauto. } + assert (lMG !! length reqd = Some we) as Hlenreq. + { inversion Hprefixh2 as [suf Hlen]. + rewrite Hlen -app_assoc. + rewrite lookup_app_r //= Nat.sub_diag //. } + destruct (DB_GSTV_log_events n Hnh) as (e' & He' & (He'time & He'keys)). + assert (we = e') as Heqe. { rewrite Hnth in He'. by inversion He'. } + rewrite Heqe - He'time. + apply valid_state_log_no_dup in HvalidG as HnoDup. + rewrite -Heqe in He'. + split. + - eapply NoDup_lookup; [done|done|done]. + - set_solver. } + iModIntro. + rewrite /global_inv_def. iSplitL "HlM HmS HmapF HknwF". + { iNext. iExists _, _. by iFrame. } + iModIntro. + wp_apply network_util_proof.wp_unSOME; first done. + iIntros "_". + wp_pures. + wp_apply (monitor_release_spec with "[$Hmon Hpl HmainLog $Hlocked]"). + { iExists logV', logM'. by iFrame "#∗". } + iIntros (v ->). + do 2 wp_pure _. + iApply ("HΦ" $! ($ we) (reqd ++ [we])). + iSplit; first done. + iExists we. + iSplit; first done. + iSplit; [iPureIntro; set_solver|]. + iSplit. + { iPureIntro. unfold DB_Serializable. + simplify_eq /=. destruct Hser as (? & ? & ? & Hser & ?). + simplify_eq /=. destruct Hser as (? & ? & ? & ? & ?). + by simplify_eq /=. } + do 2 (iSplit; first done). + iExists γF. + iFrame "#∗". + Qed. + +End Followers_MT_spec_params. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_init_leader.v b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_init_leader.v new file mode 100644 index 0000000..f335aee --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_init_leader.v @@ -0,0 +1,174 @@ +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params mt_server_code. +From aneris.examples.reliable_communication.lib.mt_server.spec + Require Import api_spec. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras + log_resources + resources_def + resources_global_inv + resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import + log_proof + repdb_serialization. +From aneris.examples.reliable_communication.lib.repdb.proof.leader + Require Import + clients_mt_user_params + followers_mt_user_params + proof_of_client_handler + proof_of_followers_handler + proof_of_update_log_copy_loop. + +Section Init_Leader_Proof. + Context `{aG : !anerisG Mdl Σ, dbparams : !DB_params, dbg: !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + Context (leader_si leaderF_si : message → iProp Σ). + Context (SrvLeaderInit SrvLeaderFInit : iProp Σ). + Notation MTC := (client_handler_at_leader_user_params γL γM N). + Notation MTF := (follower_handler_user_params γL γM N). + Context (γdbF : gname). + + Definition init_leader_res : iProp Σ := + ⌜N !! DB_addrF = Some γdbF⌠∗ + Global_Inv γL γM N ∗ + own_log_auth γL (1/2) [] ∗ + SrvLeaderInit ∗ + known_replog_token DB_addrF γdbF ∗ + own_log_auth γdbF (1/2) [] ∗ + SrvLeaderFInit. + + Definition init_leader_spec_internal A := + DB_addr ∈ A → + DB_addrF ∈ A → + ip_of_address DB_addrF = ip_of_address DB_addr → + port_of_address DB_addrF ≠port_of_address DB_addr → + ⊢ + {{{ fixed A ∗ + DB_addr ⤇ leader_si ∗ + DB_addrF ⤇ leaderF_si ∗ + (@run_server_spec _ _ _ _ MTC SrvLeaderInit leader_si) ∗ + (@run_server_spec _ _ _ _ MTF SrvLeaderFInit leaderF_si) ∗ + init_leader_res ∗ + DB_addr ⤳ (∅, ∅) ∗ + DB_addrF ⤳ (∅, ∅) ∗ + free_ports (ip_of_address DB_addr) {[port_of_address DB_addr]} ∗ + free_ports (ip_of_address DB_addrF) {[port_of_address DB_addrF]} }}} + init_leader (s_serializer DB_serialization) + #DB_addr #DB_addrF @[ip_of_address DB_addr] + {{{ RET #(); True }}}. + + Lemma init_leader_spec_internal_holds A : init_leader_spec_internal A. + Proof. + iIntros (HinA HinFA HipEq HprNeq) "!# %Φ Hr HΦ". + iDestruct "Hr" as + "(#HA & #Hsi & #HsiF & HInitLeaderSpec & HInitLeaderFSpec + & HinitRes & Hmh & HmhF & Hfp & HfpF)". + rewrite /init_leader. + wp_pures. + wp_apply (wp_log_create with "[//]"). + iIntros (logL logV) "(HpL & %HlogV)". + wp_pures. + wp_apply (wp_log_create with "[//]"). + iIntros (logLF logVF) "(HpLF & %HlogVF)". + wp_pures. + wp_apply (wp_map_empty with "[//]"). + iIntros (kvsV HkvsV). + wp_alloc kvsL as "HpKvs". + wp_pures. + iDestruct "HinitRes" + as "(%Htk & #HGinv & HownL & HsrvInit & #HFtkn & HownF & HsrvFinit)". + iDestruct (get_obs with "[$HownL]") as "#HobsL". + rewrite -Qp_quarter_quarter. + rewrite {1} Qp_quarter_quarter. + iDestruct (own_log_auth_split _ (1/4) (1/4) with "[$HownF]") + as "(HownF1 & HownF2)". + wp_apply (new_monitor_spec + (DB_InvName .@ "leader_main") (ip_of_address DB_addr) + (log_monitor_inv_def + (ip_of_address DB_addr) γL (1/2) logL + (leader_local_main_res kvsL)) + with "[HownL HpL HpKvs]") . + iExists logV, []. + iSplit; first done. + iFrame. + iExists kvsV, ∅. + iSplit; first done. + iSplit. + { iPureIntro. apply valid_state_local_empty. } + iFrame. + iIntros (mγ mv) "#HLInv". + wp_pures. + symmetry in HipEq. + rewrite {4 5} HipEq. + wp_apply (new_monitor_spec + (DB_InvName .@ "leader_secondary") (ip_of_address DB_addrF) + (log_monitor_inv_def + (ip_of_address DB_addrF) γdbF (1/4) logLF + (leader_local_secondary_res γL γdbF)) + with "[HownF1 HpLF HFtkn HobsL]") . + iExists logVF, []. + iSplit; first done. + iFrame "#∗". + iIntros (mFγ mFv) "#HLFInv". + wp_pures. + wp_apply aneris_wp_fork. + iSplitR "HInitLeaderSpec HsrvInit Hmh Hfp". + - iNext. + wp_pures. + wp_apply aneris_wp_fork. + iSplitR "HInitLeaderFSpec HsrvFinit HmhF HfpF". + -- iNext. + wp_pures. + wp_apply aneris_wp_fork. + iSplitL "HΦ"; iNext; [ by iApply "HΦ"|]. + rewrite -HipEq. + wp_apply (update_log_copy_loop_spec γL γM N HipEq γdbF mFγ + with "[$HownF2]"); [ | done]. + iFrame "#∗". + rewrite /leader_local_secondary_inv. + rewrite /log_monitor_inv. + by rewrite HipEq. + -- rewrite /start_leader_processing_followers. + iNext. + wp_pures. + assert (DB_addr ≠DB_addrF) as Hneq. + { intro Heq. destruct DB_addr, DB_addrF. by inversion Heq. } + wp_pures. + wp_apply ("HInitLeaderFSpec" with "[] [$HsrvFinit $HmhF $HfpF]"); + [|by iFrame "#"|done]. + iIntros (v1 v2 Ψ) "!> HP HΨ". + wp_pures. + iApply (follower_request_handler_spec with "[HLFInv $HP]"); + [done| |done]. + iFrame "#". + - rewrite /start_leader_processing_clients. + iNext. + wp_pures. + rewrite -HipEq. + wp_apply ("HInitLeaderSpec" with "[] [$HsrvInit $Hmh $Hfp]"); + [|by iFrame "#"|done]. + iIntros (v1 v2 Ψ) "!> HP HΨ". + wp_pures. + by iApply (client_request_handler_at_leader_spec with "[$HLInv $HP]"). + Qed. + +End Init_Leader_Proof. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_proxy.v b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_proxy.v new file mode 100644 index 0000000..e11dde4 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_proxy.v @@ -0,0 +1,223 @@ +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params mt_server_code. +From aneris.examples.reliable_communication.lib.mt_server.spec + Require Import api_spec. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras + resources_def + resources_global_inv + resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import + repdb_serialization. +From aneris.examples.reliable_communication.lib.repdb.proof.leader + Require Import + clients_mt_user_params. + +Section Client_Proxy_Proof. + Context `{!anerisG Mdl Σ, dbparams : !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + Context (srv_si : message → iProp Σ). + Notation MTC := (client_handler_at_leader_user_params γL γM N). + + Definition write_spec_internal + (ip : ip_address) (wr : val) : iProp Σ := + Eval simpl in + â–¡ (∀ (E : coPset) (k : Key) (v : SerializableVal) + (P : iProp Σ) (Q : write_event → wrlog → wrlog → iProp Σ), + ⌜↑DB_InvName ⊆ E⌠-∗ + ⌜k ∈ DB_keys⌠-∗ + â–¡ (P + ={⊤, E}=∗ + ∃ (h : wrlog) (a_old: option write_event), + ⌜at_key k h = a_old⌠∗ + own_mem_user γM k 1 a_old ∗ + own_obs γL DB_addr h ∗ + â–· (∀ (hf : ghst) (a_new : we), + ⌜at_key k hf = None⌠-∗ + ⌜we_key a_new = k⌠-∗ + ⌜we_val a_new = v⌠-∗ + ⌜∀ e, e ∈ h → e <â‚œ a_new⌠-∗ + own_mem_user γM k 1 (Some a_new) -∗ + own_obs γL DB_addr (h ++ hf ++ [a_new]) ={E,⊤}=∗ Q a_new h hf)) -∗ + {{{ P }}} + wr #k v @[ip] + {{{ RET #(); + ∃ (h hf : wrlog) (a: write_event), Q a h hf }}})%I. + + Lemma write_spec_internal_holds {MTR:MTS_resources} A ip γ lk (reqh : val) : + Global_Inv γL γM N -∗ + fixed A -∗ + DB_addr ⤇ srv_si -∗ + @make_request_spec _ _ _ _ MTC _ -∗ + is_lock (DB_InvName.@"leader") ip γ lk + (MTSCanRequest ip reqh) -∗ + write_spec_internal ip + (λ: "k" "v", + match: (λ: "req", + acquire lk ;; + let: "res" := make_request reqh "req" in release lk ;; "res")%V + (InjL ("k", "v")) with + InjL "_u" => #() + | InjR "_abs" => assert: #false + end). + Proof. + iIntros "#Hinv #HA #Hsi #Hspec #Hlk". + rewrite /write_spec_internal. + iIntros (E k v P Q HE Hkeys) "!# #Hviewshift". + iIntros (Φ) "!#". + iIntros "HP HΦ". + wp_pures. + wp_apply (acquire_spec with "Hlk"). + iIntros (w) "(->&Hlocked&Hreq)". + wp_pures. + wp_apply ("Hspec" with "[$Hreq HP]"). + { iSplit. + - iPureIntro. + simplify_eq /=. + assert (s_valid_val DB_serialization v) as Hs by (apply v.(SV_ser)). + eexists _. left. split; first done. + exists #k, v . split; first done. split; last done. + simplify_eq /=. by eexists _. + - simplify_eq /=. + rewrite /ReqPre. iFrame "#". iLeft. + iExists E, k, v, P, Q. + do 4 (iSplit; first done). + iFrame "#∗". } + iIntros (repd repv) "[Hreq Hpost]". + wp_pures. + wp_apply (release_spec with "[$Hlk $Hlocked $Hreq]"). + iIntros (w) "->". + wp_pures. + iDestruct "Hpost" as "[Hpost|Habs]". + - iDestruct "Hpost" as (E0 k0 v0 P0 Q0 Hinl) "Hpost". + iDestruct "Hpost" as (a_new h hf Hrepd ->) "Hpost". + wp_pures. + iApply "HΦ". + inversion Hinl. + eauto with iFrame. + - by iDestruct "Habs" as (k0 w0 q0 Hinr) "_". + Qed. + + Definition read_spec_internal (ip : ip_address) + (rd : val) (k : Key) (q : Qp) + (wo : option write_event) : iProp Σ := + ⌜k ∈ DB_keys⌠-∗ + {{{ own_mem_user γM k q wo }}} + rd #k @[ip] + {{{vo, RET vo; + own_mem_user γM k q wo ∗ + ((⌜vo = NONEV⌠∗ ⌜wo = NoneâŒ) ∨ + (∃ a, ⌜vo = SOMEV (we_val a)⌠∗ ⌜wo = Some aâŒ)) + }}}%I. + + Lemma read_spec_internal_holds {MTR:MTS_resources} A ip γ lk (reqh : val) : + Global_Inv γL γM N -∗ + fixed A -∗ + DB_addr ⤇ srv_si -∗ + @make_request_spec _ _ _ _ MTC _ -∗ + is_lock (DB_InvName.@"leader") ip γ lk + (MTSCanRequest ip reqh) -∗ + ∀ (k : Key) (q : Qp) (h : option write_event), + read_spec_internal ip + (λ: "k", + match: (λ: "req", + acquire lk ;; + let: "res" := make_request reqh "req" in release lk ;; "res")%V + (InjR "k") with + InjL "_abs" => assert: #false + | InjR "r" => "r" + end) + k q h. + Proof. + iIntros "#Hinv #HA #Hsi #Hspec #Hlk". + iIntros (k q h). + rewrite /read_spec_internal. + iIntros (Hkeys Φ) "!#". + iIntros "Hk HΦ". + wp_pures. + wp_apply (acquire_spec with "Hlk"). + iIntros (v) "(->&Hlocked&Hreq)". + wp_pures. + wp_apply ("Hspec" with "[$Hreq Hk]"). + { iSplit. + - iPureIntro. + simplify_eq /=. + eapply sum_is_ser_valid. + simplify_eq /=. simpl. + rewrite /sum_is_ser. + eexists _, _. by right. + - simplify_eq /=. + rewrite /ReqPre. iFrame "#". iRight. + iExists _, _, _. by iFrame. } + iIntros (repd repv) "[Hreq Hpost]". + wp_pures. + wp_apply (release_spec with "[$Hlk $Hlocked $Hreq]"). + iIntros (v) "->". + wp_pures. + iDestruct "Hpost" as "[Habs|Hpost]". + - by iDestruct "Habs" as (E k0 v0 P0 Q0 Habs) "d". + - iDestruct "Hpost" as (k0 w0 q0 Hinr) "Hpost". + iDestruct "Hpost" as (vo Hrepd ->) "(Hmem & Hpost)". + wp_pures. + iApply "HΦ". + inversion Hinr. + iFrame. + Qed. + + Definition init_client_leader_proxy_internal {MTR : MTS_resources} + (A : gset socket_address) (sa : socket_address) : iProp Σ := + ⌜DB_addr ∈ A⌠→ + ⌜sa ∉ A⌠→ + {{{ fixed A ∗ + DB_addr ⤇ srv_si ∗ + sa ⤳ (∅, ∅) ∗ + (@init_client_proxy_spec _ _ _ _ MTC _ srv_si) ∗ + (@make_request_spec _ _ _ _ MTC _) ∗ + free_ports (ip_of_address sa) {[port_of_address sa]} }}} + init_client_leader_proxy (s_serializer DB_serialization) + #sa #DB_addr @[ip_of_address sa] + {{{ wr rd, RET (wr, rd); + (∀ k q h, read_spec_internal (ip_of_address sa) rd k q h) ∗ + write_spec_internal (ip_of_address sa) wr }}}. + + Lemma init_client_leader_proxy_internal_holds {MTR : MTS_resources} A sa : + Global_Inv γL γM N ⊢ init_client_leader_proxy_internal A sa. + Proof. + iIntros "#Hinv". + iIntros (HA HnA). + iIntros (Φ) "!#". + iIntros "(#Hf & #Hsi & Hmh & #HClient_proxySpec & # Hreq_spec & Hfp) HΦ". + rewrite /init_client_leader_proxy. + wp_pures. + wp_apply ("HClient_proxySpec" with "[$Hf $Hfp $Hmh $Hsi][HΦ]"); first done. + iNext. + iIntros (reqh) "Hreq". + wp_pures. + wp_apply (newlock_spec (DB_InvName .@ "leader") with "Hreq"). + iIntros (lk γ) "#Hlk". + wp_pures. + iApply "HΦ". + iSplit. + - by iApply read_spec_internal_holds. + - by iApply write_spec_internal_holds. + Qed. + +End Client_Proxy_Proof. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_update_log_copy_loop.v b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_update_log_copy_loop.v new file mode 100644 index 0000000..92a69c9 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/leader/proof_of_update_log_copy_loop.v @@ -0,0 +1,150 @@ +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics coq_tactics reduction spec_patterns. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import aneris_lifting. +From aneris.aneris_lang.program_logic Require Import aneris_weakestpre. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.lib.mt_server + Require Import user_params mt_server_code. +From aneris.examples.reliable_communication.lib.mt_server.spec + Require Import api_spec. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events resources. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras log_resources resources_def + resources_global_inv resources_local_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import + repdb_serialization log_proof. +From aneris.examples.reliable_communication.lib.repdb.proof.leader + Require Import + clients_mt_user_params. + +Import log_proof. + +Section UpdateLogCopy_Proof. + Context `{!anerisG Mdl Σ, dbparams : !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + Context (HipEq : ip_of_address DB_addr = ip_of_address DB_addrF). + + Definition own_replog_loop γ l : iProp Σ := + known_replog_token DB_addrF γ ∗ own_logL_obs γL l ∗ own_log_auth γ (1/4) l. + + Lemma update_log_copy_loop_spec + (γF mFγ mCγ : gname) (kvsL logCL logFL : loc) (mvC mvF : val) : + {{{ Global_Inv γL γM N ∗ + leader_local_main_inv γL kvsL logCL mCγ mvC ∗ + leader_local_secondary_inv γL logFL γF mFγ mvF ∗ + own_replog_loop γF [] + }}} + update_log_copy_loop #logCL mvC #logFL mvF #() @[ip_of_address DB_addr] + {{{ RET #(); True }}}. + Proof. + iIntros (Φ) "((#Htks & #HGinv) & #HinvL & #HinvF & Hloop) HΦ". + rewrite /update_log_copy_loop. + do 12 wp_pure _. + (* pose (@nil_length) as Hnl. *) + replace 0%Z with (Z.of_nat 0%nat); last done. + iAssert (⌜0%nat = List.length (@nil write_eventO)âŒ)%I as "Hlen". + { done. } + iRevert "Hlen". + generalize 0%nat at 1 2 as m. + generalize (@nil write_eventO) as l. + iIntros (lF n Hlen). + iLöb as "IH" forall (lF n Hlen) "Hloop". + wp_pures. + wp_apply (monitor_acquire_spec with "[HinvL]"); first by iFrame "#". + iIntros (v) "( -> & Hlocked & Hres)". + wp_pures. + iDestruct "Hres" as (logV logM) "(%Hlog & Hpl & HmainLog & HmainRes)". + iAssert (⌜lF `prefix_of` logMâŒ)%I as "%Hprefix". + { iDestruct "Hloop" as "(_ & Hobs & _)". + iApply (own_obs_prefix with "[$HmainLog][$Hobs]"). } + assert (length lF ≤ length logM) as Hlen2. + { by apply prefix_length. } + wp_apply (wp_log_wait_until + with "[$HinvL $Hlocked $Hpl $HmainLog $HmainRes][Hloop HΦ]"). + { naive_solver. } + iNext. + iIntros (logV' logM'). + iIntros "(%Hlen' & %Hlog' & Hlocked & HmainRes & Hpl & HmainLog)". + wp_pures. + wp_load. + wp_pures. + iAssert (⌜lF `prefix_of` logM'âŒ)%I as "%Hprefix2". + { iDestruct "Hloop" as "(_ & Hobs & _)". + by iDestruct (own_obs_prefix with "[$HmainLog][$Hobs]") as "%Hprefix2". } + iDestruct (get_obs with "[$HmainLog]") as "#HobsM'". + wp_apply (monitor_release_spec + with "[$HinvL $Hlocked Hpl HmainLog HmainRes]"). + iExists _, _. eauto with iFrame. + iIntros (v ->). + wp_pures. + rewrite HipEq. + wp_apply (monitor_acquire_spec with "[$HinvF]"). + iIntros (v) "( -> & Hlocked & Hres)". + wp_pures. + iDestruct "Hres" as (logVF logMF) "(%HlogF & HplF & HLogOwnF & HResF)". + wp_store. + iDestruct "Hloop" as "(#HknownTkn & #Hobs & HownLoop)". + iDestruct (own_log_auth_combine + with "[$HLogOwnF][$HownLoop]") as "(HownFHalf1 & ->)". + assert (length lF < length logM') by lia. + clear logM Hlog Hprefix logV n Hlen Hlen' Hlen2. + rewrite /Global_Inv /global_inv_def. + iApply fupd_aneris_wp. + iInv DB_InvName as ">HGinvRes" "Hcl". + iDestruct "HGinvRes" as (L M Hkes Hdom Hdisj) "HGinvRes". + iDestruct "HGinvRes" as "(HownS & HownL & HknownN & HmapN & %HvSt)". + iAssert (⌜N !! DB_addrF = Some γFâŒ)%I as "%HinF". + by iDestruct (known_replog_in_N with "[$HknownN $HknownTkn]") as "%HinN". + iDestruct (big_sepM_lookup_acc _ N DB_addrF γF with "[$HmapN]") + as "(Hres & HmapN)"; [done|]. + iDestruct "Hres" as (l) "(#HknownTkn' & #Hobs' & HownFHalf2)". + iDestruct (own_log_auth_combine + with "[$HownFHalf1][$HownFHalf2]") as "(HownF & ->)". + rewrite Qp_quarter_quarter Qp_half_half. + iMod (own_log_auth_update _ l logM' + with "[$HownF]") as "HownF"; first done. + rewrite -Qp_half_half. + rewrite {1} Qp_half_half. + iDestruct (own_log_auth_split with "HownF") as "[HownF1 HownF2]". + rewrite -Qp_quarter_quarter. + rewrite {1} Qp_quarter_quarter. + iMod ("Hcl" with "[HownF1 HmapN HknownN HownS HownL]") as "_". + { iNext. iExists L, M. iFrame "#∗". + do 3 (iSplit; first done). + iSplit; last done. + iApply "HmapN". + iExists logM'. iFrame "#∗". } + iModIntro. + iDestruct (own_log_auth_split with "HownF2") as "[HownF1 HownF2]". + wp_apply (monitor_broadcast_spec + with "[$HinvF $Hlocked HplF HResF HownF1]"). + { iExists _, logM'. + rewrite /leader_local_secondary_res. + iFrame "#∗". + done. } + iIntros "(Hlocked & Hres)". + wp_pures. + wp_apply (monitor_release_spec with "[$HinvF $Hlocked $Hres]"). + iIntros (v ->). + do 4 wp_pure _. + assert (∃ lV : val, logV' = (lV, #(length logM'))%V ∧ is_list logM' lV) + as (lV & -> & Hlst') by done. + do 1 wp_pure _. + iApply ("IH" $! logM' with "[//][$HΦ][$HownF2]"). + iFrame "#∗". + Qed. + +End UpdateLogCopy_Proof. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/log_proof.v b/aneris/examples/reliable_communication/lib/repdb/proof/log_proof.v new file mode 100644 index 0000000..d300caa --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/log_proof.v @@ -0,0 +1,172 @@ +From iris.algebra Require Import agree auth excl gmap dfrac max_prefix_list. +From iris.algebra Require Import updates local_updates. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof assert_proof. +From aneris.examples.reliable_communication.lib.repdb + Require Export log_code. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import log_resources. + +Import lock_proof. + +Section Log. + Context `{!anerisG Mdl Σ, !lockG Σ}. + Context {Aty : Type}. + Notation A := (leibnizO Aty). + Context `{inG Σ (mono_listUR A)}. + Context `[!Inject A val]. + + Lemma wp_log_create ip : + {{{ True }}} + log_create #() @[ip] + {{{ logL logV, RET #logL; logL ↦[ip] logV ∗ ⌜is_log [] logVâŒ}}}. + Proof. + iIntros (Φ) "_ HΦ". + wp_rec. wp_pures. + wp_alloc l as "Hl". + iApply "HΦ". iFrame. iPureIntro. + by eexists. + Qed. + + Lemma wp_log_add_entry ip logL logV logM (x : A) : + {{{ ⌜is_log logM logV⌠∗ logL ↦[ip] logV }}} + log_add_entry #logL $x @[ip] + {{{ logV', RET #(); + ⌜is_log (logM ++ [x]) logV'⌠∗ logL ↦[ip] logV' }}}. + Proof. + iIntros (Φ) "(%Hl & Hp) HΦ". + destruct Hl as (lV & -> & Hlst). + wp_lam. wp_pures. + wp_load. wp_pures. + wp_apply (wp_list_cons _ []); first done. + iIntros (v) "%Hl2". + wp_apply wp_list_append; first done. + iIntros (v') "%Hl'". + wp_pures. + wp_store. + iApply "HΦ". + iFrame. + iPureIntro. + eexists; rewrite app_length /=; split; last done. + do 3 f_equal; lia. + Qed. + + + Lemma wp_log_next ip logL logV logM q : + {{{ ⌜is_log logM logV⌠∗ logL ↦[ip]{q} logV }}} + log_next #logL @[ip] + {{{ n, RET #n; + ⌜n = List.length logM⌠∗ ⌜is_log (logM) logV⌠∗ logL ↦[ip]{q} logV}}}. + Proof. + iIntros (Φ) "(%Hl & Hp) HΦ". + destruct Hl as (lV & -> & Hlst). + wp_lam. + wp_load. + wp_pures. + iApply "HΦ". + iFrame. + iPureIntro. + split; by eexists. + Qed. + + Lemma wp_log_length ip logL logV logM q : + {{{ ⌜is_log logM logV⌠∗ logL ↦[ip]{q} logV }}} + log_length #logL @[ip] + {{{ n, RET #n; + ⌜n = List.length logM⌠∗ ⌜is_log (logM) logV⌠∗ logL ↦[ip]{q} logV}}}. + Proof. + iIntros (Φ) "(%Hl & Hp) HΦ". + destruct Hl as (lV & -> & Hlst). + wp_lam. + wp_load. + wp_pures. + iApply "HΦ". + iFrame. + iPureIntro. + split; by eexists. + Qed. + +Lemma wp_log_get ip logL logV logM i q : + {{{ ⌜i < List.length logM⌠∗ + ⌜is_log logM logV⌠∗ logL ↦[ip]{q} logV }}} + log_get #logL #i @[ip] + {{{ x, RET (SOMEV $x); + ⌜List.nth_error logM i = Some x⌠∗ + ⌜is_log (logM) logV⌠∗ logL ↦[ip]{q} logV}}}. + Proof. + iIntros (Φ) "(%Hi & %Hl & Hp) HΦ". + destruct Hl as (lV & -> & Hlst). + wp_lam. + wp_pures. + wp_load. + wp_pures. + wp_apply wp_list_nth_some; [eauto with lia|]. + iIntros (v (x & -> & Hsome)). + iApply "HΦ". + iFrame. + iPureIntro. + split; eauto; last by eexists. + Qed. + + Lemma wp_log_wait_until ip + γlog q logM (* created at the logical setup *) + monN monγ monV monR logL logV i (* created at the allocation of physical data *): + {{{ ⌜i ≤ List.length logM⌠∗ ⌜is_log logM logV⌠∗ + is_monitor monN ip monγ monV (log_monitor_inv_def ip γlog q logL monR) ∗ + locked monγ ∗ (monR logM) ∗ logL ↦[ip] logV ∗ own_log_auth γlog q logM }}} + log_wait_until #logL monV #i @[ip] + {{{ logV' logM', RET #(); + ⌜i < List.length logM'⌠∗ ⌜is_log logM' logV'⌠∗ + locked monγ ∗ (monR logM') ∗ logL ↦[ip] logV' ∗ own_log_auth γlog q logM' }}}. + Proof. + iIntros (Φ) "(%Hi & %Hl & #Hmon & Hlocked & Hres & Hp & Hown) HΦ". + wp_lam. + wp_pures. + case_bool_decide as Hi2 ; first by lia. + wp_pures. + wp_apply (wp_log_next with "[$Hp //]"). + iIntros (n) "(-> & _ & Hp)". + wp_pures. + case_bool_decide as Hiz; first by lia. + wp_pure _. + clear Hiz Hi2. + iDestruct (get_obs with "Hown") as "#Hobs". + iLöb as "IH" forall (logV logM Hl Hi) "Hres Hp Hown Hobs". + wp_pures. + wp_apply (wp_log_next with "[$Hp //]"). + iIntros (n) "(-> & _ & Hp)". + wp_pures. + case_bool_decide as Hiz2. + - wp_pure _. + wp_apply (monitor_wait_spec with "[$Hmon Hres $Hlocked Hp Hown]"). + iExists _, _. iFrame. eauto. + iIntros (v) "(-> & Hlocked & Hres)". + iDestruct "Hres" as (logV' logM' Hlog') "(Hp & Hown & Hres)". + do 2 wp_pure _. + iDestruct (own_obs_prefix with "[$Hown][$Hobs]") as "%Hpre". + assert (i ≤ length logM') as Hi'. + list_simplifier. + by apply prefix_length. + iSpecialize ("IH" $! logV' logM' Hlog' Hi'). + iDestruct (get_obs with "Hown") as "#Hobs'". + iApply ("IH" with "[$Hlocked][$HΦ][$Hres][$Hp][$Hown][$Hobs']"). + - wp_pure _. + wp_apply wp_assert. + wp_pures. + iSplitR. + iPureIntro. + f_equal. + case_bool_decide; eauto with lia. + iNext. + iApply "HΦ". + iFrame. + eauto with lia. + Qed. + + End Log. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/proof_of_db_init.v b/aneris/examples/reliable_communication/lib/repdb/proof/proof_of_db_init.v new file mode 100644 index 0000000..dc3cabb --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/proof_of_db_init.v @@ -0,0 +1,230 @@ +From iris.algebra Require Import excl. +From iris.algebra Require Import auth gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic.lib Require Import invariants. +From iris.bi.lib Require Import fractional. +From aneris.prelude Require Import collect. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import ast. +From aneris.aneris_lang.lib.serialization Require Import serialization_code. +From aneris.aneris_lang Require Import lang. +From aneris.aneris_lang Require Import tactics proofmode. +From aneris.aneris_lang.program_logic + Require Import aneris_weakestpre aneris_lifting. +From aneris.aneris_lang.lib Require Import assert_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.examples.reliable_communication.prelude + Require Import ser_inj. +From aneris.examples.reliable_communication.spec + Require Import ras. +From aneris.examples.reliable_communication.lib.mt_server.spec + Require Import api_spec. +From aneris.examples.reliable_communication.lib.mt_server.proof + Require Import mt_server_proof. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import + ras + events + resources + api_spec. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras + log_resources + resources_def + resources_local_inv + resources_global_inv. +From aneris.examples.reliable_communication.lib.repdb.proof + Require Import + log_proof + repdb_serialization + db_resources_instance. +From aneris.examples.reliable_communication.lib.repdb.proof.leader + Require Import + clients_mt_user_params + followers_mt_user_params + proof_of_client_handler + proof_of_followers_handler + proof_of_init_leader + proof_of_proxy + proof_of_update_log_copy_loop. +From aneris.examples.reliable_communication.lib.repdb.proof.follower + Require Import + clients_at_follower_mt_user_params + proof_of_clients_handler + proof_of_proxy + proof_of_sync_loop + proof_of_init_follower. + +Import user_params. + +Section Init_setup_proof. + Context `{!anerisG Mdl Σ, DB : !DB_params, !DBPreG Σ, ras.SpecChanG Σ}. + + Lemma init_setup_holds (E : coPset) : + ↑DB_InvName ⊆ E → + DB_addr ∉ DB_followers → + DB_addrF ∉ DB_followers → + ⊢ |={E}=> + ∃ (DBRS : @DB_resources _ _ _ _ DB) + (Init_leader : iProp Σ) + (leader_si : message → iProp Σ) + (leaderF_si : message → iProp Σ), + GlobalInv ∗ + Obs DB_addr [] ∗ + ([∗ set] k ∈ DB_keys, k ↦ₖ None) ∗ + Init_leader ∗ + ((init_leader_spec Init_leader leader_si leaderF_si) ∗ + (init_client_proxy_leader_spec leader_si)) ∗ + ([∗ set] fsa ∈ DB_followers, + ∃ (f_si : message → iProp Σ) + (Init_follower : iProp Σ), + Init_follower ∗ + Obs fsa [] ∗ + (init_follower_spec fsa Init_follower f_si leaderF_si) ∗ + (init_client_proxy_follower_spec fsa f_si)). + Proof. + iIntros (HE Hn1 Hn2). + iMod (own_alloc + (â— (to_agree <$> ∅ : (gmapUR socket_address (agreeR gnameO))))) as + (γFls) "Hgnames"; first by apply auth_auth_valid. + set ( dbg := + {| + IDBG_Global_mem := DB_preG_Global_mem; + IDBG_Global_history_mono := DB_preG_Global_history_mono; + IDBG_Known_replog := DB_preG_Known_replog; + IDBG_lockG := DB_preG_lockG; + IDBG_known_replog_name := γFls + |}). + iMod (alloc_gmem) as (γM) "(HownSys & HownUser)". + iMod (alloc_leader_logM) as (γL) "(#HobsL & HlogLM)". + iDestruct (Obs_own_log_obs with "[$HobsL]") as "HobsL'". + iMod (alloc_logM_and_followers_gnames γL with "[$HobsL' $Hgnames]") + as (N) "(%Hdom & Hreplog & Hmap & Hmap')"; first done. + set (DBR := DbRes γL γM N). + set (MTSC := client_handler_at_leader_user_params γL γM N). + set (MTSF := follower_handler_user_params γL γM N). + set (MTSCInit := @mts_init _ _ _ _ _). + iExists DBR. + iMod (MTS_init_setup E MTSC) + as (leader_si SrvInit MTRC) "(Hsinit & #HsrvS & #HcltS & #HreqS)". + { simplify_eq /=; solve_ndisj. } + iMod (MTS_init_setup E MTSF) + as (leaderF_si SrvInitF MTRF) "(HsinitF & #HsrvSF & #HcltSF & #HreqSF)". + { simplify_eq /=; solve_ndisj. } + iAssert (([∗ map] sa↦γ ∈ N, known_replog_token sa γ)%I) as "#Htks". + { iApply (big_sepM_mono with "[$Hmap]"). + by iIntros (sa γsa Hin) "(Hkn & _ & _)". } + iAssert (⌜∃ γdbF, N !! DB_addrF = Some γdbFâŒ)%I as (γdbF) "%NdbF". + { iPureIntro. apply elem_of_dom. set_solver. } + iDestruct (big_sepM_delete _ N DB_addrF γdbF with "Htks") + as "#(HtkF & Htks')"; first done. + set (initL := init_leader_res γL γM N SrvInit SrvInitF γdbF). + rewrite -{4} Qp_half_half. + iDestruct (own_log_auth_split _ (1/2) (1/2) [] with "[$HlogLM]") + as "(HlogL1 & HlogL2)". + iMod (inv_alloc + DB_InvName _ + (global_inv_def γL γM N) + with "[HownSys Hreplog HlogL1 Hmap]") as "#HGinv". + { iNext. + iExists [], (gset_to_gmap (@None write_event) DB_keys). + iSplit; first by rewrite dom_gset_to_gmap. + iSplit; first done. + iSplit; first by iPureIntro; set_solver. + iFrame. + iSplitL; last by iPureIntro; apply valid_state_empty. + rewrite /own_replog_global. + iApply (big_sepM_mono with "[HobsL' $Hmap]"). + iIntros (sa γsa Hin) "(Hkn & Hobs & Hown)". + eauto with iFrame. } + iExists initL, leader_si, leaderF_si. + simpl. + iFrame "HGinv Htks HobsL HownUser Hsinit HsinitF HlogL2 HtkF". + iDestruct (big_sepM_delete _ N DB_addrF γdbF with "Hmap'") + as "(HdbF & Hmap')"; first done. + iAssert (own_log_obs γdbF [])%I as "#HobsdbF". + iApply (get_obs with "[$HdbF]"). + iSplitL "HdbF"; first by iFrame. + - iSplitR. + -- iSplitL. + --- iModIntro. + iIntros (A). + rewrite /init_leader_spec. + iIntros "%HinA1 %HinA2 %HipEq1 %HipEq2 !#" (Ψ). + iIntros "(Hf & #Hsi1 & #Hsi2 & HinitL + & Hmh1 & Hmh2 & Hfp1 & Hfp2) HΨ". + iApply (init_leader_spec_internal_holds + with "[-HΨ $Hf $HinitL][$HΨ]"); + try eauto with iFrame. + --- iModIntro. + iIntros (A). + rewrite /init_client_proxy_leader_spec. + iIntros (ca HinA HcaA). + iIntros "!#" (Ψ). + iIntros "(Hf & #Hsi1 & Hmh1 & Hfp1) HΨ". + iApply (init_client_leader_proxy_internal_holds + with "[$HGinv $Htks][//][//][-HΨ $HcltS][$HΨ]"); + try eauto with iFrame. + -- assert (DB_followers ⊆ dom N) as Hsubset by set_solver. + assert (DB_followers = dom (delete DB_addrF N)) as HeqDB by set_solver. + clear Hdom. + rewrite HeqDB. + rewrite HeqDB in Hsubset Hn1. + clear HeqDB. + (* TODO : do induction on N instead of DB_followers! *) + iInduction (delete DB_addrF N) as [|fsa Fls N0] "IH" using map_ind; + [by iModIntro; rewrite dom_empty_L |]. + rewrite !big_sepM_insert; [|done..]. + rewrite dom_insert_L. + rewrite big_sepS_insert; last by apply not_elem_of_dom. + iDestruct "Htks'" as "(Htk & Htks')". + iDestruct "Hmap'" as "(Hres & Hmap')". + iAssert (own_replog_obs γL fsa [])%I as "#HobsF". + iFrame "#". + iExists Fls. iFrame "#". + by iApply get_obs. + iSplitR "Hmap'"; last first. + iApply ("IH" with "[][][$Htks'][$Hmap']"); iPureIntro; set_solver. + set (MTSFF := client_handler_at_follower_user_params γL γM N fsa). + iMod (MTS_init_setup E MTSFF) as (f_si initF MTRFF) + "(HinitF & #HFsrvSF & #HFcltS & #HFreqS)". + { simplify_eq /=; solve_ndisj. } + iModIntro. + set (InitFRes := init_follower_res fsa γL γM N initF Fls). + iExists f_si, InitFRes. + iFrame "HobsF". + iSplitL. + { iFrame "#∗". iExists γdbF. iFrame "#". iExists γdbF. iFrame "#∗". } + iSplitL. + --- rewrite /init_follower_spec. + iIntros (f2lsa A) "%HinA1 %HinA2 %HnA %HipEq1 %HprNeq !# %Ψ". + iIntros "(Hf & #Hsi1 & #Hsi2 & HinitF & Hmh1 + & Hmh2 & Hfp1 & Hfp2) HΨ". + iApply (@init_follower_spec_internal_holds _ _ _ _ _ + f2lsa fsa γL γM N f_si leaderF_si initF Fls MTRF + with "[//][//][//][//][//] + [$Hf $HinitF $Hmh1 $Hmh2 $Hsi1 $Hsi2 $Hfp1 $Hfp2][$HΨ]"); + try eauto with iFrame. + --- rewrite /init_client_proxy_follower_spec. + iIntros (A ca HcaA HnA). + iIntros "!#" (Ψ). + iIntros "(Hf & #Hsi1 & Hmh1 & Hfp1) HΨ". + iApply (init_client_proxy_follower_internal_holds with + "[$HGinv $Htks][][//][//][$Hsi1 $HFcltS $HFreqS $Hf $Hmh1 $Hfp1][$HΨ]"). + iPureIntro; set_solver. + Qed. + +End Init_setup_proof. + +Global Instance db_init_instance + `{!anerisG Mdl Σ, !DB_params, !DBPreG Σ, SpecChanG Σ}: DB_init. + Proof. + split. iIntros (E HE Hn1 Hn2). + iMod (init_setup_holds E HE Hn1 Hn2) + as "(%DBRes & %init & %lsi & %lsfi & Hinit)". + iModIntro. + iExists _, _, _, _. by iFrame. + Qed. diff --git a/aneris/examples/reliable_communication/lib/repdb/proof/repdb_serialization.v b/aneris/examples/reliable_communication/lib/repdb/proof/repdb_serialization.v new file mode 100644 index 0000000..3f3fe99 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/proof/repdb_serialization.v @@ -0,0 +1,154 @@ +From aneris.aneris_lang Require Import lang. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.examples.reliable_communication.prelude Require Import ser_inj. +From aneris.examples.reliable_communication.lib.repdb Require Import repdb_code. +From aneris.examples.reliable_communication.lib.repdb.spec Require Import db_params. + +Section Repdb_ser. + + Context `{!DB_params}. + + Definition write_serialization := + prod_serialization string_serialization DB_serialization. + + Definition read_serialization := string_serialization. + + Definition req_c2l_serialization := + sum_serialization write_serialization read_serialization. + + Definition rep_l2c_serialization := + sum_serialization + unit_serialization + (option_serialization DB_serialization). + + Definition req_f2l_serialization := int_serialization. + + Definition rep_l2f_serialization := + prod_serialization + (prod_serialization string_serialization DB_serialization) + int_serialization. + + Definition req_c2f_serialization := read_serialization. + + Definition rep_f2c_serialization := option_serialization DB_serialization. + + Lemma req_c2l_ser_is_injective : ser_is_injective req_c2l_serialization. + Proof. + apply sum_ser_is_ser_injective. + - apply prod_ser_is_ser_injective. + -- apply string_ser_is_ser_injective. + -- apply DB_ser_inj. + - apply string_ser_is_ser_injective. + Qed. + + (* TODO : move to lib. *) + Lemma unit_ser_is_ser_injective : + ser_is_injective unit_serialization. + Proof. + intros s mval1 mval2 Hs1%s_is_ser_valid Hs2%s_is_ser_valid. + simplify_eq /=. rewrite /unit_valid_val in Hs1, Hs2. by subst. + Qed. + + (* TODO : move to lib. *) + Lemma unit_ser_is_ser_injective_alt : + ser_is_injective_alt unit_serialization. + Proof. + intros s1 s2 mval Heq1 Heq2. + inversion Heq1. inversion Heq2. by simplify_eq. + Qed. + + (* TODO : move to lib. *) + Lemma option_ser_is_ser_injective ser: + ser_is_injective ser → + ser_is_injective (option_serialization ser). + Proof. + intros Hser s mval1 mval2 Hs1 Hs2. + destruct Hs1 as [ (n1 & Hn1) | (v1 & s1 & -> & Hs1 & Hvs1) ]; + destruct Hs2 as [ (n2 & Hn2) | (v2 & s2 & -> & Hs2 & Hvs2) ]; simplify_eq /=. + - done. + - f_equal. by eapply Hser. + Qed. + + (* TODO : move to lib. *) + Lemma option_ser_is_ser_injective_alt ser: + ser_is_injective_alt ser → + ser_is_injective_alt (option_serialization ser). + Proof. + intros Hser1 s1 s2 mval Hs1 Hs2. + destruct Hs1 as [(-> & Hvs1)|(v1 & str1 & Heq11 & Heq12 & Hvs1)]; + destruct Hs2 as [(v2 & Hvs2)|(v2 & str2 & Heq21 & Heq22 & Hvs2)]; simplify_eq /=. + - done. + - f_equal. by eapply Hser1. + Qed. + + Lemma rep_l2c_ser_is_injective : ser_is_injective rep_l2c_serialization. + Proof. + apply sum_ser_is_ser_injective. + - apply unit_ser_is_ser_injective. + - apply option_ser_is_ser_injective. + apply DB_ser_inj. + Qed. + + Lemma req_c2l_ser_is_injective_alt : ser_is_injective_alt req_c2l_serialization. + Proof. + apply sum_ser_is_ser_injective_alt. + - apply prod_ser_is_ser_injective_alt. + -- apply string_ser_is_ser_injective_alt. + -- apply DB_ser_inj_alt. + - apply string_ser_is_ser_injective_alt. + Qed. + + Lemma rep_l2c_ser_is_injective_alt : ser_is_injective_alt rep_l2c_serialization. + Proof. + apply sum_ser_is_ser_injective_alt. + - apply unit_ser_is_ser_injective_alt. + - apply option_ser_is_ser_injective_alt. + apply DB_ser_inj_alt. + Qed. + + Lemma req_f2l_ser_is_injective : + ser_is_injective req_f2l_serialization. + Proof. apply int_ser_is_ser_injective. Qed. + + Lemma req_f2l_ser_is_injective_alt : + ser_is_injective_alt req_f2l_serialization. + Proof. apply int_ser_is_ser_injective_alt. Qed. + + Lemma rep_l2f_ser_is_injective : + ser_is_injective rep_l2f_serialization. + Proof. + apply prod_ser_is_ser_injective. + - apply prod_ser_is_ser_injective. + -- apply string_ser_is_ser_injective. + -- apply DB_ser_inj. + - apply int_ser_is_ser_injective. + Qed. + + Lemma rep_l2f_ser_is_injective_alt : + ser_is_injective_alt rep_l2f_serialization. + Proof. + apply prod_ser_is_ser_injective_alt. + - apply prod_ser_is_ser_injective_alt. + -- apply string_ser_is_ser_injective_alt. + -- apply DB_ser_inj_alt. + - apply int_ser_is_ser_injective_alt. + Qed. + + Lemma req_c2f_ser_is_injective : + ser_is_injective req_c2f_serialization. + Proof. apply string_ser_is_ser_injective. Qed. + + Lemma req_c2f_ser_is_injective_alt : + ser_is_injective_alt req_c2f_serialization. + Proof. apply string_ser_is_ser_injective_alt. Qed. + + + Lemma rep_f2c_ser_is_injective : + ser_is_injective rep_f2c_serialization. + Proof. apply option_ser_is_ser_injective, DB_ser_inj. Qed. + + Lemma rep_f2c_ser_is_injective_alt : + ser_is_injective_alt rep_f2c_serialization. + Proof. apply option_ser_is_ser_injective_alt, DB_ser_inj_alt. Qed. + +End Repdb_ser. diff --git a/aneris/examples/reliable_communication/lib/repdb/repdb_code.v b/aneris/examples/reliable_communication/lib/repdb/repdb_code.v index 74ced92..4893892 100644 --- a/aneris/examples/reliable_communication/lib/repdb/repdb_code.v +++ b/aneris/examples/reliable_communication/lib/repdb/repdb_code.v @@ -6,7 +6,9 @@ From aneris.aneris_lang.lib Require Import map_code. From aneris.aneris_lang.lib Require Import network_util_code. From aneris.aneris_lang.lib.serialization Require Import serialization_code. From aneris.examples.reliable_communication.lib.repdb Require Import log_code. -From aneris.examples.reliable_communication Require Import client_server_code. +From aneris.examples.reliable_communication.lib.mt_server Require Import mt_server_code. + +(** Serializers *) Definition write_serializer val_ser := prod_serializer string_serializer val_ser. @@ -28,54 +30,15 @@ Definition req_c2f_ser := read_serializer. Definition rep_f2c_ser val_ser := option_serializer val_ser. -(** Generic methods for multi-threaded server with monitored requests. *) - -Definition service_loop : val := - λ: "c" "mon" "request_handler" <>, - letrec: "loop" <> := - let: "req" := recv "c" in - monitor_acquire "mon";; - let: "rep" := "request_handler" "mon" "req" in - monitor_release "mon";; - send "c" "rep";; - "loop" #() in - "loop" #(). - -Definition accept_new_connections_loop : val := - λ: "skt" "mon" "request_handler" <>, - letrec: "loop" <> := - let: "new_conn" := accept "skt" in - let: "c" := Fst "new_conn" in - let: "_a" := Snd "new_conn" in - Fork (service_loop "c" "mon" "request_handler" #());; - "loop" #() in - "loop" #(). - -Definition run_server ser deser : val := - λ: "addr" "mon" "request_handler", - let: "skt" := make_server_skt ser deser "addr" in - server_listen "skt";; - Fork (accept_new_connections_loop "skt" "mon" "request_handler" #()). - (** Leader *) Definition follower_request_handler : val := λ: "log" "mon" "req", + monitor_acquire "mon";; log_wait_until "log" "mon" "req";; - unSOME (log_get "log" "req"). - -Definition client_request_handler_at_leader : val := - λ: "db" "log" "mon" "req", - match: "req" with - InjL "p" => - let: "k" := Fst "p" in - let: "v" := Snd "p" in - "db" <- (map_insert "k" "v" ! "db");; - log_add_entry "log" ("k", "v");; - monitor_signal "mon";; - InjL #() - | InjR "k" => InjR (map_lookup "k" ! "db") - end. + let: "res" := unSOME (log_get "log" "req") in + monitor_release "mon";; + "res". Definition update_log_copy_loop : val := λ: "logC" "monC" "logF" "monF" <>, @@ -92,15 +55,32 @@ Definition update_log_copy_loop : val := "loop" (Snd "logC_copy") in "loop" #0. -Definition start_leader_processing_clients ser : val := - λ: "addr" "db" "log" "mon" <>, - run_server (rep_l2c_ser ser) (req_c2l_ser ser) "addr" "mon" - (client_request_handler_at_leader "db" "log"). - Definition start_leader_processing_followers ser : val := λ: "addr" "log" "mon" <>, - run_server (rep_l2f_ser ser) req_f2l_ser "addr" "mon" - (follower_request_handler "log"). + run_server (rep_l2f_ser ser) req_f2l_ser "addr" + (λ: "req", follower_request_handler "log" "mon" "req"). + +Definition client_request_handler_at_leader : val := + λ: "db" "log" "mon" "req", + monitor_acquire "mon";; + let: "res" := match: "req" with + InjL "p" => + let: "k" := Fst "p" in + let: "v" := Snd "p" in + "db" <- (map_insert "k" "v" ! "db");; + let: "n" := log_length "log" in + log_add_entry "log" ("k", "v", "n");; + monitor_signal "mon";; + InjL #() + | InjR "k" => InjR (map_lookup "k" ! "db") + end in + monitor_release "mon";; + "res". + +Definition start_leader_processing_clients ser : val := + λ: "addr" "db" "log" "mon" <>, + run_server (rep_l2c_ser ser) (req_c2l_ser ser) "addr" + (λ: "req", client_request_handler_at_leader "db" "log" "mon" "req"). Definition init_leader ser : val := λ: "addr0" "addr1", @@ -113,38 +93,62 @@ Definition init_leader ser : val := Fork (start_leader_processing_followers ser "addr1" "logF" "monF" #());; Fork (update_log_copy_loop "logC" "monC" "logF" "monF" #()). +Definition init_client_leader_proxy ser : val := + λ: "clt_addr" "srv_addr", + let: "rpc" := init_client_proxy (req_c2l_ser ser) (rep_l2c_ser ser) + "clt_addr" "srv_addr" in + let: "lk" := newlock #() in + let: "reqf" := λ: "req", + acquire "lk";; + let: "res" := make_request "rpc" "req" in + release "lk";; + "res" in + let: "write" := λ: "k" "v", + match: "reqf" (InjL ("k", "v")) with + InjL "_u" => #() + | InjR "_abs" => assert: #false + end in + let: "read" := λ: "k", + match: "reqf" (InjR "k") with + InjL "_abs" => assert: #false + | InjR "r" => "r" + end in + ("write", "read"). + (** Follower. *) Definition client_request_handler_at_follower : val := - λ: "db" "_mon" "req_k", map_lookup "req_k" ! "db". + λ: "db" "mon" "req_k", + monitor_acquire "mon";; + let: "res" := map_lookup "req_k" ! "db" in + monitor_release "mon";; + "res". Definition start_follower_processing_clients ser : val := λ: "addr" "db" "mon", - run_server (rep_f2c_ser ser) req_c2f_ser "addr" "mon" - (client_request_handler_at_follower "db"). + run_server (rep_f2c_ser ser) req_c2f_ser "addr" + (λ: "req", client_request_handler_at_follower "db" "mon" "req"). Definition sync_loop : val := - λ: "ch" "db" "log" "mon", - letrec: "aux" <> := - let: "i" := log_next "log" in - send "ch" "i";; - let: "rep" := recv "ch" in + λ: "db" "log" "mon" "rpc" "n", + letrec: "aux" "i" := + let: "rep" := make_request "rpc" "i" in let: "k" := Fst (Fst "rep") in let: "v" := Snd (Fst "rep") in let: "j" := Snd "rep" in assert: ("i" = "j");; monitor_acquire "mon";; - log_add_entry "log" ("k", "v");; + log_add_entry "log" ("k", "v", "j");; "db" <- (map_insert "k" "v" ! "db");; monitor_release "mon";; - "aux" #() in - "aux" #(). + "aux" ("i" + #1) in + "aux" "n". Definition sync_with_server ser : val := λ: "l_addr" "f2l_addr" "db" "log" "mon", - let: "skt" := make_client_skt req_f2l_ser (rep_l2f_ser ser) "f2l_addr" in - let: "ch" := connect "skt" "l_addr" in - sync_loop "ch" "db" "log" "mon". + let: "rpc" := init_client_proxy req_f2l_ser (rep_l2f_ser ser) "f2l_addr" + "l_addr" in + Fork (sync_loop "db" "log" "mon" "rpc" #0). Definition init_follower ser : val := λ: "l_addr" "f2l_addr" "f_addr", @@ -154,39 +158,14 @@ Definition init_follower ser : val := sync_with_server ser "l_addr" "f2l_addr" "db" "log" "mon";; start_follower_processing_clients ser "f_addr" "db" "mon". -(** Client Proxies. *) - -Definition request : val := - λ: "ch" "lk" "req", - acquire "lk";; - send "ch" "req";; - let: "msg" := recv "ch" in - release "lk";; - "msg". - -Definition init_client_leader_proxy ser : val := - λ: "clt_addr" "srv_addr", - let: "skt" := make_client_skt (req_c2l_ser ser) (rep_l2c_ser ser) - "clt_addr" in - let: "ch" := connect "skt" "srv_addr" in - let: "lk" := newlock #() in - let: "write" := λ: "k" "v", - match: request "ch" "lk" (InjL ("k", "v")) with - InjL "_u" => #() - | InjR "_abs" => assert: #false - end in - let: "read" := λ: "k", - match: request "ch" "lk" (InjR "k") with - InjL "_abs" => assert: #false - | InjR "r" => "r" - end in - ("write", "read"). - Definition init_client_follower_proxy ser : val := - λ: "clt_addr" "f_addr", - let: "skt" := make_client_skt req_c2f_ser (rep_f2c_ser ser) "clt_addr" in - let: "ch" := connect "skt" "f_addr" in + λ: "clt_addr" "srv_addr", + let: "rpc" := init_client_proxy req_c2f_ser (rep_f2c_ser ser) "clt_addr" + "srv_addr" in let: "lk" := newlock #() in - let: "read" := λ: "k", - request "ch" "lk" "k" in - "read". + let: "reqf" := λ: "req", + acquire "lk";; + let: "res" := make_request "rpc" "req" in + release "lk";; + "res" in + "reqf". diff --git a/aneris/examples/reliable_communication/lib/repdb/resources/log_resources.v b/aneris/examples/reliable_communication/lib/repdb/resources/log_resources.v new file mode 100644 index 0000000..0bfaa86 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/resources/log_resources.v @@ -0,0 +1,164 @@ +From iris.algebra Require Import auth dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics. +From aneris.aneris_lang Require Import lang resources inject tactics proofmode. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof. + +(* ------------------------------------------------------------------------ *) + Section Logical_Log_Resources. + Context `{!anerisG Mdl Σ}. + Context {Aty : Type}. + Notation A := (leibnizO Aty). + Context `{inG Σ (mono_listUR A)}. + + (** Log resources. *) + + (** ** Owned by global invariant of the system. *) + Definition own_log_auth (γ : gname) (q : Qp) (l : list A) : iProp Σ := + own γ (â—ML{ DfracOwn q } l). + + (** ** Duplicable observation describing the prefix of a log. *) + Definition own_log_obs (γ : gname) (l : list A) : iProp Σ := + own γ (â—¯ML l). + + Lemma get_obs (γ : gname) (q : Qp) (l : list A) : + own_log_auth γ q l ⊢ own_log_obs γ l. + Proof. + iIntros "Hown". + rewrite /own_log_obs. + iApply (own_mono with "Hown"). + apply mono_list_included. + Qed. + + Lemma get_obs_prefix (γ : gname) (l1 l2 l3 : list A) : + l3 = l1 ++ l2 → + own_log_obs γ l3 ⊢ own_log_obs γ l1. + Proof. + rewrite /own_log_obs. + iIntros (Hl3) "Hauth". + iApply (own_mono with "Hauth"). + apply mono_list_lb_mono. + list_simplifier. + by eexists. + Qed. + + Lemma get_auth_obs_prefix (γ : gname) (q : Qp) (l1 l2 l3 : list A) : + l3 = l1 ++ l2 → + own_log_auth γ q l3 ⊢ own_log_obs γ l1. + Proof. + rewrite /own_log_obs /own_log_auth. + iIntros (Hl3) "Hauth". + iDestruct (get_obs with "Hauth") as "Hobs". + by iApply get_obs_prefix. + Qed. + + Lemma own_obs_prefix (γ : gname) (q : Qp) (L l : list A) : + own_log_auth γ q L ⊢ own_log_obs γ l -∗ ⌜l `prefix_of` LâŒ. + Proof. + iIntros "Hown Hobs". + rewrite /own_log_obs. + iDestruct (own_valid_2 with "[$Hown][$Hobs]") as "%Hvalid". + apply mono_list_both_dfrac_valid_L in Hvalid. + naive_solver. + Qed. + + Lemma own_log_auth_combine γ q1 q2 l1 l2 : + own_log_auth γ q1 l1 -∗ + own_log_auth γ q2 l2 -∗ + own_log_auth γ (q1 + q2) l1 ∗ ⌜l1 = l2âŒ. + Proof. + iIntros "H1 H2". + iDestruct (own_valid_2 with "[$H1][$H2]") as "%Hvalid". + rewrite mono_list_auth_dfrac_op_valid_L dfrac_op_own in Hvalid. + destruct Hvalid as (Hvalid & ->). + iCombine "H1 H2" as "H3". + rewrite /own_log_auth. rewrite -dfrac_op_own. + rewrite mono_list_auth_dfrac_op. by iFrame. + Qed. + + Lemma own_log_auth_split γ q1 q2 l1 : + own_log_auth γ (q1 + q2) l1 ⊢ + own_log_auth γ q1 l1 ∗ own_log_auth γ q2 l1. + Proof. + iIntros "H1". + rewrite /own_log_auth. + rewrite -dfrac_op_own mono_list_auth_dfrac_op. + iDestruct "H1" as "(H11 & H12)". iFrame. + Qed. + + Lemma obs_obs_prefix γ l1 l2 : + own_log_obs γ l1 ∗ own_log_obs γ l2 -∗ + ⌜l1 `prefix_of` l2 ∨ l2 `prefix_of` l1âŒ. + Proof. + iIntros "[Hown1 Hown2]". + by iDestruct (own_valid_2 with "Hown1 Hown2") as + %Hvalid%mono_list_lb_op_valid_L. + Qed. + + Lemma obs_length_agree (γ : gname) (l1 l2 : list A) : + length l1 = length l2 → + own_log_obs γ l1 ⊢ own_log_obs γ l2 -∗ ⌜l1 = l2âŒ. + Proof. + iIntros (Hlen) "Hown1 Hown2". + iDestruct (obs_obs_prefix with "[$Hown1 $Hown2]") + as %[[k Hprefix]|[k Hprefix]]. + - iPureIntro. simplify_eq. + destruct k; [by rewrite right_id|]. + rewrite app_length in Hlen. simpl in Hlen. lia. + - iPureIntro. simplify_eq. + destruct k; [by rewrite right_id|]. + rewrite app_length in Hlen. simpl in Hlen. lia. + Qed. + + Lemma own_log_auth_update γ l1 l2 : + l1 `prefix_of` l2 → + own_log_auth γ 1 l1 ==∗ own_log_auth γ 1 l2. + Proof. + iIntros (Hprefix) "Hown". + iMod (own_update with "Hown"); [|done]. + by apply mono_list_update. + Qed. + +End Logical_Log_Resources. + +Section Physical_Log_Spec. + Context `{!anerisG Mdl Σ, !lockG Σ}. + Context {Aty : Type}. + Notation A := (leibnizO Aty). + Context `{inG Σ (mono_listUR A)}. + Context `{!Inject A val}. + + Definition inject_log (xs : list A) := + ($xs, #(List.length xs))%V. + + Global Program Instance Inject_log `{!Inject A val} + : Inject (list A) val := {| inject := inject_log |}. + Next Obligation. + intros ? [] xs ys. + - inversion ys as [[Hinj Hinj2]]. + symmetry. apply nil_length_inv. naive_solver. + - inversion ys as [[Hinj Hinj2]]. + destruct xs as [| x xs]; first done. + simplify_eq. + inversion Hinj as [[Hinj3]]. apply Inject_list in Hinj3. + naive_solver. + Qed. + + Definition is_log (logM : list A) (logV : val) := + ∃ (lV : val), logV = (lV, #(List.length logM))%V ∧ is_list logM lV. + + Definition log_monitor_inv_def + (ip : ip_address) (γlog : gname) (q: Qp) + (logL : loc) (Res : list A → iProp Σ) : iProp Σ := + ∃ logV logM, + ⌜is_log logM logV⌠∗ + logL ↦[ip] logV ∗ + own_log_auth γlog q logM ∗ + Res logM. + + Definition log_monitor_inv monN ip monγ monV γlog q logL monR := + is_monitor monN ip monγ monV (log_monitor_inv_def ip γlog q logL monR). + +End Physical_Log_Spec. diff --git a/aneris/examples/reliable_communication/lib/repdb/resources/ras.v b/aneris/examples/reliable_communication/lib/repdb/resources/ras.v new file mode 100644 index 0000000..69ab850 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/resources/ras.v @@ -0,0 +1,31 @@ +From iris.algebra Require Import auth gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.bi.lib Require Import fractional. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources. +From aneris.aneris_lang.lib Require Import lock_proof. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events. +From aneris.examples.reliable_communication.lib.repdb + Require Import model. + +Import gen_heap_light. +Import lock_proof. + + +(* -------------------------------------------------------------------------- *) +(** Resource Algebras and global ghost names needed to define resources. *) + +Class IDBG Σ := + { IDBG_Global_mem :> + inG Σ (authR (gen_heapUR Key (option write_event))); + IDBG_Global_history_mono :> + inG Σ (mono_listUR write_eventO); + IDBG_Known_replog :> + inG Σ (authR (gmapUR socket_address (agreeR gnameO))); + (* IDBG_free_replogG :> *) + (* inG Σ (gset_disjUR socket_address); *) + IDBG_lockG :> lockG Σ; + IDBG_known_replog_name : gname; + (* IDBG_free_replog_set_name : gname; *) + }. diff --git a/aneris/examples/reliable_communication/lib/repdb/resources/resources_def.v b/aneris/examples/reliable_communication/lib/repdb/resources/resources_def.v new file mode 100644 index 0000000..14306d5 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/resources/resources_def.v @@ -0,0 +1,169 @@ +From stdpp Require Import numbers. +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.examples.reliable_communication.lib.repdb + Require Import model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import ras log_resources. + +Import gen_heap_light. +Import lock_proof. + + +Section Known_followers. + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + + (* ------------------------------------------------------------------------ *) + (** Resources about free/known replicated logs. *) + + (** ** Ownership for a replicated log known by the system. *) + Definition known_replog_token (sa : socket_address) (γ : gnameO) : iProp Σ := + own IDBG_known_replog_name (â—¯ {[ sa := to_agree γ ]}). + + Global Instance known_replog_token_Persistent sa γ : + Persistent (known_replog_token sa γ). + Proof. apply _. Qed. + + (** ** Ownership of all replicated logs known by the system. *) + Definition known_replog_tokens (N : gmap socket_address gnameO) : iProp Σ := + (* own IDBG_free_replog_set_name (GSet (dom N)) ∗ *) + own IDBG_known_replog_name (â— (to_agree <$> N : gmap _ _ )). + + Lemma known_replog_token_agree sa γ1 γ2 : + known_replog_token sa γ1 -∗ known_replog_token sa γ2 -∗ ⌜γ1 = γ2âŒ. + Proof. + iIntros "Hγ1 Hγ2". + iDestruct (own_valid_2 with "Hγ1 Hγ2") as %Hval. + iPureIntro. + rewrite -auth_frag_op singleton_op in Hval. + apply auth_frag_valid_1 in Hval. + specialize (Hval sa). + rewrite lookup_singleton in Hval. + rewrite Some_op in Hval. + revert Hval. + rewrite Some_valid. + intros Hval. + by apply (to_agree_op_inv_L (A:=leibnizO _ )) in Hval. + Qed. + + Lemma known_replog_in_N N sa γsa: + known_replog_tokens N ∗ known_replog_token sa γsa -∗ + ⌜N !! sa = Some γsaâŒ. + Proof. + iIntros "[Htoks Htok]". + rewrite /known_replog_tokens /known_replog_token. + iDestruct (own_valid_2 with "Htoks Htok") as %Hvalid. + rewrite auth_both_valid_discrete in Hvalid. + destruct Hvalid as [Hincluded _]. + iPureIntro. + revert Hincluded. + rewrite singleton_included_l; intros (w & Hw1 & Hw2). + revert Hw2; rewrite -Hw1; clear Hw1. + rewrite lookup_fmap. clear w. + intros [|(w & w' & Hw1 & Hw2 & Hw3)]%option_included; [done|]. + destruct (N !! sa); last by inversion Hw2. + simplify_eq /=. + destruct Hw3 as [->%(@to_agree_inj)%leibniz_equiv|Hw3]; [done|]. + by apply to_agree_included in Hw3 as ->%leibniz_equiv. + Qed. + +End Known_followers. + +Section Resources_definition. + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL γM : gname). + + (* ------------------------------------------------------------------------ *) + (** Abstract global memory definition and properties. *) + + Definition own_mem_user (k : Key) (q: Qp) (a : option write_event) := + lmapsto γM k q a. + + Definition own_mem_sys M := gen_heap_light_ctx γM M. + + (** Properties of points-to connective *) + Lemma OwnMemKey_timeless_holds k q v : Timeless (own_mem_user k q v). + Proof. apply _. Qed. + + Lemma OwnMemKey_exclusive_holds k q v v' : + own_mem_user k 1 v ⊢ own_mem_user k q v' -∗ False. + Proof. + rewrite /own_mem_user. + iIntros "Hown1 Hown2". + iDestruct (lmapsto_valid_2 with "Hown1 Hown2") as %Hvalid. + rewrite frac_valid in Hvalid. + by apply Qp_not_add_le_l in Hvalid. + Qed. + + (* Maybe remove ? *) + Lemma OwnMemKey_fractional_holds k v : Fractional (λ q, own_mem_user k q v). + Proof. apply _. Qed. + + Lemma OwnMemKey_as_fractional_holds k q v : + AsFractional (own_mem_user k q v) (λ q, own_mem_user k q v) q. + Proof. apply _. Qed. + + Lemma OwnMemKey_combine_holds k q q' v v' : + own_mem_user k q v ∗ own_mem_user k q' v' ⊢ + own_mem_user k (q + q') v ∗ ⌜v = v'âŒ. + Proof. + iIntros "[Hown1 Hown2]". + iApply (lmapsto_combine with "Hown1 Hown2"). + Qed. + + Lemma OwnMemKey_split_holds k q1 q2 v : + own_mem_user k (q1 + q2) v ⊢ own_mem_user k q1 v ∗ own_mem_user k q2 v. + Proof. iIntros "[Hown1 Hown2]". by iFrame. Qed. + + Lemma own_mem_update k M (we : option write_event) (we' : write_event) : + own_mem_user k 1%Qp we ⊢ + own_mem_sys M ==∗ own_mem_user k 1%Qp (Some we') ∗ own_mem_sys (<[k := Some we']>M). + Proof. + iIntros "Hown1 Hown2". + iMod (gen_heap_light_update with "Hown2 Hown1") as "[Hown2 Hown1]". + iModIntro. iFrame. + Qed. + + (* ------------------------------------------------------------------------ *) + (** Principal & replicated log ownership predicates *) + + (** ** Principal log. *) + Definition own_logL_global L : iProp Σ := own_log_auth γL (1/2) L. + + Definition own_logL_obs L : iProp Σ := own γL (â—¯ML L). + + (** ** Replicated logs. *) + + Definition own_replog_global γ sa l : iProp Σ := + known_replog_token sa γ ∗ own_logL_obs l ∗ own_log_auth γ (1/2) l. + + Definition own_replog_obs sa l : iProp Σ := + ∃ γ, known_replog_token sa γ ∗ own_logL_obs l ∗ own γ (â—¯ML l). + + (** ** General Obs predicate : socket_address → wrlog → iProp Σ. *) + Definition own_obs sa l : iProp Σ := + (⌜sa = DB_addr⌠∗ own_logL_obs l) ∨ own_replog_obs sa l. + + Lemma Obs_timeless_holds a h : Timeless (own_obs a h). + Proof. apply _. Qed. + + Lemma Obs_persistent_holds a h : Persistent (own_obs a h). + Proof. apply _. Qed. + + Lemma Obs_own_log_obs DB_addr L: + own_obs DB_addr L ⊢ own_log_obs γL L. + Proof. + iIntros "[(%_ & #Hobs)|#Hobs]"; [iFrame "#"|]. + by iDestruct "Hobs" as (γ) "(_ & Hobs & _)". + Qed. + +End Resources_definition. diff --git a/aneris/examples/reliable_communication/lib/repdb/resources/resources_global_inv.v b/aneris/examples/reliable_communication/lib/repdb/resources/resources_global_inv.v new file mode 100644 index 0000000..371f179 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/resources/resources_global_inv.v @@ -0,0 +1,419 @@ +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics. +From aneris.prelude Require Import list. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.examples.reliable_communication.lib.repdb + Require Import model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import ras log_resources resources_def. + +Import gen_heap_light. +Import lock_proof. + + +Section Global_Invariant. + + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL γM : gname) (N : gmap socket_address gname). + + (* ------------------------------------------------------------------------ *) + (** Definition of the global invariant. *) + Definition global_inv_def : iProp Σ := + ∃ (L : wrlog) + (M : gmap Key (option write_event)), + ⌜DB_keys = dom M⌠∗ + ⌜dom N = DB_followers ∪ {[DB_addrF]}⌠∗ + ⌜DB_followers ## {[DB_addrF]}⌠∗ + own_mem_sys γM M ∗ + own_logL_global γL L ∗ + known_replog_tokens N ∗ + ([∗ map] sa ↦ γ ∈ N, ∃ l, own_replog_global γL γ sa l) ∗ + ⌜valid_state L MâŒ. + + Definition Global_Inv : iProp Σ := + ([∗ map] sa ↦ γ ∈ N, known_replog_token sa γ) ∗ + inv DB_InvName global_inv_def. + + + + (* TODO: Utils: Move! *) + Lemma obs_prefix_leader_follower sa h h' : + own_obs γL sa h -∗ own_logL_global γL h' -∗ + ⌜h `prefix_of` h'âŒ. + Proof. + iIntros "Hobs HlogL". + iDestruct "Hobs" as "[[%Heq Hobs]|Hobs]". + { by iDestruct (own_obs_prefix with "HlogL Hobs") as %Hprefix. } + iDestruct "Hobs" as (γ) "(Hrep & Hobs & HL)". + by iDestruct (own_obs_prefix with "HlogL Hobs") as %Hprefix. + Qed. + + (* ------------------------------------------------------------------------ *) + (** Properties entailed by the global invariant. *) + + Lemma Global_InvPersistent : Persistent Global_Inv. + Proof. apply _. Qed. + + Lemma OwnMemKey_key_holds k q we E : + nclose DB_InvName ⊆ E → + Global_Inv ⊢ + own_mem_user γM k q (Some we) ={E}=∗ + own_mem_user γM k q (Some we) ∗ ⌜we_key we = kâŒ. + Proof. + iIntros (HE) "[H HGinv] Hmem". + iInv DB_InvName as (L M) ">IH". + iDestruct "IH" as (Hkeys Hdom Hfollower) "(Hmems&HlogL&Htoks&Hlogs&%Hvalid)". + destruct Hvalid. + iDestruct (gen_heap_light_valid with "Hmems Hmem") as %Hvalid'. + assert (we_key we = k) as Hkey. + { by eapply DB_GSTV_mem_we_key. } + iModIntro. iSplitR "Hmem". + { iExists _, _. iFrame. eauto. } + iFrame. done. + Qed. + + Lemma Obs_compare_holds a a' h h' : + own_obs γL a h -∗ own_obs γL a' h' -∗ ⌜h ≤ₚ h'⌠∨ ⌜h' ≤ₚ hâŒ. + Proof. + iIntros "Hobs1 Hobs2". + iDestruct "Hobs1" as "[[%Heq1 Hobs1] | Hobs1]"; + iDestruct "Hobs2" as "[[%Heq2 Hobs2] | Hobs2]". + - by iDestruct (obs_obs_prefix with "[$Hobs1 $Hobs2]") as %H''. + - iDestruct "Hobs2" as (γ) "(_ & Hobs2 & _)". + by iDestruct (obs_obs_prefix with "[$Hobs1 $Hobs2]") as %H''. + - iDestruct "Hobs1" as (γ) "(_ & Hobs1 & _)". + by iDestruct (obs_obs_prefix with "[$Hobs1 $Hobs2]") as %H''. + - iDestruct "Hobs1" as (γ1) "(_ & Hobs1 & _)". + iDestruct "Hobs2" as (γ2) "(_ & Hobs2 & _)". + by iDestruct (obs_obs_prefix with "[$Hobs1 $Hobs2]") as %H''. + Qed. + + Lemma Obs_exists_at_leader_holds a1 h1 E: + ↑DB_InvName ⊆ E → Global_Inv ⊢ + own_obs γL a1 h1 ={E}=∗ ∃ h2, own_obs γL DB_addr h2 ∗ ⌜h1 ≤ₚ h2âŒ. + Proof. + iIntros (HE) "[Htok HGinv] Hobs". + iInv DB_InvName as ">IH". + iDestruct "IH" as (L M Hkeys Hdom Hdisj) + "(Hmem & HlogL & Htoks & Hglob & %Hvalid)". + iDestruct (obs_prefix_leader_follower with "Hobs HlogL") as %Hprefix. + iDestruct (get_obs with "HlogL") as "#Hobs'". + iModIntro. + iSplitR "Hobs'". + { iExists _, _. iFrame. done. } + iModIntro. iExists L. + iFrame "#". iSplit; [by iLeft|done]. + Qed. + + Lemma Obs_get_smaller_holds a h h' : + h ≤ₚ h' → own_obs γL a h' -∗ own_obs γL a h. + Proof. + iIntros (Hprefix%mono_list_lb_mono) "[[%Heq Hobs]|Hobs]". + - iLeft. iSplit; [done|by iApply own_mono]. + - iDestruct "Hobs" as (γ) "(Hlog&HlogL&Hown)". + iRight. iExists _. iFrame. + iSplitL "HlogL"; by iApply own_mono. + Qed. + + (* TODO: Remove *) + (* Lemma Obs_snoc_time_holds a h1 e1 h2 E : *) + (* nclose DB_InvName ⊆ E → *) + (* own_obs γL a (h1 ++ [e1] ++ h2) ={E}=∗ *) + (* ⌜∀ e0, e0 ∈ h1 → e0 <â‚œ e1⌠∧ ⌜∀ e2, e2 ∈ h2 → e1 <â‚œ e2âŒ. *) + (* Proof. Admitted. *) + + (* Todo: Remove *) + (* Lemma Obs_ext_we_holds a a' h h' E : *) + (* nclose DB_InvName ⊆ E → *) + (* Global_Inv ⊢ own_obs γL a h -∗ own_obs γL a' h' ={E}=∗ *) + (* ⌜∀ e e', e ∈ h → e' ∈ h' → e =â‚œ e' → e = e'âŒ. *) + (* Proof. Admitted. *) + + (* TODO: Remove *) + (* Lemma Obs_ext_hist_holds a1 a2 h1 h2 k E : *) + (* nclose DB_InvName ⊆ E → *) + (* at_key k h1 = at_key k h2 → *) + (* Global_Inv ⊢ own_obs γL a1 h1 -∗ own_obs γL a2 h2 ={E}=∗ *) + (* ⌜hist_at_key k h1 = hist_at_key k h2âŒ. *) + (* Proof. Admitted. *) + + (* TODO: Used ad-hoc outside API: fix? *) + Lemma OwnMemKey_wo_obs_holds k q wo E : + nclose DB_InvName ⊆ E → + Global_Inv ⊢ + own_mem_user γM k q wo ={E}=∗ + own_mem_user γM k q wo ∗ + ∃ h, own_obs γL DB_addr h ∗ ⌜at_key k h = woâŒ. + Proof. + iIntros (HE) "[Htok HGinv] Hmem". + iInv DB_InvName as (L M) ">IH". + iDestruct "IH" as (Hkeys Hdom Hfollower) "(Hmems&HlogL&Htoks&Hlogs&%Hvalid)". + rewrite /own_logL_global /own_log_auth. rewrite mono_list_auth_lb_op. + iDestruct "HlogL" as "[HlogL Hobs]". + iDestruct (gen_heap_light_valid with "Hmems Hmem") as %Hvalid'. + assert (M !! k = Some (at_key k L)) as Heq'. + { destruct Hvalid. + eapply DB_GSTV_mem_log_coh. + apply elem_of_dom. done. } + assert (at_key k L = wo) as Hatkey. + { rewrite Heq' in Hvalid'. by simplify_eq. } + iModIntro. + iSplitR "Hmem Hobs". + { iExists _, _. iFrame. done. } + iModIntro. iFrame. + iExists _. iFrame. iSplit; [|done]. by iLeft. + Qed. + + Lemma OwnMemKey_some_obs_we_holds k q we E : + nclose DB_InvName ⊆ E → + Global_Inv ⊢ + own_mem_user γM k q (Some we) ={E}=∗ + own_mem_user γM k q (Some we) ∗ + ∃ h, own_obs γL DB_addr h ∗ ⌜at_key k h = Some weâŒ. + Proof. + iIntros (HE) "HGinv Hmem". + iMod (OwnMemKey_wo_obs_holds with "HGinv Hmem") as "H"; [solve_ndisj|]. + iModIntro. done. + Qed. + + Lemma OwnMemKey_obs_frame_prefix_holds a k q h h' E : + nclose DB_InvName ⊆ E → + h ≤ₚ h' → + Global_Inv ⊢ + own_mem_user γM k q (at_key k h) ∗ own_obs γL a h' ={E}=∗ + own_mem_user γM k q (at_key k h) ∗ ⌜at_key k h = at_key k h'âŒ. + Proof. + iIntros (HE Hprefix) "[Htok HGinv] [Hmem Hobs]". + iInv DB_InvName as (L M) ">IH". + iDestruct "IH" as (Hkeys Hdom Hfollower) "(Hmems&HlogL&Htoks&Hlogs&%Hvalid)". + assert (∃ wo, at_key k h = wo) as [wo Heq]. + { destruct (at_key k h); by eexists _. } + iDestruct (gen_heap_light_valid with "Hmems Hmem") as %Hvalid'. + rewrite Heq in Hvalid'. + iDestruct (obs_prefix_leader_follower with "Hobs HlogL") as %Hprefix'. + assert (M !! k = Some (at_key k L)) as Heq'. + { destruct Hvalid. + eapply DB_GSTV_mem_log_coh. + apply elem_of_dom. done. } + assert (at_key k L = wo) as Hatkey. + { rewrite Heq' in Hvalid'. by simplify_eq. } + iModIntro. + iSplitR "Hmem". + { iExists _, _. iFrame. done. } + iFrame. + iModIntro. + iPureIntro. + destruct Hvalid. + assert (NoDup L) as HNoDup. + { by apply log_events_no_dup. } + destruct (wo). + { rewrite Heq. symmetry. + assert (NoDup h') by by eapply NoDup_prefix. + by eapply (NoDup_last_filter_Some _ h h' L). } + rewrite Heq. + symmetry. + by eapply (NoDup_last_filter_None _ h' L). + Qed. + + Lemma OwnMemKey_obs_frame_prefix_some_holds a k q h h' we E : + nclose DB_InvName ⊆ E → + h ≤ₚ h' → + at_key k h = Some we → + Global_Inv ⊢ + own_mem_user γM k q (Some we) ∗ own_obs γL a h' ={E}=∗ + own_mem_user γM k q (Some we) ∗ ⌜at_key k h' = Some weâŒ. + Proof. + iIntros (HE Hprefx <-) "HGinv [Hmem Hobs]". + iMod (OwnMemKey_obs_frame_prefix_holds with "HGinv [$Hmem $Hobs]") + as "[$ %Heq]"; [solve_ndisj|done|]. + iModIntro. iPureIntro. by symmetry. + Qed. + + Lemma OwnMemKey_some_obs_frame_holds a k q we h hf E : + nclose DB_InvName ⊆ E → + Global_Inv ⊢ + own_mem_user γM k q (Some we) ∗ own_obs γL a (h ++ [we] ++ hf) ={E}=∗ + own_mem_user γM k q (Some we) ∗ ⌜at_key k hf = NoneâŒ. + Proof. + iIntros (?) "#[Htoks Hinv] [Hu1 #Hu2]". + iInv DB_InvName as + (lM M) ">(%Hkeys & %HNdom & %Hfollowers & Hsys & Hglog & HknN & Hreplogs & %Hvs)". + iDestruct (obs_prefix_leader_follower with "Hu2 Hglog") as %[fr ->]. + rewrite -!assoc !(assoc _ h). + rewrite -!assoc !(assoc _ h) in Hvs. + iDestruct (gen_heap_light_valid with "Hsys Hu1") as %HMk. + pose proof HMk as HMk'. + rewrite (DB_GSTV_mem_log_coh _ _ Hvs k) in HMk; last by apply elem_of_dom; eauto. + simplify_eq. + iModIntro. + iSplitR "Hu1". + { iNext; iExists _, _; iFrame; eauto. } + iFrame. + iModIntro; iPureIntro. + apply (at_key_not_in_app _ _ fr). + eapply at_key_app_none; first by eapply valid_state_log_no_dup. + rewrite HMk. + rewrite at_key_snoc_some; first done. + eapply at_key_has_key; done. + Qed. + + Lemma OwnMemKey_none_obs_holds a k q h E : + nclose DB_InvName ⊆ E → + Global_Inv ⊢ + own_mem_user γM k q None ∗ own_obs γL a h ={E}=∗ + own_mem_user γM k q None ∗ ⌜hist_at_key k h = []âŒ. + Proof. + iIntros (?) "#[Htoks Hinv] [Hu1 #Hu2]". + iInv DB_InvName as + (lM M) ">(%Hkeys & %HNdom & %Hfollowers & Hsys & Hglog & HknN & Hreplogs & %Hvs)". + iDestruct (obs_prefix_leader_follower with "Hu2 Hglog") as %[fr ->]. + iDestruct (gen_heap_light_valid with "Hsys Hu1") as %HMk. + pose proof HMk as HMk'. + rewrite (DB_GSTV_mem_log_coh _ _ Hvs k) in HMk; last by apply elem_of_dom; eauto. + simplify_eq. + iModIntro. + iSplitR "Hu1". + { iNext; iExists _, _; iFrame; eauto. } + iFrame. + iModIntro; iPureIntro. + apply hist_at_key_empty_at_key. + apply (at_key_not_in_app _ _ fr); done. + Qed. + + (* TODO: Remove *) + (* Lemma OwnMemKey_allocated_holds k q h0 h1 we0 E : *) + (* nclose DB_InvName ⊆ E → *) + (* h0 ≤ₚ h1 → *) + (* at_key k h0 = Some we0 → *) + (* Global_Inv ⊢ *) + (* own_mem_user γM k q (at_key k h1) ={E}=∗ *) + (* ∃ we1, own_mem_user γM k q (at_key k h1) ∗ *) + (* ⌜at_key k h1 = Some we1⌠∗ ⌜we0 ≤ₜ we1âŒ. *) + (* Proof. Admitted. *) + + (* TODO: Used ad hoc outside of API: fix? *) + Lemma Obs_we_serializable a h E we : + nclose DB_InvName ⊆ E → + Global_Inv ⊢ + own_obs γL a (h ++ [we]) ={E}=∗ + ⌜Serializable + (prod_serialization + (prod_serialization string_serialization DB_serialization) + int_serialization) ($ we)âŒ. + Proof. + iIntros (HE) "[H HGinv] Hobs". + iInv DB_InvName as (L M) ">IH". + iDestruct "IH" as (Hkeys Hdom Hfollower) "(Hmems&HlogL&Htoks&Hlogs&%Hvalid)". + iDestruct (obs_prefix_leader_follower with "Hobs HlogL") as %[k Heq]. + iModIntro. + iSplitR "Hobs". + { iExists _, _. iFrame. done. } + iModIntro. iPureIntro. + eapply log_events_serializable; [done|]. + set_solver. +Qed. + +End Global_Invariant. + +Section Alloc_resources. + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + + Lemma alloc_gmem : + ⊢ |==> + ∃ γM : gname, + own_mem_sys γM (gset_to_gmap (@None write_event) DB_keys) ∗ + ([∗ set] k ∈ DB_keys, own_mem_user γM k 1%Qp None). + Proof. + iMod (own_alloc (â— (to_gen_heap ((gset_to_gmap (@None write_event) ∅))))) as (γ) "HM"; [by apply auth_auth_valid|]. + iAssert (|==> + own γ (â— to_gen_heap (gset_to_gmap None DB_keys)) ∗ + ([∗ set] k ∈ DB_keys, lmapsto γ k 1 None))%I + with "[HM]" as "HF". + { iInduction DB_keys as [|a l Hnotin] "IHl" using set_ind_L. + - iModIntro. rewrite big_sepS_empty. iFrame. + - iMod ("IHl" with "HM") as "[HM Hs]". + iMod (gen_heap_light_alloc _ a with "HM") as "[HM H]". + { by apply lookup_gset_to_gmap_None. } + rewrite big_sepS_union; [|set_solver]. + rewrite big_sepS_singleton. + iFrame. + by rewrite gset_to_gmap_union_singleton. } + iMod "HF". + iModIntro. iExists γ. done. + Qed. + + Lemma alloc_leader_logM : + ⊢ |==> ∃ γL, own_obs γL DB_addr [] ∗ own_log_auth γL 1 []. + Proof. + iMod (own_alloc (â—ML [] â‹… â—¯ML [])) as (γ) "[Hown1 Hown2]". + { apply mono_list_both_dfrac_valid. + by split; [done|exists []; done]. } + iExists γ. iFrame. by iLeft. + Qed. + + Lemma alloc_logM_and_followers_gnames γL : + DB_addrF ∉ DB_followers → + own_log_obs γL [] ∗ + known_replog_tokens ∅ ⊢ |==> + ∃ (N : gmap socket_address gname), + ⌜dom N = DB_followers ∪ {[DB_addrF]}⌠∗ + known_replog_tokens N ∗ + ([∗ map] sa ↦ γ ∈ N, + known_replog_token sa γ ∗ + own_log_obs γ [] ∗ + own_log_obs γL [] ∗ + own_log_auth γ (1/2) []) ∗ + ([∗ map] sa ↦ γ ∈ N, own_log_auth γ (1/2) []). + Proof. + iIntros (Hfollower) "[#Hlog Htoks]". + iMod (own_alloc (â—ML [] â‹… â—¯ML [])) as (γF) "[HlogFa HlogFf]". + { apply mono_list_both_dfrac_valid. + by split; [done|exists []; done]. } + iMod (own_update with "Htoks") as "[Htoks HtokF]". + { apply (auth_update_alloc _ + ({[DB_addrF := to_agree γF]}) + ({[DB_addrF := to_agree γF]})). + rewrite fmap_empty. + by apply alloc_singleton_local_update. } + iInduction (DB_followers) as [|f s Hnin] "IH" using set_ind_L. + { + iModIntro. iExists {[DB_addrF := γF]}. + rewrite /known_replog_tokens. + rewrite fmap_insert fmap_empty. + rewrite !big_opM_singleton. iFrame "#∗". + iSplit; [ iPureIntro; set_solver |]. + rewrite -{1}Qp_half_half -dfrac_op_own mono_list_auth_dfrac_op. + iDestruct "HlogFa" as "[$ $]". } + iMod ("IH" with "[] HlogFa HlogFf Htoks HtokF") + as (N Hdom) "(Htoks & Hlogs & HN)". + { iPureIntro. set_solver. } + iClear "IH". + iMod (own_alloc (â—ML [] â‹… â—¯ML [])) as (γ) "[HlogFa HlogFf]". + { apply mono_list_both_dfrac_valid. + by split; [done|exists []; done]. } + iMod (own_update with "Htoks") as "[Htoks Htok]". + { apply (auth_update_alloc _ + (to_agree <$> (<[f:=γ]>N)) + ({[f := to_agree γ]})). + rewrite fmap_insert. + apply alloc_singleton_local_update; [|done]. + rewrite -not_elem_of_dom. set_solver. } + iExists (<[f := γ]>N). + rewrite !big_opM_insert; [|rewrite -not_elem_of_dom; set_solver..]. + iFrame "#∗". + iModIntro. + iSplit; [ iPureIntro; set_solver |]. + rewrite -{1}Qp_half_half -dfrac_op_own mono_list_auth_dfrac_op. + iDestruct "HlogFa" as "[$ $]". + Qed. + +End Alloc_resources. diff --git a/aneris/examples/reliable_communication/lib/repdb/resources/resources_local_inv.v b/aneris/examples/reliable_communication/lib/repdb/resources/resources_local_inv.v new file mode 100644 index 0000000..087a6a3 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/resources/resources_local_inv.v @@ -0,0 +1,76 @@ +From iris.algebra Require Import agree auth excl gmap dfrac. +From iris.algebra.lib Require Import mono_list. +From iris.base_logic Require Import invariants. +From iris.bi.lib Require Import fractional. +From iris.proofmode Require Import tactics. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang Require Import lang resources inject. +From aneris.aneris_lang.lib Require Import + list_proof monitor_proof lock_proof map_proof. +From aneris.examples.reliable_communication.lib.repdb + Require Import model. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params events. +From aneris.examples.reliable_communication.lib.repdb.resources + Require Import + ras resources_def log_resources. + +Import gen_heap_light. +Import lock_proof. + +Section Local_Invariants. + + Context `{!anerisG Mdl Σ, !DB_params, !IDBG Σ}. + Context (γL : gname). + + (* ------------------------------------------------------------------------ *) + (** Leader's principal and secondary local invariants. *) + + Definition leader_local_main_res (kvsL : loc) (logM : wrlog) : iProp Σ := + ∃ (kvsV : val) (kvsM : gmap Key val), + ⌜is_map kvsV kvsM⌠∗ + ⌜valid_state_local logM kvsM⌠∗ + kvsL ↦[ip_of_address DB_addr] kvsV. + + Definition leader_local_main_inv + (kvsL logL : loc) (mγ : gname) (mV : val) : iProp Σ := + log_monitor_inv + (DB_InvName .@ "leader_main") (ip_of_address DB_addr) mγ mV + γL (1/2) logL (leader_local_main_res kvsL). + + Definition leader_local_secondary_res + (γF : gname) (logM : wrlog) : iProp Σ := + known_replog_token DB_addrF γF ∗ own_logL_obs γL logM. + + Definition leader_local_secondary_inv + (logFL : loc) (γF : gname) (mγ : gname) (mV : val) : iProp Σ := + log_monitor_inv + (DB_InvName .@ "leader_secondary") (ip_of_address DB_addrF) mγ mV + γF (1/4) logFL (leader_local_secondary_res γF). + + (* ------------------------------------------------------------------------ *) + (** Follower's local invariant. *) + + Definition follower_local_res + (kvsL : loc) (sa : socket_address) (γsa : gname) (logM : wrlog) : iProp Σ := + ∃ (kvsV : val) (kvsM : gmap Key val), + ⌜is_map kvsV kvsM⌠∗ + ⌜valid_state_local logM kvsM⌠∗ + kvsL ↦[ip_of_address sa] kvsV ∗ + known_replog_token sa γsa ∗ + own_logL_obs γL logM. + + Definition follower_local_inv (kvsL logL : loc) + (sa : socket_address) (mγ : gname) (mV : val) : iProp Σ := + ∃ (γsa : gname), + log_monitor_inv + (DB_InvName.@socket_address_to_str sa) (ip_of_address sa) mγ mV + γsa (1/4) logL + (follower_local_res kvsL sa γsa). + + Lemma follower_local_inv_pers (kvsL logL : loc) + (sa : socket_address) (mγ : gname) (mV : val) : + Persistent (follower_local_inv kvsL logL sa mγ mV). + Proof. apply _. Qed. + +End Local_Invariants. diff --git a/aneris/examples/reliable_communication/lib/repdb/spec/api_spec.v b/aneris/examples/reliable_communication/lib/repdb/spec/api_spec.v new file mode 100644 index 0000000..8052ae5 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/spec/api_spec.v @@ -0,0 +1,256 @@ +From iris.algebra Require Import auth gmap excl excl_auth. +From aneris.algebra Require Import monotone. +From aneris.aneris_lang Require Import network resources proofmode. +From aneris.aneris_lang.lib Require Import list_proof lock_proof. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.aneris_lang.program_logic Require Import lightweight_atomic. +From aneris.examples.reliable_communication.lib.repdb + Require Import repdb_code. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events resources ras. + +Section API_spec. + Context `{!anerisG Mdl Σ, !DB_time, !DB_params, !DB_resources}. + + Definition write_spec + (wr : val) (sa : socket_address) : iProp Σ := + Eval simpl in + â–¡ (∀ (E : coPset) (k : Key) (v : SerializableVal) + (P : iProp Σ) (Q : we → ghst → ghst → iProp Σ), + ⌜↑DB_InvName ⊆ E⌠-∗ + ⌜k ∈ DB_keys⌠-∗ + â–¡ (P + ={⊤, E}=∗ + ∃ (h : ghst) (a_old: option we), + ⌜at_key k h = a_old⌠∗ + k ↦ₖ a_old ∗ + Obs DB_addr h ∗ + â–· (∀ (hf : ghst) (a_new : we), + ⌜at_key k hf = None⌠-∗ + ⌜we_key a_new = k⌠-∗ + ⌜we_val a_new = v⌠-∗ + ⌜∀ e, e ∈ h → e <â‚œ a_new⌠-∗ + k ↦ₖ Some a_new -∗ + Obs DB_addr (h ++ hf ++ [a_new]) ={E,⊤}=∗ Q a_new h hf)) -∗ + {{{ P }}} + wr #k v @[ip_of_address sa] + {{{ RET #(); + ∃ (h hf : ghst) (a: we), Q a h hf }}})%I. + + Definition write_spec_atomic + (wr : val) (sa : socket_address) : iProp Σ := + ∀ (E : coPset) (k : Key) (v : SerializableVal), + ⌜↑DB_InvName ⊆ E⌠-∗ + ⌜k ∈ DB_keys⌠-∗ + <<< ∀∀ (h : ghst) (a_old : option we), + ⌜at_key k h = a_old⌠∗ + k ↦ₖ a_old ∗ + Obs DB_addr h >>> + wr #k v @[ip_of_address sa] E + <<<â–· ∃∃ hf a_new, RET #(); + ⌜at_key k hf = None⌠∗ + ⌜we_key a_new = k⌠∗ + ⌜we_val a_new = v⌠∗ + ⌜∀ e, e ∈ h → e <â‚œ a_new⌠∗ + k ↦ₖ Some a_new ∗ + Obs DB_addr (h ++ hf ++ [a_new]) >>>. + + Lemma write_spec_write_spec_atomic wr sa : + write_spec wr sa -∗ write_spec_atomic wr sa. + Proof. + iIntros "#Hwr" (E k v HE Hkeys Φ) "!> Hvs". + iApply ("Hwr" $! E k v _ (λ _ _ _, Φ #()) with "[] [] [] Hvs"); + [ done .. | | ]. + { iIntros "!> Hvs". + iMod "Hvs" as (h a_old) "[(%Hatkey & Hk & Hobs) Hclose]". + iModIntro. iExists _, _. iFrame. iSplit; first done. + iNext. iIntros (hf anew Hhf Hnk Hnv) "Hpre1 Hpre2 Hpre3". + iApply "Hclose". eauto 10 with iFrame. } + iIntros "!> H". iDestruct "H" as (_ _ _) "H". iApply "H". + Qed. + + Definition simplified_write_spec (wr : val) (sa : socket_address) + (k : Key) (v : SerializableVal) (h : ghst) : iProp Σ := + ⌜k ∈ DB_keys⌠-∗ + {{{ ∃ wo : option we, k ↦ₖ wo ∗ Obs DB_addr h ∗ ⌜at_key k h = wo⌠}}} + wr #k v @[ip_of_address sa] + {{{ RET #(); + ∃ (hf : ghst) (a: we), ⌜we_key a = k⌠∗ ⌜we_val a = v⌠∗ + ⌜at_key k hf = None⌠∗ Obs DB_addr (h ++ hf ++ [a]) ∗ + k ↦ₖ Some a + }}}%I. + + Definition read_spec + (rd : val) (sa : socket_address) (k : Key) (q : Qp) + (wo : option we) : iProp Σ := + ⌜k ∈ DB_keys⌠-∗ + {{{ k ↦ₖ{q} wo }}} + rd #k @[ip_of_address sa] + {{{vo, RET vo; + k ↦ₖ{q} wo ∗ ((⌜vo = NONEV⌠∗ ⌜wo = NoneâŒ) ∨ + (∃ a, ⌜vo = SOMEV (we_val a)⌠∗ ⌜wo = Some aâŒ)) + }}}%I. + + Definition read_at_follower_spec + (rd : val) (csa f2csa : socket_address) (k : Key) (h : ghst) : iProp Σ := + ⌜k ∈ DB_keys⌠-∗ + {{{ Obs f2csa h }}} + rd #k @[ip_of_address csa] + {{{vo, RET vo; + ∃ h', ⌜h ≤ₚ h'⌠∗ Obs f2csa h' ∗ + ((⌜vo = NONEV⌠∗ ⌜at_key k h' = NoneâŒ) ∨ + (∃ a, ⌜vo = SOMEV (we_val a)⌠∗ ⌜at_key k h' = Some aâŒ)) + }}}%I. + + Lemma get_simplified_write_spec wr sa : + write_spec wr sa ⊢ ∀ k v h, simplified_write_spec wr sa k v h. + Proof. + iIntros "#Hwr" (k v h). + iDestruct (write_spec_write_spec_atomic with "Hwr") as "#Hswr". + iIntros (Hk Φ) "!> HP HΦ". + iApply "Hswr"; [done..|]. + iApply fupd_mask_intro; [done|]; iIntros "Hclose". + iDestruct "HP" as (wo) "(Hk & Hobs & %Hatkey)". + iExists _, _. iFrame "Hk Hobs". iSplit; [done|]. + iIntros "!>" (hf wo') "(%Hatkey'&%Hkew&%Hval&%Hle&Hk&#Hobs')". + iMod "Hclose". iModIntro. iApply "HΦ". + iExists _, _. by iFrame "#∗". + Qed. + + Definition init_leader_spec Init_leader leader_si leaderF_si : iProp Σ := + ∀ A, + ⌜DB_addr ∈ A⌠→ + ⌜DB_addrF ∈ A⌠→ + ⌜ip_of_address DB_addrF = ip_of_address DB_addr⌠→ + ⌜port_of_address DB_addrF ≠port_of_address DB_addr⌠→ + {{{ fixed A ∗ + DB_addr ⤇ leader_si ∗ + DB_addrF ⤇ leaderF_si ∗ + Init_leader ∗ + DB_addr ⤳ (∅, ∅) ∗ + DB_addrF ⤳ (∅, ∅) ∗ + free_ports (ip_of_address DB_addr) {[port_of_address DB_addr]} ∗ + free_ports (ip_of_address DB_addrF) {[port_of_address DB_addrF]} }}} + init_leader (s_serializer DB_serialization) + #DB_addr #DB_addrF @[ip_of_address DB_addr] + {{{ RET #(); True }}}. + + Definition init_follower_spec f2csa initF f_si lF_si : iProp Σ := + ∀ f2lsa A, + ⌜DB_addrF ∈ A⌠→ + ⌜f2csa ∈ A⌠→ + ⌜f2lsa ∉ A⌠→ + ⌜ip_of_address f2csa = ip_of_address f2lsa⌠→ + ⌜port_of_address f2csa ≠port_of_address f2lsa⌠→ + {{{ fixed A ∗ + f2csa ⤇ f_si ∗ + DB_addrF ⤇ lF_si ∗ + initF ∗ + f2csa ⤳ (∅, ∅) ∗ + f2lsa ⤳ (∅, ∅) ∗ + free_ports (ip_of_address f2csa) {[port_of_address f2csa]} ∗ + free_ports (ip_of_address f2lsa) {[port_of_address f2lsa]} }}} + init_follower (s_serializer DB_serialization) + #DB_addrF #f2lsa #f2csa @[ip_of_address f2csa] + {{{ RET #(); True }}}. + + Definition init_client_proxy_leader_spec leader_si : iProp Σ := + ∀ (A : gset socket_address) (sa : socket_address), + ⌜DB_addr ∈ A⌠→ + ⌜sa ∉ A⌠→ + {{{ fixed A ∗ + DB_addr ⤇ leader_si ∗ + sa ⤳ (∅, ∅) ∗ + free_ports (ip_of_address sa) {[port_of_address sa]} }}} + init_client_leader_proxy (s_serializer DB_serialization) + #sa #DB_addr @[ip_of_address sa] + {{{ wr rd, RET (wr, rd); + (∀ k q h, read_spec rd sa k q h) ∗ write_spec wr sa }}}. + + Definition init_client_proxy_follower_spec f2csa f_si : iProp Σ := + ∀ A csa, + ⌜f2csa ∈ A⌠→ + ⌜csa ∉ A⌠→ + {{{ fixed A ∗ + f2csa ⤇ f_si ∗ + csa ⤳ (∅, ∅) ∗ + free_ports (ip_of_address csa) {[port_of_address csa]} }}} + init_client_follower_proxy (s_serializer DB_serialization) + #csa #f2csa @[ip_of_address csa] + {{{ rd, RET rd; + (∀ k h, read_at_follower_spec rd csa f2csa k h) }}}. + +End API_spec. + +Section Init. + Context `{!anerisG Mdl Σ, DB : !DB_params, !DB_time, !DBPreG Σ }. + + Class DB_init := { + DB_init_setup E : + ↑DB_InvName ⊆ E → + DB_addr ∉ DB_followers → + DB_addrF ∉ DB_followers → + ⊢ |={E}=> + ∃ (DBRS : @DB_resources _ _ _ _ DB) + (Init_leader : iProp Σ) + (leader_si : message → iProp Σ) + (leaderF_si : message → iProp Σ), + GlobalInv ∗ + Obs DB_addr [] ∗ + ([∗ set] k ∈ DB_keys, k ↦ₖ None) ∗ + Init_leader ∗ + ((init_leader_spec Init_leader leader_si leaderF_si) ∗ + (init_client_proxy_leader_spec leader_si)) ∗ + ([∗ set] fsa ∈ DB_followers, + ∃ (f_si : message → iProp Σ) + (Init_follower : iProp Σ), + Init_follower ∗ + Obs fsa [] ∗ + (init_follower_spec fsa Init_follower f_si leaderF_si) ∗ + (init_client_proxy_follower_spec fsa f_si)) + }. + +End Init. + +(* Definition read_spec + (rd : val) (sa : socket_address) : iProp Σ := + Eval simpl in + â–¡ (∀ (E : coPset) (k : Key) + (P : iProp Σ) + (Q1 : option we → ghst → iProp Σ) + (Q2 : we → ghst → iProp Σ), + ⌜↑DB_InvName ⊆ E⌠-∗ + ⌜k ∈ DB_keys⌠-∗ + â–¡ (P ={⊤, E}=∗ + ∃ (h : ghst) (q : Qp) (ao: option we), + ⌜at_key k h = ao⌠∗ + Obs DB_addr h ∗ + k ↦ₖ{q} ao ∗ + â–· ((⌜ao = None⌠∗ (k ↦ₖ{q} None) ={E,⊤}=∗ Q1 ao h) ∧ + (∀ a, ⌜ao = Some a⌠∗ (k ↦ₖ{q} Some a) ={E,⊤}=∗ Q2 a h))) -∗ + {{{ P }}} + rd #k @[ip_of_address sa] + {{{ vo, RET vo; + ∃ (h : ghst) (eo: option we), + (⌜vo = NONEV⌠∗ ⌜eo = None⌠∗ Q1 eo h) ∨ + (∃ v e, ⌜vo = SOMEV v⌠∗ ⌜eo = Some e⌠∗ ⌜we_val e = v⌠∗ Q2 e h) + }}})%I. + + Definition read_spec_atomic (rd : val) (sa : socket_address) : iProp Σ := + ∀ (E : coPset) (k : Key), + ⌜↑DB_InvName ⊆ E⌠-∗ + ⌜k ∈ DB_keys⌠-∗ + <<< ∀∀ (h : ghst) (q : Qp) (a_old : option we), + ⌜at_key k h = a_old⌠∗ + Obs DB_addr h ∗ + k ↦ₖ{q} a_old >>> + rd #k @[ip_of_address sa] E + <<<â–· RET match a_old with None => NONEV | Some a => SOMEV (we_val a) end; + (⌜a_old = None⌠∗ k ↦ₖ{q} None) ∨ + (∃ e, ⌜a_old = Some e⌠∗ + (k ↦ₖ{q} Some e)) >>>. + + *) + + (* Lemma get_simplified_read_spec wr sa : + read_spec wr sa ⊢ ∀ k q h, simplified_read_spec wr sa k q h. *) diff --git a/aneris/examples/reliable_communication/lib/repdb/spec/db_params.v b/aneris/examples/reliable_communication/lib/repdb/spec/db_params.v new file mode 100644 index 0000000..f904089 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/spec/db_params.v @@ -0,0 +1,34 @@ +From RecordUpdate Require Import RecordSet. +From aneris.aneris_lang Require Import network resources. +From aneris.aneris_lang.lib.serialization Require Import serialization_proof. +From aneris.examples.reliable_communication.prelude Require Import ser_inj. + +Definition Key := string. + +(** Arguments that user supplies to the interface *) + +Class DB_params := { + DB_addr : socket_address; + DB_addrF : socket_address; + DB_followers : gset socket_address; + DB_keys : gset Key; + DB_InvName : namespace; + DB_serialization : serialization; + DB_ser_inj : ser_is_injective DB_serialization; + DB_ser_inj_alt : ser_is_injective_alt DB_serialization; +}. + +Notation DB_Serializable v := (Serializable DB_serialization v). + +Record SerializableVal `{!DB_params} := + SerVal {SV_val : val; + SV_ser : DB_Serializable SV_val }. + +Coercion SV_val : SerializableVal >-> val. + +Existing Instance SV_ser. + +Arguments SerVal {_} _ {_}. + +Definition socket_address_to_str (sa : socket_address) : string := + match sa with SocketAddressInet ip p => ip +:+ (string_of_pos p) end. diff --git a/aneris/examples/reliable_communication/lib/repdb/spec/events.v b/aneris/examples/reliable_communication/lib/repdb/spec/events.v new file mode 100644 index 0000000..40e3506 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/spec/events.v @@ -0,0 +1,327 @@ +From aneris.aneris_lang Require Import lang. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time stdpp_utils. + +(** Write and apply events *) + +Section Write_event. + Context `{!DB_time}. + + Record we := + { + we_key : Key; + we_val : val; + we_time : Time; + }. + +End Write_event. + +Notation ghst := (list we). +Notation "h ≤ₚ h'" := (h `prefix_of` h') (at level 20). + +Notation "s '<â‚œ' t" := + (TM_lt (we_time s) (we_time t)) (at level 70, no associativity). + +Notation "s '≤ₜ' t" := + (TM_lt (we_time s) (we_time t) ∨ s = t) (at level 70, no associativity). +Notation "s '=â‚œ' t" := + (we_time s = we_time t) (at level 70, no associativity). + +Section Events_lemmas. + Context `{!DB_time}. + + Global Instance we_dec : EqDecision we. + Proof. solve_decision. Qed. + + Global Instance we_countable : Countable we. + Proof. + refine {| encode := λ a, encode (we_key a, we_val a, we_time a); + decode := λ n, + (λ x, {| we_key := x.1.1; we_val := x.1.2; + we_time := x.2; |}) <$> + @decode + (Key * val * Time)%type + _ _ n + |}. + by intros []; rewrite /= decode_encode /=. + Qed. + + Definition hist_at_key (k : Key) (h : ghst) : ghst := + filter (λ x, we_key x = k) h. + + Definition at_key (k : Key) (h : ghst) : option we := + last (hist_at_key k h). + + Lemma at_key_elem_of k l we : at_key k l = Some we → we ∈ l. + Proof. intros ?; eapply elem_of_list_filter; apply last_Some_elem_of; done. Qed. + + Lemma last_snoc_inv {A:Type} (l : list A) e: + last l = Some e → ∃ l', l = l' ++ [e]. + Proof. + intros Hl. induction l as [| x l IHl]; first done. + destruct l as [ | y l']. + - simpl in *. exists []. by list_simplifier. + - rewrite last_cons_cons in Hl. specialize (IHl Hl). + destruct IHl as (l'' & Hl''). + rewrite Hl''. by exists (x :: l''). + Qed. + + Lemma at_key_singleton (e : we) : at_key (we_key e) [e] = Some e. + Proof. rewrite -last_singleton /at_key /hist_at_key. f_equal. + by rewrite filter_cons_True. + Qed. + + Lemma hist_at_key_app k h1 h2 : + hist_at_key k (h1 ++ h2) = hist_at_key k h1 ++ hist_at_key k h2. + Proof. + rewrite /hist_at_key. + by rewrite filter_app. + Qed. + + Lemma hist_at_key_singleton k e: + hist_at_key k [e] = [e] ↔ at_key k [e] = Some e. + Proof. + split; intros Hh. + rewrite -last_singleton /at_key. + - by rewrite Hh. + - rewrite /at_key in Hh. + rewrite /hist_at_key. + rewrite /hist_at_key in Hh. + erewrite filter_cons_True; first done. + rewrite filter_cons in Hh. + by destruct ((decide (we_key e = k))). + Qed. + + Lemma hist_at_key_none_singleton k e: + we_key e ≠k → + hist_at_key k [e] = []. + Proof. + intros Hne. + rewrite /hist_at_key. + by rewrite filter_cons_False. + Qed. + + Lemma hist_at_key_some_singleton k e: + we_key e = k → + hist_at_key k [e] = [e]. + Proof. + intros He. + rewrite /hist_at_key. + by rewrite filter_cons_True. + Qed. + + Lemma hist_at_key_empty k : + hist_at_key k [] = []. + Proof. naive_solver. Qed. + + Lemma hist_at_key_empty_at_key k h: + hist_at_key k h = [] ↔ at_key k h = None. + Proof. + rewrite /at_key; split; intros Hh. + by rewrite Hh. + by apply last_None in Hh. + Qed. + + Lemma hist_at_key_frame_r_singleton k h e : + we_key e ≠k → + hist_at_key k (h ++ [e]) = hist_at_key k h. + Proof. + intros Hnek. + rewrite hist_at_key_app. + apply hist_at_key_none_singleton in Hnek as ->. + by list_simplifier. + Qed. + + Lemma hist_at_key_frame_r_suffix k h hf : + at_key k hf = None → + hist_at_key k (h ++ hf) = hist_at_key k h. + Proof. + intros Hnone. + rewrite hist_at_key_app. + apply hist_at_key_empty_at_key in Hnone as ->. + by list_simplifier. + Qed. + + Lemma hist_at_key_frame_l_singleton k h e : + we_key e ≠k → + hist_at_key k ([e] ++ h) = hist_at_key k h. + Proof. + intros Hnek. + rewrite hist_at_key_app. + apply hist_at_key_none_singleton in Hnek as ->. + by list_simplifier. + Qed. + + Lemma hist_at_key_frame_l_prefix k h hf : + at_key k hf = None → + hist_at_key k (hf ++ h) = hist_at_key k h. + Proof. + intros Hnone. + rewrite hist_at_key_app. + apply hist_at_key_empty_at_key in Hnone as ->. + by list_simplifier. + Qed. + + Lemma hist_at_key_add_r_singleton k h e : + we_key e = k → + hist_at_key k (h ++ [e]) = hist_at_key k h ++ [e]. + Proof. + intros Hek. + rewrite hist_at_key_app. + apply hist_at_key_some_singleton in Hek as ->. + by list_simplifier. + Qed. + + Lemma hist_at_key_add_l_singleton k h e : + we_key e = k → + hist_at_key k ([e] ++ h) = [e] ++ hist_at_key k h. + Proof. + intros Hnek. + rewrite hist_at_key_app. + apply hist_at_key_some_singleton in Hnek as ->. + by list_simplifier. + Qed. + + Lemma at_key_snoc_none k h e : + we_key e ≠k → at_key k (h ++ [e]) = at_key k h. + Proof. + intros Hk. + rewrite /at_key. + specialize (hist_at_key_frame_r_singleton k h _ Hk). + intros Heq. by rewrite Heq. + Qed. + + Lemma at_key_snoc_some k h e : + we_key e = k → at_key k (h ++ [e]) = Some e. + Proof. + intros Hk. + rewrite /at_key. + specialize (hist_at_key_add_r_singleton k h _ Hk). + intros Heq. rewrite Heq. by rewrite last_snoc. + Qed. + + Lemma obs_le_factor_common_prefix (h1 h2 h3 : list we) : + (h1 ++ h2) ≤ₚ (h1 ++ h3) → h2 ≤ₚ h3. + Proof. + intros Hp. induction h1; first done. + rewrite -!app_comm_cons in Hp. + apply prefix_cons_inv_2 in Hp. eauto. + Qed. + + Lemma obs_le_factor_at_singleton (h1 h2 : list we) (e : we) : + h1 ≠[] → h1 ≤ₚ ([e] ++ h2) → ∃ h1', h1 = [e] ++ h1' ∧ h1' ≤ₚ h2. + Proof. + intros H1n Hp. + destruct h1 eqn:Hh1; first done. + apply prefix_cons_inv_1 in Hp as Heq. + apply prefix_cons_inv_2 in Hp. + naive_solver. + Qed. + + Lemma hist_at_key_le_empty k h : [] ≤ₚ hist_at_key k h. + Proof. by apply prefix_nil. Qed. + + Lemma obs_le_hist_at_key_le h1 h2 k : + h1 ≤ₚ h2 → hist_at_key k h1 ≤ₚ hist_at_key k h2. + Proof. + generalize h2. induction h1. + - rewrite hist_at_key_empty. + intros. apply hist_at_key_le_empty. + - clear h2. intros h2 Hle. destruct h2 eqn:Hh2. + + by inversion Hle. + + pose (prefix_cons_inv_1 a w _ _ Hle) as Heq. + rewrite Heq. clear Heq. + apply prefix_cons_inv_2 in Hle. + specialize (IHh1 _ Hle). + rewrite /hist_at_key. + assert (w :: h1 = [w] ++ h1) as -> by naive_solver. + assert (w :: l = [w] ++ l) as -> by naive_solver. + rewrite !filter_app. apply prefix_app. + naive_solver. + Qed. + + Lemma obs_le_at_key_hist_at_key h1 hf h2 k : + h2 = h1 ++ hf → hist_at_key k h1 = hist_at_key k h2 → + hist_at_key k hf = []. + Proof. + intros Heq Hk. rewrite Heq in Hk. + rewrite /hist_at_key in Hk. rewrite filter_app in Hk. + rewrite {1}(app_nil_end (filter (λ x : we, we_key x = k) h1)) in Hk. + apply app_inv_head in Hk. symmetry in Hk. eauto. + Qed. + + Lemma at_key_le_in k h1 h2 e : + at_key k h1 = Some e → + hist_at_key k h1 ≤ₚ hist_at_key k h2 → + e ∈ hist_at_key k h2. + Proof. + intros Hkh1 Hle. + destruct Hle as (hf & Hle'). + rewrite Hle'. + rewrite /at_key in Hkh1. + apply last_snoc_inv in Hkh1 as (l' & Hkh1). + rewrite Hkh1. set_solver. + Qed. + + Lemma at_key_hist_at_key_inv k h e : + at_key k h = Some e → + ∃ hl hr, h = hl ++ [e] ++ hr ∧ hist_at_key k hr = []. + Proof. + intros Hk. + rewrite /at_key /hist_at_key in Hk. + apply last_filter_postfix in Hk. + destruct Hk as (ys & zs & -> & Hk). + exists ys, zs. + split; [done|]. + induction zs as [|z zs IHzs]; [done|]. + apply Forall_cons in Hk. + destruct Hk as [Hz Hk]. + specialize (IHzs Hk). + by rewrite /hist_at_key filter_cons_False. + Qed. + + Lemma at_key_has_key k h we : + at_key k h = Some we → we_key we = k. + Proof. + intros Hatkey. apply last_Some_elem_of, elem_of_list_filter in Hatkey. + by destruct Hatkey as [Hatkey _]. + Qed. + + Lemma at_key_app_in_r k h h' we : + at_key k h' = Some we → at_key k (h ++ h') = Some we. + Proof. rewrite /at_key /hist_at_key filter_app last_app. intros ->; done. Qed. + + Lemma at_key_not_in_app k h h' : + at_key k (h ++ h') = None → at_key k h = None ∧ at_key k h' = None. + Proof. + rewrite /at_key /hist_at_key filter_app last_app. + destruct (filter _ h') as [|?? _] using rev_ind; first done. + rewrite last_snoc; done. + Qed. + + Lemma at_key_app_none k h hf : + NoDup (h ++ hf) → + at_key k h = at_key k (h ++ hf) → + at_key k hf = None. + Proof. + intros Hnd Heq. + symmetry in Heq. + destruct (at_key k hf) as [we'|] eqn:Hkhf; last done. + destruct (at_key k h) as [we|] eqn:Hkh; last first. + { pose proof (hist_at_key_frame_l_prefix _ hf _ Hkh) as Heq'. + apply hist_at_key_empty_at_key in Heq. + rewrite Heq in Heq'; symmetry in Heq'. + apply hist_at_key_empty_at_key in Heq'; simplify_eq. } + pose proof (at_key_app_in_r _ h _ _ Hkhf); simplify_eq. + assert (∃ i, h !! i = Some we) as [i Hi]. + { eapply elem_of_list_lookup_1, at_key_elem_of; done. } + assert (∃ j, hf !! j = Some we) as [j Hj]. + { eapply elem_of_list_lookup_1, at_key_elem_of; done. } + assert (i < length h)%nat by by apply lookup_lt_is_Some_1; eauto. + assert (i = length h + j)%nat; last lia. + eapply NoDup_alt; [exact Hnd| |]. + { rewrite lookup_app_l; done. } + { rewrite lookup_app_r; last lia. rewrite minus_plus; done. } + Qed. + +End Events_lemmas. diff --git a/aneris/examples/reliable_communication/lib/repdb/spec/ras.v b/aneris/examples/reliable_communication/lib/repdb/spec/ras.v new file mode 100644 index 0000000..a244ca1 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/spec/ras.v @@ -0,0 +1,36 @@ +From iris.algebra Require Import auth gmap excl excl_auth. +From iris.algebra.lib Require Import mono_list. +From aneris.lib Require Import gen_heap_light. +From aneris.aneris_lang.lib Require Import lock_proof. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import db_params time events resources. + + +Class DBG `{!DB_time} Σ := + { DBG_Global_mem :> inG Σ (authR (gen_heapUR Key (option we))); + DBG_Global_history_mono :> inG Σ (mono_listUR (leibnizO we)); + DBG_Known_replog :> inG Σ (authR (gmapUR socket_address (agreeR gnameO))); + (* DBG_free_replogG :> inG Σ (gset_disjUR socket_address); *) + DBG_lockG :> lockG Σ; + DBG_known_replog_name : gname; + (* DBG_free_replog_set_name : gname; *) + }. + +Class DBPreG `{!DB_time} Σ := + { DB_preG_Global_mem :> inG Σ (authR (gen_heapUR Key (option we))); + DB_preG_Global_history_mono :> inG Σ (mono_listUR (leibnizO we)); + DB_preG_Known_replog :> + inG Σ (authR (gmapUR socket_address (agreeR gnameO))); + (* DB_preG_free_replogG :> inG Σ (gset_disjUR socket_address); *) + DB_preG_lockG :> lockG Σ; + }. + +Definition DBΣ `{!DB_time} : gFunctors := + #[GFunctor (authR (gen_heapUR Key (option we))); + GFunctor (mono_listUR (leibnizO we)); + GFunctor (authR (gmapUR socket_address (agreeR gnameO))); + (* GFunctor (gset_disjUR socket_address); *) + lockΣ]. + +Instance subG_DB_preGΣ `{!DB_time, !lockG Σ} : subG DBΣ Σ → DBPreG Σ. +Proof. solve_inG. Qed. diff --git a/aneris/examples/reliable_communication/lib/repdb/spec/resources.v b/aneris/examples/reliable_communication/lib/repdb/spec/resources.v new file mode 100644 index 0000000..4fa346f --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/spec/resources.v @@ -0,0 +1,116 @@ +From stdpp Require Import list. +From iris.algebra Require Import frac. +From iris.bi.lib Require Import fractional. +From aneris.aneris_lang Require Export resources. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Export db_params time events. + +Section Predicates. + Context `{!anerisG Mdl Σ, !DB_time, !DB_params}. + Reserved Notation "k ↦ₖ{ q } v" (at level 20). + Reserved Notation "k ↦ₖ v" (at level 20). + + Class DB_resources := { + + (** System global invariant *) + GlobalInv : iProp Σ; + GlobalInvPersistent :> Persistent GlobalInv; + + (** Logical points-to connective *) + OwnMemKey : Key → frac → option we → iProp Σ + where "k ↦ₖ{ q } v" := (OwnMemKey k q v) + and "k ↦ₖ v" := (OwnMemKey k 1 v); + + (** Observed requests *) + Obs : socket_address → ghst → iProp Σ; + + (** Properties of points-to connective *) + OwnMemKey_timeless k q v :> Timeless (k ↦ₖ{ q } v); + OwnMemKey_exclusive k q v v' : + k ↦ₖ{ 1 } v ⊢ k ↦ₖ{ q } v' -∗ False; + OwnMemKey_fractional k v :> + Fractional (λ q, k ↦ₖ{ q } v); + OwnMemKey_as_fractional k q v :> + AsFractional (k ↦ₖ{ q } v) (λ q, k ↦ₖ{ q } v) q ; + OwnMemKey_combine k q q' v v' : + k ↦ₖ{ q } v ∗ k ↦ₖ{ q' } v' ⊢ + k ↦ₖ{ q + q'} v ∗ ⌜v = v'⌠; + OwnMemKey_split k q1 q2 v : + k ↦ₖ{ q1 + q2 } v ⊢ k ↦ₖ{ q1 } v ∗ k ↦ₖ{ q2 } v ; + OwnMemKey_key k q we E : + nclose DB_InvName ⊆ E → + GlobalInv ⊢ + k ↦ₖ{q} Some we ={E}=∗ + k ↦ₖ{q} Some we ∗ ⌜we_key we = kâŒ; + + (** Properties of observed requests *) + Obs_timeless a h :> Timeless (Obs a h); + Obs_persistent a h :> Persistent (Obs a h); + Obs_compare a a' h h' : + Obs a h -∗ Obs a' h' -∗ + ⌜h ≤ₚ h'⌠∨ ⌜h' ≤ₚ hâŒ; + Obs_exists_at_leader a1 h1 E: ↑DB_InvName ⊆ E → GlobalInv ⊢ + Obs a1 h1 ={E}=∗ ∃ h2, Obs DB_addr h2 ∗ ⌜h1 ≤ₚ h2âŒ; + Obs_get_smaller a h h' : + h ≤ₚ h' → Obs a h' -∗ Obs a h; + (* Obs_snoc_time a h1 e1 h2 E : *) + (* nclose DB_InvName ⊆ E → *) + (* Obs a (h1 ++ [e1] ++ h2) ={E}=∗ *) + (* ⌜∀ e0, e0 ∈ h1 → e0 <â‚œ e1⌠∧ *) + (* ⌜∀ e2, e2 ∈ h2 → e1 <â‚œ e2âŒ; *) + (* Obs_ext_we a a' h h' E : *) + (* nclose DB_InvName ⊆ E → *) + (* GlobalInv ⊢ Obs a h -∗ Obs a' h' ={E}=∗ *) + (* ⌜∀ e e', e ∈ h → e' ∈ h' → e =â‚œ e' → e = e'âŒ; *) + (* Obs_ext_hist a1 a2 h1 h2 k E : *) + (* nclose DB_InvName ⊆ E → *) + (* at_key k h1 = at_key k h2 → *) + (* GlobalInv ⊢ Obs a1 h1 -∗ Obs a2 h2 ={E}=∗ *) + (* ⌜hist_at_key k h1 = hist_at_key k h2âŒ; *) + + (** Relations between points-to connective and observed requests *) + OwnMemKey_some_obs_we k q we E : + nclose DB_InvName ⊆ E → + GlobalInv ⊢ + k ↦ₖ{ q } Some we ={E}=∗ + k ↦ₖ{ q } Some we ∗ + ∃ h, Obs DB_addr h ∗ ⌜at_key k h = Some weâŒ; + OwnMemKey_obs_frame_prefix a k q h h' E : + nclose DB_InvName ⊆ E → + h ≤ₚ h' → + GlobalInv ⊢ + k ↦ₖ{ q } (at_key k h) ∗ Obs a h' ={E}=∗ + k ↦ₖ{ q } (at_key k h) ∗ ⌜at_key k h = at_key k h'âŒ; + OwnMemKey_obs_frame_prefix_some a k q h h' we E : + nclose DB_InvName ⊆ E → + h ≤ₚ h' → + at_key k h = Some we → + GlobalInv ⊢ + k ↦ₖ{ q } Some we ∗ Obs a h' ={E}=∗ + k ↦ₖ{ q } Some we ∗ ⌜at_key k h' = Some weâŒ; + OwnMemKey_some_obs_frame a k q we h hf E : + nclose DB_InvName ⊆ E → + GlobalInv ⊢ + k ↦ₖ{ q } (Some we) ∗ Obs a (h ++ [we] ++ hf) ={E}=∗ + k ↦ₖ{ q } (Some we) ∗ ⌜at_key k hf = NoneâŒ; + OwnMemKey_none_obs a k q h E : + nclose DB_InvName ⊆ E → + GlobalInv ⊢ + k ↦ₖ{ q } None ∗ Obs a h ={E}=∗ + k ↦ₖ{ q } None ∗ ⌜hist_at_key k h = []âŒ; + (* OwnMemKey_allocated k q h0 h1 we0 E : *) + (* nclose DB_InvName ⊆ E → *) + (* h0 ≤ₚ h1 → *) + (* at_key k h0 = Some we0 → *) + (* GlobalInv ⊢ *) + (* k ↦ₖ{ q } (at_key k h1) ={E}=∗ *) + (* ∃ we1, k ↦ₖ{ q } (at_key k h1) ∗ *) + (* ⌜at_key k h1 = Some we1⌠∗ ⌜we0 ≤ₜ we1âŒ; *) + }. + +End Predicates. + +Arguments DB_resources {_ _ _ _ _}. + +Notation "k ↦ₖ v" := (OwnMemKey k 1 v) (at level 20). +Notation "k ↦ₖ{ q } v" := (OwnMemKey k q v) (at level 20). diff --git a/aneris/examples/reliable_communication/lib/repdb/spec/stdpp_utils.v b/aneris/examples/reliable_communication/lib/repdb/spec/stdpp_utils.v new file mode 100644 index 0000000..585a20d --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/spec/stdpp_utils.v @@ -0,0 +1,200 @@ +From stdpp Require Import tactics sets list. + +(** TODO: Get all of this merged into stdpp *) + +(* About [last] *) +Lemma last_app_cons {A : Type} (xs ys : list A) x : + last (xs ++ x :: ys) = last (x :: ys). +Proof. induction xs as [|y xs IHxs]; [done|by destruct xs]. Qed. + +Lemma last_Some_elem_of {A : Type} (l : list A) x : + last l = Some x → x ∈ l. +Proof. + intros Hl. + induction l as [|y l IHl] using rev_ind; [done|]. + rewrite last_snoc in Hl. inversion Hl as [[Heq]]. + apply elem_of_app. right. by apply elem_of_list_singleton. +Qed. + +Lemma last_cons_ne {A:Type} (l : list A) x y : + x ≠y → last (x :: l) = Some y → last l = Some y. +Proof. rewrite last_cons. destruct (last l); [done|naive_solver]. Qed. + +(* About [prefix_of] *) +Lemma elem_of_prefix {A:Type} (l1 l2 : list A) x : + l1 `prefix_of` l2 → x ∈ l1 → x ∈ l2. +Proof. intros [l' ->] Hin. apply elem_of_app. by left. Qed. + +Lemma prefix_sync_eq {A:Type} k1 k2 (l1 l2 l1' l2' : list A) : + k1 ∉ l2 → k2 ∉ l1 → + (l1 ++ [k1] ++ l1') `prefix_of` (l2 ++ [k2] ++ l2') → + l1 = l2. +Proof. + intros Hk1 Hk2 Hl. + generalize dependent l1. + induction l2 as [|x l2 IHl2]; intros l1 Hk2 Hl. + - destruct l1 as [|y l1]. + + done. + + assert (y = k2). + { by eapply prefix_cons_inv_1. } + assert (k2 ≠y). + { set_solver. } + done. + - destruct l1 as [|y l1]. + + assert (x = k1) as ->. + { symmetry. by eapply prefix_cons_inv_1. } + set_solver. + + assert (x = y) as ->. + { symmetry. by eapply prefix_cons_inv_1. } + subst. + assert (l1 = l2) as ->. + { eapply IHl2. + { set_solver. } + { set_solver. } + simpl in *. + by eapply prefix_cons_inv_2. } + done. +Qed. + +Lemma prefix_app_inv {A : Type} (xs ys zs : list A) : + (xs ++ ys) `prefix_of` (xs ++ zs) → ys `prefix_of` zs. +Proof. + intros Hperm. + induction xs. + - done. + - simpl in *. + apply IHxs. + by eapply prefix_cons_inv_2. +Qed. + +(* About [delete] *) +Lemma elem_of_list_delete {A : Type} x i (l : list A) : + x ∈ delete i l → x ∈ l. +Proof. + revert i. + induction l as [|z l IHl]; [done|]; intros i Hin. + destruct i as [|i]; [by right|]. + apply elem_of_cons in Hin. + destruct Hin as [-> | Hin]; [by left|]. + right. by eapply IHl. +Qed. + +(* About [sublist_of] *) +Lemma elem_of_sublist {A : Type} x (l1 l2 : list A) : + x ∈ l1 → l1 `sublist_of` l2 → x ∈ l2. +Proof. + intros Hin Hle. + rewrite sublist_alt in Hle. + destruct Hle as [l' ->]. + induction l' as [|y l' IHl']; [done|]. + apply IHl'. + by eapply elem_of_list_delete. +Qed. + +Lemma sublist_filter {A : Type} `{!EqDecision A} P `{! ∀ x : A, Decision (P x)} + (xs : list A) : + filter P xs `sublist_of` xs. +Proof. + induction xs; [done|]. + rewrite filter_cons. destruct (decide (P a)). + { by apply sublist_skip. } + by apply sublist_cons. +Qed. + +Lemma sublist_of_split {A} (l1 l2 l : list A) x : + l1 ++ [x] ++ l2 `sublist_of` l → + ∃ l1' l2', l = l1' ++ [x] ++ l2' ∧ l1 `sublist_of` l1' ∧ l2 `sublist_of` l2'. +Proof. + intros Hl. + apply sublist_app_l in Hl. + destruct Hl as [k1 [k2 [-> [Hle1 Hle2]]]]. + apply sublist_cons_l in Hle2. + destruct Hle2 as [k1' [k2' [-> Hle3]]]. + simpl in *. + exists (k1++k1'), k2'. + split. rewrite app_assoc. naive_solver. + split; [|done]. + rewrite sublist_app_r. + exists l1, []. + split; [by rewrite app_nil_r|]. + split; [done|]. + apply sublist_nil_l. +Qed. + +(* About [filter] *) +Lemma filter_nil_notin {A : Type} `{!EqDecision A} P `{! ∀ x : A, Decision (P x)} + (xs : list A) (x : A) : + filter P xs = [] → P x → x ∉ xs. +Proof. + intros Hfilter HP Hin. + induction xs. + - set_solver. + - destruct (decide (x = a)). + { subst. rewrite filter_cons_True in Hfilter; done. } + apply elem_of_cons in Hin. + destruct Hin as [Heq|Hin]; [done|]. + simpl in Hfilter. + rewrite filter_cons in Hfilter. + destruct (decide (P a)); [done|]. + apply IHxs; done. +Qed. + +(* About [filter] with [last] *) +Lemma last_filter_postfix `{!EqDecision A} P + `{! ∀ x : A, Decision (P x)} l x : + last (filter P l) = Some x → + ∃ l1 l2, l = l1 ++ [x] ++ l2 ∧ Forall (λ z, ¬ (P z)) l2. +Proof. + intros Hl. + assert (P x) as HPx. + { by eapply elem_of_list_filter, last_Some_elem_of. } + pose proof (elem_of_list_split_r l x) as (l1&l2&->&Hinl2). + { by eapply elem_of_list_filter, last_Some_elem_of. } + exists l1, l2. + split; [done|]. + induction l2 as [|z l2 IHl2]; [done|]. + apply not_elem_of_cons in Hinl2. destruct Hinl2 as [Hneq Hnin]. + rewrite filter_app, filter_cons_True, filter_cons, last_app_cons in Hl; [|done]. + destruct (decide (P z)). + + rewrite last_cons_cons in Hl. + assert (last (filter P l2) = Some x) as Helemof. + { destruct (filter P l2); [by inversion Hl|done]. } + apply last_Some_elem_of in Helemof. + pose proof (elem_of_list_filter P l2 x) as [Helemof' _]. + specialize (Helemof' Helemof). + by destruct Helemof' as [_ Helemof']. + + apply Forall_cons. split; [done|]. + eapply IHl2; [|done]. + by rewrite filter_app, filter_cons_True, last_app_cons. +Qed. + +(* About [list_subseteq] (NB: we use none of these) *) +Lemma list_subseteq_cons {A : Type} x (l1 l2 : list A) : + l1 ⊆ l2 → x :: l1 ⊆ x :: l2 . +Proof. + intros Hin y Hy%elem_of_cons. + destruct Hy as [-> | Hy]; [by left|]. right. by apply Hin. +Qed. + +Lemma list_subseteq_cons_r {A : Type} x (l1 l2 : list A) : + l1 ⊆ l2 → l1 ⊆ x :: l2 . +Proof. intros Hin y Hy. right. by apply Hin. Qed. + +Lemma list_delete_subseteq {A : Type} i (l : list A) : + delete i l ⊆ l. +Proof. + revert i. + induction l; intros i. + - done. + - destruct i as [|i]. + + simpl. apply list_subseteq_cons_r. done. + + simpl. apply list_subseteq_cons. done. +Qed. + +Lemma filter_subseteq {A : Type} `{!EqDecision A} P `{! ∀ x : A, Decision (P x)} + (xs : list A) : + filter P xs ⊆ xs. +Proof. + induction xs; [done|]. + rewrite filter_cons. destruct (decide (P a)); set_solver. +Qed. diff --git a/aneris/examples/reliable_communication/lib/repdb/spec/time.v b/aneris/examples/reliable_communication/lib/repdb/spec/time.v new file mode 100644 index 0000000..ed3d082 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/spec/time.v @@ -0,0 +1,46 @@ +From stdpp Require Import gmap. + +(** Abstract Notion of Timestamps with Total Order. *) + +Section Time. + + + Class DB_time := { + Time : Type; + TM_lt : relation Time; + TM_lt_TO :> StrictOrder TM_lt; + TM_lt_tricho : ∀ m n : Time, TM_lt m n ∨ m = n ∨ TM_lt n m; + TM_EqDecision :> EqDecision Time; + TM_Countable :> Countable Time; + (* TM_max : Time → Time → Time. TODO *) + }. + + (* Class Timed {dbt: DB_time} (T : Type) := time : T → Time. *) + + (* Notation "s '<â‚œ' t" := *) + (* (TM_lt (time s) (time t)) (at level 70, no associativity). *) + (* Notation "t1 '≤ₜ' t2" := *) + (* (TM_lt (time t1) (time t2) ∨ (time t1 = time t2)) *) + (* (at level 70, no associativity). *) + (* Notation "t1 '=â‚œ' t2" := *) + (* (time t1 = time t2) (at level 70, no associativity). *) + End Time. + +(* +Notation "s '<â‚œ@{' d '}' t" := + (TM_lt (@time d _ _ s) (@time d _ _ t)) + (at level 70, no associativity, format "s '<â‚œ@{' d '}' t"). +Notation "s '≤ₜ@{' d '}' t" := + (TM_lt (@time d _ _ s) (@time d _ _ t) ∨ (@time d _ _ s) = (@time d _ _ t)) + (at level 70, no associativity, format "s '≤ₜ@{' d '}' t"). +Notation "s '=â‚œ@{' d '}' t" := + ((@time d _ _ s) = (@time d _ _ t)) + (at level 70, no associativity, format "s '=â‚œ@{' d '}' t"). +*) + +(* Notation "s '<â‚œ' t" := *) +(* (TM_lt (time s) (time t)) (at level 70, no associativity). *) +(* Notation "s '≤ₜ' t" := *) +(* (TM_lt (time s) (time t) ∨ (time s = time t)) (at level 70, no associativity). *) +(* Notation "s '=â‚œ' t" := *) +(* (time s = time t) (at level 70, no associativity). *) diff --git a/aneris/examples/reliable_communication/lib/repdb/spec/utils.v b/aneris/examples/reliable_communication/lib/repdb/spec/utils.v new file mode 100644 index 0000000..cc68a10 --- /dev/null +++ b/aneris/examples/reliable_communication/lib/repdb/spec/utils.v @@ -0,0 +1,49 @@ +From iris.proofmode Require Import proofmode. +From aneris.examples.reliable_communication.lib.repdb.spec + Require Import resources stdpp_utils events. + +Section with_Σ. + Context `{!anerisG Mdl Σ, TM : !DB_time, DB : !DB_params, + !DB_events, !DB_resources}. + + (* TODO: maybe add frame after [we1] here *) + (* Lemma OwnMemKey_Obs_extend a E h k we1 we2 : *) + (* nclose DB_InvName ⊆ E → *) + (* we_key we1 = we_key we2 → *) + (* we1 ≠we2 → *) + (* GlobalInv -∗ *) + (* Obs a (h ++ [we1]) -∗ *) + (* k ↦ₖ Some we2 ={E}=∗ *) + (* k ↦ₖ Some we2 ∗ *) + (* ∃ hf, Obs DB_addr (h ++ [we1] ++ hf ++ [we2]). *) + (* Proof. *) + (* iIntros (HE Heq Hneq) "#HGinv #Hobs Hk". *) + (* iMod (OwnMemKey_key with "[$HGinv][$Hk]") as "[Hk %Hkey]"; [solve_ndisj|]. *) + (* iMod (OwnMemKey_some_obs_we with "[$HGinv][$Hk]") as "[Hk (%h' & #Hobs' & %Hatkey)]"; [solve_ndisj|]. *) + (* iDestruct (Obs_compare with "Hobs Hobs'") as %Hle. *) + (* destruct Hle as [Hle | Hle]; last first. *) + (* { (* Solve contradiction *) *) + (* iMod (OwnMemKey_obs_frame_prefix_some with "[$HGinv][$Hk $Hobs]") *) + (* as "[Hk %Hatkey']"; [solve_ndisj|done..|]. *) + (* rewrite at_key_snoc_some in Hatkey'; naive_solver. } *) + (* assert (Some we2 = at_key k h') as ->. *) + (* { by rewrite Hatkey. } *) + (* iMod (OwnMemKey_allocated with "[$HGinv][$Hk]") as "(%we' & Hk & %Hatkey' & %Hle')"; *) + (* [solve_ndisj|done|apply at_key_snoc_some; naive_solver|]. *) + (* assert (we' = we2) as -> by naive_solver. clear Hatkey'. *) + (* iFrame "Hk". *) + (* destruct Hle as [h'' ->]. *) + (* rewrite /at_key /hist_at_key in Hatkey. *) + (* rewrite !filter_app in Hatkey. *) + (* rewrite filter_cons_True in Hatkey; [|naive_solver]. *) + (* rewrite -app_assoc in Hatkey. *) + (* rewrite last_app_cons in Hatkey. *) + (* apply last_cons_ne in Hatkey; [|done]. *) + (* apply last_filter_postfix in Hatkey. *) + (* destruct Hatkey as (yz & zs & -> & HP). *) + (* iDestruct (Obs_get_smaller with "Hobs'") as "Hobs''". *) + (* { rewrite !app_assoc. apply prefix_app_r. rewrite -!app_assoc. done. } *) + (* by eauto. *) + (* Qed. *) + +End with_Σ. diff --git a/aneris/examples/reliable_communication/proof/client/proof_of_connect_step_1.v b/aneris/examples/reliable_communication/proof/client/proof_of_connect_step_1.v index 7bc1ba2..66f3896 100644 --- a/aneris/examples/reliable_communication/proof/client/proof_of_connect_step_1.v +++ b/aneris/examples/reliable_communication/proof/client/proof_of_connect_step_1.v @@ -133,8 +133,8 @@ Section Proof_of_connect_step_1. iDestruct "Hy3" as "[(%Hm & Hh & Hmh & Hres)|(%Hm & Hh & Hmh)]". (* Case 1/2 : m ∉ R *) * iDestruct (client_interp_le with "[$Hres]") as "#Hres_pers". - iDestruct (big_sepS_insert_2 m with "[] [$HmhR Hres_pers]") - as "#HmhRext"; first done. + iDestruct (big_sepS_insert_2 m with "Hres_pers [$HmhR Hres_pers]") + as "#HmhRext". iDestruct "Hres" as (mval Hsender Hser) "Hres". wp_apply (s_deser_spec ((msg_serialization RCParams_srv_ser))); first done. @@ -173,7 +173,7 @@ Section Proof_of_connect_step_1. (* wp_apply (aneris_wp_send_duplicate with "[$Hh $Hmh]"); *) (* [done | done | set_solver | | ]. iFrame "Hsrv_si". *) (* iIntros "(Hh & Hmh)". wp_pures. *) - iApply ("IH" with "[] [HΨ] [$Hh] [Hmh] [$HmhRext] [Hcnd1]"). + iApply ("IH" with "[] [HΨ] [$Hh] [Hmh] [$HmhRext] [Hcnd1]"). { iIntros (m') "Hm'". iDestruct "Hm'" as (ck γs' Hser1 ? ?) "(#Htk & Hm')". iApply (conn_step_1_init_holds clt_addr R0 with "[Hm']"). @@ -185,7 +185,7 @@ Section Proof_of_connect_step_1. rewrite Hn. subst. iRight. iDestruct "Hgh" as (γs') "(H1 & H2)". eauto. } ** iDestruct "Hres" as (ackid -> n) "(-> & Hfr)". wp_pures. - iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhRext] [Hcnd1]"). + iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhRext] [Hcnd1]"). { iIntros (m') "Hm'". iDestruct "Hm'" as (ck γs' Hser1 ? ?) "(#Htk & Hm')". iApply (conn_step_1_init_holds clt_addr R0 with "[Hm']"). @@ -194,7 +194,7 @@ Section Proof_of_connect_step_1. { iApply (conn_incoming_msg_cond_1_extend _ _ _ n); eauto. } { iApply (conn_incoming_msg_cond_2_extend _ _ _ n); eauto. } ** iDestruct "Hres" as (i w -> n) "(Heq & Hidmsg)". wp_pures. - iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhRext] [Hcnd1]"). + iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhRext] [Hcnd1]"). { iIntros (m') "Hm'". iDestruct "Hm'" as (ck γs' Hser1 ? ?) "(#Htk & Hm')". iApply (conn_step_1_init_holds clt_addr R0 with "[Hm']"). @@ -203,7 +203,7 @@ Section Proof_of_connect_step_1. { iApply (conn_incoming_msg_cond_1_extend _ _ _ n); eauto. } { iApply (conn_incoming_msg_cond_2_extend _ _ _ n); eauto. } (* Case 1/2 : m ∈ R *) - * iDestruct (big_sepS_elem_of _ _ _ Hm with "[$HmhR]") as "Hm". + * iDestruct (big_sepS_elem_of _ _ _ Hm with "HmhR") as "Hm". iDestruct "Hm" as (mval Hsender Hser) "Hres". wp_apply (s_deser_spec ((msg_serialization RCParams_srv_ser))); first done. @@ -230,27 +230,26 @@ Section Proof_of_connect_step_1. (* Case B: the reply is COOKIE-ACK. *) (* Check whether the reply is INIT-ACK and #(m_sender m) = #RCParams_srv_saddr. *) *** wp_pures. - iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhR] [$Hcnd1] [$Hcnd2]"); [| ]. + iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhR] [$Hcnd1] [$Hcnd2]"); [| ]. { iIntros (m') "Hm'". iDestruct "Hm'" as (ck γs' Hser1 ? ?) "(#Htk' & Hm')". iApply (conn_step_1_init_holds clt_addr R0 with "[Hm']"). iExists ck. iFrame "#∗". eauto. } iIntros (v) "Hpost". iApply "HΨ"; subst; eauto. ** iDestruct "Hres" as (ackid -> n) "(-> & Hfr)". wp_pures. - iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhR] [$Hcnd1] [$Hcnd2]"). + iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhR] [$Hcnd1] [$Hcnd2]"). { iIntros (m') "Hm'". iDestruct "Hm'" as (ck γs' Hser1 ? ?) "(#Htk & Hm')". iApply (conn_step_1_init_holds clt_addr R0 with "[Hm']"). iExists ck. iFrame "#∗". eauto. } iIntros (v) "Hpost". iApply "HΨ"; subst; eauto. ** iDestruct "Hres" as (i w -> n) "(Heq & Hidmsg)". wp_pures. - iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhR] [$Hcnd1] [$Hcnd2]"). + iApply ("IH" with "[] [HΨ] [$Hh] [$Hmh] [$HmhR] [$Hcnd1] [$Hcnd2]"). { iIntros (m') "Hm'". iDestruct "Hm'" as (ck γs' Hser1 ? ?) "(#Htk & Hm')". iApply (conn_step_1_init_holds clt_addr R0 with "[Hm']"). iExists ck. iFrame "#∗". eauto. } iIntros (v) "Hpost". iApply "HΨ"; subst; eauto. - Unshelve. apply _. apply _. Qed. End Proof_of_connect_step_1. diff --git a/aneris/examples/reliable_communication/proof/client/proof_of_connect_step_2.v b/aneris/examples/reliable_communication/proof/client/proof_of_connect_step_2.v index 50df9f6..bdc1d3b 100644 --- a/aneris/examples/reliable_communication/proof/client/proof_of_connect_step_2.v +++ b/aneris/examples/reliable_communication/proof/client/proof_of_connect_step_2.v @@ -144,8 +144,8 @@ Section Proof_of_connect_step_2. iDestruct "Hy3" as "[(%Hm & Hh & Hmh & Hres)|(%Hm & Hh & Hmh)]". (* Case 1/2 : m ∉ R *) * iDestruct (client_interp_le with "[$Hres]") as "#Hres_pers". - iDestruct (big_sepS_insert_2 m with "[] [$HmhR Hres_pers]") - as "#HmhRext"; first done. + iDestruct (big_sepS_insert_2 m with "Hres_pers [$HmhR Hres_pers]") + as "#HmhRext". iDestruct "Hres" as (mval Hsender Hser) "Hres". wp_apply (s_deser_spec ((msg_serialization RCParams_srv_ser))); first done. @@ -217,7 +217,7 @@ Section Proof_of_connect_step_2. iIntros (v) "Hpost". iApply "HΨ"; subst; eauto. iApply (conn_incoming_msg_cond_2_extend _ _ _ n with "[] [$Hcnd2]"); eauto. (* Case 1/2 : m ∈ R *) - * iDestruct (big_sepS_elem_of _ _ _ Hm with "[$HmhR]") as "#Hm". + * iDestruct (big_sepS_elem_of _ _ _ Hm with "HmhR") as "#Hm". iDestruct "Hm" as (mval Hsender Hser) "#Hres". wp_apply (s_deser_spec ((msg_serialization RCParams_srv_ser))); first done. @@ -282,7 +282,6 @@ Section Proof_of_connect_step_2. rewrite Heq2. subst; eauto with iFrame. } iIntros (v) "Hpost". iApply "HΨ"; subst; eauto. - Unshelve. apply _. apply _. Qed. End Proof_of_connect_step_2. diff --git a/aneris/examples/reliable_communication/proof/common_user/proof_of_recv.v b/aneris/examples/reliable_communication/proof/common_user/proof_of_recv.v index 9b3c5ef..e14f861 100644 --- a/aneris/examples/reliable_communication/proof/common_user/proof_of_recv.v +++ b/aneris/examples/reliable_communication/proof/common_user/proof_of_recv.v @@ -53,7 +53,7 @@ Section Proof_of_recv. iLeft. iSplitR; [done|]. iExists _, _, _, _, _, _, _, _. iExists _, _, _, _, _, _. - by iFrame "#∗"; eauto. } Unshelve. + by iFrame "#∗"; eauto. } destruct Hqeq as (h & t & tv & -> & -> & Hq'). iDestruct "Hvs" as "[(%w' & -> & Hfrag) Hvs]". wp_pures. diff --git a/aneris/examples/reliable_communication/proof/server/proof_of_accept.v b/aneris/examples/reliable_communication/proof/server/proof_of_accept.v index 22c4227..03c9de2 100644 --- a/aneris/examples/reliable_communication/proof/server/proof_of_accept.v +++ b/aneris/examples/reliable_communication/proof/server/proof_of_accept.v @@ -31,7 +31,7 @@ Section Proof_of_accept. Lemma accept_internal_spec (skt : val) : {{{ isServerSocketInternal skt true }}} accept skt @[ip_of_address RCParams_srv_saddr] - {{{ γe c (clt_addr: socket_address) v, RET v; ⌜v = (c, #clt_addr)%V⌠∗ + {{{ γe c (clt_addr: socket_address), RET (c, #clt_addr); (isServerSocketInternal skt true) ∗ c ↣{ γe, ip_of_address RCParams_srv_saddr, RCParams_srv_ser} iProto_dual RCParams_protocol ∗ ChannelAddrToken γe (RCParams_srv_saddr, clt_addr) }}}. @@ -67,7 +67,7 @@ Section Proof_of_accept. wp_apply (release_spec with "[$Hlocked $Hqlk Hcql HresS]"). + iExists _, _; eauto with iFrame. + iIntros (v ->). wp_pures. iApply "HΦ". iFrame. - iSplit; first done. iExists srv_skt_l. iSplit; first done. + iExists srv_skt_l. iSplit; first done. iRight. iSplit; first done. eauto with iFrame. Qed. diff --git a/aneris/examples/reliable_communication/proof/server/proof_of_make_server_skt.v b/aneris/examples/reliable_communication/proof/server/proof_of_make_server_skt.v index a0770d1..fbb44a2 100644 --- a/aneris/examples/reliable_communication/proof/server/proof_of_make_server_skt.v +++ b/aneris/examples/reliable_communication/proof/server/proof_of_make_server_skt.v @@ -24,7 +24,7 @@ Section Proof_of_make_server_skt. Notation srv_ip := (ip_of_address RCParams_srv_saddr). - Lemma make_server_skt_internal_spec A : + Lemma make_server_skt_internal_spec A : {{{ free_ports srv_ip {[port_of_address RCParams_srv_saddr]} ∗ RCParams_srv_saddr ⤳ (∅, ∅) ∗ RCParams_srv_saddr ⤇ server_interp ∗ diff --git a/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_process_data.v b/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_process_data.v index eacfdba..bd1da2a 100644 --- a/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_process_data.v +++ b/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_process_data.v @@ -36,7 +36,7 @@ Section Proof_of_server_conn_step_3. -- ACKID or SEQID, handled by process_data_on_chan. *) -(** We start by factoring out the case when the msg is ACKID or SEQID. *) + (** We start by factoring out the case when the msg is ACKID or SEQID. *) Lemma server_conn_step_process_data_spec_transmission_data (skl : loc) (skt_passive : val) skt sock h (cml : loc) cmv (cql : loc) qlk γqlk mval m @@ -80,7 +80,7 @@ Section Proof_of_server_conn_step_3. }}} server_conn_step_process_data (skt, #cml, (#cql, qlk))%V (cdata, #ck, (#ackId, #sidLBid))%V mval #(m_sender m) @[srv_ip] - {{{ v, RET v; ⌜v = #()⌠∗ isServer_listening_loop_resources skt_passive }}}. + {{{ v, RET v; ⌜v = #()⌠∗ isServer_listening_loop_resources skt_passive }}}. Proof. iIntros (Hsrv_skt Hdom Hdomc Hsm Hmap Hdest Hsaddr Hsblk Φ). iIntros "(%Hskt & #Hqlk & #Hsi & #Hcsi & #Hsinv & Hspat) HΦ". @@ -447,7 +447,7 @@ Section Proof_of_server_conn_step_3. (* Case 1.1 INIT CASE. *) (* ----------------------------------------------------------------- *) (* Absurd case, as we can show that m is actually in R0. *) - { iDestruct (big_sepM_lookup _ cM (m_sender m) (Connected (cdata, ck, (ackId, sidLBid))) Hsm with "[$HknRes]") + { iDestruct (big_sepM_lookup _ cM (m_sender m) (Connected (cdata, ck, (ackId, sidLBid))) Hsm with "HknRes") as "Habs". iAssert ((∃ (m' : message) (mval' : val), ⌜m' ∈ R0⌠∗ @@ -466,7 +466,7 @@ Section Proof_of_server_conn_step_3. (* ----------------------------------------------------------------- *) (* Regardless dynamic check, this case is absurd, which we show using the validity law governing the cookie resource. *) - iDestruct (big_sepM_lookup _ cM (m_sender m) (Connected (cdata, ck, (ackId, sidLBid))) Hsm with "[$HknRes]") + iDestruct (big_sepM_lookup _ cM (m_sender m) (Connected (cdata, ck, (ackId, sidLBid))) Hsm with "HknRes") as "Habs". { iDestruct "Habs" as (γs'' ck') "(_ & [(%Habs & _) |Habs])"; [naive_solver|]. iDestruct "Habs" as (??????) "Habs". @@ -477,8 +477,7 @@ Section Proof_of_server_conn_step_3. iDestruct "Hres" as "[Hres|(Hopened' & [(%_ & %H2 & _)|(%_a & %_b & %H2 & _)])]"; [|done.. ]. iDestruct "Hres" as (???) "(%Habs & (%x & %Hx & Hres))". iDestruct "Hres" as "[(-> & _)|(_ & _ & Hres & _ & _)]"; first done. - by iDestruct (CookieRes_excl with "[$Hck] [$Hres]") as "Habs'". - Unshelve. apply _. apply _. } + by iDestruct (CookieRes_excl with "[$Hck] [$Hres]") as "Habs'". } Qed. End Proof_of_server_conn_step_3. diff --git a/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_to_establish_conn.v b/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_to_establish_conn.v index 1a865d2..853f03b 100644 --- a/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_to_establish_conn.v +++ b/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_to_establish_conn.v @@ -211,7 +211,7 @@ Section Proof_of_server_conn_step_2. (* Case 2.2.1. We show that m ∈ R0 is absurd. *) (* ----------------------------------------------------------------- *) { apply bool_decide_eq_true_1 in Hm. - iDestruct (big_sepS_elem_of _ R0 m Hm with "[$HmsgRres]") as "Hmsgres". + iDestruct (big_sepS_elem_of _ R0 m Hm with "HmsgRres") as "Hmsgres". iDestruct "Hmsgres" as (γs0 mval0 n0 Hser0) "(#Htk0 & [#(%Hl & %Hl2) | (%x & %y & %Habs1 & %Habs2)])"; @@ -427,9 +427,7 @@ Section Proof_of_server_conn_step_2. iRight. iExists c, sidLBLoc, ackIdLoc. rewrite lookup_insert. naive_solver. - - iApply (big_sepS_mono _ _ _ with "[$HmsgRres]"). - Unshelve. - 2:{ apply _. } + - iApply (big_sepS_mono _ _ _ with "HmsgRres"). iIntros (m0 Hm0) "#Hres". destruct (bool_decide (m_sender m = m_sender m0)) eqn:Hmeq. + apply bool_decide_eq_true_1 in Hmeq. @@ -451,8 +449,7 @@ Section Proof_of_server_conn_step_2. iLeft. by rewrite lookup_insert_ne. * iDestruct "Hr" as (???) "%Habs". iExists γs0, _, n0. iFrame "#∗". iSplit; first done. - iRight. rewrite lookup_insert_ne; subst; eauto. - + exact γqlk. } + iRight. rewrite lookup_insert_ne; subst; eauto. } iApply big_sepM_insert_delete. iSplitR "HknResAcc". assert (n = ck0) as -> by naive_solver. diff --git a/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_to_open_new_conn.v b/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_to_open_new_conn.v index abf2c8e..c852b82 100644 --- a/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_to_open_new_conn.v +++ b/aneris/examples/reliable_communication/proof/server/proof_of_server_conn_step_to_open_new_conn.v @@ -78,8 +78,8 @@ Section Proof_of_server_conn_step_1. replace ck with (Z.of_nat ckn); last by lia. wp_apply fupd_aneris_wp. iMod (session_map_update _ _ RCParams_protocol ckn (nroot : namespace) (⊤ :coPset) - with "[] [] [$HknM] [$Hstep]") as "HupdRes"; - [ by solve_ndisj | by rewrite -Hdom in Hdomc |]. + with "[] [$HknM] [$Hstep]") as "HupdRes"; + [ by rewrite -Hdom in Hdomc |]. iModIntro. iDestruct "HupdRes" as (γs) "(HknM & #Hstk & Hhopened & HckF & HckRes & HcanInit1 & HcanInit2)". @@ -143,12 +143,11 @@ Section Proof_of_server_conn_step_1. iFrame "#∗"; eauto. iSplit; first done. iSplit; [ by rewrite !dom_insert_L Hdom |]. - Unshelve. 2:{ apply γqlk. } (* It is convenient to show that the case m ∈ R is absurd. *) destruct (bool_decide (m ∈ R)) eqn:Hm. { apply bool_decide_eq_true_1 in Hm. iAssert (∃ cs, ⌜cM !! m_sender m = Some csâŒ)%I as "%Habs". - { iDestruct (big_sepS_elem_of _ R m Hm with "[$HmsgRres]") as "Hres". + { iDestruct (big_sepS_elem_of _ R m Hm with "HmsgRres") as "Hres". iDestruct "Hres" as (γs0 mval0 n0 Hser0) "(#Htk0 & [#(%Hl & %Hl2) | #Hr])"; [eauto|]. iDestruct "Hr" as (???) "%Habs"; eauto. } @@ -171,9 +170,7 @@ Section Proof_of_server_conn_step_1. rewrite Hseq lookup_insert Hargeq. rewrite Hargeq Hseq in Hser. eauto. - - iApply (big_sepS_mono _ _ _ with "[$HmsgRres]"). - Unshelve. - 2:{ apply _. } + - iApply (big_sepS_mono _ _ _ with "HmsgRres"). iIntros (m0 Hm0) "#Hres". destruct (bool_decide (m_sender m = m_sender m0)) eqn:Hmeq. + apply bool_decide_eq_true_1 in Hmeq. diff --git a/aneris/examples/reliable_communication/proof/server/proof_of_server_listen.v b/aneris/examples/reliable_communication/proof/server/proof_of_server_listen.v index 03157d6..b6e26be 100644 --- a/aneris/examples/reliable_communication/proof/server/proof_of_server_listen.v +++ b/aneris/examples/reliable_communication/proof/server/proof_of_server_listen.v @@ -24,11 +24,10 @@ Section Proof_of_server_listen. Context (N : namespace). Notation srv_ip := (ip_of_address RCParams_srv_saddr). - Lemma server_recv_on_listening_skt_loop_spec (skt_passive : val) : {{{ isServer_listening_loop_resources skt_passive }}} - server_recv_on_listening_skt_loop skt_passive @[srv_ip] - {{{ w, RET w; False }}}. + server_recv_on_listening_skt_loop skt_passive @[srv_ip] + {{{ w, RET w; False }}}. Proof. iIntros (Φ) "HsrRes HΦ". iDestruct "HsrRes" @@ -181,14 +180,14 @@ Section Proof_of_server_listen. rewrite Hsktsrv' in Hsktsrv. inversion Hsktsrv. subst. iApply ("IH" with "[] [$Hsl] [-HΦ] [HΦ]"); [naive_solver | iFrame |done]. } (* Message is a duplicate. *) - iDestruct (big_sepS_elem_of _ _ m with "[$Hdomfrag]") as "%Habs"; [set_solver|]. - by rewrite Hdom in Habs. Unshelve. apply _. + iDestruct (big_sepS_elem_of _ _ m with "Hdomfrag") as "%Habs"; [set_solver|]. + by rewrite Hdom in Habs. Qed. Lemma server_listen_internal_spec (skt : val) : {{{ isServerSocketInternal skt false }}} server_listen skt @[ip_of_address RCParams_srv_saddr] - {{{ v, RET v; ⌜v = #()⌠∗ isServerSocketInternal skt true }}}. + {{{ RET #(); isServerSocketInternal skt true }}}. Proof. iIntros (Φ) "HsrvRes HΦ". iDestruct "HsrvRes" as (srv_skt_l <-) "[(_ & HsrvRes)|(%Habs & _)]"; [|done]. @@ -222,7 +221,7 @@ Section Proof_of_server_listen. rewrite -Qp_div_add_distr pos_to_Qp_add Qp_div_diag //=. } wp_apply (aneris_wp_fork with "[-]"). iSplitL "HΦ Hl2". - + wp_pures. iApply "HΦ". iNext. iSplit; [done|]. iExists srv_skt_l. iSplit; [done|]. + + wp_pures. iApply "HΦ". iNext. iExists srv_skt_l. iSplit; [done|]. iRight. iSplit; [done|]. iExists _, _, _. diff --git a/aneris/examples/reliable_communication/proof/server/server_resources.v b/aneris/examples/reliable_communication/proof/server/server_resources.v index a236dc1..738907a 100644 --- a/aneris/examples/reliable_communication/proof/server/server_resources.v +++ b/aneris/examples/reliable_communication/proof/server/server_resources.v @@ -38,7 +38,7 @@ Section Server_resources. | HalfOpened of nat | Connected of ((val * nat) * (loc * loc)). - #[global] Program Instance Inject_conn_state : Inject conn_state val := + #[global] Program Instance Inject_conn_state : Inject conn_state val := {| inject a := match a with | HalfOpened n => InjLV #n diff --git a/aneris/examples/reliable_communication/resources/chan_endpoints_resources.v b/aneris/examples/reliable_communication/resources/chan_endpoints_resources.v index 3d94e06..49c0c2f 100644 --- a/aneris/examples/reliable_communication/resources/chan_endpoints_resources.v +++ b/aneris/examples/reliable_communication/resources/chan_endpoints_resources.v @@ -30,10 +30,10 @@ Section Endpoint_MetaData. iPureIntro. by apply (to_agree_op_inv_L (A:= _ )) in Hval. Qed. - Definition ChannelSideToken (γe : endpoint_name) (s : side) : iProp Σ := - own (endpoint_side_name γe) (to_agree s). + Definition ChannelSideToken (γe : endpoint_name) (s : side) : iProp Σ := + own (endpoint_side_name γe) (to_agree s). - Lemma ChannelSideToken_agree γe s1 s2 : + Lemma ChannelSideToken_agree γe s1 s2 : ChannelSideToken γe s1 -∗ ChannelSideToken γe s2 -∗ ⌜s1 = s2âŒ. Proof. iIntros "HA HB". iDestruct (own_valid_2 with "HA HB") as %Hval. @@ -41,7 +41,7 @@ Section Endpoint_MetaData. Qed. Definition ChannelIdxsToken (γe : endpoint_name) (pl : loc * loc) : iProp Σ := - own (endpoint_idxs_name γe) (to_agree pl). + own (endpoint_idxs_name γe) (to_agree pl). Lemma ChannelIdxsToken_agree γe pl1 pl2 : ChannelIdxsToken γe pl1 -∗ ChannelIdxsToken γe pl2 -∗ ⌜pl1 = pl2âŒ. diff --git a/aneris/examples/reliable_communication/resources/chan_session_resources.v b/aneris/examples/reliable_communication/resources/chan_session_resources.v index ef9496d..281b278 100644 --- a/aneris/examples/reliable_communication/resources/chan_session_resources.v +++ b/aneris/examples/reliable_communication/resources/chan_session_resources.v @@ -29,7 +29,7 @@ Section KnownSessions. Proof. apply _. Qed. Lemma session_token_agree sa γ1 γ2 : - session_token sa γ1 -∗ session_token sa γ2 -∗ ⌜γ1 = γ2âŒ. + session_token sa γ1 -∗ session_token sa γ2 -∗ ⌜γ1 = γ2âŒ. Proof. iIntros "Hγ1 Hγ2". iDestruct (own_valid_2 with "Hγ1 Hγ2") as %Hval. @@ -47,7 +47,6 @@ Section KnownSessions. End KnownSessions. - Section OneShot. Context `{!anerisG Mdl Σ, !chanG Σ, !server_ghost_names}. @@ -145,12 +144,9 @@ Section iProto_sessions. Qed. - (* TODO: remember to set up the namespace N correctly - as global parameter in user params. *) Lemma session_map_update (M : session_names_map) (sa : socket_address) (p : iProto Σ) (cookie : nat) (N: namespace) (E : coPset) : - ⌜↑N ⊆ E⌠-∗ (* Do we need this hypothesis about masks ? *) ⌜sa ∉ dom M⌠-∗ known_sessions M -∗ steps_lb 0 ={E}=∗ @@ -163,7 +159,7 @@ Section iProto_sessions. can_init γ sa p Left ∗ can_init γ sa (iProto_dual p) Right. Proof. - iIntros (Hmask Hfresh) "Hkn #Hlb". + iIntros (Hfresh) "Hkn #Hlb". iMod (iProto_init p) as (γ_p) "(Hp_auth & Hpl & Hpr)". iMod (auth_list_alloc with "[//]") as (γ_Tl) "(HTl_auth & HTl_A)". iMod (auth_list_alloc with "[//]") as (γ_Rl) "(HRl_auth & HRl_A)". @@ -171,11 +167,7 @@ Section iProto_sessions. iMod (auth_list_alloc with "[//]") as (γ_Rr) "(HRr_auth & HRr_A)". set (γ_chan := ChanName γ_p γ_Tl γ_Tr γ_Rl γ_Rr (N.@ (socket_address_to_str sa))). iMod (mono_nat_own_alloc 0%nat) as (γ_srv_idx) "(Hsrv_idxA & Hsrv_idxF)". - (* iMod (own_alloc (A := mono_natUR) (â—MN{#1} 0)) as (γ_srv_idx) "Hsrv_idx". *) - (* { apply mono_nat_auth_valid. } *) iMod (mono_nat_own_alloc 0%nat) as (γ_clt_idx) "(Hclt_idxA & Hclt_idxF)". - (* iMod (own_alloc (A := mono_natUR) (â—MN{#1} 0)) as (γ_clt_idx) "Hclt_idx". *) - (* { apply mono_nat_auth_valid. } *) iMod (own_alloc (â— (to_agree <$> (∅: session_names_map) : session_names_mapUR))) as (γsa) "Hsa". { rewrite fmap_empty. by apply auth_auth_valid. } diff --git a/aneris/examples/reliable_communication/spec/api_spec.v b/aneris/examples/reliable_communication/spec/api_spec.v index cbbdbba..2be7cfc 100644 --- a/aneris/examples/reliable_communication/spec/api_spec.v +++ b/aneris/examples/reliable_communication/spec/api_spec.v @@ -13,12 +13,11 @@ Canonical Structure valO := leibnizO val. Notation iProto Σ := (iProto Σ val). Notation iMsg Σ := (iMsg Σ val). - Section API_spec. Context `{ !anerisG Mdl Σ }. - Context `{ !@Chan_mapsto_resource Σ}. - Context `{ UP : !Reliable_communication_service_params}. - Context `{ !SessionResources UP}. + Context `{ !@Chan_mapsto_resource Σ }. + Context `{ UP : !Reliable_communication_service_params }. + Context `{ !SessionResources UP }. Implicit Types p : iProto Σ. Implicit Types TT : tele. @@ -29,18 +28,19 @@ Section API_spec. Notation srv_si := reserved_server_socket_interp. Notation srv_ip := (ip_of_address srv_saddr). - Definition make_client_skt_spec (clt_addr : socket_address) (A : gset socket_address) : Prop := + Definition make_client_skt_spec : Prop := + ∀ (clt_addr : socket_address) (A : gset socket_address), {{{ ⌜clt_addr ∉ A⌠∗ clt_addr ⤳ (∅, ∅) ∗ free_ports (ip_of_address clt_addr) {[port_of_address clt_addr]} ∗ RCParams_srv_saddr ⤇ srv_si ∗ - fixed A - }}} + fixed A }}} make_client_skt (s_serializer clt_ser) (s_serializer srv_ser) #clt_addr @[ip_of_address clt_addr] {{{ skt, RET skt; CltCanConnect skt clt_addr }}}. - Definition make_server_skt_spec A : Prop := + Definition make_server_skt_spec : Prop := + ∀ A, {{{ srv_saddr ⤇ srv_si ∗ ⌜RCParams_srv_saddr ∈ A⌠∗ fixed A ∗ @@ -52,49 +52,49 @@ Section API_spec. @[srv_ip] {{{ skt, RET skt; SrvCanListen skt }}}. - Definition server_listen_spec (skt : val) : Prop := + Definition server_listen_spec : Prop := + ∀ (skt : val), {{{ SrvCanListen skt }}} server_listen skt @[srv_ip] - {{{ v, RET v; ⌜v = #()⌠∗ SrvListens skt }}}. + {{{ RET #(); SrvListens skt }}}. - Definition accept_spec (skt : val) : Prop := + Definition accept_spec : Prop := + ∀ (skt : val), {{{ SrvListens skt }}} accept skt @[srv_ip] - {{{ c (client_addr: socket_address) v, RET v; ⌜v = (c, #client_addr)%V⌠∗ - SrvListens skt ∗ - c ↣{ srv_ip, RCParams_srv_ser } iProto_dual RCParams_protocol - }}}. + {{{ c (client_addr: socket_address), RET (c, #client_addr); + SrvListens skt ∗ + c ↣{ srv_ip, RCParams_srv_ser } iProto_dual RCParams_protocol }}}. - Definition connect_spec (skt : val) (clt_addr : socket_address) : Prop := + Definition connect_spec : Prop := + ∀ (skt : val) (clt_addr : socket_address), {{{ CltCanConnect skt clt_addr }}} connect skt #RCParams_srv_saddr @[ip_of_address clt_addr] {{{ c, RET c; - c ↣{ ip_of_address clt_addr, RCParams_clt_ser } RCParams_protocol - }}}. + c ↣{ ip_of_address clt_addr, RCParams_clt_ser } RCParams_protocol }}}. - Definition send_spec (c : val) v p ip serA : Prop := + Definition send_spec : Prop := + ∀ (c : val) v p ip serA, {{{ c ↣{ ip, serA } (<!> MSG v; p)%proto ∗ ⌜Serializable serA v⌠}}} send c v @[ip] {{{ RET #(); c ↣{ ip, serA } p }}}. - Definition send_spec_tele - TT c (tt : TT) - (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip serA : Prop := + Definition send_spec_tele : Prop := + ∀ TT c (tt : TT) (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip serA, {{{ c ↣{ ip , serA } (<!.. (x : TT) > MSG (v x) {{ P x }}; p x)%proto ∗ P tt ∗ ⌜Serializable serA (v tt)⌠}}} send c (v tt) @[ip] {{{ RET #(); c ↣{ ip , serA } (p tt)%proto }}}. - Definition try_recv_spec - TT (c : val) (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip ser - : Prop := + Definition try_recv_spec : Prop := + ∀ TT (c : val) (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip ser, {{{ c ↣{ ip , ser } (<?.. x> MSG (v x) {{ P x }}; p x)%proto }}} try_recv c @[ip] {{{ w, RET w; (⌜w = NONEV⌠∗ c ↣{ ip, ser } (<?.. x> MSG (v x) {{ P x }}; p x)%proto) ∨ (∃ x : TT, ⌜w = SOMEV (v x)⌠∗ c ↣{ ip, ser } (p x)%proto ∗ P x) }}}. - Definition recv_spec TT c (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip ser - : Prop := + Definition recv_spec : Prop := + ∀ TT c (v : TT → val) (P : TT → iProp Σ) (p : TT → iProto Σ) ip ser, {{{ c ↣{ ip, ser } (<?.. x> MSG (v x) {{ â–· P x }}; p x)%proto }}} recv c @[ip] {{{ x, RET v x; c ↣{ ip, ser } p x ∗ P x }}}. @@ -119,19 +119,19 @@ Section Init. Reliable_communication_init_setup E (UP : Reliable_communication_service_params): ↑RCParams_srv_N ⊆ E → - True ⊢ |={E}=> + ⊢ |={E}=> ∃ ( _ : Chan_mapsto_resource), ∃ (SnRes : SessionResources UP), SrvInit ∗ - ⌜(∀ sa A, make_client_skt_spec UP SnRes sa A)⌠∗ - ⌜(∀ A, make_server_skt_spec UP SnRes A)⌠∗ - ⌜(∀ skt sa, connect_spec UP SnRes skt sa)⌠∗ - ⌜(∀ skt, server_listen_spec UP SnRes skt)⌠∗ - ⌜(∀ skt, accept_spec UP SnRes skt)⌠∗ - ⌜(∀ c v p ip ser, send_spec c v p ip ser)⌠∗ - ⌜(∀ TT c t v P q ip s, send_spec_tele TT c t v P q ip s)⌠∗ - ⌜(∀ TT c v P q ip ser, try_recv_spec TT c v P q ip ser)⌠∗ - ⌜(∀ TT c v P q ip ser, recv_spec TT c v P q ip ser)⌠+ ⌜make_client_skt_spec UP SnRes⌠∗ + ⌜make_server_skt_spec UP SnRes⌠∗ + ⌜connect_spec UP SnRes⌠∗ + ⌜server_listen_spec UP SnRes⌠∗ + ⌜accept_spec UP SnRes⌠∗ + ⌜send_spec⌠∗ + ⌜send_spec_tele⌠∗ + ⌜try_recv_spec⌠∗ + ⌜recv_spec⌠}. End Init. @@ -147,18 +147,18 @@ Section Reliable_communication_Specified_API_def. `{ UP : !Reliable_communication_service_params} `{!SessionResources UP} := { - RCSpec_make_client_skt_spec sa A: make_client_skt_spec _ _ sa A; - RCSpec_make_server_skt_spec A : make_server_skt_spec _ _ A; - RCSpec_connect_spec skt sa : connect_spec _ _ skt sa; - RCSpec_server_listen_spec skt : server_listen_spec _ _ skt; - RCSpec_accept_spec skt : accept_spec _ _ skt; + RCSpec_make_client_skt_spec : make_client_skt_spec _ _; + RCSpec_make_server_skt_spec : make_server_skt_spec _ _; + RCSpec_connect_spec : connect_spec _ _; + RCSpec_server_listen_spec : server_listen_spec _ _; + RCSpec_accept_spec : accept_spec _ _; }. Class Reliable_communication_Specified_API_session := { - RCSpec_send_spec c v p ip ser : send_spec c v p ip ser; - RCSpec_send_spec_tele TT c t v P q ip s : send_spec_tele TT c t v P q ip s; - RCSpec_try_recv_spec TT c v P q ip ser : try_recv_spec TT c v P q ip ser; - RCSpec_recv_spec TT c v P q ip ser : recv_spec TT c v P q ip ser + RCSpec_send_spec : send_spec; + RCSpec_send_spec_tele : send_spec_tele; + RCSpec_try_recv_spec : try_recv_spec; + RCSpec_recv_spec : recv_spec }. End Reliable_communication_Specified_API_def. diff --git a/aneris/prelude/list.v b/aneris/prelude/list.v index 9c5b64a..9f82740 100644 --- a/aneris/prelude/list.v +++ b/aneris/prelude/list.v @@ -1,5 +1,5 @@ From Coq.ssr Require Import ssreflect. -From stdpp Require Import list. +From stdpp Require Import list gmap. Definition flatten {A : Type} (l : list (list A)) : list A := fold_right (λ l1 l2, l1 ++ l2) [] l. @@ -56,3 +56,189 @@ Proof. rewrite minus_plus /=. rewrite lookup_app_r; first done. rewrite Nat.sub_diag; done. Qed. + +Lemma prefix_Some_None {A} (P : A → Prop) `{!∀ x, Decision (P x)} xs ys zs x : + last (filter P xs) = Some x → + last (filter P ys) = None → + xs `prefix_of` ys ++ zs → + ys `prefix_of` xs. +Proof. + intros Hsome Hnone Hprefix. + rewrite last_None in Hnone. + generalize dependent xs. + induction ys as [|y ys]; intros xs Hsome Hprefix. + { by apply prefix_nil. } + destruct xs as [|x' xs]; [done|]. + assert (y = x') as <-. + { by apply prefix_cons_inv_1 in Hprefix. } + apply prefix_cons. + rewrite filter_cons in Hnone. + apply prefix_cons_inv_2 in Hprefix. + rewrite filter_cons in Hsome. + apply IHys; [by destruct (decide (P y))|by destruct (decide (P y))|done]. +Qed. + +Lemma prefix_cons_nil {A:Type} (xs : list A) y ys : + xs ≠[] → + xs `prefix_of` y :: ys → + [y] `prefix_of` xs. +Proof. + intros Hneq Hprefix. + destruct xs; [done|]. + apply prefix_cons_inv_1 in Hprefix. + rewrite Hprefix. + by apply prefix_cons, prefix_nil. +Qed. + +Lemma last_filter_app_r {A} (P : A → Prop) `{!∀ x, Decision (P x)} xs ys x : + last (filter P (xs ++ ys)) = Some x → + last (filter P xs) = None → + last (filter P ys) = Some x. +Proof. + intros Hsome Hnone%last_None. + by rewrite filter_app Hnone in Hsome. +Qed. + +Lemma prefix_split_eq {A} (P : A → Prop) `{!∀ x, Decision (P x)} xs ys zs x y : + last (filter P xs) = Some x → + last (filter P ys) = None → + last (filter P zs) = None → + xs `prefix_of` ys ++ [y] ++ zs → + x = y. +Proof. + intros Hsome Hnone1 Hnone2 Hprefix. + assert (ys `prefix_of` xs) as [k ->]. + { by eapply prefix_Some_None. } + apply prefix_app_inv in Hprefix. + apply last_filter_app_r in Hsome; [|done]. + assert ([y] `prefix_of` k) as [k' ->]. + { eapply prefix_cons_nil; [|done]. by intros ->. } + rewrite filter_app in Hsome. + rewrite last_None in Hnone2. + apply prefix_app_inv in Hprefix. + destruct Hprefix as [k'' ->]. + rewrite filter_app in Hnone2. + apply app_eq_nil in Hnone2. + destruct Hnone2 as [Hnone2 _]. + rewrite Hnone2 in Hsome. + rewrite filter_cons in Hsome. + destruct (decide (P y)); [|done]. + simpl in *. by simplify_eq. +Qed. + +Lemma elem_of_last_filter_exists_Some + {A} `{EqDecision A} (P : A → Prop) `{!∀ x, Decision (P x)} xs x y : + last (filter P xs) = x → + y ∈ xs → P y → + ∃ x', last (filter P xs) = Some x'. +Proof. + intros Hlast Hin HPy. + induction xs as [|z xs IHxs]; [by set_solver|]. + destruct (decide (P z)) as [HPz|HPz]. + - rewrite filter_cons_True; [done|]. + assert (last (filter P xs) = None ∨ + ∃ x', last (filter P xs) = Some x') as Hfilter. + { by destruct (last (filter P xs)); [right; eexists _|left]. } + destruct Hfilter as [Hnone|[x' Hsome]]. + + exists z. rewrite last_None in Hnone. by rewrite Hnone. + + exists x'. rewrite last_cons. by rewrite Hsome. + - rewrite filter_cons_False; [done|]. + rewrite filter_cons_False in Hlast; [done|]. + assert (y ≠z) as Hneq. + { intros Heq. by simplify_eq. } + apply elem_of_cons in Hin. + destruct Hin as [Hin|Hin]; [done|by apply IHxs]. +Qed. + +Lemma NoDup_prefix {A} (xs ys : list A) : + NoDup ys → + xs `prefix_of` ys → + NoDup xs. +Proof. + revert ys. + induction xs as [|x xs IHxs]; intros ys HNoDup Hprefix. + { by apply NoDup_nil. } + apply NoDup_cons. + destruct ys as [|y ys]. + { destruct Hprefix as [k Heq]. + by rewrite -app_comm_cons in Heq. } + assert (x = y) as <- by by apply prefix_cons_inv_1 in Hprefix. + apply prefix_cons_inv_2 in Hprefix. + apply NoDup_cons in HNoDup as [Hnin HNoDup]. + split; [|by eapply IHxs]. + intros Hin. apply Hnin. + by eapply elem_of_prefix. +Qed. + +Lemma Forall_filter_empty {A} P `{!∀ x, Decision (P x)} (xs : list A) : + Forall (λ x, ¬ P x) xs → + filter P xs = []. +Proof. + intros HForall. + induction xs as [|x xs]; [done|]. + apply Forall_cons in HForall as [HPx HForall]. + rewrite filter_cons_False; [done|]. + by apply IHxs. +Qed. + +Lemma NoDup_last_filter_Some {A} P `{!∀ x, Decision (P x)} (xs ys zs : list A) x : + NoDup zs → + last (filter P xs) = Some x → + last (filter P zs) = Some x → + xs `prefix_of` ys → + ys `prefix_of` zs → + last (filter P ys) = Some x. +Proof. + intros HNoDup Hxs Hzs Hprefix Hprefix'. + assert (NoDup ys) as HNoDupys by by eapply NoDup_prefix. + assert (NoDup xs) as HNoDupxs by by eapply NoDup_prefix. + assert (xs `prefix_of` zs) as Hprefix'' by by eapply transitivity. + assert (last (filter P xs) = Some x) as Hxs' by done. + assert (last (filter P zs) = Some x) as Hzs' by done. + apply last_filter_Some in Hxs as (l1 & l2 & -> & HP). + apply last_filter_Some in Hzs as (k1 & k2 & -> & HP'). + assert (l1 = k1 ∧ x = x ∧ l2 `prefix_of` k2) as (Heq1 & Heq2 & Hprefix'''). + { eapply prefix_not_elem_of_app_cons_inv. + { apply NoDup_app in HNoDup as (_&Hnin&HNoDup). + intros Hin. + apply Hnin in Hin. + apply Hin. by left. } + { apply NoDup_app in HNoDupxs as (_&Hnin&HNoDupxs). + intros Hin. + apply Hnin in Hin. + apply Hin. by left. } + done. } + simplify_eq. + destruct Hprefix as [k ->]. + rewrite -!assoc in Hprefix'. + apply prefix_app_inv in Hprefix'. + rewrite -app_comm_cons in Hprefix'. + apply prefix_cons_inv_2 in Hprefix'. + rewrite filter_app. + rewrite last_app. + rewrite Hxs'. + destruct Hprefix' as [k' ->]. + apply Forall_app in HP' as [HP' _]. + apply Forall_app in HP' as [_ HP']. + by rewrite Forall_filter_empty. +Qed. + +Lemma NoDup_last_filter_None {A} P `{!∀ x, Decision (P x)} (xs ys : list A) : + NoDup ys → + last (filter P ys) = None → + xs `prefix_of` ys → + last (filter P xs) = None. +Proof. + revert ys. + induction xs as [|x xs IHxs]; intros ys HNodup Hys Hprefix; [done|]. + destruct ys as [|y ys]. + { destruct Hprefix as [k Heq]. + by rewrite -app_comm_cons in Heq. } + assert (x = y) as <- by by apply prefix_cons_inv_1 in Hprefix. + apply prefix_cons_inv_2 in Hprefix. + rewrite filter_cons in Hys. + rewrite filter_cons. + destruct (decide (P x)) as [HPx|HPx]. + { rewrite last_cons in Hys. by destruct (last (filter P ys)). } + eapply IHxs; [by eapply NoDup_cons_1_2|done|done]. +Qed. diff --git a/ml_sources/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.ml b/ml_sources/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.ml index 8277dc6..8e78091 100644 --- a/ml_sources/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.ml +++ b/ml_sources/examples/reliable_communication/examples/dlm_db_example/dlm_db_example_code.ml @@ -1,41 +1,42 @@ open !Ast open Serialization_code open Dlm_code -open Ddb_code +open Repdb_code -let do_transaction lk wr = +let do_writes lk wr = dlock_acquire lk; - wr "x" 1; - wr "y" 37; + wr "x" 37; + wr "y" 1; dlock_release lk -let repeat_read_until lk rd k v = +let do_reads lk rd = let rec loop () = dlock_acquire lk; - let res = rd k in - dlock_release lk; - if res = Some v - then () - else begin - unsafe (fun () -> Unix.sleepf 2.0); loop () - end + let vx = rd "x" in + if vx = Some 37 + then + begin + let vy = rd "y" in + assert (vy = Some 1); + dlock_release lk; + vy + end + else + begin + dlock_release lk; + unsafe (fun () -> Unix.sleepf 2.0); + loop () + end in loop () -let do_read lk rd = - ignore (repeat_read_until lk rd "x" 1); - dlock_acquire lk; - let vy = rd "y" in - dlock_release lk; - assert (vy = Some 37) - -let node0 clt_addr00 clt_addr01 dlock_srv_addr db_srv_addr = - let lk_chan = dlock_subscribe_client clt_addr00 dlock_srv_addr in - let db_funs = install_proxy int_serializer clt_addr01 db_srv_addr in +let node0 clt_addr00 clt_addr01 dl_addr db_laddr = + let lk_chan = dlock_subscribe_client clt_addr00 dl_addr in + let db_funs = init_client_leader_proxy int_serializer clt_addr01 db_laddr in let (wr, _rd) = db_funs in - do_transaction lk_chan wr + do_writes lk_chan wr -let node1 clt_addr10 clt_addr11 dlock_srv_addr db_srv_addr = - let lk_chan = dlock_subscribe_client clt_addr10 dlock_srv_addr in - let db_funs = install_proxy int_serializer clt_addr11 db_srv_addr in +let node1 clt_addr10 clt_addr11 dl_addr db_laddr = + let lk_chan = dlock_subscribe_client clt_addr10 dl_addr in + let db_funs = init_client_leader_proxy int_serializer clt_addr11 db_laddr in let (_wr, rd) = db_funs in - do_read lk_chan rd + do_reads lk_chan rd diff --git a/ml_sources/examples/reliable_communication/examples/dlm_db_example/dune b/ml_sources/examples/reliable_communication/examples/dlm_db_example/dune index 0222de9..aca7ba1 100644 --- a/ml_sources/examples/reliable_communication/examples/dlm_db_example/dune +++ b/ml_sources/examples/reliable_communication/examples/dlm_db_example/dune @@ -1,4 +1,4 @@ (executable (name dlm_db_example_code) (flags :standard -rectypes) - (libraries client_server_code dlm_code ddb_code aneris)) \ No newline at end of file + (libraries dlm_code repdb_code aneris)) \ No newline at end of file diff --git a/ml_sources/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.ml b/ml_sources/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.ml new file mode 100644 index 0000000..64b1c58 --- /dev/null +++ b/ml_sources/examples/reliable_communication/examples/repdb_leader_followers/causality_example_code.ml @@ -0,0 +1,29 @@ +open !Ast +open Serialization_code +open Repdb_code + +let do_writes wr = + wr "x" 37; + wr "y" 1 + +let wait_on_read rd k v = + let rec loop () = + let res = rd k in + if res = Some v + then () + else (unsafe (fun () -> Unix.sleepf 2.0); loop ()) + in loop () + +let do_reads rd = + wait_on_read rd "y" 1; + let vx = rd "x" in + assert (vx = Some 37) + +let node0 clt_addr0 db_laddr = + let db_funs = init_client_leader_proxy int_serializer clt_addr0 db_laddr in + let (wr, _rd) = db_funs in + do_writes wr + +let node1 clt_addr1 faddr = + let rd = init_client_follower_proxy int_serializer clt_addr1 faddr in + do_reads rd diff --git a/ml_sources/examples/reliable_communication/examples/repdb_leader_followers/dune b/ml_sources/examples/reliable_communication/examples/repdb_leader_followers/dune new file mode 100644 index 0000000..10a8510 --- /dev/null +++ b/ml_sources/examples/reliable_communication/examples/repdb_leader_followers/dune @@ -0,0 +1,4 @@ +(executable + (name causality_example_code) + (flags :standard -rectypes) + (libraries repdb_code aneris)) \ No newline at end of file diff --git a/ml_sources/examples/reliable_communication/lib/mt_server/dune b/ml_sources/examples/reliable_communication/lib/mt_server/dune new file mode 100644 index 0000000..ca2f7d7 --- /dev/null +++ b/ml_sources/examples/reliable_communication/lib/mt_server/dune @@ -0,0 +1,4 @@ + (library + (name mt_server_code) + (flags :standard -rectypes) + (libraries aneris client_server_code)) diff --git a/ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.ml b/ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.ml new file mode 100644 index 0000000..1b92998 --- /dev/null +++ b/ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.ml @@ -0,0 +1,43 @@ +open Ast +open Client_server_code + + +type ('a, 'b) rcb = ('a, 'b) chan_descr + + +let service_loop c (request_handler : 'req -> 'rep) () : unit = + let rec loop () = + let req = recv c in + let rep = request_handler req in + send c rep; + loop () + in loop () + +let accept_new_connections_loop skt request_handler () : unit = + let rec loop () = + let new_conn = accept skt in + let (c, _a) = new_conn in + fork (service_loop c request_handler) (); + loop () + in loop () + +let run_server + (ser[@metavar] : 'repl serializer) + (deser[@metavar] : 'req serializer) + addr + (request_handler : 'req -> 'rep) : unit = + let (skt : ('repl, 'req) server_skt) = make_server_skt ser deser addr in + server_listen skt; + fork (accept_new_connections_loop skt request_handler) () + +let make_request (ch : ('req, 'repl) chan_descr) : 'req -> 'repl = + fun req -> + send ch req; + recv ch + +let init_client_proxy + (ser[@metavar] : 'req serializer) (deser[@metavar] : 'repl serializer) + clt_addr srv_addr : ('a, 'b) rcb = + let skt = make_client_skt ser deser clt_addr in + let ch = connect skt srv_addr in + ch diff --git a/ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.mli b/ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.mli new file mode 100644 index 0000000..4fa5bf0 --- /dev/null +++ b/ml_sources/examples/reliable_communication/lib/mt_server/mt_server_code.mli @@ -0,0 +1,11 @@ +open Ast + +type ('a, 'b) rcb + +val run_server : 'repl serializer -> 'req serializer -> + saddr -> ('req -> 'repl) -> unit + +val make_request : ('req, 'repl) rcb -> ('req -> 'repl) + +val init_client_proxy : 'req serializer -> 'repl serializer -> + saddr -> saddr -> ('req, 'repl) rcb diff --git a/ml_sources/examples/reliable_communication/lib/repdb/dune b/ml_sources/examples/reliable_communication/lib/repdb/dune index 1a750d4..dfc3cb2 100644 --- a/ml_sources/examples/reliable_communication/lib/repdb/dune +++ b/ml_sources/examples/reliable_communication/lib/repdb/dune @@ -1,4 +1,4 @@ (library (name repdb_code) (flags :standard -rectypes) - (libraries aneris client_server_code)) + (libraries aneris mt_server_code)) diff --git a/ml_sources/examples/reliable_communication/lib/repdb/log_code.ml b/ml_sources/examples/reliable_communication/lib/repdb/log_code.ml index 6cffbad..615bd39 100644 --- a/ml_sources/examples/reliable_communication/lib/repdb/log_code.ml +++ b/ml_sources/examples/reliable_communication/lib/repdb/log_code.ml @@ -1,8 +1,7 @@ open Ast open List_code -type 'a log_entry = ('a * int) -type 'a log = ('a log_entry alist * int) Atomic.t +type 'a log = ('a alist * int) Atomic.t (* -------------------------------------------------------------------------- *) (** Operations on log of requests *) @@ -14,14 +13,14 @@ let log_create () : 'a log = ref (list_nil, 0) (* the log and next free index. * let log_add_entry (log : 'a log) (req : 'a) = let lp = !log in let (data, next) = lp in - let data' = list_append data (list_cons (req, next) list_nil) in + let data' = list_append data (list_cons req list_nil) in log := (data', next + 1) let log_next (log : 'a log) = snd !log let log_length (log : 'a log) = snd !log -let log_get (log : 'a log) (i : int) : 'a log_entry option = +let log_get (log : 'a log) (i : int) : 'a option = list_nth (fst !log) i let log_wait_until log mon i : unit = diff --git a/ml_sources/examples/reliable_communication/lib/repdb/repdb_code.ml b/ml_sources/examples/reliable_communication/lib/repdb/repdb_code.ml index a3bd7cd..a026678 100644 --- a/ml_sources/examples/reliable_communication/lib/repdb/repdb_code.ml +++ b/ml_sources/examples/reliable_communication/lib/repdb/repdb_code.ml @@ -3,18 +3,15 @@ open Map_code open Network_util_code open Serialization_code open Log_code -open Client_server_code +open Mt_server_code -(* Type definitions *) -type 'a wr_reqTy = string * 'a -type 'a reqTy = ('a wr_reqTy, string) sumTy +(* Type aliases *) +type 'a reqTy = (string * 'a, string) sumTy type 'a repTy = (unit, 'a option) sumTy -type 'a db_chan = ('a repTy, 'a reqTy) chan_descr type 'a dbTy = ((string, 'a) amap) -(* -------------------------------------------------------------------------- *) (** Serializers *) -(* -------------------------------------------------------------------------- *) + let write_serializer (val_ser[@metavar]) = prod_serializer string_serializer val_ser let read_serializer = string_serializer @@ -28,56 +25,15 @@ let rep_l2f_ser (val_ser[@metavar]) = let req_c2f_ser = read_serializer let rep_f2c_ser (val_ser[@metavar]) = option_serializer val_ser -(* -------------------------------------------------------------------------- *) -(** Generic methods for multi-threaded server with monitored requests. *) -(* -------------------------------------------------------------------------- *) - -(** Serve requests on the the channel `c` via monitored queue of events. *) -let service_loop c mon (request_handler : monitor -> 'req -> 'rep) () : unit = - let rec loop () = - let req = recv c in - monitor_acquire mon; - let rep = request_handler mon req in - monitor_release mon; - send c rep; - loop () - in loop () - -let accept_new_connections_loop skt mon request_handler () : unit = - let rec loop () = - let new_conn = accept skt in - let (c, _a) = new_conn in - fork (service_loop c mon request_handler) (); - loop () - in loop () - -let run_server (ser[@metavar]) (deser[@metavar]) addr mon - (request_handler : monitor -> 'req -> 'rep) : unit = - let (skt : ('repl, 'req) server_skt) = make_server_skt ser deser addr in - server_listen skt; - fork (accept_new_connections_loop skt mon request_handler) () - -(* -------------------------------------------------------------------------- *) (** Leader *) -(* -------------------------------------------------------------------------- *) (** Processes the follower's request. *) -let follower_request_handler log mon req : 'a wr_reqTy log_entry = +let follower_request_handler log mon req : ((string * 'a) * int) = + monitor_acquire mon; log_wait_until log mon req; - unSOME (log_get log req) - -(** Processes the request event (request & the reply cell). *) -let client_request_handler_at_leader - (db : 'a dbTy Atomic.t) (log :'a log) (mon : monitor) (req : 'a reqTy) = - match req with - | InjL p -> (* WRITE REQUEST *) - let (k, v) = p in - db := map_insert k v !db; (* Write value v to the key k. *) - log_add_entry log (k,v); - monitor_signal mon; - InjL () - | InjR k -> (* READ REQUEST *) - InjR (map_lookup k !db) (* Read the key k. *) + let res = unSOME (log_get log req) in + monitor_release mon; + res let update_log_copy_loop logC monC logF monF () = let rec loop i = @@ -93,16 +49,35 @@ let update_log_copy_loop logC monC logF monF () = loop (snd logC_copy) in loop 0 +let start_leader_processing_followers (ser[@metavar]) addr log mon () = + run_server (rep_l2f_ser ser) req_f2l_ser addr + (fun req -> follower_request_handler log mon req) + +(** Processes the request event (request & the reply cell). *) +let client_request_handler_at_leader (db : 'a dbTy Atomic.t) (log : ((string * 'a) * int) log) + (mon : monitor) (req : 'a reqTy) : 'a repTy = + monitor_acquire mon; + let res = + match req with + | InjL p -> (* WRITE REQUEST *) + let (k, v) = p in + db := map_insert k v !db; (* Write value v to the key k. *) + let n = log_length log in + log_add_entry log ((k,v), n); + monitor_signal mon; + InjL () + | InjR k -> (* READ REQUEST *) + InjR (map_lookup k !db) (* Read the key k. *) + in + monitor_release mon; + res + (** Initialization of the leader-followers database. *) let start_leader_processing_clients (ser[@metavar]) addr db log mon () = - run_server (rep_l2c_ser ser) (req_c2l_ser ser) addr mon - (client_request_handler_at_leader db log) - -let start_leader_processing_followers (ser[@metavar]) addr log mon () = - run_server (rep_l2f_ser ser) req_f2l_ser addr mon - (follower_request_handler log) + run_server (rep_l2c_ser ser) (req_c2l_ser ser) addr + (fun req -> client_request_handler_at_leader db log mon req) -let init_leader (ser[@metavar]) addr0 addr1 : unit = +let init_leader (ser[@metavar] : 'a serializer) addr0 addr1 : unit = let logC = log_create () in let logF = log_create () in let (db : 'a dbTy Atomic.t) = ref (map_empty ()) in @@ -112,36 +87,53 @@ let init_leader (ser[@metavar]) addr0 addr1 : unit = fork (start_leader_processing_followers ser addr1 logF monF) (); fork (update_log_copy_loop logC monC logF monF) () -(* -------------------------------------------------------------------------- *) +let init_client_leader_proxy (ser[@metavar]) clt_addr srv_addr = + let rpc = init_client_proxy (req_c2l_ser ser) (rep_l2c_ser ser) clt_addr srv_addr in + let lk = newlock () in + let reqf req = + acquire lk; + let res = make_request rpc req in + release lk; + res + in + let write k v = + match reqf (InjL (k, v)) with + | InjL _u -> () + | InjR _abs -> assert false in + let read k = + match reqf (InjR k) with + | InjL _abs -> assert false + | InjR r -> r + in (write, read) + (** Follower. *) -(* -------------------------------------------------------------------------- *) (** Processes the read-only request event (request & the reply cell). *) -let client_request_handler_at_follower (db : 'a dbTy Atomic.t) _mon req_k = - map_lookup req_k !db (* Read the key k. *) +let client_request_handler_at_follower (db : 'a dbTy Atomic.t) mon req_k = + monitor_acquire mon; + let res = map_lookup req_k !db in (* Read the key k. *) + monitor_release mon; + res let start_follower_processing_clients (ser[@metavar]) addr db mon = - run_server (rep_f2c_ser ser) req_c2f_ser addr mon - (client_request_handler_at_follower db) - -let sync_loop ch db log mon : unit = - let rec aux () = - let i = log_next log in - send ch i; - let rep = recv ch in + run_server (rep_f2c_ser ser) req_c2f_ser addr + (fun req -> client_request_handler_at_follower db mon req) + +let sync_loop db log mon rpc n : unit = + let rec aux i = + let rep = make_request rpc i in let ((k, v), j) = rep in assert (i = j); monitor_acquire mon; - log_add_entry log (k,v); + log_add_entry log ((k,v), j); db := map_insert k v !db; monitor_release mon; - aux () - in aux () + aux (i + 1) + in aux n let sync_with_server (ser[@metavar]) l_addr f2l_addr db log mon : unit = - let skt = make_client_skt req_f2l_ser (rep_l2f_ser ser) f2l_addr in - let ch = connect skt l_addr in - sync_loop ch db log mon + let rpc = init_client_proxy req_f2l_ser (rep_l2f_ser ser) f2l_addr l_addr in + fork (sync_loop db log mon rpc) 0 (** Initialization of the follower. *) let init_follower (ser[@metavar]) l_addr f2l_addr f_addr = @@ -151,36 +143,12 @@ let init_follower (ser[@metavar]) l_addr f2l_addr f_addr = sync_with_server ser l_addr f2l_addr db log mon; start_follower_processing_clients ser f_addr db mon -(* -------------------------------------------------------------------------- *) -(** Client Proxies. *) -(* -------------------------------------------------------------------------- *) - -let request (ch : ('a, 'b) chan_descr) (lk : Mutex.t) (req : 'a) : 'b = - acquire lk; - send ch req; - let msg = recv ch in - release lk; - msg - -let init_client_leader_proxy (ser[@metavar]) clt_addr srv_addr = - let skt = make_client_skt - (req_c2l_ser ser) - (rep_l2c_ser ser) clt_addr in - let ch = connect skt srv_addr in - let lk = newlock () in - let write k v = - match request ch lk (InjL (k, v)) with - | InjL _u -> () - | InjR _abs -> assert false in - let read k = - match request ch lk (InjR k) with - | InjL _abs -> assert false - | InjR r -> r - in (write, read) - -let init_client_follower_proxy (ser[@metavar]) clt_addr f_addr = - let skt = make_client_skt req_c2f_ser (rep_f2c_ser ser) clt_addr in - let ch = connect skt f_addr in +let init_client_follower_proxy (ser[@metavar]) clt_addr srv_addr = + let rpc = init_client_proxy req_c2f_ser (rep_f2c_ser ser) clt_addr srv_addr in let lk = newlock () in - let read k = request ch lk k in - read + let reqf req = + acquire lk; + let res = make_request rpc req in + release lk; + res in + reqf diff --git a/ml_sources/examples/reliable_communication/lib/repdb/repdb_code.mli b/ml_sources/examples/reliable_communication/lib/repdb/repdb_code.mli new file mode 100644 index 0000000..d0d9e12 --- /dev/null +++ b/ml_sources/examples/reliable_communication/lib/repdb/repdb_code.mli @@ -0,0 +1,8 @@ +open !Ast + +val init_leader : 'a serializer -> saddr -> saddr -> unit +val init_follower : 'a serializer -> saddr -> saddr -> saddr -> unit +val init_client_leader_proxy : 'a serializer -> saddr -> saddr -> + (string -> 'a -> unit) * (string -> 'a option) +val init_client_follower_proxy : 'a serializer -> saddr -> saddr -> + (string -> 'a option) -- GitLab