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