Library zoo_persistent.sstore_2
Require Import iris.base_logic.lib.ghost_map.
Require Import zoo.prelude.
Require Import zoo.common.fin_maps.
Require Import zoo.common.list.
Require Import zoo.common.treemap.
Require Import zoo.iris.base_logic.lib.mono_gmap.
Require Import zoo.base.
Require Import zoo_std.list.
Require Export zoo_persistent.sstore_2__code.
Require Import zoo_persistent.sstore_2__types.
Require Import zoo.options.
Implicit Type l r node cnode base root dst : location.
Implicit Type nodes : list location.
Implicit Type v t s : val.
Implicit Type σ σ₀ : gmap location val.
Module base.
#[local] Definition generation :=
nat.
Implicit Type g : generation.
#[local] Notation "data '.(gen)'" := (
fst data
)(at level 2,
left associativity,
format "data .(gen)"
) : stdpp_scope.
#[local] Notation "data '.(val)'" := (
snd data
)(at level 2,
left associativity,
format "data .(val)"
) : stdpp_scope.
#[local] Definition store :=
gmap location (generation × val).
Implicit Type ς : store.
Implicit Type data : generation × val.
Record descriptor := Descriptor
{ descriptor۰gen : generation
; descriptor۰store : store
}.
Add Printing Constructor descriptor.
Implicit Type descr : descriptor.
Implicit Type cnodes : gmap location descriptor.
Class Sstore2G Σ `{zoo۰G : !ZooG Σ} :=
{ #[local] sstore_2۰G۰nodes۰G :: ghost_mapG Σ location descriptor
}.
Definition sstore_2۰Σ :=
#[ghost_mapΣ location descriptor
].
#[global] Instance subGーsstore_2۰Σ Σ `{zoo۰G : !ZooG Σ} :
subG sstore_2۰Σ Σ →
Sstore2G Σ.
Section sstore_2۰G.
Context `{sstore_2۰G : Sstore2G Σ}.
#[local] Definition metadata :=
gname.
Implicit Type γ : metadata.
#[local] Definition store۰on σ₀ ς :=
ς ∪ (pair 0 <$> σ₀).
#[local] Definition store۰generation g ς :=
map_Forall (λ r data, data.(gen) ≤ g) ς.
#[local] Definition descriptor۰wf σ₀ descr :=
dom descr.(descriptor۰store) ⊆ dom σ₀ ∧
store۰generation descr.(descriptor۰gen) descr.(descriptor۰store).
Record delta := Delta
{ delta۰ref : location
; delta۰gen : generation
; delta۰val : val
; delta۰node : location
}.
Add Printing Constructor delta.
Implicit Type δ : delta.
Implicit Type δs : list delta.
Implicit Type path : list (list delta).
#[local] Notation "δ '.(delta۰data)'" := (
pair δ.(delta۰gen) δ.(delta۰val)
)(at level 2,
left associativity,
format "δ .(delta۰data)"
) : stdpp_scope.
#[local] Definition delta۰patch δ :=
(δ.(delta۰ref), δ.(delta۰data)).
#[local] Definition deltas۰apply δs ς :=
list_to_map (delta۰patch <$> δs) ∪ ς.
#[local] Fixpoint deltas۰chain node δs dst : iProp Σ :=
match δs with
| [] ⇒
⌜node = dst⌝
| δ :: δs ⇒
node ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #δ.(delta۰node) ) ∗
deltas۰chain δ.(delta۰node) δs dst
end.
#[local] Definition edge : Set :=
location × list delta.
Implicit Type ϵ : edge.
Implicit Type ϵs : gmap location edge.
#[local] Definition cnodes۰auth γ cnodes :=
ghost_map_auth γ 1 cnodes.
#[local] Definition cnodes۰elem γ cnode descr :=
ghost_map_elem γ cnode DfracDiscarded descr.
#[local] Definition cnode۰model γ σ₀ cnode descr ϵ ς : iProp Σ :=
let cnode' := ϵ.1 in
let δs := ϵ.2 in
⌜descriptor۰wf σ₀ descr⌝ ∗
cnodes۰elem γ cnode descr ∗
⌜NoDup $ delta۰ref <$> δs⌝ ∗
⌜store۰on σ₀ descr.(descriptor۰store) = store۰on σ₀ $ deltas۰apply δs ς⌝ ∗
deltas۰chain cnode δs cnode'.
Definition sstore_2۰model t σ₀ σ : iProp Σ :=
∃ l γ g root ς,
⌜t = #l⌝ ∗
⌜σ = snd <$> ς⌝ ∗
l ↪[nroot.@"impl"] γ ∗
l.[gen] ↦ #g ∗
l.[root] ↦ #root ∗
root ↦ᵣ §Root ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ ς,
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜descriptor۰wf σ₀ (Descriptor g ς)⌝ ∗
if decide (g = 0) then
cnodes۰auth γ ∅
else
∃ cnodes ϵs base descr δs,
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
⌜cnodes !! base = Some descr⌝ ∗
⌜descr.(descriptor۰gen) < g⌝ ∗
cnode۰model γ σ₀ base descr (root, δs) ς ∗
⌜δs = [] → ς = descr.(descriptor۰store)⌝ ∗
⌜Forall (λ δ, ∃ data, ς !! δ.(delta۰ref) = Some data ∧ data.(gen) = g) δs⌝ ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base cnodes; ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
Definition sstore_2۰snapshot s t σ : iProp Σ :=
∃ l γ g cnode descr,
⌜t = #l⌝ ∗
⌜s = (t, #g, #cnode)%V⌝ ∗
⌜σ = snd <$> descr.(descriptor۰store)⌝ ∗
⌜descr.(descriptor۰gen) ≤ g⌝ ∗
l ↪[nroot.@"impl"] γ ∗
cnodes۰elem γ cnode descr.
#[local] Instance deltas۰chainーtimeless node δs dst :
Timeless (deltas۰chain node δs dst).
#[global] Instance sstore_2۰modelーtimeless t σ₀ σ :
Timeless (sstore_2۰model t σ₀ σ).
#[global] Instance sstore_2۰snapshotーpersistent s t σ :
Persistent (sstore_2۰snapshot s t σ).
#[local] Lemma store۰onーdom σ₀ ς :
dom (store۰on σ₀ ς) = dom σ₀ ∪ dom ς.
#[local] Lemma store۰onーdom' σ₀ ς :
dom ς ⊆ dom σ₀ →
dom (store۰on σ₀ ς) = dom σ₀.
#[local] Lemma store۰onーlookup {σ₀ ς} r data :
store۰on σ₀ ς !! r = Some data ↔
ς !! r = Some data
∨ ς !! r = None ∧
data.(gen) = 0 ∧
σ₀ !! r = Some data.(val).
#[local] Lemma store۰onーlookup' {σ₀ ς} r data :
ς !! r = Some data →
store۰on σ₀ ς !! r = Some data.
#[local] Lemma store۰onーinsert r data σ₀ ς :
store۰on σ₀ (<[r := data]> ς) = <[r := data]> (store۰on σ₀ ς).
#[local] Lemma store۰onーinsertーsupport r v σ₀ ς :
σ₀ !! r = None →
dom ς ⊆ dom σ₀ →
store۰on (<[r := v]> σ₀) ς = <[r := (0, v)]> (store۰on σ₀ ς).
#[local] Lemma store۰onーdeltas۰apply σ₀ δs ς :
store۰on σ₀ (deltas۰apply δs ς) = deltas۰apply δs (store۰on σ₀ ς).
#[local] Lemma store۰generationーle {g ς} g' :
g ≤ g' →
store۰generation g ς →
store۰generation g' ς.
#[local] Lemma store۰generationーinsert g ς r data :
store۰generation g ς →
data.(gen) ≤ g →
store۰generation g (<[r := data]> ς).
#[local] Lemma deltas۰applyーnil ς :
deltas۰apply [] ς = ς.
#[local] Lemma deltas۰applyーcons δ δs ς :
deltas۰apply (δ :: δs) ς = <[δ.(delta۰ref) := δ.(delta۰data)]> (deltas۰apply δs ς).
#[local] Lemma deltas۰applyーsingleton δ ς :
deltas۰apply [δ] ς = <[δ.(delta۰ref) := δ.(delta۰data)]> ς.
#[local] Lemma deltas۰applyーapp δs1 δs2 ς :
deltas۰apply (δs1 ++ δs2) ς = deltas۰apply δs1 (deltas۰apply δs2 ς).
#[local] Lemma deltas۰applyーsnoc δs δ ς :
deltas۰apply (δs ++ [δ]) ς = deltas۰apply δs (<[δ.(delta۰ref) := δ.(delta۰data)]> ς).
#[local] Lemma deltas۰applyーsnoc' δs r g v node ς :
deltas۰apply (δs ++ [Delta r g v node]) ς = deltas۰apply δs (<[r := (g, v)]> ς).
#[local] Lemma deltas۰applyーdom δs ς :
dom (deltas۰apply δs ς) = list_to_set (delta۰ref <$> δs) ∪ dom ς.
#[local] Lemma deltas۰applyーlookup δs δ r data ς :
NoDup (delta۰ref <$> δs) →
δ ∈ δs →
r = δ.(delta۰ref) →
data = δ.(delta۰data) →
deltas۰apply δs ς !! r = Some data.
#[local] Lemma deltas۰applyーlookup' δs r data ς :
NoDup (delta۰ref <$> δs) →
(r, data) ∈ delta۰patch <$> δs →
deltas۰apply δs ς !! r = Some data.
#[local] Lemma deltas۰apply۰lookupーne r δs ς :
NoDup (delta۰ref <$> δs) →
r ∉ (delta۰ref <$> δs) →
deltas۰apply δs ς !! r = ς !! r.
#[local] Lemma deltas۰applyーpermutation δs1 δs2 ς :
NoDup (delta۰ref <$> δs1) →
δs1 ≡ₚ δs2 →
deltas۰apply δs1 ς = deltas۰apply δs2 ς.
#[local] Lemma deltas۰chainーcons src δ δs dst :
src ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #δ.(delta۰node) ) -∗
deltas۰chain δ.(delta۰node) δs dst -∗
deltas۰chain src (δ :: δs) dst.
#[local] Lemma deltas۰chainーnilーinv src dst :
deltas۰chain src [] dst ⊢
⌜src = dst⌝.
#[local] Lemma deltas۰chainーconsーinv src δ δs dst :
deltas۰chain src (δ :: δs) dst ⊢
src ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #δ.(delta۰node) ) ∗
deltas۰chain δ.(delta۰node) δs dst.
#[local] Lemma deltas۰chainーsnoc {src δs dst} r g v dst' :
deltas۰chain src δs dst -∗
dst ↦ᵣ ‘Diff( #r, #g, v, #dst' ) -∗
deltas۰chain src (δs ++ [Delta r g v dst']) dst'.
#[local] Lemma deltas۰chainーapp₁ src δs1 δs2 dst :
deltas۰chain src (δs1 ++ δs2) dst ⊢
let node := default src $ delta۰node <$> last δs1 in
deltas۰chain src δs1 node ∗
deltas۰chain node δs2 dst.
#[local] Lemma deltas۰chainーapp₂ src δs1 node δs2 dst :
deltas۰chain src δs1 node -∗
deltas۰chain node δs2 dst -∗
deltas۰chain src (δs1 ++ δs2) dst.
#[local] Lemma deltas۰chainーsnocーinv src δs δ dst :
deltas۰chain src (δs ++ [δ]) dst ⊢
let node := default src $ delta۰node <$> last δs in
⌜δ.(delta۰node) = dst⌝ ∗
deltas۰chain src δs node ∗
node ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #dst ).
#[local] Lemma deltas۰chainーlookup {src δs dst} i δ :
δs !! i = Some δ →
deltas۰chain src δs dst ⊢
deltas۰chain src (take ˖i δs) δ.(delta۰node) ∗
deltas۰chain δ.(delta۰node) (drop ˖i δs) dst.
#[local] Lemma deltas۰chainーlookup' {src δs dst} i δ :
δs !! i = Some δ →
deltas۰chain src δs dst ⊢
∃ node,
⌜ if i is 0 then
node = src
else
∃ δ',
δs !! pred i = Some δ' ∧
δ'.(delta۰node) = node
⌝ ∗
deltas۰chain src (take i δs) node ∗
node ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #δ.(delta۰node) ) ∗
deltas۰chain δ.(delta۰node) (drop ˖i δs) dst.
#[local] Definition cnodesーalloc root :
⊢ |==>
∃ γ,
cnodes۰auth γ ∅.
#[local] Definition cnodesーlookup γ cnodes cnode descr :
cnodes۰auth γ cnodes -∗
cnodes۰elem γ cnode descr -∗
⌜cnodes !! cnode = Some descr⌝.
#[local] Lemma cnodesーinsert {γ cnodes} cnode descr :
cnodes !! cnode = None →
cnodes۰auth γ cnodes ⊢ |==>
cnodes۰auth γ (<[cnode := descr]> cnodes) ∗
cnodes۰elem γ cnode descr.
Lemma sstore_2۰modelーvalid t σ₀ σ :
sstore_2۰model t σ₀ σ ⊢
⌜dom σ ⊆ dom σ₀⌝.
Lemma sstore_2۰modelーexclusive t σ₀1 σ1 σ₀2 σ2 :
sstore_2۰model t σ₀1 σ1 -∗
sstore_2۰model t σ₀2 σ2 -∗
False.
Lemma sstore_2٠createーspec :
{{{
True
}}}
sstore_2٠create ()
{{{
t
, RET t;
(∃ l, ⌜t = #l⌝ ∗ meta_token l (↑nroot.@"user")) ∗
sstore_2۰model t ∅ ∅
}}}.
Lemma sstore_2٠refーspec t σ₀ σ v :
{{{
sstore_2۰model t σ₀ σ
}}}
sstore_2٠ref t v
{{{
r
, RET #r;
⌜σ₀ !! r = None⌝ ∗
sstore_2۰model t (<[r := v]> σ₀) σ
}}}.
Lemma sstore_2٠getーspec {t σ₀ σ r} v :
(σ ∪ σ₀) !! r = Some v →
{{{
sstore_2۰model t σ₀ σ
}}}
sstore_2٠get t #r
{{{
RET v;
sstore_2۰model t σ₀ σ
}}}.
Lemma sstore_2٠setーspec t σ₀ σ r v :
r ∈ dom σ₀ →
{{{
sstore_2۰model t σ₀ σ
}}}
sstore_2٠set t #r v
{{{
RET ();
sstore_2۰model t σ₀ (<[r := v]> σ)
}}}.
Lemma sstore_2٠captureーspec t σ₀ σ :
{{{
sstore_2۰model t σ₀ σ
}}}
sstore_2٠capture t
{{{
s
, RET s;
sstore_2۰model t σ₀ σ ∗
sstore_2۰snapshot s t σ
}}}.
#[local] Definition collect۰inv γ σ₀ root ς cnodes ϵs base descr δs : iProp Σ :=
root ↦ᵣ §Root ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ ς,
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
⌜cnodes !! base = Some descr⌝ ∗
cnode۰model γ σ₀ base descr (root, δs) ς ∗
⌜δs = [] → ς = descr.(descriptor۰store)⌝ ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base cnodes; ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
#[local] Lemma sstore_2٠collectーspecーbaseーchain {γ σ₀ root ς cnodes ϵs base descr δs} i δ node acc :
δs !! i = Some δ →
δ.(delta۰node) = node →
{{{
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠collect #node acc
{{{
acc'
, RET (#root, acc');
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
plist۰model acc' acc $ tail $
(λ δ, #δ.(delta۰node)) <$> reverse (drop i δs)
}}}.
#[local] Definition collectーspecification γ σ₀ root ς cnodes ϵs base descr δs : iProp Σ :=
∀ cnode descr_cnode path acc,
{{{
⌜cnodes !! cnode = Some descr_cnode⌝ ∗
⌜treemap۰path ϵs base cnode path⌝ ∗
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠collect #cnode acc
{{{
acc'
, RET (#root, acc');
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
plist۰model acc' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
[ #cnode]
}}}.
#[local] Lemma sstore_2٠collectーspecーchain {γ σ₀ root ς cnodes ϵs base descr δs} cnode ϵ i 𝝳 node path acc :
ϵs !! cnode = Some ϵ →
ϵ.2 !! i = Some 𝝳 →
𝝳.(delta۰node) = node →
treemap۰path ϵs base ϵ.1 path →
{{{
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
collectーspecification γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠collect #node acc
{{{
acc'
, RET (#root, acc');
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
plist۰model acc' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
((λ δ, #δ.(delta۰node)) <$> reverse (drop i ϵ.2))
}}}.
#[local] Lemma sstore_2٠collectーspec {γ σ₀ root ς cnodes ϵs base descr δs} cnode descr_cnode path acc :
cnodes !! cnode = Some descr_cnode →
treemap۰path ϵs base cnode path →
{{{
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠collect #cnode acc
{{{
acc'
, RET (#root, acc');
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
plist۰model acc' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
[ #cnode]
}}}.
#[local] Definition revert۰pre₁ γ σ₀ root ς cnodes ϵs base descr δs : iProp Σ :=
∃ v_root,
root ↦ᵣ v_root ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ ς,
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
⌜cnodes !! base = Some descr⌝ ∗
cnode۰model γ σ₀ base descr (root, δs) ς ∗
⌜δs = [] → ς = descr.(descriptor۰store)⌝ ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base cnodes; ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
#[local] Definition revert۰pre₂ γ σ₀ ς cnodes ϵs base descr_base δs_base cnode descr_cnode δs_cnode node : iProp Σ :=
∃ v_node,
node ↦ᵣ v_node ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ ς,
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
⌜cnodes !! base = Some descr_base⌝ ∗
cnode۰model γ σ₀ base descr_base (node, δs_base) ς ∗
⌜cnodes !! cnode = Some descr_cnode⌝ ∗
cnode۰model γ σ₀ cnode descr_cnode (node, δs_cnode) ς ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base $ delete cnode cnodes; delete cnode ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
#[local] Definition revert۰post γ σ₀ cnodes ϵs base descr : iProp Σ :=
base ↦ᵣ §Root ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ descr.(descriptor۰store),
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
cnode۰model γ σ₀ base descr (base, []) descr.(descriptor۰store) ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base cnodes; ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
#[local] Lemma sstore_2٠revertーspecーaux {γ σ₀ ς cnodes ϵs base descr_base δs_base cnode descr_cnode δs_cnode node} base' descr_base' path δs acc :
cnodes !! base' = Some descr_base' →
treemap۰path ϵs cnode base' path →
ϵs !! cnode = Some (base, δs) →
0 < length δs_cnode →
NoDup (delta۰ref <$> δs_cnode ++ δs_base) →
list۰model' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs_cnode) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
[ #base'] →
{{{
revert۰pre₂ γ σ₀ ς cnodes ϵs base descr_base δs_base cnode descr_cnode δs_cnode node
}}}
sstore_2٠revert #node acc
{{{
ϵs
, RET ();
revert۰post γ σ₀ cnodes ϵs base' descr_base'
}}}.
#[local] Lemma sstore_2٠revertーspec {γ σ₀ root ς cnodes ϵs base descr_base δs} base' descr_base' path acc :
cnodes !! base' = Some descr_base' →
treemap۰path ϵs base base' path →
list۰model' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
[ #base'] →
{{{
revert۰pre₁ γ σ₀ root ς cnodes ϵs base descr_base δs
}}}
sstore_2٠revert #root acc
{{{
ϵs
, RET ();
revert۰post γ σ₀ cnodes ϵs base' descr_base'
}}}.
#[local] Lemma sstore_2٠rerootーspec {γ σ₀ root ς cnodes ϵs base descr δs} base' descr' path :
cnodes !! base' = Some descr' →
treemap۰path ϵs base base' path →
{{{
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠reroot #base'
{{{
ϵs
, RET ();
revert۰post γ σ₀ cnodes ϵs base' descr'
}}}.
Lemma sstore_2٠restoreーspec t σ₀ σ s σ' :
{{{
sstore_2۰model t σ₀ σ ∗
sstore_2۰snapshot s t σ'
}}}
sstore_2٠restore t s
{{{
RET ();
sstore_2۰model t σ₀ σ'
}}}.
End sstore_2۰G.
#[global] Opaque sstore_2۰model.
#[global] Opaque sstore_2۰snapshot.
End base.
Require zoo_persistent.sstore_2__opaque.
Class Sstore2G Σ `{zoo۰G : !ZooG Σ} :=
{ #[local] sstore_2۰G۰raw۰G :: base.Sstore2G Σ
; #[local] sstore_2۰G۰support۰G :: MonoGmapG Σ location val
}.
Definition sstore_2۰Σ :=
#[base.sstore_2۰Σ
; mono_gmap۰Σ location val
].
#[global] Instance subGーsstore_2۰Σ Σ `{zoo۰G : !ZooG Σ} :
subG sstore_2۰Σ Σ →
Sstore2G Σ.
Section sstore_2۰G.
Context `{sstore_2۰G : Sstore2G Σ}.
#[local] Definition metadata :=
gname.
Implicit Type γ : metadata.
Definition sstore_2۰model t σ : iProp Σ :=
∃ l γ σ₀ ς,
⌜t = #l⌝ ∗
⌜σ ⊆ ς ∪ σ₀⌝ ∗
l ↪[nroot.@"user"] γ ∗
mono_gmap۰auth γ (DfracOwn 1) σ₀ ∗
base.sstore_2۰model t σ₀ ς.
Definition sstore_2۰snapshot s t σ : iProp Σ :=
∃ l γ σ₀ ς,
⌜t = #l⌝ ∗
⌜σ ⊆ ς ∪ σ₀⌝ ∗
l ↪[nroot.@"user"] γ ∗
mono_gmap۰lb γ σ₀ ∗
base.sstore_2۰snapshot s t ς.
#[global] Instance sstore_2۰modelーtimeless t σ :
Timeless (sstore_2۰model t σ).
#[global] Instance sstore_2۰snapshotーpersistent s t σ :
Persistent (sstore_2۰snapshot s t σ).
Lemma sstore_2۰modelーexclusive t σ1 σ2 :
sstore_2۰model t σ1 -∗
sstore_2۰model t σ2 -∗
False.
Lemma sstore_2٠createーspec :
{{{
True
}}}
sstore_2٠create ()
{{{
t
, RET t;
sstore_2۰model t ∅
}}}.
Lemma sstore_2٠refーspec t σ v :
{{{
sstore_2۰model t σ
}}}
sstore_2٠ref t v
{{{
r
, RET #r;
⌜σ !! r = None⌝ ∗
sstore_2۰model t (<[r := v]> σ)
}}}.
Lemma sstore_2٠getーspec {t σ r} v :
σ !! r = Some v →
{{{
sstore_2۰model t σ
}}}
sstore_2٠get t #r
{{{
RET v;
sstore_2۰model t σ
}}}.
Lemma sstore_2٠setーspec t σ r v :
r ∈ dom σ →
{{{
sstore_2۰model t σ
}}}
sstore_2٠set t #r v
{{{
RET ();
sstore_2۰model t (<[r := v]> σ)
}}}.
Lemma sstore_2٠captureーspec t σ :
{{{
sstore_2۰model t σ
}}}
sstore_2٠capture t
{{{
s
, RET s;
sstore_2۰model t σ ∗
sstore_2۰snapshot s t σ
}}}.
Lemma sstore_2٠restoreーspec t σ s σ' :
{{{
sstore_2۰model t σ ∗
sstore_2۰snapshot s t σ'
}}}
sstore_2٠restore t s
{{{
RET ();
sstore_2۰model t σ'
}}}.
End sstore_2۰G.
#[global] Opaque sstore_2۰model.
#[global] Opaque sstore_2۰snapshot.
Require Import zoo.prelude.
Require Import zoo.common.fin_maps.
Require Import zoo.common.list.
Require Import zoo.common.treemap.
Require Import zoo.iris.base_logic.lib.mono_gmap.
Require Import zoo.base.
Require Import zoo_std.list.
Require Export zoo_persistent.sstore_2__code.
Require Import zoo_persistent.sstore_2__types.
Require Import zoo.options.
Implicit Type l r node cnode base root dst : location.
Implicit Type nodes : list location.
Implicit Type v t s : val.
Implicit Type σ σ₀ : gmap location val.
Module base.
#[local] Definition generation :=
nat.
Implicit Type g : generation.
#[local] Notation "data '.(gen)'" := (
fst data
)(at level 2,
left associativity,
format "data .(gen)"
) : stdpp_scope.
#[local] Notation "data '.(val)'" := (
snd data
)(at level 2,
left associativity,
format "data .(val)"
) : stdpp_scope.
#[local] Definition store :=
gmap location (generation × val).
Implicit Type ς : store.
Implicit Type data : generation × val.
Record descriptor := Descriptor
{ descriptor۰gen : generation
; descriptor۰store : store
}.
Add Printing Constructor descriptor.
Implicit Type descr : descriptor.
Implicit Type cnodes : gmap location descriptor.
Class Sstore2G Σ `{zoo۰G : !ZooG Σ} :=
{ #[local] sstore_2۰G۰nodes۰G :: ghost_mapG Σ location descriptor
}.
Definition sstore_2۰Σ :=
#[ghost_mapΣ location descriptor
].
#[global] Instance subGーsstore_2۰Σ Σ `{zoo۰G : !ZooG Σ} :
subG sstore_2۰Σ Σ →
Sstore2G Σ.
Section sstore_2۰G.
Context `{sstore_2۰G : Sstore2G Σ}.
#[local] Definition metadata :=
gname.
Implicit Type γ : metadata.
#[local] Definition store۰on σ₀ ς :=
ς ∪ (pair 0 <$> σ₀).
#[local] Definition store۰generation g ς :=
map_Forall (λ r data, data.(gen) ≤ g) ς.
#[local] Definition descriptor۰wf σ₀ descr :=
dom descr.(descriptor۰store) ⊆ dom σ₀ ∧
store۰generation descr.(descriptor۰gen) descr.(descriptor۰store).
Record delta := Delta
{ delta۰ref : location
; delta۰gen : generation
; delta۰val : val
; delta۰node : location
}.
Add Printing Constructor delta.
Implicit Type δ : delta.
Implicit Type δs : list delta.
Implicit Type path : list (list delta).
#[local] Notation "δ '.(delta۰data)'" := (
pair δ.(delta۰gen) δ.(delta۰val)
)(at level 2,
left associativity,
format "δ .(delta۰data)"
) : stdpp_scope.
#[local] Definition delta۰patch δ :=
(δ.(delta۰ref), δ.(delta۰data)).
#[local] Definition deltas۰apply δs ς :=
list_to_map (delta۰patch <$> δs) ∪ ς.
#[local] Fixpoint deltas۰chain node δs dst : iProp Σ :=
match δs with
| [] ⇒
⌜node = dst⌝
| δ :: δs ⇒
node ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #δ.(delta۰node) ) ∗
deltas۰chain δ.(delta۰node) δs dst
end.
#[local] Definition edge : Set :=
location × list delta.
Implicit Type ϵ : edge.
Implicit Type ϵs : gmap location edge.
#[local] Definition cnodes۰auth γ cnodes :=
ghost_map_auth γ 1 cnodes.
#[local] Definition cnodes۰elem γ cnode descr :=
ghost_map_elem γ cnode DfracDiscarded descr.
#[local] Definition cnode۰model γ σ₀ cnode descr ϵ ς : iProp Σ :=
let cnode' := ϵ.1 in
let δs := ϵ.2 in
⌜descriptor۰wf σ₀ descr⌝ ∗
cnodes۰elem γ cnode descr ∗
⌜NoDup $ delta۰ref <$> δs⌝ ∗
⌜store۰on σ₀ descr.(descriptor۰store) = store۰on σ₀ $ deltas۰apply δs ς⌝ ∗
deltas۰chain cnode δs cnode'.
Definition sstore_2۰model t σ₀ σ : iProp Σ :=
∃ l γ g root ς,
⌜t = #l⌝ ∗
⌜σ = snd <$> ς⌝ ∗
l ↪[nroot.@"impl"] γ ∗
l.[gen] ↦ #g ∗
l.[root] ↦ #root ∗
root ↦ᵣ §Root ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ ς,
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜descriptor۰wf σ₀ (Descriptor g ς)⌝ ∗
if decide (g = 0) then
cnodes۰auth γ ∅
else
∃ cnodes ϵs base descr δs,
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
⌜cnodes !! base = Some descr⌝ ∗
⌜descr.(descriptor۰gen) < g⌝ ∗
cnode۰model γ σ₀ base descr (root, δs) ς ∗
⌜δs = [] → ς = descr.(descriptor۰store)⌝ ∗
⌜Forall (λ δ, ∃ data, ς !! δ.(delta۰ref) = Some data ∧ data.(gen) = g) δs⌝ ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base cnodes; ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
Definition sstore_2۰snapshot s t σ : iProp Σ :=
∃ l γ g cnode descr,
⌜t = #l⌝ ∗
⌜s = (t, #g, #cnode)%V⌝ ∗
⌜σ = snd <$> descr.(descriptor۰store)⌝ ∗
⌜descr.(descriptor۰gen) ≤ g⌝ ∗
l ↪[nroot.@"impl"] γ ∗
cnodes۰elem γ cnode descr.
#[local] Instance deltas۰chainーtimeless node δs dst :
Timeless (deltas۰chain node δs dst).
#[global] Instance sstore_2۰modelーtimeless t σ₀ σ :
Timeless (sstore_2۰model t σ₀ σ).
#[global] Instance sstore_2۰snapshotーpersistent s t σ :
Persistent (sstore_2۰snapshot s t σ).
#[local] Lemma store۰onーdom σ₀ ς :
dom (store۰on σ₀ ς) = dom σ₀ ∪ dom ς.
#[local] Lemma store۰onーdom' σ₀ ς :
dom ς ⊆ dom σ₀ →
dom (store۰on σ₀ ς) = dom σ₀.
#[local] Lemma store۰onーlookup {σ₀ ς} r data :
store۰on σ₀ ς !! r = Some data ↔
ς !! r = Some data
∨ ς !! r = None ∧
data.(gen) = 0 ∧
σ₀ !! r = Some data.(val).
#[local] Lemma store۰onーlookup' {σ₀ ς} r data :
ς !! r = Some data →
store۰on σ₀ ς !! r = Some data.
#[local] Lemma store۰onーinsert r data σ₀ ς :
store۰on σ₀ (<[r := data]> ς) = <[r := data]> (store۰on σ₀ ς).
#[local] Lemma store۰onーinsertーsupport r v σ₀ ς :
σ₀ !! r = None →
dom ς ⊆ dom σ₀ →
store۰on (<[r := v]> σ₀) ς = <[r := (0, v)]> (store۰on σ₀ ς).
#[local] Lemma store۰onーdeltas۰apply σ₀ δs ς :
store۰on σ₀ (deltas۰apply δs ς) = deltas۰apply δs (store۰on σ₀ ς).
#[local] Lemma store۰generationーle {g ς} g' :
g ≤ g' →
store۰generation g ς →
store۰generation g' ς.
#[local] Lemma store۰generationーinsert g ς r data :
store۰generation g ς →
data.(gen) ≤ g →
store۰generation g (<[r := data]> ς).
#[local] Lemma deltas۰applyーnil ς :
deltas۰apply [] ς = ς.
#[local] Lemma deltas۰applyーcons δ δs ς :
deltas۰apply (δ :: δs) ς = <[δ.(delta۰ref) := δ.(delta۰data)]> (deltas۰apply δs ς).
#[local] Lemma deltas۰applyーsingleton δ ς :
deltas۰apply [δ] ς = <[δ.(delta۰ref) := δ.(delta۰data)]> ς.
#[local] Lemma deltas۰applyーapp δs1 δs2 ς :
deltas۰apply (δs1 ++ δs2) ς = deltas۰apply δs1 (deltas۰apply δs2 ς).
#[local] Lemma deltas۰applyーsnoc δs δ ς :
deltas۰apply (δs ++ [δ]) ς = deltas۰apply δs (<[δ.(delta۰ref) := δ.(delta۰data)]> ς).
#[local] Lemma deltas۰applyーsnoc' δs r g v node ς :
deltas۰apply (δs ++ [Delta r g v node]) ς = deltas۰apply δs (<[r := (g, v)]> ς).
#[local] Lemma deltas۰applyーdom δs ς :
dom (deltas۰apply δs ς) = list_to_set (delta۰ref <$> δs) ∪ dom ς.
#[local] Lemma deltas۰applyーlookup δs δ r data ς :
NoDup (delta۰ref <$> δs) →
δ ∈ δs →
r = δ.(delta۰ref) →
data = δ.(delta۰data) →
deltas۰apply δs ς !! r = Some data.
#[local] Lemma deltas۰applyーlookup' δs r data ς :
NoDup (delta۰ref <$> δs) →
(r, data) ∈ delta۰patch <$> δs →
deltas۰apply δs ς !! r = Some data.
#[local] Lemma deltas۰apply۰lookupーne r δs ς :
NoDup (delta۰ref <$> δs) →
r ∉ (delta۰ref <$> δs) →
deltas۰apply δs ς !! r = ς !! r.
#[local] Lemma deltas۰applyーpermutation δs1 δs2 ς :
NoDup (delta۰ref <$> δs1) →
δs1 ≡ₚ δs2 →
deltas۰apply δs1 ς = deltas۰apply δs2 ς.
#[local] Lemma deltas۰chainーcons src δ δs dst :
src ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #δ.(delta۰node) ) -∗
deltas۰chain δ.(delta۰node) δs dst -∗
deltas۰chain src (δ :: δs) dst.
#[local] Lemma deltas۰chainーnilーinv src dst :
deltas۰chain src [] dst ⊢
⌜src = dst⌝.
#[local] Lemma deltas۰chainーconsーinv src δ δs dst :
deltas۰chain src (δ :: δs) dst ⊢
src ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #δ.(delta۰node) ) ∗
deltas۰chain δ.(delta۰node) δs dst.
#[local] Lemma deltas۰chainーsnoc {src δs dst} r g v dst' :
deltas۰chain src δs dst -∗
dst ↦ᵣ ‘Diff( #r, #g, v, #dst' ) -∗
deltas۰chain src (δs ++ [Delta r g v dst']) dst'.
#[local] Lemma deltas۰chainーapp₁ src δs1 δs2 dst :
deltas۰chain src (δs1 ++ δs2) dst ⊢
let node := default src $ delta۰node <$> last δs1 in
deltas۰chain src δs1 node ∗
deltas۰chain node δs2 dst.
#[local] Lemma deltas۰chainーapp₂ src δs1 node δs2 dst :
deltas۰chain src δs1 node -∗
deltas۰chain node δs2 dst -∗
deltas۰chain src (δs1 ++ δs2) dst.
#[local] Lemma deltas۰chainーsnocーinv src δs δ dst :
deltas۰chain src (δs ++ [δ]) dst ⊢
let node := default src $ delta۰node <$> last δs in
⌜δ.(delta۰node) = dst⌝ ∗
deltas۰chain src δs node ∗
node ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #dst ).
#[local] Lemma deltas۰chainーlookup {src δs dst} i δ :
δs !! i = Some δ →
deltas۰chain src δs dst ⊢
deltas۰chain src (take ˖i δs) δ.(delta۰node) ∗
deltas۰chain δ.(delta۰node) (drop ˖i δs) dst.
#[local] Lemma deltas۰chainーlookup' {src δs dst} i δ :
δs !! i = Some δ →
deltas۰chain src δs dst ⊢
∃ node,
⌜ if i is 0 then
node = src
else
∃ δ',
δs !! pred i = Some δ' ∧
δ'.(delta۰node) = node
⌝ ∗
deltas۰chain src (take i δs) node ∗
node ↦ᵣ ‘Diff( #δ.(delta۰ref), #δ.(delta۰gen), δ.(delta۰val), #δ.(delta۰node) ) ∗
deltas۰chain δ.(delta۰node) (drop ˖i δs) dst.
#[local] Definition cnodesーalloc root :
⊢ |==>
∃ γ,
cnodes۰auth γ ∅.
#[local] Definition cnodesーlookup γ cnodes cnode descr :
cnodes۰auth γ cnodes -∗
cnodes۰elem γ cnode descr -∗
⌜cnodes !! cnode = Some descr⌝.
#[local] Lemma cnodesーinsert {γ cnodes} cnode descr :
cnodes !! cnode = None →
cnodes۰auth γ cnodes ⊢ |==>
cnodes۰auth γ (<[cnode := descr]> cnodes) ∗
cnodes۰elem γ cnode descr.
Lemma sstore_2۰modelーvalid t σ₀ σ :
sstore_2۰model t σ₀ σ ⊢
⌜dom σ ⊆ dom σ₀⌝.
Lemma sstore_2۰modelーexclusive t σ₀1 σ1 σ₀2 σ2 :
sstore_2۰model t σ₀1 σ1 -∗
sstore_2۰model t σ₀2 σ2 -∗
False.
Lemma sstore_2٠createーspec :
{{{
True
}}}
sstore_2٠create ()
{{{
t
, RET t;
(∃ l, ⌜t = #l⌝ ∗ meta_token l (↑nroot.@"user")) ∗
sstore_2۰model t ∅ ∅
}}}.
Lemma sstore_2٠refーspec t σ₀ σ v :
{{{
sstore_2۰model t σ₀ σ
}}}
sstore_2٠ref t v
{{{
r
, RET #r;
⌜σ₀ !! r = None⌝ ∗
sstore_2۰model t (<[r := v]> σ₀) σ
}}}.
Lemma sstore_2٠getーspec {t σ₀ σ r} v :
(σ ∪ σ₀) !! r = Some v →
{{{
sstore_2۰model t σ₀ σ
}}}
sstore_2٠get t #r
{{{
RET v;
sstore_2۰model t σ₀ σ
}}}.
Lemma sstore_2٠setーspec t σ₀ σ r v :
r ∈ dom σ₀ →
{{{
sstore_2۰model t σ₀ σ
}}}
sstore_2٠set t #r v
{{{
RET ();
sstore_2۰model t σ₀ (<[r := v]> σ)
}}}.
Lemma sstore_2٠captureーspec t σ₀ σ :
{{{
sstore_2۰model t σ₀ σ
}}}
sstore_2٠capture t
{{{
s
, RET s;
sstore_2۰model t σ₀ σ ∗
sstore_2۰snapshot s t σ
}}}.
#[local] Definition collect۰inv γ σ₀ root ς cnodes ϵs base descr δs : iProp Σ :=
root ↦ᵣ §Root ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ ς,
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
⌜cnodes !! base = Some descr⌝ ∗
cnode۰model γ σ₀ base descr (root, δs) ς ∗
⌜δs = [] → ς = descr.(descriptor۰store)⌝ ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base cnodes; ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
#[local] Lemma sstore_2٠collectーspecーbaseーchain {γ σ₀ root ς cnodes ϵs base descr δs} i δ node acc :
δs !! i = Some δ →
δ.(delta۰node) = node →
{{{
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠collect #node acc
{{{
acc'
, RET (#root, acc');
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
plist۰model acc' acc $ tail $
(λ δ, #δ.(delta۰node)) <$> reverse (drop i δs)
}}}.
#[local] Definition collectーspecification γ σ₀ root ς cnodes ϵs base descr δs : iProp Σ :=
∀ cnode descr_cnode path acc,
{{{
⌜cnodes !! cnode = Some descr_cnode⌝ ∗
⌜treemap۰path ϵs base cnode path⌝ ∗
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠collect #cnode acc
{{{
acc'
, RET (#root, acc');
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
plist۰model acc' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
[ #cnode]
}}}.
#[local] Lemma sstore_2٠collectーspecーchain {γ σ₀ root ς cnodes ϵs base descr δs} cnode ϵ i 𝝳 node path acc :
ϵs !! cnode = Some ϵ →
ϵ.2 !! i = Some 𝝳 →
𝝳.(delta۰node) = node →
treemap۰path ϵs base ϵ.1 path →
{{{
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
collectーspecification γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠collect #node acc
{{{
acc'
, RET (#root, acc');
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
plist۰model acc' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
((λ δ, #δ.(delta۰node)) <$> reverse (drop i ϵ.2))
}}}.
#[local] Lemma sstore_2٠collectーspec {γ σ₀ root ς cnodes ϵs base descr δs} cnode descr_cnode path acc :
cnodes !! cnode = Some descr_cnode →
treemap۰path ϵs base cnode path →
{{{
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠collect #cnode acc
{{{
acc'
, RET (#root, acc');
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs ∗
plist۰model acc' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
[ #cnode]
}}}.
#[local] Definition revert۰pre₁ γ σ₀ root ς cnodes ϵs base descr δs : iProp Σ :=
∃ v_root,
root ↦ᵣ v_root ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ ς,
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
⌜cnodes !! base = Some descr⌝ ∗
cnode۰model γ σ₀ base descr (root, δs) ς ∗
⌜δs = [] → ς = descr.(descriptor۰store)⌝ ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base cnodes; ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
#[local] Definition revert۰pre₂ γ σ₀ ς cnodes ϵs base descr_base δs_base cnode descr_cnode δs_cnode node : iProp Σ :=
∃ v_node,
node ↦ᵣ v_node ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ ς,
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
⌜cnodes !! base = Some descr_base⌝ ∗
cnode۰model γ σ₀ base descr_base (node, δs_base) ς ∗
⌜cnodes !! cnode = Some descr_cnode⌝ ∗
cnode۰model γ σ₀ cnode descr_cnode (node, δs_cnode) ς ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base $ delete cnode cnodes; delete cnode ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
#[local] Definition revert۰post γ σ₀ cnodes ϵs base descr : iProp Σ :=
base ↦ᵣ §Root ∗
( [∗ map] r ↦ data ∈ store۰on σ₀ descr.(descriptor۰store),
r.[ref_gen] ↦ #data.(gen) ∗
r.[ref_value] ↦ data.(val)
) ∗
⌜treemap۰rooted ϵs base⌝ ∗
cnodes۰auth γ cnodes ∗
cnode۰model γ σ₀ base descr (base, []) descr.(descriptor۰store) ∗
[∗ map] cnode ↦ descr; ϵ ∈ delete base cnodes; ϵs,
∃ descr',
⌜cnodes !! ϵ.1 = Some descr'⌝ ∗
cnode۰model γ σ₀ cnode descr ϵ descr'.(descriptor۰store).
#[local] Lemma sstore_2٠revertーspecーaux {γ σ₀ ς cnodes ϵs base descr_base δs_base cnode descr_cnode δs_cnode node} base' descr_base' path δs acc :
cnodes !! base' = Some descr_base' →
treemap۰path ϵs cnode base' path →
ϵs !! cnode = Some (base, δs) →
0 < length δs_cnode →
NoDup (delta۰ref <$> δs_cnode ++ δs_base) →
list۰model' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs_cnode) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
[ #base'] →
{{{
revert۰pre₂ γ σ₀ ς cnodes ϵs base descr_base δs_base cnode descr_cnode δs_cnode node
}}}
sstore_2٠revert #node acc
{{{
ϵs
, RET ();
revert۰post γ σ₀ cnodes ϵs base' descr_base'
}}}.
#[local] Lemma sstore_2٠revertーspec {γ σ₀ root ς cnodes ϵs base descr_base δs} base' descr_base' path acc :
cnodes !! base' = Some descr_base' →
treemap۰path ϵs base base' path →
list۰model' acc $ tail $
((λ δ, #δ.(delta۰node)) <$> reverse δs) ++
((λ δ, #δ.(delta۰node)) <$> reverse (concat path)) ++
[ #base'] →
{{{
revert۰pre₁ γ σ₀ root ς cnodes ϵs base descr_base δs
}}}
sstore_2٠revert #root acc
{{{
ϵs
, RET ();
revert۰post γ σ₀ cnodes ϵs base' descr_base'
}}}.
#[local] Lemma sstore_2٠rerootーspec {γ σ₀ root ς cnodes ϵs base descr δs} base' descr' path :
cnodes !! base' = Some descr' →
treemap۰path ϵs base base' path →
{{{
collect۰inv γ σ₀ root ς cnodes ϵs base descr δs
}}}
sstore_2٠reroot #base'
{{{
ϵs
, RET ();
revert۰post γ σ₀ cnodes ϵs base' descr'
}}}.
Lemma sstore_2٠restoreーspec t σ₀ σ s σ' :
{{{
sstore_2۰model t σ₀ σ ∗
sstore_2۰snapshot s t σ'
}}}
sstore_2٠restore t s
{{{
RET ();
sstore_2۰model t σ₀ σ'
}}}.
End sstore_2۰G.
#[global] Opaque sstore_2۰model.
#[global] Opaque sstore_2۰snapshot.
End base.
Require zoo_persistent.sstore_2__opaque.
Class Sstore2G Σ `{zoo۰G : !ZooG Σ} :=
{ #[local] sstore_2۰G۰raw۰G :: base.Sstore2G Σ
; #[local] sstore_2۰G۰support۰G :: MonoGmapG Σ location val
}.
Definition sstore_2۰Σ :=
#[base.sstore_2۰Σ
; mono_gmap۰Σ location val
].
#[global] Instance subGーsstore_2۰Σ Σ `{zoo۰G : !ZooG Σ} :
subG sstore_2۰Σ Σ →
Sstore2G Σ.
Section sstore_2۰G.
Context `{sstore_2۰G : Sstore2G Σ}.
#[local] Definition metadata :=
gname.
Implicit Type γ : metadata.
Definition sstore_2۰model t σ : iProp Σ :=
∃ l γ σ₀ ς,
⌜t = #l⌝ ∗
⌜σ ⊆ ς ∪ σ₀⌝ ∗
l ↪[nroot.@"user"] γ ∗
mono_gmap۰auth γ (DfracOwn 1) σ₀ ∗
base.sstore_2۰model t σ₀ ς.
Definition sstore_2۰snapshot s t σ : iProp Σ :=
∃ l γ σ₀ ς,
⌜t = #l⌝ ∗
⌜σ ⊆ ς ∪ σ₀⌝ ∗
l ↪[nroot.@"user"] γ ∗
mono_gmap۰lb γ σ₀ ∗
base.sstore_2۰snapshot s t ς.
#[global] Instance sstore_2۰modelーtimeless t σ :
Timeless (sstore_2۰model t σ).
#[global] Instance sstore_2۰snapshotーpersistent s t σ :
Persistent (sstore_2۰snapshot s t σ).
Lemma sstore_2۰modelーexclusive t σ1 σ2 :
sstore_2۰model t σ1 -∗
sstore_2۰model t σ2 -∗
False.
Lemma sstore_2٠createーspec :
{{{
True
}}}
sstore_2٠create ()
{{{
t
, RET t;
sstore_2۰model t ∅
}}}.
Lemma sstore_2٠refーspec t σ v :
{{{
sstore_2۰model t σ
}}}
sstore_2٠ref t v
{{{
r
, RET #r;
⌜σ !! r = None⌝ ∗
sstore_2۰model t (<[r := v]> σ)
}}}.
Lemma sstore_2٠getーspec {t σ r} v :
σ !! r = Some v →
{{{
sstore_2۰model t σ
}}}
sstore_2٠get t #r
{{{
RET v;
sstore_2۰model t σ
}}}.
Lemma sstore_2٠setーspec t σ r v :
r ∈ dom σ →
{{{
sstore_2۰model t σ
}}}
sstore_2٠set t #r v
{{{
RET ();
sstore_2۰model t (<[r := v]> σ)
}}}.
Lemma sstore_2٠captureーspec t σ :
{{{
sstore_2۰model t σ
}}}
sstore_2٠capture t
{{{
s
, RET s;
sstore_2۰model t σ ∗
sstore_2۰snapshot s t σ
}}}.
Lemma sstore_2٠restoreーspec t σ s σ' :
{{{
sstore_2۰model t σ ∗
sstore_2۰snapshot s t σ'
}}}
sstore_2٠restore t s
{{{
RET ();
sstore_2۰model t σ'
}}}.
End sstore_2۰G.
#[global] Opaque sstore_2۰model.
#[global] Opaque sstore_2۰snapshot.