Library zoo.program_logic.ghost_state

Require Export iris.bi.lib.fractional.
Require Import iris.base_logic.lib.ghost_map.
Require Import iris.base_logic.lib.invariants.

Require Import zoo.prelude.
Require Import zoo.iris.bi.big_op.
Require Import zoo.iris.base_logic.lib.auth_nat_max.
Require Import zoo.iris.base_logic.lib.ghost_heap.
Require Import zoo.iris.base_logic.lib.ghost_list.
Require Import zoo.iris.base_logic.lib.mono_list.
Require Import zoo.iris.diaframe.
Require Export zoo.language.language.
Require Import zoo.language.notations.
Require Import zoo.options.

Implicit Type cnt ns nt : nat.
Implicit Type pid : prophet_id.
Implicit Type tid : thread_id.
Implicit Type l : location.
Implicit Type v : val.
Implicit Type vs : list val.
Implicit Type hdr : header.
Implicit Type hdrs : gmap location header.
Implicit Type σ : state.
Implicit Type proph : val × val.
Implicit Type prophs : list (val × val).
Implicit Type prophets : gmap prophet_id (list (val × val)).
Implicit Type κ κs : list observation.

Parameter zoo_counter : location.

Class ZooG₀ Σ :=
  { #[local] zoo۰G₀۰headers۰G :: GhostHeapG Σ location header
  ; #[local] zoo۰G₀۰heap۰G :: ghost_mapG Σ location val
  ; #[local] zoo۰G₀۰prophets۰G :: ghost_mapG Σ prophet_id (list (val × val))
  ; #[local] zoo۰G₀۰steps۰G :: AuthNatMaxG Σ
  ; #[local] zoo۰G₀۰locals۰G :: GhostListG Σ val
  ; #[local] zoo۰G₀۰counter۰G :: MonoListG Σ val
  }.

#[local] Definition zoo۰Σ₀ :=
  #[ghost_heap۰Σ location header
  ; ghost_mapΣ location val
  ; ghost_mapΣ prophet_id (list (val × val))
  ; auth_nat_max۰Σ
  ; ghost_list۰Σ val
  ; mono_list۰Σ val
  ].
#[local] Instance subGzoo۰Σ₀ Σ :
  subG zoo۰Σ₀ Σ
  ZooG₀ Σ.

Class ZooGpre Σ :=
  { #[global] zoo۰Gpre۰inv۰Gpre :: invGpreS Σ
  ; #[local] zoo۰Gpre۰G₀ :: ZooG₀ Σ
  }.

Definition zoo۰Σ :=
  #[invΣ
  ; zoo۰Σ₀
  ].
#[global] Instance subGzoo۰Σ Σ :
  subG zoo۰Σ Σ
  ZooGpre Σ.

Class ZooG Σ :=
  { #[global] zoo۰G۰inv۰G :: invGS Σ
  ; #[local] zoo۰G۰G₀ :: ZooG₀ Σ
  ; zoo۰G۰headers۰name : ghost_heap۰name
  ; zoo۰G۰heap۰name : gname
  ; zoo۰G۰prophets۰name : gname
  ; zoo۰G۰steps۰name : gname
  ; zoo۰G۰locals۰name : gname
  ; zoo۰G۰counter۰name : gname
  }.
#[global] Arguments Build_ZooG {_ _ _} _ _ _ _ _ _ : assert.

Section zoo۰G₀.
  Context `{zoo۰G₀ : !ZooG₀ Σ}.

  #[local] Definition headers۰auth' γ_headers hdrs :=
    ghost_heap۰auth γ_headers hdrs.
  #[local] Definition headers۰at' γ_headers l hdr :=
    ghost_heap۰at γ_headers l DfracDiscarded hdr.

  #[local] Definition meta_token' γ_headers l E :=
    ghost_heap۰meta_token γ_headers l E.
  #[local] Definition meta' `{Countable A} γ_headers l ι (x : A) :=
    ghost_heap۰meta γ_headers l ι x.

  #[local] Lemma headersalloc hdrs :
     |==>
       γ_headers,
      headers۰auth' γ_headers hdrs.
