packages feed

cpsa-4.4.3: coq/Run_sem.v

(* Correctness of Run semantics

Copyright (c) 2021 The MITRE Corporation

This program is free software: you can redistribute it and/or
modify it under the terms of the BSD License as published by the
University of California. *)

(** This library contains proofs that the semantics specified in
    [Roletran.Run] and [Roletran.Sem] agree. *)

Require Import FunInd List Bool Arith.
Require Import Preamble Proc Alg Sem Alt_sem Run.
Open Scope nat_scope.

Lemma expr_sem_implies_run_expr:
  forall ev tr us exp val tr' us',
    expr_sem ev tr us exp val tr' us' ->
    run_expr (mkRSt ev tr us) exp =
    Some (mkRSt ev tr' us', val).
Proof.
  intros.
  inv H; simpl;
    repeat match goal with
           | [ H: lookup _ _ = Some _ |- _ ] => rewrite H
           end; auto.
  - rewrite H2; simpl.
    destruct (bool_dec (alg_eqb (inv b) (inv b)) true) as [G|G].
    + rewrite G; auto.
    + contradiction G.
      rewrite alg_eq_correct; auto.
  - rewrite Nat.eqb_refl; auto.
Qed.

Lemma run_expr_implies_expr_sem:
  forall rst exp val rst',
    run_expr rst exp = Some (rst', val) ->
    expr_sem (renv rst) (rtr rst) (runiqs rst)
             exp val (rtr rst') (runiqs rst') /\
    renv rst = renv rst'.
Proof.
  intros.
  destruct exp; simpl in H.
  - inv H; simpl; auto.
  - destruct (option_dec (lookup n (renv rst))) as [G|G].
    + rewrite G in H; inv H.
    + destruct G as [b G]; rewrite G in H; inv H; auto.
  - destruct (option_dec (lookup n (renv rst))) as [G|G].
    + rewrite G in H; inv H.
    + destruct G as [b G]; rewrite G in H.
      destruct (option_dec (lookup n0 (renv rst))) as [F|F].
      * rewrite F in H; inv H.
      * destruct F as [c F]; rewrite F in H; inv H; auto.
  - destruct (option_dec (lookup n (renv rst))) as [G|G].
    + rewrite G in H; inv H.
    + destruct G as [b G]; rewrite G in H.
      destruct (option_dec (lookup n0 (renv rst))) as [F|F].
      * rewrite F in H; inv H.
      * destruct F as [c F]; rewrite F in H; inv H; auto.
  - destruct (option_dec (lookup n (renv rst))) as [G|G].
    + rewrite G in H; inv H.
    + destruct G as [b G]; rewrite G in H.
      destruct b; inv H.
      split; auto.
      eapply Expr_frst; eauto.
  - destruct (option_dec (lookup n (renv rst))) as [G|G].
    + rewrite G in H; inv H.
    + destruct G as [b G]; rewrite G in H.
      destruct b; inv H.
      split; auto.
      eapply Expr_scnd; eauto.
  - destruct (option_dec (lookup n (renv rst))) as [G|G].
    + rewrite G in H; inv H.
    + destruct G as [b G]; rewrite G in H.
      destruct b; inv H.
      destruct (option_dec (lookup n0 (renv rst))) as [F|F].
      * rewrite F in H1; inv H1; destruct b; inv H0.
      * destruct F as [c F]; rewrite F in H1.
        destruct (alt_bool_dec (negb (has_enc c))) as [D|D];
          rewrite D in H1; simpl in H1.
        destruct (bool_dec (alg_eqb c (inv b2)) true) as [E|E].
        -- rewrite E in H1; inv H1.
           apply alg_eq_correct in E; subst.
           split; auto.
           eapply Expr_decr; eauto.
           apply negb_true_iff in D; auto.
        -- rewrite not_true_iff_false in E.
           rewrite E in H1; inv H1.
        -- inv H1.
  - destruct (runiqs rst); inv H; auto.
  - destruct (option_dec (lookup n (renv rst))) as [G|G].
    + rewrite G in H; inv H.
    + destruct G as [c G]; rewrite G in H.
      destruct (rtr rst).
      * inv H.
      * destruct e.
        -- inv H.
        -- destruct c; inv H.
           destruct (bool_dec (n1 =? n0) true) as [F|F].
           ++ rewrite F in H1; inv H1.
              apply Nat.eqb_eq in F; subst; auto.
           ++ rewrite not_true_iff_false in F.
              rewrite F in H1; inv H1.
Qed.

Lemma type_check_reflect:
  forall (x: alg) (t: type),
    type_check x t = true <-> Sem.type_check t x.
Proof.
  intros.
  unfold type_check.
  rewrite orb_true_iff.
  repeat rewrite type_eq_correct.
  rewrite Sem.type_check_type_of; intuition.
Qed.

Lemma stmt_sem_implies_run_stmt:
  forall ev tr us cmd ev' tr' us',
    stmt_sem ev tr us cmd ev' tr' us' ->
    run_stmt (mkRSt ev tr us) cmd =
    Some (mkRSt ev' tr' us').
Proof.
  intros.
  inv H.
  - apply expr_sem_implies_run_expr in H0.
    rewrite <- type_check_reflect in H1.
    simpl.
    rewrite H0.
    rewrite H1; auto.
  - simpl.
    rewrite H0.
    rewrite Nat.eqb_refl; auto.
    rewrite H1.
    destruct (bool_dec (alg_eqb a a) true) as [G|G].
    + rewrite G; auto.
    + contradiction G.
      rewrite alg_eq_correct; auto.
  - simpl.
    rewrite H0.
    rewrite H1.
    rewrite H2.
    simpl.
    destruct (bool_dec (alg_eqb b b) true) as [G|G].
    + rewrite G; auto.
    + contradiction G.
      rewrite alg_eq_correct; auto.
  - simpl.
    rewrite H0.
    rewrite H1.
    rewrite H2.
    simpl.
    destruct (bool_dec (alg_eqb (inv b) (inv b)) true) as [G|G].
    + rewrite G; auto.
    + contradiction G.
      rewrite alg_eq_correct; auto.
Qed.

Lemma run_stmt_implies_stmt_sem:
  forall rst cmd rst',
    run_stmt rst cmd = Some rst' ->
    stmt_sem (renv rst) (rtr rst) (runiqs rst)
             cmd (renv rst') (rtr rst') (runiqs rst').
Proof.
  intros; destruct cmd; simpl in *.
  - inv H.
  - destruct d as [v t].
    destruct (option_dec (run_expr rst e)) as [G|G].
    + rewrite G in H; inv H.
    + destruct G as [b G].
      destruct b as [st x].
      rewrite G in H.
      destruct (bool_dec (type_check x t) true) as [F|F].
      * rewrite F in H.
        inv H; simpl.
        rewrite type_check_reflect in F.
        apply run_expr_implies_expr_sem in G; auto.
        destruct G.
        rewrite <- H0.
        eapply Stmt_bind; eauto.
      * rewrite not_true_iff_false in F.
        rewrite F in H; inv H.
  - destruct (rtr rst).
    + inv H.
    + destruct e.
      * destruct (option_dec (lookup n (renv rst))) as [G|G].
        -- rewrite G in H; inv H.
        -- destruct G.
           rewrite H0 in H.
           destruct x; inv H.
           destruct (bool_dec (n2 =? n1) true) as [G|G].
           ++ rewrite G in H2; inv H2.
              apply Nat.eqb_eq in G; subst.
              destruct (option_dec (lookup n0 (renv rst))) as [G|G].
              ** rewrite G in H1; inv H1.
              ** destruct G.
                 rewrite H in H1.
                 destruct (bool_dec (alg_eqb a x) true) as [F|F].
                 --- rewrite F in H1; inv H1.
                     rewrite alg_eq_correct in F; subst.
                     apply Stmt_send; auto.
                 --- rewrite not_true_iff_false in F.
                     rewrite F in H1; inv H1.
           ++ rewrite not_true_iff_false in G.
              rewrite G in H2; inv H2.
      * inv H.
  - destruct (option_dec (lookup n (renv rst))) as [G|G].
    + rewrite G in H; inv H.
    + destruct G.
      rewrite H0 in H.
      destruct (option_dec (lookup n0 (renv rst))) as [G|G].
      * rewrite G in H; inv H.
      * destruct G.
        rewrite H1 in H.
        destruct (alt_bool_dec (has_enc x)) as [F|F];
          rewrite F in H; simpl in H.
        inv H.
        destruct (bool_dec (alg_eqb x x0) true) as [G|G].
        -- rewrite G in H; inv H.
           apply alg_eq_correct in G; subst.
           eapply Stmt_same; eauto.
        -- rewrite not_true_iff_false in G.
           rewrite G in H; inv H.
  - alt_option_dec (lookup n (renv rst)) x G;
      rewrite G in H.
    + inv H.
    + alt_option_dec (lookup n0 (renv rst)) y F;
        rewrite F in H.
      * inv H.
      * destruct (alt_bool_dec (has_enc x)) as [D|D];
          rewrite D in H; simpl in H.
        inv H.
        destruct (alt_bool_dec (alg_eqb x (inv y))) as [E|E];
          rewrite E in H.
        -- inv H.
           apply alg_eq_correct in E.
           eapply Stmt_invp; eauto.
        -- inv H.
Qed.

Lemma stmt_list_sem_implies_run_stmts:
  forall ev_in tr us outs stmts ev,
    stmt_list_sem ev_in tr us outs stmts ev ->
    run_stmts (mkRSt ev_in tr us) stmts = Some (ev, outs).
Proof.
  intros.
  induction H.
  - unfold Basics.flip in H.
    simpl.
    rewrite H; auto.
  - apply stmt_sem_implies_run_stmt in H.
    simpl; rewrite H.
    destruct stmt; simpl; simpl in H; auto.
    inv H.
Qed.

Functional Scheme run_stmts_ind :=
  Induction for run_stmts Sort Prop.

Lemma run_stmts_implies_stmt_list_sem:
  forall rst stmts ev outs,
    run_stmts rst stmts = Some (ev, outs) ->
    stmt_list_sem (renv rst) (rtr rst) (runiqs rst) outs stmts ev.
Proof.
  intros.
  functional induction (run_stmts rst stmts); inv H.
  - rewrite e2.
    rewrite e3.
    apply Stmt_return; auto.
  - inv e2.
  - apply run_stmt_implies_stmt_sem in e1.
    apply IHo in H1.
    eapply Stmt_pair; eauto.
  - apply run_stmt_implies_stmt_sem in e1.
    apply IHo in H1.
    eapply Stmt_pair; eauto.
  - apply run_stmt_implies_stmt_sem in e1.
    apply IHo in H1.
    eapply Stmt_pair; eauto.
  - apply run_stmt_implies_stmt_sem in e1.
    apply IHo in H1.
    eapply Stmt_pair; eauto.
Qed.

Lemma sem_bind_inputs_aux:
  forall ds xs ev,
    ins_inputs ds xs ->
    bind_inputs ds xs ev = Some (rev (mk_env ds xs) ++ ev).
Proof.
  intros ds xs ev H.
  revert ev.
  induction H; intros; simpl; auto.
  rewrite <- type_check_reflect in H.
  rewrite H.
  rewrite IHins_inputs; simpl; auto.
  repeat rewrite <- app_assoc.
  repeat rewrite rev_app_distr; simpl.
  simpl; auto.
Qed.

Lemma sem_bind_inputs:
  forall ds xs,
    ins_inputs ds xs ->
    bind_inputs ds xs nil = Some (rev (mk_env ds xs)).
Proof.
  intros.
  rewrite sem_bind_inputs_aux; auto.
  rewrite app_nil_r; auto.
Qed.

Functional Scheme bind_inputs_ind :=
  Induction for bind_inputs Sort Prop.

Lemma sem_ins_inputs_aux:
  forall ds xs ev ev',
    bind_inputs ds xs ev = Some ev' ->
    ins_inputs ds xs.
Proof.
  intros.
  functional induction (bind_inputs ds xs ev); simpl; auto; inv H.
  apply type_check_reflect in e2.
  apply Ins_inputs_pair; auto.
Qed.

Lemma sem_ins_inputs:
  forall ds xs ev,
    bind_inputs ds xs nil = Some ev ->
    ins_inputs ds xs /\ ev = rev (mk_env ds xs).
Proof.
  intros.
  assert (G: ins_inputs ds xs).
  - eapply sem_ins_inputs_aux; eauto.
  - split; auto.
    pose proof (sem_bind_inputs ds xs).
    apply H0 in G.
    rewrite G in H.
    inv H; auto.
Qed.

Lemma sem'_implies_run:
  forall (p: proc) (ev: env) (tr: list evt) (us: list alg),
    sem' p ev tr us ->
    exists outs,
      get_outs ev (body p) = Some outs /\
      run p (get_ins ev (ins p)) tr us = Some (ev, outs).
Proof.
  intros.
  unfold sem' in H.
  repeat destruct_ex_and.
  exists x.
  split; auto.
  unfold run.
  rewrite sem_bind_inputs; auto.
  rewrite rev_involutive.
  eapply stmt_list_sem_implies_run_stmts in H1; eauto.
Qed.

(** The semantics as a predicate implies the semantics as a function. *)

Theorem sem_implies_run:
  forall (p: proc) (ev: env) (ex: role),
    sem p ev ex ->
    run p (inputs ex) (trace ex) (uniqs ex) =
    Some (ev, outputs ex).
Proof.
  intros.
  erewrite sem_implies_inputs; eauto.
  pose proof H as G.
  apply sem_implies_sem' in H.
  apply sem_implies_outputs in G.
  unfold sem' in H.
  repeat destruct_ex_and.
  rewrite G in H0.
  inv H0.
  apply sem_bind_inputs in H.
  apply stmt_list_sem_implies_run_stmts in H1.
  unfold run.
  rewrite H; auto.
  rewrite rev_involutive; auto.
Qed.

(** The semantics as a function implies the semantics as a predicate. *)

Theorem run_implies_sem':
  forall p tr us ev outs,
    run p (get_ins ev (ins p)) tr us = Some (ev, outs) ->
    sem' p ev tr us.
Proof.
  intros.
  unfold run in H.
  destruct (option_dec (bind_inputs (ins p) (get_ins ev (ins p)) nil)) as [G|G].
  - rewrite G in H; inv H.
  - destruct G as [ev' G].
    rewrite G in H.
    apply sem_ins_inputs in G.
    destruct G; subst.
    rewrite rev_involutive in H.
    unfold sem'.
    split; auto.
    exists outs.
    eapply run_stmts_implies_stmt_list_sem in H; eauto.
    split; auto.
    apply stmt_list_sem_implies_outputs in H; auto.
Qed.