Definition on_path b o p :=
In b (concat (lookup_path_oram o p)).

(* Specifications: *)
Lemma block_dec (b : block) bs :
In b bs \/ ~ In b bs.
Lemma on_path_dec b o : forall p,
on_path b o p \/ ~ on_path b o p.
Lemma pos_map_stable_across_wb : forall n p s start,
state_position_map s = state_position_map (write_back_r start p n s).
Lemma calc_path_pos_map_same : forall id s s',
state_position_map s = state_position_map s' ->
calc_path id s = calc_path id s'.
Lemma in_clear_path b o : forall p p',
In b (concat (lookup_path_oram o p)) ->
~ In b (concat (lookup_path_oram o p')) ->
In b (concat (lookup_path_oram (clear_path o p') p)).
Lemma get_pre_wb_st_Read_state_state : forall (id id' : block_id) (v : nat) (s : state) (p_new : path),
blk_in_state id v s ->
blk_in_state id v ((get_pre_wb_st id' Read s
(calc_path id' s) p_new)).
Lemma get_pre_wb_st_Write_state_state : forall (id id' : block_id) (v v': nat) (s : state) (p_new : path),
id <> id' ->
blk_in_state id v s ->
blk_in_state id v ((get_pre_wb_st id' (Write v') s
(calc_path id' s) p_new)).
Lemma In_path_in_tree_block : forall o p b,
In b (concat (lookup_path_oram o p)) ->
In b (get_all_blks_tree o).
Lemma NoDup_tree_id_same_v:
forall id v v' l,
NoDup (List.map block_blockid l) ->
In (Block id v) l ->
In (Block id v') l ->
v = v'.
Lemma In_tree_in_path :
forall s id v,
well_formed s ->
In (Block id v) (get_all_blks_tree (state_oram s)) ->
blk_in_path id v s.
Lemma blk_in_p_nil_Some id v o1 o2 data :
blk_in_p id v (node (Some data) o1 o2) [] ->
In (Block id v) data.
Lemma blk_in_p_nil_None id v o1 o2 :
~ blk_in_p id v (node None o1 o2) [].
Lemma blk_in_p_cons_true id v o1 o2 p data :
blk_in_p id v o1 p ->
blk_in_p id v (node data o1 o2) (true :: p).
Lemma blk_in_p_cons_false id v o1 o2 p data :
blk_in_p id v o2 p ->
blk_in_p id v (node data o1 o2) (false :: p).
Lemma blk_in_p_true_Some id v o1 o2 p data :
blk_in_p id v (node (Some data) o1 o2) (true :: p) ->
In (Block id v) data \/ blk_in_p id v o1 p.
Lemma blk_in_p_true_None id v o1 o2 p :
blk_in_p id v (node None o1 o2) (true :: p) ->
blk_in_p id v o1 p.
Lemma blk_in_p_false_Some id v o1 o2 p data :
blk_in_p id v (node (Some data) o1 o2) (false :: p) ->
In (Block id v) data \/ blk_in_p id v o2 p.
Lemma blk_in_p_false_None id v o1 o2 p :
blk_in_p id v (node None o1 o2) (false :: p) ->
blk_in_p id v o2 p.
Lemma blk_in_p_clear_path:
forall o p p_new id v,
blk_in_p id v (clear_path o p) p_new ->
blk_in_p id v o p_new.
Lemma stash_path_combined_rel_Rd_undef : forall (id id' : block_id) (s : state) (p_new : path),
well_formed s ->
undef id s ->
undef id ((get_pre_wb_st id' Read s
(calc_path id' s) p_new)).
Lemma stash_path_combined_rel_Wr_undef : forall (id id' : block_id) (v : nat) (s : state) (p_new : path),
id <> id' ->
well_formed s ->
undef id' s ->
undef id' ((get_pre_wb_st id (Write v) s
(calc_path id s) p_new)).
Lemma get_pre_wb_st_Write_stsh : forall (id : block_id) (v : nat) (s : state) (p_new : path),
blk_in_stash id v
((get_pre_wb_st id (Write v) s
(calc_path id s)
p_new)).
Lemma calc_path_write_bk_r_stable : forall start id s n p ,
calc_path id (write_back_r start p n s) = calc_path id s.
Lemma path_conversion : forall o lvl p p' b,
isEqvPath p p' lvl = true ->
at_lvl_in_path o lvl p b -> at_lvl_in_path o lvl p' b.
Lemma locate_comp_block_selection :
forall o p p' lvl lvl' dlt,
(lvl < lvl')%nat ->
locate_node_in_tr (up_oram_tr o lvl dlt p') lvl' p =
locate_node_in_tr o lvl' p.
Lemma at_lvl_in_path_blocks_selection :
forall s p p' lvl lvl' b,
(lvl < lvl')%nat ->
at_lvl_in_path (state_oram s) lvl' p b ->
at_lvl_in_path (state_oram (blocks_selection p' lvl s)) lvl' p b.
Lemma kv_in_delta_in_tree :
forall (o : oram) (id : block_id) (v : nat) (del : list block) (lvl: nat )(p :path),
In (Block id v) del ->
coord_in_bound o p lvl ->
at_lvl_in_path (up_oram_tr o lvl del p) lvl p (Block id v).
Lemma path_eq_get_cand_bs : forall id v h p stop m,
In (Block id v) (get_cand_bs h p stop m) ->
isEqvPath p (lookup_dict (makeBoolList false LOP) id m) stop = true.
Lemma stash_block_selection : forall p s id v lvl,
well_formed s ->
length p = LOP ->
Nat.le lvl LOP ->
blk_in_stash id v s ->
blk_in_stash id v (blocks_selection p lvl s) \/
(at_lvl_in_path (state_oram
(blocks_selection p lvl s)) lvl p (Block id v) /\
at_lvl_in_path (state_oram
(blocks_selection p lvl s)) lvl (calc_path id s) (Block id v)
).
Lemma up_oram_tr_preserves_pb : forall o lvl dlt p n,
is_p_b_tr o n ->
is_p_b_tr (up_oram_tr o lvl dlt p) n.
Lemma disjoint_weaken2 : forall dlt l lst,
disjoint_list
(List.map block_blockid l)
(List.map block_blockid lst) ->
subset_rel dlt lst ->
disjoint_list
(List.map block_blockid l)
(List.map block_blockid dlt).
Lemma get_write_back_blocks_subset : forall lst p lvl pos_map,
subset_rel (get_write_back_blocks p lst 4 lvl pos_map) lst.
Lemma In_path_in_tree : forall o p id,
In id (List.map block_blockid (concat (lookup_path_oram o p))) ->
In id (List.map block_blockid (get_all_blks_tree o)).
Lemma in_up_oram_tr : forall o id lvl dlt p p',
NoDup (List.map block_blockid (get_all_blks_tree o)) ->
In id (List.map block_blockid (get_all_blks_tree (up_oram_tr o lvl dlt p'))) ->
In id (List.map block_blockid (concat (lookup_path_oram o p))) ->
In id (List.map block_blockid (concat (lookup_path_oram (up_oram_tr o lvl dlt p') p))).
Lemma get_write_back_blocks_pos_map : forall id p stsh lvl pos_map,
In id (List.map block_blockid
(get_write_back_blocks p stsh 4 lvl pos_map)) ->
let p' := lookup_dict (makeBoolList false LOP) id pos_map in
isEqvPath p p' lvl = true.
Lemma isEqvPath_lookup_path_oram : forall o n id lvl dlt p p',
is_p_b_tr o (S n) ->
length p = n ->
length p' = n ->
(lvl < n)%nat ->
In id (List.map block_blockid dlt) ->
isEqvPath p p' lvl = true ->
In id (List.map block_blockid
(concat (lookup_path_oram
(up_oram_tr o lvl dlt p) p'))).
Lemma blocks_selection_wf : forall
(p : path) (lvl : nat) (s : state),
well_formed s ->
length p = LOP ->
(lvl < LOP)%nat ->
well_formed (blocks_selection p lvl s).
Lemma write_back_wf : forall (step start : nat) (s : state) (p : path),
length p = LOP ->
well_formed s ->
Nat.le (start + step) LOP ->
well_formed (write_back_r start p step  s).
Lemma write_back_in_stash_kv_rel_aux : forall n s p id v start,
well_formed s ->
length p = LOP ->
Nat.le (start + n) LOP ->
blk_in_stash id v s ->
blk_in_stash id v (write_back_r start p n s) \/
exists k, (start <= k /\
at_lvl_in_path (state_oram (write_back_r start p n s)) k p (Block id v) /\
at_lvl_in_path (state_oram (write_back_r start p n s)) k (calc_path id s) (Block id v))%nat.
Lemma locate_node_in_path : forall o lvl p b,
locate_node_in_tr o lvl p = Some b ->
In b (lookup_path_oram o p).
Lemma weaken_at_lvl_in_path : forall o lvl p id v,
at_lvl_in_path o lvl p (Block id v) ->
blk_in_p id v o p.
Lemma write_back_in_stash_state : forall s id v p,
well_formed s ->
length p = LOP ->
blk_in_stash id v s ->
blk_in_state id v (write_back_r O p (length p) s).
Lemma get_post_wb_st_stsh_state : forall (id : block_id) (v : nat) (s : state) (p : path),
well_formed s ->
length p = LOP ->
blk_in_stash id v s ->
blk_in_state id v (get_post_wb_st s p).