End zoo۰G₀.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Definition headers۰auth :=
    headers۰auth' zoo۰G۰headers۰name.
  Definition headers۰at :=
    headers۰at' zoo۰G۰headers۰name.

  Definition meta_token :=
    meta_token' zoo۰G۰headers۰name.
  Definition meta `{Countable A} :=
    meta' (A := A) zoo۰G۰headers۰name.
End zoo۰G.

Notation "l ↦ₕ hdr" := (
  headers۰at l hdr
)(at level 20,
  format "l ↦ₕ hdr"
) : bi_scope.

Notation "l ↪[ ι ] x" := (
  meta l ι x
)(at level 20,
  format "l ↪[ ι ] x"
) : bi_scope.
Notation "l ↪ x" := (
  meta l nroot x
)(at level 20,
  format "l ↪ x"
) : bi_scope.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  #[global] Instance headers۰attimeless l hdr :
    Timeless (l ↦ₕ hdr).

  #[global] Instance headers۰atpersistent l hdr :
    Persistent (l ↦ₕ hdr).

  Lemma headers۰atagree l hdr1 hdr2 :
    l ↦ₕ hdr1 -∗
    l ↦ₕ hdr2 -∗
    hdr1 = hdr2.
End zoo۰G.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  #[global] Instance meta_tokentimeless l N :
    Timeless (meta_token l N).
  #[global] Instance metatimeless `{Countable A} l ι (x : A) :
    Timeless (l ↪[ι] x).

  #[global] Instance metapersistent `{Countable A} l ι (x : A) :
    Persistent (l ↪[ι] x).

  Lemma meta_tokendifference {l} E1 E2 :
    E1 E2
    meta_token l E2 ⊣⊢
      meta_token l E1
      meta_token l (E2 E1).

  Lemma metaset `{Countable A} {l E} (x : A) ι :
     ι E
    meta_token l E |==>
    l ↪[ι] x.
  Lemma metaagree `{Countable A} l ι (x1 x2 : A) :
    l ↪[ι] x1 -∗
    l ↪[ι] x2 -∗
    x1 = x2.

  Lemma headerslookup hdrs l hdr :
    headers۰auth hdrs -∗
    l ↦ₕ hdr -∗
    hdrs !! l = Some hdr.

  Lemma headersinsert {hdrs} l hdr :
    hdrs !! l = None
    headers۰auth hdrs |==>
      headers۰auth (<[l := hdr]> hdrs)
      l ↦ₕ hdr
      meta_token l .
End zoo۰G.

#[global] Opaque headers۰auth'.
#[global] Opaque headers۰at'.
#[global] Opaque meta_token'.
#[global] Opaque meta'.

