Section DelegatingCalculator.
Variables (l1 l2 : Label).
Hypothesis (lab_disj : l2 != l1).
Variable f : input -> option nat.
Variable prec : input -> bool.
Variables (cs1 cls1 : seq nid).
Variables (cs2 cls2 : seq nid).
Notation nodes1 := (cs1 ++ cls1).
Notation nodes2 := (cs2 ++ cls2).
Hypothesis Huniq1 : uniq nodes1.
Hypothesis Huniq2 : uniq nodes2.
(* Protocol I'm a server in *)
Notation cal1 := (cal_with_inv l1 f prec cs1 cls1).
Notation cal2 := (cal_with_inv l2 f prec cs2 cls2).
Notation W1 := (mkWorld cal1).
Notation W2 := (mkWorld cal2).
(* Composite world *)
Definition V := W1 \+ W2.
(* This server node *)
Variable sv : nid.
(* It's a server in protocol cal1 *)
Hypothesis  Hs1 : sv \in cs1.
(* It's a client in protocol cal2 *)
Hypothesis  Hc2 : sv \in cls2.
(* Delegate server *)
Variable sd : nid.
Hypothesis  Hs2 : sd \in cs2.
Notation loc i k := (getLocal sv (getStatelet i k)).
Notation loc1 i := (loc i l1).
Notation loc2 i := (loc i l2).
(* Delegate computation to someone else *)
Definition delegate_f := compute_f l2 f prec cs2 cls2 _ Hc2 sd.
Notation cal_ii := (ii l1 f prec cs1 cls1).
Definition receive_msg :=
with_inv cal_ii (blocking_receive_req l1 f prec cs1 cls1 _ Hs1).
Definition send_ans to args ans :=
with_inv cal_ii (send_answer l1 f prec cs1 cls1 _ Hs1 to args ans).
Definition delegating_body_spec :=
forall _ : unit,
DHT [sv, V]
(fun i =>
loc1 i = st :-> ([::]:reqs) /\
loc2 i = st :-> ([::]:reqs),
fun (r : unit) m =>
loc1 m = st :-> ([::]:reqs) /\
loc2 m = st :-> ([::]:reqs)).
Program Definition delegating_body :
delegating_body_spec := fun (_ : unit) =>
Do _ (
r <-- uinject (receive_msg);
let: (from, args) := r in
(* Delegate computations *)
ans <-- uinject (delegate_f args);
uinject (send_ans from args ans);;
ret sv V tt).

Lemma hook_complete_unit (c : context) : hook_complete (c, Unit).