Timings for config_proof.v
- /home/gitlab-runner/builds/v6HyzL39/0/coq/coq/_bench/opam.OLD/ocaml-OLD/.opam-switch/build/coq-perennial.dev/./src/program_proof/vrsm/configservice/config_proof.v.timing
- /home/gitlab-runner/builds/v6HyzL39/0/coq/coq/_bench/opam.NEW/ocaml-NEW/.opam-switch/build/coq-perennial.dev/./src/program_proof/vrsm/configservice/config_proof.v.timing
From Perennial.program_proof Require Import grove_prelude.
From iris.algebra Require Import dfrac_agree mono_list.
From Perennial.program_proof Require Import marshal_stateless_proof std_proof.
From Perennial Require Import config_marshal_proof vrsm.renewable_lease.
From Perennial.program_proof.grove_shared Require Import urpc_proof.
From iris.base_logic Require Import lib.ghost_var mono_nat.
From Perennial Require Import paxos.start_proof paxos.weakread_proof paxos.tryacquire_proof paxos.init_proof.
From Goose.github_com.mit_pdos.gokv.vrsm Require Export configservice.
From Perennial.goose_lang Require Import crash_borrow crash_modality.
Record t :=
mk {
epoch : u64 ;
reservedEpoch : u64 ;
leaseExpiration : u64 ;
wantLeaseToExpire : bool ;
config : list u64 ;
}.
Definition encode (x:t) : list u8 :=
u64_le x.(epoch) ++
u64_le x.(reservedEpoch) ++
u64_le x.(leaseExpiration) ++
u64_le (if x.(wantLeaseToExpire) then U64 1 else U64 0) ++
(u64_le (length x.(config)) ++ concat (u64_le <$> x.(config))).
Lemma list_u64_to_byte_inj a b :
concat (u64_le <$> a) = concat (u64_le <$> b) → a = b.
rewrite fmap_cons concat_cons.
rewrite fmap_cons concat_cons in H.
apply app_inj_1 in H as [? H]; last done.
apply (f_equal le_to_u64) in H0.
by repeat rewrite u64_le_to_word in H0.
Global Instance encode_inj : Inj eq eq encode.
apply app_inj_1 in H as [? H]; last done.
apply app_inj_1 in H as [? H]; last done.
apply app_inj_1 in H as [? H]; last done.
apply app_inj_1 in H as [? H]; last done.
apply (f_equal le_to_u64) in H0, H1, H2.
repeat rewrite u64_le_to_word in H0, H1, H2.
by destruct wantLeaseToExpire0, wantLeaseToExpire1.
apply app_inj_1 in H as [? H]; last done.
by apply list_u64_to_byte_inj.
Definition own (l:loc) (x:t) : iProp Σ :=
∃ conf_sl,
"Hepoch" ∷ l ↦[state :: "epoch"] #x.(epoch) ∗
"HreservedEpoch" ∷ l ↦[state :: "reservedEpoch"] #x.(reservedEpoch) ∗
"HleaseExpiration" ∷ l ↦[state :: "leaseExpiration"] #x.(leaseExpiration) ∗
"HwantLeaseToExpire" ∷ l ↦[state :: "wantLeaseToExpire"] #x.(wantLeaseToExpire) ∗
"Hconf" ∷ l ↦[state :: "config"] (slice_val conf_sl) ∗
"#Hconf_sl" ∷ readonly (own_slice_small conf_sl uint64T 1 x.(config))
.
Lemma wp_decode (x:t) sl q :
{{{
own_slice_small sl byteT q (encode x)
}}}
decodeState (slice_val sl)
{{{
l, RET #l; own l x
}}}
.
wp_apply (wp_allocStruct); first by val_ty.
iDestruct (struct_fields_split with "Hl") as "HH".
wp_apply (wp_ref_to); first by val_ty.
wp_apply (wp_ReadInt with "[$]").
wp_apply (wp_ReadInt with "[$]").
wp_apply (wp_ReadInt with "[$]").
wp_apply (wp_ref_of_zero); first done.
wp_apply (wp_ReadInt with "[$]").
wp_apply (Config.wp_Decode with "[$Hsl]").
by destruct x, wantLeaseToExpire; iFrame.
Lemma wp_encode l (x:t) :
{{{
own l x
}}}
encodeState #l
{{{
sl, RET (slice_val sl); own_slice_small sl byteT 1 (encode x) ∗
own l x
}}}
.
wp_apply (wp_ref_of_zero); first done.
change (slice.nil) with (slice_val Slice.nil).
wp_apply (wp_WriteInt with "[]").
wp_apply (wp_WriteInt with "[$]").
wp_apply (wp_WriteInt with "[$]").
wp_apply (wp_WriteInt with "[$]").
wp_apply (Config.wp_Encode with "[]").
iIntros (??) "(%Henc & _ & HconfEnc)".
iDestruct (own_slice_to_small with "HconfEnc") as "HconfEnc".
wp_apply (wp_WriteBytes with "[$Hsl $HconfEnc]").
iApply own_slice_to_small.
rewrite /encode Heqb -app_assoc.
repeat iExists _; iFrame "∗#".
wp_apply (wp_WriteInt with "[$]").
wp_apply (Config.wp_Encode with "[]").
iIntros (??) "(%Henc & _ & HconfEnc)".
iDestruct (own_slice_to_small with "HconfEnc") as "HconfEnc".
wp_apply (wp_WriteBytes with "[$Hsl $HconfEnc]").
iApply own_slice_to_small.
rewrite /encode Heqb -app_assoc.
repeat iExists _; iFrame "∗#".
Definition config_server_names := mp_server_names.
Record config_names :=
{
epoch_gn:gname ;
repoch_gn:gname ;
config_val_gn:gname ;
paxos_gn:paxos_system_names ;
}.
Class t Σ :=
mk {
Pwf : list u64 → iProp Σ ;
Ntop: namespace ;
initconfig : list u64 ;
HPwf_into_crash : ∀ (hG: heapGS Σ), IntoCrash (□ Pwf initconfig)%I (λ hG', □ Pwf initconfig)%I ;
}
.
Class configG Σ := {
config_configG :> ghost_varG Σ (list u64) ;
config_urpcG :> urpcregG Σ ;
config_epochG :> mono_natG Σ ;
config_paxosG :> paxosG Σ ;
config_leaseG :> renewable_leaseG Σ ;
}.
Definition configΣ := #[mono_natΣ ; paxosΣ ; ghost_varΣ (list u64) ; urpcregΣ ; renewable_leaseΣ ].
Global Instance subG_configΣ {Σ} : subG configΣ Σ → configG Σ.
Implicit Type γ : config_names.
Context `{!gooseGlobalGS Σ}.
Context `{params:configParams.t Σ}.
(*
Context `{!Pwf.t Σ}.
Context `{ppeers:!peers.t}.
Context `{pconf:!init.t}.
Context `{pNtop:!Ntop.t}. *)
Definition own_latest_epoch γ (epoch:u64) : iProp Σ :=
mono_nat_auth_own γ.(epoch_gn) (1/2) (int.nat epoch).
Definition own_reserved_epoch γ (epoch:u64) : iProp Σ :=
mono_nat_auth_own γ.(repoch_gn) (1/2) (int.nat epoch).
Definition is_reserved_epoch_lb γ (epoch:u64) : iProp Σ :=
mono_nat_lb_own γ.(repoch_gn) (int.nat epoch).
Definition own_config γ (conf:list u64) : iProp Σ :=
ghost_var γ.(config_val_gn) (1/2) conf
.
Definition N := Ntop .@ "sub".
Definition epochLeaseN := N .@ "epochLeaseN".
Program Definition ReserveEpochAndGetConfig_core_spec γ Φ :=
(
£ 1 -∗
(|={⊤∖↑N,∅}=> ∃ reservedEpoch conf, own_reserved_epoch γ reservedEpoch ∗ own_config γ conf ∗
(⌜int.nat reservedEpoch < int.nat (word.add reservedEpoch (U64 1))⌝ -∗
own_reserved_epoch γ (word.add reservedEpoch (U64 1)) -∗ own_config γ conf ={∅,⊤∖↑N}=∗
Φ (word.add reservedEpoch 1) conf
))
)%I.
Program Definition GetConfig_core_spec γ Φ :=
(∀ conf, Pwf conf -∗ Φ conf)%I.
Program Definition TryWriteConfig_core_spec γ (epoch:u64) (new_conf:list u64) Φ : iProp Σ :=
is_reserved_epoch_lb γ epoch ∗
(□ Pwf new_conf) ∗
(£ 1 -∗ |={⊤∖↑N,∅}=> ∃ latest_epoch reserved_epoch conf,
own_latest_epoch γ latest_epoch ∗
own_reserved_epoch γ reserved_epoch ∗
own_config γ conf ∗
(⌜ reserved_epoch = epoch ⌝ -∗
own_config γ new_conf -∗
own_reserved_epoch γ reserved_epoch -∗
own_latest_epoch γ epoch ={∅,⊤∖↑N}=∗ Φ (U64 0))
) ∗
(∀ (err:u64), ⌜err ≠ 0⌝ → Φ err)
.
Program Definition GetLease_core_spec γ (epoch:u64) Φ : iProp Σ :=
(∀ (leaseExpiration:u64) γl,
is_lease epochLeaseN γl (own_latest_epoch γ epoch) -∗
is_lease_valid_lb γl leaseExpiration -∗ Φ (U64 0) leaseExpiration
) ∧
(∀ (err:u64), ⌜err ≠ 0⌝ → Φ err (U64 0))
.
Program Definition ReserveEpochAndGetConfig_spec γ :=
λ (encoded_args:list u8), λne (Φ : list u8 -d> iPropO Σ) ,
( (* no args *)
ReserveEpochAndGetConfig_core_spec γ (λ newEpoch conf,
∀ enc_conf,
⌜Config.has_encoding enc_conf conf⌝ -∗
Φ (u64_le 0 ++ u64_le newEpoch ++ enc_conf)
) ∗
(∀ err, ⌜ err ≠ U64 0 ⌝ -∗ Φ (u64_le err))
)%I.
rewrite /ReserveEpochAndGetConfig_core_spec.
Program Definition GetConfig_spec γ :=
λ (encoded_args:list u8), λne (Φ : list u8 -d> iPropO Σ) ,
( (* no args *)
GetConfig_core_spec γ (λ conf, ∀ reply,
⌜Config.has_encoding reply conf⌝ -∗
Φ reply
)
)%I.
Program Definition TryWriteConfig_spec γ :=
λ (enc_args:list u8), λne (Φ : list u8 -d> iPropO Σ) ,
( ∃ epoch new_conf enc_new_conf,
⌜enc_args = u64_le epoch ++ enc_new_conf⌝ ∗
⌜Config.has_encoding enc_new_conf new_conf⌝ ∗
TryWriteConfig_core_spec γ epoch new_conf (λ err, ∀ reply,
⌜reply = u64_le err⌝ -∗
Φ reply
)
)%I.
unfold TryWriteConfig_core_spec.
Program Definition GetLease_spec γ :=
λ (enc_args:list u8), λne (Φ : list u8 -d> iPropO Σ) ,
( ∃ epoch ,
⌜enc_args = u64_le epoch⌝ ∗
GetLease_core_spec γ epoch (λ (err:u64) (leaseExpiration:u64), ∀ reply,
⌜reply = u64_le err ++ u64_le leaseExpiration⌝ -∗
Φ reply
)
)%I.
unfold GetLease_core_spec.
Definition is_config_host (host:u64) γ : iProp Σ :=
∃ γrpc,
"#H0" ∷ is_urpc_spec_pred γrpc host (U64 0) (ReserveEpochAndGetConfig_spec γ) ∗
"#H1" ∷ is_urpc_spec_pred γrpc host (U64 1) (GetConfig_spec γ) ∗
"#H2" ∷ is_urpc_spec_pred γrpc host (U64 2) (TryWriteConfig_spec γ) ∗
"#H3" ∷ is_urpc_spec_pred γrpc host (U64 3) (GetLease_spec γ) ∗
"#Hdom" ∷ is_urpc_dom γrpc {[ (U64 0) ; (U64 1) ; (U64 2) ; (U64 3) ]}
.
Definition configN := N .@ "paxos".
Definition configPaxosN := configN .@ "paxos".
Definition configInvN := configN .@ "inv".
Definition own_Config_ghost γ (st:state.t) : iProp Σ :=
∃ γl,
"Hconf_ghost" ∷ own_config γ st.(state.config) ∗
"Hreserved_ghost" ∷ own_reserved_epoch γ st.(state.reservedEpoch) ∗
"Hlatest_epoch" ∷ post_lease epochLeaseN γl (own_latest_epoch γ st.(state.epoch)) ∗
"HleaseExp" ∷ own_lease_expiration γl st.(state.leaseExpiration) ∗
"%HresIneq" ∷ ⌜ int.nat st.(state.epoch) <= int.nat st.(state.reservedEpoch) ⌝
.
Definition is_config_inv γ : iProp Σ :=
inv configInvN (∃ st,
"Hst" ∷ own_state γ.(paxos_gn) (state.encode st) ∗
"Hghost" ∷ own_Config_ghost γ st
)
.
Definition configWf (a:list u8) : iProp Σ :=
∃ st, ⌜ a = state.encode st ⌝ ∗ □ Pwf st.(state.config)
.
Definition initstate : list u8 :=
state.encode (state.mk 0 0 0 false initconfig ).
Local Instance pParams : paxosParams.t Σ :=
paxosParams.mk Σ initstate configWf configPaxosN.
Definition config_crash_resources γ (γsrv:config_server_names) d : iProp Σ :=
own_file_inv γ.(paxos_gn) γsrv d
.
Definition is_config_invs γ : iProp Σ :=
"#Hconfig_inv" ∷ is_config_inv γ
.
Definition is_config_server_host me paxosMe γ γsrv : iProp Σ :=
"#Hinvs" ∷ is_config_invs γ ∗
"#HhostConf" ∷ is_config_host me γ ∗
"#HhostPaxos" ∷ is_paxos_server_host paxosMe γ.(paxos_gn) γsrv
.
(* XXX: maybe use is_config_server_host? *)
Definition is_config_peers (paxosHosts: list u64) γ : iProp Σ :=
is_paxos_hosts paxosHosts γ.(paxos_gn).
Definition is_config_hosts (hosts: list u64) γ : iProp Σ :=
"#Hhosts" ∷ ([∗ list] host ∈ hosts, is_config_host host γ) ∗
"%Hnonempty" ∷ ⌜ 0 < length hosts ⌝
.
Context `{params:configParams.t Σ}.
Existing Instance pParams.
Definition is_Server (s:loc) γ : iProp Σ :=
∃ (p:loc) γsrv,
"#Hs" ∷ readonly (s ↦[Server :: "s"] #p) ∗
"#Hsrv" ∷ is_Server p γ.(paxos_gn) γsrv ∗
"#Hconfig_inv" ∷ is_config_inv γ
.
Definition own_tryRelease (f:val) γ (st_ptr:loc) (oldst:state.t) : iProp Σ :=
∀ (newst:state.t) Φ,
(
"Hvol" ∷ state.own st_ptr newst ∗
"#Hwf" ∷ □ Pwf newst.(state.config) ∗
"Hupd" ∷ (own_Config_ghost γ oldst ={⊤∖↑configN}=∗ own_Config_ghost γ newst ∗ Φ #true)
) -∗
(Φ #false) -∗
WP f #() {{ Φ }}
.
Lemma wp_Server__tryAcquire s γ :
{{{
is_Server s γ
}}}
Server__tryAcquire #s
{{{
(ok:bool) (st_ptr:loc) (f:val), RET (#ok, #st_ptr, f);
if ok then
∃ st,
□ Pwf st.(state.config) ∗
state.own st_ptr st ∗
own_tryRelease f γ st_ptr st
else
True
}}}
.
wp_apply (wp_Server__TryAcquire with "[$]").
setoid_rewrite decide_True.
iDestruct "Hpost" as (??) "(Hsl_ptr & #Hsl & HP & Hwp)".
iMod (readonly_load with "Hsl") as (?) "Hsl2".
iDestruct "HP" as (?) "[%Henc #HP]".
wp_apply (state.wp_decode with "[$Hsl2]").
wp_apply (state.wp_encode with "[$]").
iMod (readonly_alloc_1 with "Hsl") as "Hsl".
wp_apply ("Hwp" with "[-HΦ]").
iInv "Hconfig_inv" as "Hi" "Hclose".
iMod (lc_fupd_elim_later with "Hlc Hi") as "Hi".
iMod (fupd_mask_subseteq _) as "Hmask".
2: iMod ("Hupd" with "[$]") as "[Hghost Hupd]".
iMod ("Hclose" with "[Hghost Hst]").
repeat iExists _; iFrame.
rewrite bool_decide_false.
Lemma wp_Server__ReserveEpochAndGetConfig (server:loc) γ :
{{{
is_Server server γ
}}}
Server__ReserveEpochAndGetConfig #server
{{{
(f:val), RET f; is_urpc_handler_pred f (ReserveEpochAndGetConfig_spec γ)
}}}.
iIntros (Φ) "#His_srv HΦ".
unfold is_urpc_handler_pred.
iIntros (enc_args Ψ req_sl rep_ptr) "!# %Φ (Harg_sl & Hrep & HΨ) HΦ".
replace (slice.nil) with (slice_val Slice.nil) by done.
wp_apply (wp_WriteInt with "[]").
iIntros (rep_sl) "Hrep_sl".
wp_apply (wp_Server__tryAcquire with "[$]").
(* if not ok from tryAcquire *)
iDestruct (own_slice_to_small with "Hrep_sl") as "$".
rewrite /ReserveEpochAndGetConfig_spec /ReserveEpochAndGetConfig_core_spec /=.
iDestruct "Hpost" as (?) "(#HP & Hvol & Hwp)".
wp_apply wp_SumAssumeNoOverflow.
iDestruct "HΨ" as "[HΨ1 Hfail]".
wp_apply (wp_frame_wand with "[HΦ Hrep Hrep_sl]").
wp_apply ("Hwp" with "[-Hfail] [Hfail]").
iSplitL "Hepoch HreservedEpoch HleaseExpiration HwantLeaseToExpire Hconf Hconf_sl".
instantiate (1:=state.mk _ _ _ _ _).
repeat iExists _; simpl; iFrame "∗#".
(* start ghost reasoning *)
rewrite /ReserveEpochAndGetConfig_core_spec.
iMod (fupd_mask_subseteq _) as "Hmask".
2: iMod ("HΨ1" with "[$]") as (??) "(Hres & Hconf & Hupd)".
iCombine "Hconf Hconf_ghost" gives %[_ H].
rewrite /own_reserved_epoch.
iDestruct (mono_nat_auth_own_agree with "Hres [$]") as %[? H].
apply Z2Nat.inj in H; try word.
eapply (inj (R:=eq)) in H.
iCombine "Hres Hreserved_ghost" as "Hres".
(* FIXME: combine instance for mono_nat_auth_own *)
iMod (mono_nat_own_update with "Hres") as "[[Hres1 Hres2] _]".
iMod ("Hupd" with "[%] [$] [$]") as "HΨ".
(* end ghost reasoning *)
wp_apply (wp_NewSliceWithCap).
apply encoding.unsigned_64_nonneg.
wp_apply (wp_WriteInt with "[$]").
iIntros (enc_sl) "Hrep_sl".
wp_apply (wp_WriteInt with "[$]").
wp_apply (Config.wp_Encode with "[Hconf_sl]").
iIntros (enc_conf enc_conf_sl) "(%Hconf_enc & _ & Henc_conf_sl)".
wp_apply (wp_WriteBytes with "[$Hrep_sl Henc_conf_sl]").
iDestruct (own_slice_to_small with "Henc_conf_sl") as "$".
iIntros (?) "[Hrep_sl Henc_conf_sl]".
replace (int.nat 0%Z) with 0%nat by word.
iDestruct (own_slice_to_small with "Hrep_sl") as "?".
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
Lemma wp_Server__GetConfig (server:loc) γ :
{{{
is_Server server γ
}}}
Server__GetConfig #server
{{{
(f:val), RET f; is_urpc_handler_pred f (GetConfig_spec γ)
}}}.
iIntros (Φ) "#His_srv HΦ".
unfold is_urpc_handler_pred.
iIntros (enc_args Ψ req_sl rep_ptr) "!# %Φ (Harg_sl & Hrep & HΨ) HΦ".
wp_apply (wp_Server__WeakRead with "[$]").
iIntros (??) "[#Hsl HP]".
iDestruct "HP" as (?) "[%H HP]".
iMod (readonly_load with "Hsl") as (?) "Hsl2".
wp_apply (state.wp_decode with "[$]").
wp_apply (Config.wp_Encode with "[$]").
iIntros (??) "(%Henc & _ & Henc)".
iDestruct (own_slice_to_small with "Henc") as "Henc".
iApply ("HΨ" with "HP [//]").
Lemma wp_Server__TryWriteConfig (server:loc) γ :
{{{
is_Server server γ
}}}
Server__TryWriteConfig #server
{{{
(f:val), RET f; is_urpc_handler_pred f (TryWriteConfig_spec γ)
}}}.
iIntros (Φ) "#His_srv HΦ".
unfold is_urpc_handler_pred.
iIntros (enc_args Ψ req_sl rep_ptr) "!# %Φ (Harg_sl & Hrep & HΨ) HΦ".
iDestruct "HΨ" as (new_epoch new_conf enc_new_conf) "(%Henc & %Henc_conf & HΨ)".
change (slice.nil) with (slice_val Slice.nil).
wp_apply (wp_WriteInt with "[]").
wp_apply (wp_ReadInt with "Harg_sl").
iIntros (args_sl) "Hargs_sl".
wp_apply (Config.wp_Decode with "[$Hargs_sl]").
wp_apply (wp_Server__tryAcquire with "[$]").
iDestruct "HΨ" as "(#Hepoch_lb & #HP_new & HΨ)".
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iDestruct "Hpost" as (?) "(#HP & Hvol & Hwp)".
(* case: higher epoch is reserved *)
wp_apply (wp_frame_wand with "[HΨ HΦ Hrep_sl Hrep]").
wp_apply ("Hwp" with "[-]").
(* case: committed update, which was actually not even an update. *)
iSplitL "Hepoch HreservedEpoch HleaseExpiration HwantLeaseToExpire Hconf".
repeat iExists _; iFrame "∗#".
wp_apply (wp_WriteInt with "[]").
iIntros (rep_sl) "Hrep_sl2".
iDestruct (own_slice_to_small with "Hrep_sl2") as "Hrep_sl2".
iApply "HΨ"; last done; done.
(* case: (non-)update failed to be committed *)
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iApply "HΨ"; last done; done.
(* case: try to enter new epoch *)
wp_apply wp_GetTimeRange.
iDestruct (own_time_get_lb with "Htime") as "#Hlb".
(* case: lease is expired, so can activate new epoch right now *)
iDestruct "Hargs_state_sl" as "#Hconf_sl".
iDestruct "HΨ" as "[HΨ Hfail]".
wp_apply (wp_frame_wand with "[HΦ Hrep Hrep_sl]"); first iNamedAccu.
wp_apply ("Hwp" with "[-Hfail]").
(* case: committed update. *)
iSplitL "Hepoch HreservedEpoch HleaseExpiration HwantLeaseToExpire Hconf".
instantiate (1:=state.mk _ _ _ _ _).
repeat iExists _; simpl; iFrame "∗#".
(* start ghost reasoning *)
iMod (fupd_mask_subseteq _) as "Hmask".
2: iMod (lease_expire with "[$] [$] []") as ">Hepoch_ghost".
iApply (is_time_lb_mono with "[$]").
iMod (fupd_mask_subseteq _) as "Hmask".
2: iMod ("HΨ" with "Hlc") as "HΨ".
iDestruct "HΨ" as (???) "(Hepoch_ghost2 & Hres2 & Hconf_ghost2 & Hupd)".
iDestruct (mono_nat_auth_own_agree with "Hreserved_ghost Hres2") as %[_ ?].
assert (reserved_epoch = st.(state.reservedEpoch)) by word; subst.
iDestruct (mono_nat_auth_own_agree with "Hepoch_ghost Hepoch_ghost2") as %[_ Heq].
assert (latest_epoch = st.(state.epoch)) by word; subst.
iCombine "Hepoch_ghost Hepoch_ghost2" as "Hepoch_ghost".
iMod (mono_nat_own_update (int.nat new_epoch) with "Hepoch_ghost") as "[[Hepoch_ghost Hepoch_ghost2] _]".
iDestruct (ghost_var_agree with "Hconf_ghost Hconf_ghost2") as %->.
iCombine "Hconf_ghost Hconf_ghost2" as "Hconf_ghost".
iMod (ghost_var_update new_conf with "Hconf_ghost") as "[Hconf_ghost Hconf_ghost2]".
iDestruct (mono_nat_lb_own_valid with "Hreserved_ghost Hepoch_lb") as %[_ Hineq].
iMod ("Hupd" with "[] Hconf_ghost2 Hres2 Hepoch_ghost2") as "HΨ".
iMod (fupd_mask_subseteq _) as "Hmask".
2: iMod (lease_alloc _ epochLeaseN with "Hepoch_ghost") as (?) "(_ & Hlatest_epoch & HleaseExp)".
repeat rewrite sep_exist_r.
(* end ghost reasoning *)
wp_apply (wp_WriteInt with "[]").
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
(* case: unable to commit update *)
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iApply "Hfail"; last done; done.
(* case: lease is not expired, so mark that we want to expire it and sleep *)
iDestruct "HΨ" as "[HΨ Hfail]".
wp_apply (wp_frame_wand with "[HΦ Hrep Hrep_sl Hfail]"); first iNamedAccu.
wp_apply ("Hwp" with "[-]").
(* rsm update successful *)
repeat rewrite sep_exist_r.
instantiate (1:=state.mk _ _ _ _ _).
iExists _; simpl; iFrame "∗#".
(* unable to update rsm *)
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iApply "Hfail"; last done; done.
(* case: already entered the new epoch *)
iDestruct "HΨ" as "[HΨ Hfail]".
wp_apply (wp_frame_wand with "[HΦ Hfail Hrep Hrep_sl]"); first iNamedAccu.
wp_apply ("Hwp" with "[-]").
(* case: successful paxos write *)
repeat rewrite sep_exist_r.
instantiate (1:=state.mk _ _ _ _ _).
iExists _; simpl; iFrame "∗#".
iMod (post_lease_acc with "Hlatest_epoch") as "[>Hlatest_epoch Hclose]".
iMod (fupd_mask_subseteq _) as "Hmask".
2: iMod ("HΨ" with "[$]") as "HΨ".
iDestruct "HΨ" as (???) "(Hepoch_ghost2 & Hres2 & Hconf_ghost2 & HΨ)".
iDestruct (mono_nat_auth_own_agree with "Hreserved_ghost Hres2") as %[_ ?].
assert (reserved_epoch = st.(state.reservedEpoch)) by word; subst.
iDestruct (mono_nat_auth_own_agree with "Hlatest_epoch Hepoch_ghost2") as %[_ ?].
assert (latest_epoch = st.(state.epoch)) by word; subst.
iDestruct (ghost_var_agree with "Hconf_ghost Hconf_ghost2") as %->.
iCombine "Hconf_ghost Hconf_ghost2" as "Hconf_ghost".
iMod (ghost_var_update new_conf with "Hconf_ghost") as "[Hconf_ghost Hconf_ghost2]".
replace (new_epoch) with (st.(state.epoch)) by word.
iMod ("HΨ" with "[] Hconf_ghost2 Hres2 Hepoch_ghost2") as "HΨ".
iMod ("Hclose" with "[$]") as "Hlatest_epoch".
repeat rewrite sep_exist_r.
iExists _; simpl; iFrame "∗#".
wp_apply (wp_WriteInt with "[]").
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
(* case: paxos write failed *)
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iApply "Hfail"; last done; done.
Lemma wp_Server__GetLease (server:loc) γ :
{{{
is_Server server γ
}}}
Server__GetLease #server
{{{
(f:val), RET f; is_urpc_handler_pred f (GetLease_spec γ)
}}}.
iIntros (Φ) "#His_srv HΦ".
unfold is_urpc_handler_pred.
iIntros (enc_args Ψ req_sl rep_ptr) "!# %Φ (Harg_sl & Hrep & HΨ) HΦ".
iDestruct "HΨ" as (?) "[% HΨ]".
change (slice.nil) with (slice_val Slice.nil).
wp_apply (wp_WriteInt with "[]").
wp_apply (wp_WriteInt with "[$Hrep_sl]").
wp_apply (wp_ReadInt with "Harg_sl").
wp_apply (wp_Server__tryAcquire with "[$]").
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iDestruct "Hpost" as (?) "(#HP & Hvol & Hwp)".
wp_apply (wp_or with "[HwantLeaseToExpire]").
by rewrite -bool_decide_not.
instantiate (2:=(st.(state.wantLeaseToExpire) = true)).
by destruct st, wantLeaseToExpire.
(* case: epoch number that the caller wants is not the latest epoch, or wantToExpireLease *)
wp_apply (wp_frame_wand with "[HΨ HΦ Hrep_sl Hrep]"); first iNamedAccu.
wp_apply ("Hwp" with "[-]").
(* case: committed (non-)update *)
repeat rewrite sep_exist_r.
wp_apply (wp_WriteInt with "[]").
wp_apply (wp_WriteInt with "[$Hrep_sl]").
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iApply "HΨ"; last done; done.
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iApply "HΨ"; last done; done.
(* case: epoch matches *)
assert (epoch = st.(state.epoch)); last subst.
apply Decidable.not_or in Heqb.
wp_apply wp_GetTimeRange.
wp_bind (if: #_ then _ else _)%E.
wp_apply (wp_wand with "[HleaseExpiration]").
instantiate (1:=(λ _, ∃ (newLeaseExpiration:u64),
"%Hineq1" ∷ ⌜ int.nat st.(state.leaseExpiration) <= int.nat newLeaseExpiration⌝ ∗
"%Hineq2" ∷ ⌜ int.nat (word.add l 1000000000%Z) <=
int.nat newLeaseExpiration⌝ ∗
"HleaseExpiration" ∷ st_ptr ↦[state :: "leaseExpiration"] #newLeaseExpiration )%I).
apply Z2Nat.inj_le; try apply encoding.unsigned_64_nonneg.
apply Z2Nat.inj_le; try apply encoding.unsigned_64_nonneg.
apply Z2Nat.inj_le; try apply encoding.unsigned_64_nonneg.
wp_apply (wp_frame_wand with "[HΨ HΦ Hrep Hrep_sl]"); first iNamedAccu.
wp_apply ("Hwp" with "[-]").
(* successfully commit paxos write *)
repeat rewrite sep_exist_r.
instantiate (1:=state.mk _ _ _ _ _).
(* start ghost reasoning *)
iMod (fupd_mask_subseteq _) as "Hmask".
2: iMod (lease_renew newLeaseExpiration with "[$] [$]") as "[Hlatest_epoch HleaseExp]".
iDestruct (post_get_lease with "[$]") as "#Hlease".
iDestruct (lease_get_lb with "[$]") as "#Hlb".
iDestruct (lease_lb_mono with "[$]") as "#Hlb2".
repeat rewrite sep_exist_r.
(* end ghost reasoning *)
iDestruct ("HΨ" with "[$] [$]") as "HΨ".
wp_apply (wp_WriteInt with "[]").
wp_apply (wp_WriteInt with "[$Hrep_sl]").
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
(* case: paxos write failed *)
iDestruct (own_slice_to_small with "Hrep_sl") as "Hrep_sl".
iApply "HΨ"; last done; done.
Definition own_Clerk_inv (ck:loc) l : iProp Σ :=
∃ (leader:u64),
"Hleader" ∷ ck ↦[Clerk :: "leader"] #leader ∗
"%HleaderBound" ∷ ⌜ int.nat leader < l ⌝
.
Definition is_Clerk (ck:loc) γ : iProp Σ :=
∃ mu cls_sl (cls:list loc),
"#Hmu" ∷ readonly (ck ↦[Clerk :: "mu"] mu) ∗
"#HmuInv" ∷ is_lock N mu (own_Clerk_inv ck (length cls)) ∗
"#Hcls" ∷ readonly (ck ↦[Clerk :: "cls"] (slice_val cls_sl)) ∗
"#Hcls_sl" ∷ readonly (own_slice_small cls_sl ptrT 1 cls) ∗
"#Hrpc" ∷ ([∗ list] cl ∈ cls, ∃ srv, is_ReconnectingClient cl srv ∗ is_config_host srv γ) ∗
"%HszNonzero" ∷ ⌜ length cls > 0 ⌝
.
Lemma wp_MakeClerk hosts hosts_sl γ:
{{{
"Hhosts_sl" ∷ readonly (own_slice_small hosts_sl uint64T 1 hosts) ∗
"#Hhosts" ∷ is_config_hosts hosts γ
}}}
MakeClerk (slice_val hosts_sl)
{{{
ck, RET #ck; is_Clerk ck γ
}}}
.
iIntros (cls_ptr) "Hcls".
iMod (readonly_load with "Hhosts_sl") as (?) "Hhosts_sl".
iDestruct (own_slice_small_sz with "Hhosts_sl") as %Hsz.
wp_apply (wp_forSlice'
(λ i,
∃ sl cls,
"Hcls" ∷ cls_ptr ↦[slice.T ptrT] (slice_val sl) ∗
"Hcls_sl" ∷ own_slice sl ptrT 1 (cls) ∗
"#Hrpc" ∷ ([∗ list] cl ∈ cls, ∃ srv : u64, is_ReconnectingClient cl srv ∗ is_config_host srv γ) ∗
"%Hsz" ∷ ⌜ length cls = int.nat i ⌝
)%I
with "[] [Hcls Hcls_sl $Hhosts_sl]").
iIntros (???) "!# Hpre HΦ".
iDestruct "Hpre" as "(%Hineq & %Hlookup & #Hhost & Hpre)".
wp_apply wp_MakeReconnectingClient.
wp_bind (SliceAppend _ _ _).
change (#cl_ptr) with (loc_IntoVal.(to_val) cl_ptr).
wp_apply (wp_SliceAppend with "[$Hcls_sl]").
repeat iExists _; iFrame.
iApply (big_sepL_app with "[]").
iApply big_sepL_singleton.
wp_apply wp_new_free_lock.
iDestruct (struct_fields_split with "Hc") as "HH".
iMod (readonly_alloc_1 with "mu") as "$".
iMod (readonly_alloc_1 with "cls") as "$".
iDestruct (own_slice_to_small with "Hcls_sl") as "Hcls_sl".
iMod (readonly_alloc_1 with "Hcls_sl") as "$".
iMod (alloc_lock with "HmuInv [leader]") as "$".
repeat iExists _; iFrame.
Lemma wp_Clerk__ReserveEpochAndGetConfig (ck:loc) γ Φ :
is_Clerk ck γ -∗
□ (£ 1 -∗
(|={⊤∖↑N,∅}=> ∃ epoch conf, own_reserved_epoch γ epoch ∗ own_config γ conf ∗
(⌜int.nat epoch < int.nat (word.add epoch (U64 1))⌝ -∗
own_reserved_epoch γ (word.add epoch (U64 1)) -∗ own_config γ conf ={∅,⊤∖↑N}=∗
(∀ conf_sl, readonly (own_slice_small conf_sl uint64T 1 conf) -∗
Φ (#(LitInt $ word.add epoch (U64 1)), slice_val conf_sl)%V)))
) -∗
WP Clerk__ReserveEpochAndGetConfig #ck {{ Φ }}
.
iIntros (reply_ptr) "Hreply".
iAssert ( ∃ sl,
"Hreply" ∷ reply_ptr ↦[slice.T byteT] (slice_val sl)
)%I with "[-]" as "HH".
wp_apply (acquire_spec with "[$]").
iIntros "[Hlocked Hown]".
wp_apply (release_spec with "[Hlocked Hleader]").
iDestruct (own_slice_to_small with "Hargs_sl") as "Hargs_sl".
apply list_lookup_lt in HleaderBound as [? Hlookup].
iMod (readonly_load with "Hcls_sl") as (?) "Hcls_sl2".
iDestruct (own_slice_small_sz with "Hcls_sl2") as %Hsl_sz.
wp_apply (wp_SliceGet with "[$Hcls_sl2]").
iDestruct (big_sepL_lookup with "Hrpc") as (?) "#[Hcl_rpc Hhost]".
wp_apply (wp_ReconnectingClient__Call2 with "Hcl_rpc [] Hargs_sl Hreply").
rewrite /ReserveEpochAndGetConfig_spec /ReserveEpochAndGetConfig_core_spec /=.
(* case: successfully reserved epoch *)
iDestruct ("HΦ" with "Hlc") as "Hupd".
(* case: got a new epoch, no error *)
iDestruct "Hupd" as (??) "(Ha&Hb&Hupd)".
iMod ("Hupd" with "[% //] [$] [$]") as "Hupd".
iIntros (?) "%Hconf_enc Hargs_sl".
iIntros (?) "Hrep Hrep_sl".
wp_apply (wp_ref_of_zero).
wp_apply (wp_ReadInt with "[$]").
wp_apply (wp_ref_of_zero).
iIntros (epoch_ptr) "Hepoch".
wp_apply (wp_ReadInt with "Hrep_sl").
wp_apply (Config.wp_Decode with "[$Hrep_sl]").
(* case: RPC ran, but was not able to reserve an epoch *)
iIntros (?) "Hrep Hrep_sl".
wp_apply (wp_ReadInt with "[$]").
(* case: ErrNotLeader, so retry *)
wp_apply (acquire_spec with "[$]").
iIntros "[Hlocked Hown]".
(* case: increase leader idx *)
wp_apply (release_spec with "[Hlocked Hleader]").
repeat iExists _; iFrame.
rewrite word.unsigned_modu_nowrap; last lia.
apply Z2Nat.inj_lt; auto using encoding.unsigned_64_nonneg.
(* case: don't increase leader idx *)
wp_apply (release_spec with "[Hlocked Hleader]").
repeat iExists _; iFrame "∗%".
(* case: some other error, still retry *)
iIntros (?) "%Herr Hreply_sl Hrep".
Lemma wp_Clerk__GetConfig (ck:loc) γ Φ :
is_Clerk ck γ -∗
□ (∀ conf conf_sl, Pwf conf -∗ readonly (own_slice_small conf_sl uint64T 1 conf)
-∗ Φ (slice_val conf_sl)%V) -∗
WP Clerk__GetConfig #ck {{ Φ }}
.
iIntros (reply_ptr) "Hreply".
iAssert ( ∃ sl,
"Hreply" ∷ reply_ptr ↦[slice.T byteT] (slice_val sl)
)%I with "[-]" as "HH".
wp_apply (wp_RandomUint64).
iDestruct (own_slice_to_small with "Hargs_sl") as "Hargs_sl".
iMod (readonly_load with "Hcls_sl") as (?) "Hcls_sl2".
iDestruct (own_slice_small_sz with "Hcls_sl2") as %Hsl_sz.
set (idx:=(u64_instance.u64.(word.modu) r cls_sl.(Slice.sz))).
assert (int.nat idx < length cls) as Hlookup.
rewrite word.unsigned_modu_nowrap; last lia.
apply Z2Nat.inj_lt; auto using encoding.unsigned_64_nonneg.
apply list_lookup_lt in Hlookup as [? Hlookup].
wp_apply (wp_SliceGet with "[$Hcls_sl2]").
iDestruct (big_sepL_lookup with "Hrpc") as (?) "#[Hcl_rpc Hhost]".
wp_apply (wp_ReconnectingClient__Call2 with "Hcl_rpc [] Hargs_sl Hreply").
iIntros (?) "Hrep Hreply_sl".
wp_apply (Config.wp_Decode with "[$Hreply_sl //]").
iApply ("HΦ" with "[$]").
iIntros (?) "%Herr Hreply_sl Hrep".
Lemma wp_Clerk__TryWriteConfig (ck:loc) new_conf new_conf_sl epoch γ Φ :
is_Clerk ck γ -∗
readonly (own_slice_small new_conf_sl uint64T 1 new_conf) -∗
is_reserved_epoch_lb γ epoch -∗
(□ Pwf new_conf) -∗
□ (£ 1 -∗ |={⊤∖↑N,∅}=> ∃ latest_epoch reserved_epoch conf,
own_latest_epoch γ latest_epoch ∗
own_reserved_epoch γ reserved_epoch ∗
own_config γ conf ∗ (⌜ epoch = reserved_epoch ⌝ -∗ own_config γ new_conf -∗
own_reserved_epoch γ reserved_epoch -∗
own_latest_epoch γ epoch
={∅,⊤∖↑N}=∗
Φ #0)
) -∗
(∀ (err:u64) , ⌜err ≠ 0⌝ -∗ Φ #err) -∗
WP Clerk__TryWriteConfig #ck #epoch (slice_val new_conf_sl)
{{ Φ }}
.
iIntros "#Hck #Hconf_sl #Hlb #HP_new #HΦ Hfail".
iIntros (reply_ptr) "Hreply".
wp_apply (wp_NewSliceWithCap).
apply encoding.unsigned_64_nonneg.
iIntros (args_ptr) "Hargs".
wp_apply (wp_WriteInt with "[$]").
wp_apply (Config.wp_Encode with "[$]").
iIntros (??) "(%HconfEnc & _ & Henc_sl)".
iDestruct (own_slice_to_small with "Henc_sl") as "Henc_sl".
wp_apply (wp_WriteBytes with "[$Hsl $Henc_sl]").
iIntros (?) "[Hargs_sl _]".
iDestruct (own_slice_to_small with "Hargs_sl") as "Hargs_sl".
replace (int.nat 0%Z) with (0%nat) by word.
iAssert ( ∃ sl,
"Hreply" ∷ reply_ptr ↦[slice.T byteT] (slice_val sl)
)%I with "[Hreply]" as "HH".
wp_apply (acquire_spec with "[$]").
iIntros "[Hlocked Hown]".
wp_apply (release_spec with "[Hlocked Hleader]").
apply list_lookup_lt in HleaderBound as [? Hlookup].
iMod (readonly_load with "Hcls_sl") as (?) "Hcls_sl2".
iDestruct (own_slice_small_sz with "Hcls_sl2") as %Hsl_sz.
wp_apply (wp_SliceGet with "[$Hcls_sl2]").
iDestruct (big_sepL_lookup with "Hrpc") as (?) "#[Hcl_rpc Hhost]".
wp_apply (wp_frame_wand with "[Hfail Hargs]"); first iNamedAccu.
wp_apply (wp_ReconnectingClient__Call2 with "Hcl_rpc [] Hargs_sl Hreply").
rewrite /TryWriteConfig_spec /TryWriteConfig_core_spec /=.
(* case: successfully wrote new config and epoch *)
iDestruct ("HΦ" with "Hlc") as "Hupd".
(* case: got a new epoch, no error *)
iDestruct "Hupd" as (???) "(H1&H2&H3&Hupd)".
iMod ("Hupd" with "[% //] [$] [$] [$]") as "Hupd".
iIntros (?) "%Hconf_enc Hargs_sl".
iIntros (?) "Hrep Hrep_sl".
iDestruct ("Hrep_sl") as "[Hrep_sl1 Hrep_sl2]".
wp_apply (wp_ReadInt with "[$]").
wp_apply (wp_ReadInt with "[$]").
(* case: RPC ran, but was not able to write *)
iIntros (?) "%HrepEnc Harg_sl".
iIntros (?) "Hrep Hrep_sl".
iDestruct "Hrep_sl" as "[Hrep_sl Hrep_sl2]".
wp_apply (wp_ReadInt with "[$]").
(* case: ErrNotLeader, so retry *)
wp_apply (acquire_spec with "[$]").
iIntros "[Hlocked Hown]".
(* case: increase leader idx *)
wp_apply (release_spec with "[Hlocked Hleader]").
repeat iExists _; iFrame.
rewrite word.unsigned_modu_nowrap; last lia.
apply Z2Nat.inj_lt; auto using encoding.unsigned_64_nonneg.
(* case: don't increase leader idx *)
wp_apply (release_spec with "[Hlocked Hleader]").
repeat iExists _; iFrame "∗%".
(* case: some other error, don't retry *)
wp_apply (wp_ReadInt with "[$]").
iIntros (?) "%Herr Hreply_sl Hrep".
Lemma wp_Clerk__GetLease (ck:loc) γ epoch Φ :
is_Clerk ck γ -∗
□ ((∀ (leaseExpiration:u64) γl,
is_lease epochLeaseN γl (own_latest_epoch γ epoch) -∗
is_lease_valid_lb γl leaseExpiration -∗ Φ (#0, #leaseExpiration)%V) ∧
(∀ (err:u64), ⌜err ≠ 0⌝ -∗ Φ (#err, #0)%V)
) -∗
WP Clerk__GetLease #ck #epoch {{ Φ }}
.
iIntros (reply_ptr) "Hreply".
wp_apply (wp_NewSliceWithCap).
apply encoding.unsigned_64_nonneg.
iIntros (args_ptr) "Hargs".
wp_apply (wp_WriteInt with "[$]").
iDestruct (own_slice_to_small with "Hargs_sl") as "Hargs_sl".
iAssert ( ∃ sl,
"Hreply" ∷ reply_ptr ↦[slice.T byteT] (slice_val sl)
)%I with "[Hreply]" as "HH".
wp_apply (acquire_spec with "[$]").
iIntros "[Hlocked Hown]".
wp_apply (release_spec with "[Hlocked Hleader]").
apply list_lookup_lt in HleaderBound as [? Hlookup].
iMod (readonly_load with "Hcls_sl") as (?) "Hcls_sl2".
iDestruct (own_slice_small_sz with "Hcls_sl2") as %Hsl_sz.
wp_apply (wp_SliceGet with "[$Hcls_sl2]").
iDestruct (big_sepL_lookup with "Hrpc") as (?) "#[Hcl_rpc Hhost]".
wp_apply (wp_frame_wand with "[Hargs]"); first iNamedAccu.
wp_apply (wp_ReconnectingClient__Call2 with "Hcl_rpc [] Hargs_sl Hreply").
rewrite /GetLease_spec /GetLease_core_spec /=.
iIntros (?) "%Henc Hargs_sl".
iIntros (?) "Hrep Hreply_sl".
iDestruct ("HΦ" with "[$] [$]") as "Hupd".
iDestruct "Hreply_sl" as "[Hrep_sl Hrep_sl2]".
wp_apply (wp_ReadInt with "[$]").
wp_apply (wp_ReadInt with "[$]").
wp_apply (wp_ReadInt with "[$]").
(* case: RPC ran, but server gave an error *)
iIntros (?) "%HrepEnc Harg_sl".
iIntros (?) "Hrep Hrep_sl".
iDestruct "Hrep_sl" as "[Hrep_sl Hrep_sl2]".
wp_apply (wp_ReadInt with "[$]").
(* case: ErrNotLeader, so retry *)
wp_apply (acquire_spec with "[$]").
iIntros "[Hlocked Hown]".
(* case: increase leader idx *)
wp_apply (release_spec with "[Hlocked Hleader]").
repeat iExists _; iFrame.
rewrite word.unsigned_modu_nowrap; last lia.
apply Z2Nat.inj_lt; auto using encoding.unsigned_64_nonneg.
(* case: don't increase leader idx *)
wp_apply (release_spec with "[Hlocked Hleader]").
repeat iExists _; iFrame "∗%".
(* case: some other error, don't retry *)
wp_apply (wp_ReadInt with "[$]").
wp_apply (wp_ReadInt with "[$]").
iIntros (?) "%Herr Hreply_sl Hrep".
Lemma wp_makeServer γ γsrv fname data (paxosMe:u64) hosts_sl init_sl (hosts: list u64) :
{{{
"Hhosts_sl" ∷ (own_slice_small hosts_sl uint64T 1 hosts) ∗
"#Hinit" ∷ readonly (own_slice_small init_sl uint64T 1 initconfig) ∗
"#Hhost" ∷ is_paxos_server_host paxosMe γ.(paxos_gn) γsrv ∗
"Hfile" ∷ crash_borrow (config_crash_resources γ γsrv data ∗ fname f↦ data)
(∃ d, config_crash_resources γ γsrv d ∗ fname f↦ d) ∗
"#Hpeers" ∷ is_config_peers hosts γ ∗
"#Hconfig_inv" ∷ is_config_inv γ ∗
"#Hwf" ∷ □ Pwf initconfig
}}}
makeServer #(str fname) #paxosMe (slice_val hosts_sl) (slice_val init_sl)
{{{
(s:loc), RET #s; is_Server s γ
}}}.
wp_apply (wp_allocStruct); first by val_ty.
iDestruct (struct_fields_split with "Hs") as "HH".
wp_apply wp_allocStruct; first by val_ty.
iDestruct (struct_fields_split with "Hs") as "HH".
wp_apply (state.wp_encode with "[HH]").
instantiate (1:=state.mk _ _ _ _ _).
wp_apply (wp_StartServer with "[$Hfile $Hhosts_sl Henc]").
iMod (readonly_alloc_1 with "s") as "#s".
Lemma wp_StartServer γ γsrv fname me (paxosMe:u64) (data:list u8) hosts_sl init_sl (hosts: list u64) :
{{{
"Hhosts_sl" ∷ (own_slice_small hosts_sl uint64T 1 hosts) ∗
"#Hinit" ∷ readonly (own_slice_small init_sl uint64T 1 initconfig) ∗
"Hfile" ∷ crash_borrow (config_crash_resources γ γsrv data ∗ fname f↦ data)
(∃ d, config_crash_resources γ γsrv d ∗ fname f↦ d) ∗
"#Hhost" ∷ is_config_server_host me paxosMe γ γsrv ∗
"#Hpeers" ∷ is_config_peers hosts γ ∗
"#Hwf" ∷ □ Pwf initconfig
}}}
StartServer #(str fname) #me #paxosMe (slice_val hosts_sl) (slice_val init_sl)
{{{
(s:loc), RET #s; is_Server s γ
}}}.
wp_apply (wp_makeServer with "[-HΦ]").
wp_apply (map.wp_NewMap u64).
iIntros (handlers) "Hhandlers".
wp_apply (wp_Server__ReserveEpochAndGetConfig).
iIntros (getEpochFn) "#HgetEpochSpec".
wp_apply (map.wp_MapInsert with "Hhandlers").
wp_apply (wp_Server__GetConfig).
iIntros (getFn) "#HgetSpec".
wp_apply (map.wp_MapInsert with "Hhandlers").
wp_apply (wp_Server__TryWriteConfig).
iIntros (writeConfigFn) "#HwriteSpec".
wp_apply (map.wp_MapInsert with "Hhandlers").
wp_apply (wp_Server__GetLease).
iIntros (getLeaseFn) "#HgetLeaseSpec".
wp_apply (map.wp_MapInsert with "Hhandlers").
wp_apply (urpc_proof.wp_MakeServer with "Hhandlers").
wp_apply (wp_StartServer_pred with "[$Hr]").
unfold handlers_complete.
repeat rewrite dom_insert_L.
iApply (big_sepM_insert_2 with "").
iApply (big_sepM_insert_2 with "").
iApply (big_sepM_insert_2 with "").
iApply (big_sepM_insert_2 with "").
by iApply big_sepM_empty.
Context `{!gooseGlobalGS Σ}.
Context `(params:configParams.t Σ).
Definition config_spec_list γ :=
[ (U64 0, ReserveEpochAndGetConfig_spec γ) ;
(U64 1, GetConfig_spec γ) ;
(U64 2, TryWriteConfig_spec γ) ;
(U64 3, GetLease_spec γ)].
Lemma alloc_config_rpc host γ :
host c↦ ∅ ={⊤}=∗
is_config_host host γ.
iMod (alloc_is_urpc_list_pred host (config_spec_list γ) with "Hchan") as (γrpc) "H".
iDestruct "H" as "(H1 & $ & $ & $ & $ & _)".
Definition own_config_res γ conf : iProp Σ :=
own_latest_epoch γ 0 ∗ own_reserved_epoch γ 0 ∗ own_config γ conf.
Existing Instance pParams.
Lemma alloc_config_system (hostPairs: list (u64 * u64)) :
length hostPairs > 0 →
([∗ list] h ∈ hostPairs, h.1 c↦ ∅ ∗ h.2 c↦ ∅) -∗
□ (Pwf initconfig)
={⊤}=∗
∃ γ,
([∗ list] h ∈ hostPairs,
∃ γsrv,
is_config_peers (hostPairs.*2) γ ∗
is_config_server_host h.1 h.2 γ γsrv ∗
config_crash_resources γ γsrv []) ∗
is_config_hosts (hostPairs.*1) γ ∗
own_config_res γ initconfig
.
iDestruct (big_sepL_sep with "Hchans") as "[Hc Hp]".
iMod (alloc_paxos_system pParams (hostPairs.*2) with "[Hp] []") as "H".
by rewrite big_sepL_fmap.
iDestruct "H" as (?) "(Hsrvs & #Hhost & Hst)".
(* allocate config-specific ghost state *)
iMod (mono_nat_own_alloc 0) as (γepoch) "[[Hepoch Hepoch2] _]".
iMod (mono_nat_own_alloc 0) as (γres) "[[Hres Hres2] _]".
iMod (ghost_var_alloc initconfig) as (γconf) "[Hconf Hconf2]".
iExists (Build_config_names _ _ _ _).
iAssert (|={⊤}=> is_config_hosts hostPairs.*1 _)%I with "[Hc]" as ">#Hhosts".
rewrite /is_config_hosts.
iApply (big_sepL_impl with "Hc").
by iMod (alloc_config_rpc with "[$]").
iMod fupd_mask_subseteq as "Hmask".
2: iMod (lease_alloc _ epochLeaseN with "Hepoch") as (?) "(_ & Hepoch & Hexp)".
iAssert (|={⊤}=> is_config_invs _)%I with "[Hst Hepoch Hexp Hres Hconf]" as ">#Hinv".
iMod (inv_alloc with "[-]") as "$"; last done.
instantiate (2:=(Build_config_names _ _ _ _)).
rewrite /own_Config_ghost /=.
iApply (big_sepL_impl with "Hsrvs").
iDestruct "H" as (?) "[#Hmphost Hcrash]".
iExists _; iFrame "Hmphost".
by rewrite /is_config_peers /=.
iDestruct (big_sepL_lookup with "Hhosts") as "$".
rewrite list_lookup_fmap.