Section zoo۰G₀.
  Context `{zoo۰G₀ : !ZooG₀ Σ}.

  #[local] Definition heap۰auth' γ_heap h :=
    ghost_map_auth (V := val) γ_heap 1 h.
  #[local] Definition pointsto' γ_heap l dq v :=
    ghost_map_elem (V := val) γ_heap l dq v.

  #[local] Lemma heapalloc h :
     |==>
       γ_heap,
      heap۰auth' γ_heap h
      [∗ map] l v h, pointsto' γ_heap l (DfracOwn 1) v.
End zoo۰G₀.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Definition heap۰auth :=
    heap۰auth' zoo۰G۰heap۰name.
  Definition pointsto :=
    pointsto' zoo۰G۰heap۰name.
End zoo۰G.

Notation "l ↦ dq v" := (
  pointsto l dq v%V
)(at level 20,
  dq custom dfrac at level 1,
  format "l ↦ dq v"
) : bi_scope.
Notation "l ↦-" := (
  ( v, l v)%I
)(at level 20,
  format "l ↦-"
) : bi_scope.

Notation "l ↦∗ dq vs" :=
  ([∗ list] i v vs, (l +ₗ i) {dq} v)%I
( at level 20,
  dq custom dfrac at level 1,
  format "l ↦∗ dq vs"
) : bi_scope.
Notation "l ↦∗-" :=
  ( vs, l ↦∗ vs)%I
( at level 20,
  format "l ↦∗-"
) : bi_scope.

Notation "l ↦ᵣ dq v" := (
  pointsto (location۰add l (Z.of_nat (in_type "ref" 0))) dq v%V
)(at level 20,
  dq custom dfrac at level 1,
  format "l ↦ᵣ dq v"
) : bi_scope.
Notation "l ↦ᵣ-" := (
  ( v, l ↦ᵣ v)%I
)(at level 20,
  format "l ↦ᵣ-"
) : bi_scope.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  #[global] Instance pointstotimeless l dq v :
    Timeless (l {dq} v).

  #[global] Instance pointstopersistent l v :
    Persistent (l v).

  #[global] Instance pointstofractional l v :
    Fractional (λ q, l {#q} v)%I.
  #[global] Instance pointstoas_fractional l q v :
    AsFractional (l {#q} v) (λ q, l {#q} v)%I q.

  Lemma pointstovalid l dq v :
    l {dq} v
     dq.
  Lemma pointstocombine l dq1 v1 dq2 v2 :
    l {dq1} v1 -∗
    l {dq2} v2 -∗
      v1 = v2
      l {dq1 dq2} v1.
  Lemma pointstovalidー2 l dq1 v1 dq2 v2 :
    l {dq1} v1 -∗
    l {dq2} v2 -∗
       (dq1 dq2)
      v1 = v2.
  Lemma pointstoagree l dq2 v1 dq1 v2 :
    l {dq1} v1 -∗
    l {dq2} v2 -∗
    v1 = v2.
  Lemma pointstodfracne l1 dq1 v1 l2 dq2 v2 :
    ¬ (dq1 dq2)
    l1 {dq1} v1 -∗
    l2 {dq2} v2 -∗
    l1 l2.
  Lemma pointstone l1 v1 l2 dq2 v2 :
    l1 v1 -∗
    l2 {dq2} v2 -∗
    l1 l2.
  Lemma pointstoexclusive l v1 dq2 v2 :
    l v1 -∗
    l {dq2} v2 -∗
    False.
  Lemma pointstopersist l dq v :
    l {dq} v |==>
    l v.

  #[global] Instance pointstocombine_sep_gives l dq1 v1 dq2 v2 :
    CombineSepGives (l {dq1} v1) (l {dq2} v2) (dq1 dq2) v1 = v2
  | 30.
  #[global] Instance pointstocombine_as l dq1 dq2 v1 v2 :
    CombineSepAs (l {dq1} v1) (l {dq2} v2) (l {dq1 dq2} v1)
  | 60.
  #[global] Instance framepointsto p l v q1 q2 q :
    FrameFractionalQp q1 q2 q
    Frame p (l {#q1} v) (l {#q2} v) (l {#q} v)
  | 5.

  Lemma heaplookup h a dq c :
    heap۰auth h -∗
    a {dq} c -∗
    h !! a = Some c.
  Lemma heapinsert {h1} h2 :
    h2 ##ₘ h1
    heap۰auth h1 |==>
      heap۰auth (h2 h1)
      [∗ map] l v h2, l v.
  Lemma heapupdate {h a c1} c2 :
    heap۰auth h -∗
    a c1 ==∗
      heap۰auth (<[a := c2]> h)
      a c2.
End zoo۰G.

#[global] Opaque heap۰auth'.
#[global] Opaque pointsto'.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Lemma big_sepL2pointstoagree ls dq1 vs1 dq2 vs2 :
    ([∗ list] l; v ls; vs1, l {dq1} v) -∗
    ([∗ list] l; v ls; vs2, l {dq2} v) -∗
    vs1 = vs2.
  Lemma big_sepL2refpointstoagree ls dq1 vs1 dq2 vs2 :
    ([∗ list] l; v ls; vs1, l ↦ᵣ{dq1} v) -∗
    ([∗ list] l; v ls; vs2, l ↦ᵣ{dq2} v) -∗
    vs1 = vs2.

  Lemma big_sepL2pointstoprefix ls1 dq1 vs1 ls2 dq2 vs2 :
    ls1 `prefix_of` ls2
    ([∗ list] l; v ls1; vs1, l {dq1} v) -∗
    ([∗ list] l; v ls2; vs2, l {dq2} v) -∗
    vs1 `prefix_of` vs2.
  Lemma big_sepL2refpointstoprefix ls1 dq1 vs1 ls2 dq2 vs2 :
    ls1 `prefix_of` ls2
    ([∗ list] l; v ls1; vs1, l ↦ᵣ{dq1} v) -∗
    ([∗ list] l; v ls2; vs2, l ↦ᵣ{dq2} v) -∗
    vs1 `prefix_of` vs2.

  Lemma big_sepL2pointstosuffix ls1 dq1 vs1 ls2 dq2 vs2 :
    ls1 `suffix_of` ls2
    ([∗ list] l; v ls1; vs1, l {dq1} v) -∗
    ([∗ list] l; v ls2; vs2, l {dq2} v) -∗
    vs1 `suffix_of` vs2.
  Lemma big_sepL2refpointstosuffix ls1 dq1 vs1 ls2 dq2 vs2 :
    ls1 `suffix_of` ls2
    ([∗ list] l; v ls1; vs1, l ↦ᵣ{dq1} v) -∗
    ([∗ list] l; v ls2; vs2, l ↦ᵣ{dq2} v) -∗
    vs1 `suffix_of` vs2.
End zoo۰G.

Section resolve_prophecies.
  #[local] Fixpoint resolve_prophecies κs pid :=
    match κs with
    | []
        []
    | κ :: κs
        if decide (pid = κ.1) then
          κ.2 :: resolve_prophecies κs pid
        else
          resolve_prophecies κs pid
    end.

  #[local] Definition resolve_prophets prophets κs :=
    map_Forall (λ pid prophs, prophs = resolve_prophecies κs pid) prophets.

  #[local] Lemma resolve_prophetsinsert κs pid prophets :
    resolve_prophets prophets κs
    pid dom prophets
    resolve_prophets (<[pid := resolve_prophecies κs pid]> prophets) κs.
End resolve_prophecies.

Section zoo۰G₀.
  Context `{zoo۰G₀ : !ZooG₀ Σ}.

  #[local] Definition prophets۰auth' γ_prophets κs pids : iProp Σ :=
     prophets,
    resolve_prophets prophets κs
    dom prophets pids
    ghost_map_auth γ_prophets 1 prophets.
  #[local] Definition prophet۰model' γ_prophets pid prophs :=
    ghost_map_elem γ_prophets pid (DfracOwn 1) prophs.

  #[local] Lemma prophetsalloc κs pids :
     |==>
       γ_prophets,
      prophets۰auth' γ_prophets κs pids.
End zoo۰G₀.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Definition prophets۰auth :=
    prophets۰auth' zoo۰G۰prophets۰name.
  Definition prophet۰model :=
    prophet۰model' zoo۰G۰prophets۰name.

  #[global] Instance prophet۰modeltimeless pid prophs :
    Timeless (prophet۰model pid prophs).

  Lemma prophet۰modelexclusive pid prophs1 prophs2 :
    prophet۰model pid prophs1 -∗
    prophet۰model pid prophs2 -∗
    False.

  Lemma prophetsnew {κs pids} pid :
    pid pids
    prophets۰auth κs pids |==>
       prophs,
      prophets۰auth κs ({[pid]} pids)
      prophet۰model pid prophs.

  Lemma prophetsresolve pid proph κs pids prophs :
    prophets۰auth ((pid, proph) :: κs) pids -∗
    prophet۰model pid prophs ==∗
       prophs',
      prophs = proph :: prophs'
      prophets۰auth κs pids
      prophet۰model pid prophs'.
End zoo۰G.

#[global] Opaque prophets۰auth'.
#[global] Opaque prophet۰model'.

Section zoo۰G₀.
  Context `{zoo۰G₀ : !ZooG₀ Σ}.

  #[local] Definition steps۰auth' γ_steps :=
    auth_nat_max۰auth γ_steps (DfracOwn 1).
  #[local] Definition steps۰lb' :=
    auth_nat_max۰lb.

  #[local] Lemma stepsalloc :
     |==>
       γ_steps,
      steps۰auth' γ_steps 0.
End zoo۰G₀.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Definition steps۰auth :=
    steps۰auth' zoo۰G۰steps۰name.
  Definition steps۰lb :=
    auth_nat_max۰lb zoo۰G۰steps۰name.
End zoo۰G.

Notation "⧖ n" := (
  steps۰lb n
)(at level 1,
  format "⧖ n"
) : bi_scope.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  #[global] Instance steps۰authtimeless ns :
    Timeless (steps۰auth ns).
  #[global] Instance steps۰lbtimeless ns :
    Timeless ( ns).

  #[global] Instance steps۰lbpersistent ns :
    Persistent ( ns).

  Lemma steps۰lbー0 :
     |==>
       0.
  Lemma steps۰lble ns1 ns2 :
    ns2 ns1
     ns1
     ns2.
  Lemma steps۰lbmax ns1 ns2 :
     ns1 -∗
     ns2 -∗
     (ns1 `max` ns2).

  Lemma steps۰lbget ns :
    steps۰auth ns
     ns.
  Lemma steps۰lbvalid ns1 ns2 :
    steps۰auth ns1 -∗
     ns2 -∗
    ns2 ns1.

  Lemma stepsupdate ns :
    steps۰auth ns |==>
    steps۰auth ˖ns.

  #[global] Instance hintsteps۰lble ns1 ns2 :
    SolveSepSideCondition (ns1 ns2)
    HINT
       ns2
     [- ;
      emp
    ] [id];
       ns1
     [
      emp
    ]
    | 60.
  #[global] Instance mergesteps۰lb ns1 ns2 :
    MergableConsume ( ns1) true (λ p Pin Pout,
      TCAnd (
        TCEq Pin ( ns2)%I
      ) (
        TCEq Pout ( (ns1 `max` ns2))%I
      )
    ).
End zoo۰G.

#[global] Opaque steps۰auth'.
#[global] Opaque steps۰lb'.

Section zoo۰G₀.
  Context `{zoo۰G₀ : !ZooG₀ Σ}.

  #[local] Definition locals۰auth' γ_locals vs :=
    ghost_list۰auth γ_locals vs.
  #[local] Definition local_pointsto' γ_locals tid dq v :=
    ghost_list۰at γ_locals tid dq v.

  #[local] Lemma localsalloc vs :
     |==>
       γ_locals,
      locals۰auth' γ_locals vs
      [∗ list] tid v vs, local_pointsto' γ_locals tid (DfracOwn 1) v.
End zoo۰G₀.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Definition locals۰auth :=
    locals۰auth' zoo۰G۰locals۰name.
  Definition local_pointsto :=
    local_pointsto' zoo۰G۰locals۰name.
End zoo۰G.

Notation "tid ↦ₗ dq v" := (
  local_pointsto tid dq v%V
)(at level 20,
  dq custom dfrac at level 1,
  format "tid ↦ₗ dq v"
) : bi_scope.
Notation "tid ↦ₗ-" := (
  ( v, tid ↦ₗ v)%I
)(at level 20,
  format "tid ↦ₗ-"
) : bi_scope.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  #[global] Instance local_pointstotimeless tid dq v :
    Timeless (tid ↦ₗ{dq} v).

  #[global] Instance local_pointstopersistent tid v :
    Persistent (tid ↦ₗ v).

  #[global] Instance local_pointstofractional tid v :
    Fractional (λ q, tid ↦ₗ{#q} v)%I.
  #[global] Instance local_pointstoas_fractional tid q v :
    AsFractional (tid ↦ₗ{#q} v) (λ q, tid ↦ₗ{#q} v)%I q.

  Lemma local_pointstovalid tid dq v :
    tid ↦ₗ{dq} v
     dq.
  Lemma local_pointstocombine tid dq1 v1 dq2 v2 :
    tid ↦ₗ{dq1} v1 -∗
    tid ↦ₗ{dq2} v2 -∗
      v1 = v2
      tid ↦ₗ{dq1 dq2} v1.
  Lemma local_pointstovalidー2 tid dq1 v1 dq2 v2 :
    tid ↦ₗ{dq1} v1 -∗
    tid ↦ₗ{dq2} v2 -∗
       (dq1 dq2)
      v1 = v2.
  Lemma local_pointstoagree tid dq2 v1 dq1 v2 :
    tid ↦ₗ{dq1} v1 -∗
    tid ↦ₗ{dq2} v2 -∗
    v1 = v2.
  Lemma local_pointstodfracne tid1 dq1 v1 tid2 dq2 v2 :
    ¬ (dq1 dq2)
    tid1 ↦ₗ{dq1} v1 -∗
    tid2 ↦ₗ{dq2} v2 -∗
    tid1 tid2.
  Lemma local_pointstone tid1 v1 tid2 dq2 v2 :
    tid1 ↦ₗ v1 -∗
    tid2 ↦ₗ{dq2} v2 -∗
    tid1 tid2.
  Lemma local_pointstoexclusive tid v1 dq2 v2 :
    tid ↦ₗ v1 -∗
    tid ↦ₗ{dq2} v2 -∗
    False.
  Lemma local_pointstopersist tid dq v :
    tid ↦ₗ{dq} v |==>
    tid ↦ₗ v.

  Lemma localslookup vs tid dq v :
    locals۰auth vs -∗
    tid ↦ₗ{dq} v -∗
    vs !! tid = Some v.

  Lemma localsupdatepush {vs} v :
    locals۰auth vs |==>
      locals۰auth (vs ++ [v])
      length vs ↦ₗ v.
  Lemma localsupdatepointsto {vs tid v} v' :
    locals۰auth vs -∗
    tid ↦ₗ v ==∗
      locals۰auth (<[tid := v']> vs)
      tid ↦ₗ v'.
End zoo۰G.

#[global] Opaque locals۰auth'.
#[global] Opaque local_pointsto'.

Section zoo۰G₀.
  Context `{zoo۰G₀ : !ZooG₀ Σ}.

  #[local] Definition zoo_counter۰auth' γ_counter vs :=
    mono_list۰auth γ_counter (DfracOwn 1) vs.
  #[local] Definition zoo_counter۰at' γ_counter id v :=
    mono_list۰at γ_counter id v.

  #[local] Lemma zoo_counteralloc :
     |==>
       γ_counter,
      zoo_counter۰auth' γ_counter (replicate 0 inhabitant).
End zoo۰G₀.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Definition zoo_counter۰auth :=
    zoo_counter۰auth' zoo۰G۰counter۰name.
  Definition zoo_counter۰at :=
    zoo_counter۰at' zoo۰G۰counter۰name.

  #[global] Instance zoo_counter۰authtimeless vs :
    Timeless (zoo_counter۰auth vs).
  #[global] Instance zoo_counter۰attimeless id v :
    Timeless (zoo_counter۰at id v).

  #[global] Instance zoo_counter۰atpersistent id v :
    Persistent (zoo_counter۰at id v).

  Lemma zoo_counter۰atget {vs} id v :
    vs !! id = Some v
    zoo_counter۰auth vs
    zoo_counter۰at id v.
  Lemma zoo_counter۰atvalid vs id v :
    zoo_counter۰auth vs -∗
    zoo_counter۰at id v -∗
    vs !! id = Some v.
  Lemma zoo_counter۰atagree id v1 v2 :
    zoo_counter۰at id v1 -∗
    zoo_counter۰at id v2 -∗
    v1 = v2.

  Lemma zoo_counterupdate {vs} v :
    zoo_counter۰auth vs |==>
    zoo_counter۰auth (vs ++ [v]).
End zoo۰G.

#[global] Opaque zoo_counter۰auth'.
#[global] Opaque zoo_counter۰at'.

Section zoo۰G.
  Context `{zoo۰G : !ZooG Σ}.

  Definition zoo_counter۰name :=
    zoo۰G۰counter۰name.
  Definition zoo_counter۰inv۰inner : iProp Σ :=
     cnt vs,
    zoo_counter ↦ᵣ #cnt
    zoo_counter۰auth vs
    length vs = cnt.
  Definition zoo_counter۰inv :=
    inv nroot zoo_counter۰inv۰inner.
End zoo۰G.

Lemma zooinit `{zoo۰Gpre : !ZooGpre Σ} `{inv۰G : !invGS Σ} hdrs h pids vs κs :
  h !! zoo_counter = Some 0%V
   |={}=>
     zoo۰G : ZooG Σ,
    zoo۰G.(zoo۰G۰inv۰G) = inv۰G
    headers۰auth hdrs
    heap۰auth h
    prophets۰auth κs pids
    steps۰auth 0
    locals۰auth vs
    zoo_counter۰inv
    ([∗ map] l v delete zoo_counter h, l v)
    ([∗ list] tid v vs, tid ↦ₗ v).

#[global] Opaque headers۰auth.
#[global] Opaque headers۰at.
#[global] Opaque meta_token.
#[global] Opaque meta.
#[global] Opaque heap۰auth.
#[global] Opaque pointsto.
#[global] Opaque prophets۰auth.
#[global] Opaque prophet۰model.
#[global] Opaque steps۰auth.
#[global] Opaque steps۰lb.
#[global] Opaque locals۰auth.
#[global] Opaque local_pointsto.
#[global] Opaque zoo_counter۰auth.
#[global] Opaque zoo_counter۰at.

Variant ownership :=
  | Own
  | Discard.

Coercion ownership۰to_dfrac own :=
  match own with
  | Own
      DfracOwn 1
  | Discard
      DfracDiscarded
  end.