Coq框架图
2018-07-24 15:42:00 0 举报
AI智能生成
coq-proof erc20框架
作者其他创作
大纲/内容
Type.v
Definition label := nat. (* ? *)
Definition value := nat.
Definition uint256 := nat.
Definition uint8 := nat.
Definition time := nat.
Definition address := nat.
Definition value := nat.
Definition uint256 := nat.
Definition uint8 := nat.
Definition time := nat.
Definition address := nat.
Parameter MAX_UINT256 : uint256.
LibEx.v
Lemma modusponens
: forall (P Q: Prop), P -> (P -> Q) -> Q.
Proof. auto. Qed.
Axiom FFF
: False.
Ltac skip
:= destruct FFF.
Ltac inv H
:= inversion H; clear H; subst.
Ltac caseEq name
:= generalize (refl_equal name); pattern name at -1 in |- *; case name.
Notation refl_equal := @eq_refl
Inductive eq (A : Type) (x : A) : A -> Prop := eq_refl : x = x
Tactic Notation "substH" hyp (H)
:= match goal with
| |- ?a -> ?b => clear H; intro H
| |- _ => fail 1 "goal must be 'A -> B'."
end.
| |- ?a -> ?b => clear H; intro H
| |- _ => fail 1 "goal must be 'A -> B'."
end.
Example
Goal forall a b :Prop, (a->b) -> (a->b). Proof. intros a b H. substH H.
Extension
Tactic Notation "substH" hyp (H) "with" constr (t) :=
generalize t; clear H; intro H.
Tactic Notation "substH" hyp (H) "with" constr (t) "into" ident (Hn) :=
generalize t; clear H; intro Hn.
generalize t; clear H; intro H.
Tactic Notation "substH" hyp (H) "with" constr (t) "into" ident (Hn) :=
generalize t; clear H; intro Hn.
Lemma eq_sym
: forall {A: Type} (n m : A), n = m -> m = n.
Proof. intros. subst; trivial. Qed.
Arguments eq_sym [A n m].
Lemma neq_sym
: forall {A: Type} (n m : A), n <> m -> m <> n.
Proof. intros. intro HF; subst; auto. Qed.
Arguments neq_sym {A} {n} {m} _ _.
Tactic Notation "gen_clear" hyp (H)
:= generalize H; clear H.
Extension
Tactic Notation "gen_clear" hyp (H1) hyp (H2)
:= generalize H1 H2; clear H1 H2.
Tactic Notation "gen_clear" hyp (H1) hyp (H2) hyp (H3)
:= generalize H1 H2 H3; clear H1 H2 H3.
Tactic Notation "gen_clear" hyp (H1) hyp (H2) hyp (H3) hyp (H4)
:= generalize H1 H2 H3 H4; clear H1 H2 H3 H4.
Tactic Notation "gen_clear" hyp (H1) hyp (H2) hyp (H3) hyp (H4) hyp (H5)
:= generalize H1 H2 H3 H4 H5; clear H1 H2 H3 H4 H5.
Tactic Notation "gen_clear" hyp (H1) hyp (H2) hyp (H3) hyp (H4) hyp (H5) hyp (H6)
:= generalize H1 H2 H3 H4 H5 H6; clear H1 H2 H3 H4 H5 H6.
Tactic Notation "split_l"
:= split; [trivial | idtac].
Extension
Tactic Notation "split_r"
:= split; [idtac | trivial ].
Tactic Notation "split_lr"
:= split; [trivial | trivial ].
Tactic Notation "split_l" "with" constr (t)
:= split; [apply t | idtac].
Tactic Notation "split_r" "with" constr (t)
:= split; [idtac | apply t ].
Tactic Notation "split_l" "by" tactic (tac)
:= split; [tac | idtac ].
Tactic Notation "split_r" "by" tactic (tac)
:= split; [idtac | tac ].
Tactic Notation "split_l_clear" "with" hyp (H)
:= split; [apply H | clear H].
Tactic Notation "split_r_clear" "with" hyp (H)
:= split; [clear H | apply H ].
Tactic Notation "inj_hyp" hyp (H)
:= injection H; clear H; intro H.
Tactic Notation "rew_clear" hyp (H)
:= rewrite H; clear H.
Tactic Notation "injection" hyp (H)
:= injection H.
Extension
Tactic Notation "injection" hyp (H) "as" simple_intropattern (pat)
:= injection H; intros pat.
TMapLib.v
Require Import LibEx.
Require Import List.
Require Import Coq.Logic.Classical_Prop.
Require Export Coq.Logic.FunctionalExtensionality.
Require Import List.
Require Import Coq.Logic.Classical_Prop.
Require Export Coq.Logic.FunctionalExtensionality.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Strict Implicit.
Section TMapLib.
beq_tac
Variable A
: Set.
Variable beq
: A -> A -> bool.
Hypothesis beq_true_eq
: forall a a' : A, beq a a' = true -> a = a'.
Hypothesis beq_false_neq
: forall a a' : A, beq a a' = false -> a <> a'.
Hypothesis eq_beq_true
: forall a a' : A, a = a' -> beq a a' = true.
Hypothesis neq_beq_false
: forall a a' : A, a <> a' -> beq a a' = false.
Variable B
: Type.
Variable zero
: B.
Lemma beq_dec
: forall a a' : A, {beq a a' = true} + {beq a a' = false}.
Proof.
intros; destruct (beq a a'); [left | right]; trivial.
Qed.
intros; destruct (beq a a'); [left | right]; trivial.
Qed.
Lemma eq_dec
: forall a a' : A, {a = a'} + {a <> a'}.
Proof.
intros; destruct (beq_dec a a'); [left | right].
apply beq_true_eq; trivial.
apply beq_false_neq; trivial.
Qed.
intros; destruct (beq_dec a a'); [left | right].
apply beq_true_eq; trivial.
apply beq_false_neq; trivial.
Qed.
Ltac beq_case_tac x y
:= let Hb := fresh "Hb" in (destruct (beq_dec x y) as [Hb | Hb]; trivial).
Lemma beq_sym
: forall a a' b, beq a a' = b -> beq a' a = b.
Proof.
intros m n b H.
destruct b.
apply eq_beq_true.
apply sym_eq.
apply beq_true_eq; trivial.
apply neq_beq_false.
apply sym_not_eq.
apply beq_false_neq; trivial.
Qed.
intros m n b H.
destruct b.
apply eq_beq_true.
apply sym_eq.
apply beq_true_eq; trivial.
apply neq_beq_false.
apply sym_not_eq.
apply beq_false_neq; trivial.
Qed.
Lemma beq_refl
: forall a, beq a a = true.
Proof.
intro m.
apply eq_beq_true; trivial.
Qed.
intro m.
apply eq_beq_true; trivial.
Qed.
Lemma beq_trans
: forall a a' a'' b, beq a a' = true
-> beq a' a'' = b
-> beq a a'' = b.
-> beq a' a'' = b
-> beq a a'' = b.
Proof.
intros m n k b H1 H2.
assert (m = n).
apply beq_true_eq; trivial.
subst m.
destruct b.
apply eq_beq_true.
apply beq_true_eq; trivial.
apply neq_beq_false.
apply beq_false_neq; trivial.
Qed.
intros m n k b H1 H2.
assert (m = n).
apply beq_true_eq; trivial.
subst m.
destruct b.
apply eq_beq_true.
apply beq_true_eq; trivial.
apply neq_beq_false.
apply beq_false_neq; trivial.
Qed.
Ltac beq_simpl_tac
:=
match goal with
(* beq rewrite directly *)
| [H : beq ?x ?y = ?f |- context [(beq ?x ?y)]] => rewrite H; beq_simpl_tac
| [H : beq ?x ?y = ?f, H0 : context [(beq ?x ?y)] |- _ ] => rewrite H in H0; beq_simpl_tac
(* beq_refl *)
| [ |- context [(beq ?x ?x)] ] =>rewrite (@beq_refl x); beq_simpl_tac
| [H : context [(beq ?x ?x)] |- _ ] =>rewrite (@beq_refl x) in H; beq_simpl_tac
(* beq_sym *)
| [ H : beq ?x ?y = ?b |- context [(beq ?y ?x)] ] => rewrite (@beq_sym x y b H); beq_simpl_tac
| [H : beq ?x ?y = ?b, H0 : context [(beq ?y ?x)] |- _ ] => rewrite (@beq_sym x y b H) in H0; beq_simpl_tac
(* neq -> beq *)
| [ H : ?x <> ?y |- context [(beq ?x ?y)] ] => rewrite (neq_beq_false H); beq_simpl_tac
| [ H : ?x <> ?y, H0 : context [(beq ?x ?y)] |- _ ] => rewrite (neq_beq_false H) in H0; beq_simpl_tac
| [ H : ?x <> ?y |- context [(beq ?y ?x)] ] => rewrite (beq_sym (neq_beq_false H)); beq_simpl_tac
| [ H : ?x <> ?y, H0 : context [(beq ?y ?x)] |- _ ] => rewrite (beq_sym (neq_beq_false H)) in H0; beq_simpl_tac
(* beq -> neq *)
| [ H : (beq ?x ?y = false) |- ?x <> ?y ] => apply (beq_false_neq H); beq_simpl_tac
| [ H : (beq ?x ?y = false) |- ?y <> ?x ] => apply (beq_false_neq (beq_sym H)); beq_simpl_tac
| [H : ?x = ?x |- _ ] => clear H; beq_simpl_tac
| [H : true = false |- _ ] => discriminate H
| [H : false = true |- _ ] => discriminate H
| [|- true = true ] => trivial
| [|- false = false ] => trivial
| [|- context [beq ?x ?y] ] => simpl; trivial
| [ H: context [beq ?x ?y] |- _ ] => simpl in H
| _ => idtac
end.
match goal with
(* beq rewrite directly *)
| [H : beq ?x ?y = ?f |- context [(beq ?x ?y)]] => rewrite H; beq_simpl_tac
| [H : beq ?x ?y = ?f, H0 : context [(beq ?x ?y)] |- _ ] => rewrite H in H0; beq_simpl_tac
(* beq_refl *)
| [ |- context [(beq ?x ?x)] ] =>rewrite (@beq_refl x); beq_simpl_tac
| [H : context [(beq ?x ?x)] |- _ ] =>rewrite (@beq_refl x) in H; beq_simpl_tac
(* beq_sym *)
| [ H : beq ?x ?y = ?b |- context [(beq ?y ?x)] ] => rewrite (@beq_sym x y b H); beq_simpl_tac
| [H : beq ?x ?y = ?b, H0 : context [(beq ?y ?x)] |- _ ] => rewrite (@beq_sym x y b H) in H0; beq_simpl_tac
(* neq -> beq *)
| [ H : ?x <> ?y |- context [(beq ?x ?y)] ] => rewrite (neq_beq_false H); beq_simpl_tac
| [ H : ?x <> ?y, H0 : context [(beq ?x ?y)] |- _ ] => rewrite (neq_beq_false H) in H0; beq_simpl_tac
| [ H : ?x <> ?y |- context [(beq ?y ?x)] ] => rewrite (beq_sym (neq_beq_false H)); beq_simpl_tac
| [ H : ?x <> ?y, H0 : context [(beq ?y ?x)] |- _ ] => rewrite (beq_sym (neq_beq_false H)) in H0; beq_simpl_tac
(* beq -> neq *)
| [ H : (beq ?x ?y = false) |- ?x <> ?y ] => apply (beq_false_neq H); beq_simpl_tac
| [ H : (beq ?x ?y = false) |- ?y <> ?x ] => apply (beq_false_neq (beq_sym H)); beq_simpl_tac
| [H : ?x = ?x |- _ ] => clear H; beq_simpl_tac
| [H : true = false |- _ ] => discriminate H
| [H : false = true |- _ ] => discriminate H
| [|- true = true ] => trivial
| [|- false = false ] => trivial
| [|- context [beq ?x ?y] ] => simpl; trivial
| [ H: context [beq ?x ?y] |- _ ] => simpl in H
| _ => idtac
end.
Tactic Notation "beq" "simpl"
:= beq_simpl_tac.
Ltac beq_rewrite_tac H
:=
match type of H with
| beq ?a ?b = true =>
match goal with
| [ |- context [(?a)]] => rewrite (@beq_true_eq a b H)
| [ |- context [(?b)]] => rewrite <- (@beq_true_eq a b H)
end
| _ => fail
end.
match type of H with
| beq ?a ?b = true =>
match goal with
| [ |- context [(?a)]] => rewrite (@beq_true_eq a b H)
| [ |- context [(?b)]] => rewrite <- (@beq_true_eq a b H)
end
| _ => fail
end.
Tactic Notation "beq" "rewrite" constr(t)
:= beq_rewrite_tac t.
Ltac beq_rewriteH_tac H H'
:=
match type of H with
| beq ?a ?b = true =>
match type of H' with
| context [(?a)] =>rewrite (@beq_true_eq a b H) in H'
| context [(?b)] =>rewrite <- (@beq_true_eq a b H) in H'
end
| _ => fail
end.
match type of H with
| beq ?a ?b = true =>
match type of H' with
| context [(?a)] =>rewrite (@beq_true_eq a b H) in H'
| context [(?b)] =>rewrite <- (@beq_true_eq a b H) in H'
end
| _ => fail
end.
Tactic Notation "beq" "rewrite" constr(t) "in" hyp(H)
:= beq_rewriteH_tac t H.
tmap
Definition tmap
:= A -> B.
Definition get (m : tmap) (a : A)
:= m a.
Lemma get_dec
: forall (m : tmap) (a : A),
{exists b, get m a = b} + {get m a = zero}.
{exists b, get m a = b} + {get m a = zero}.
Proof.
intros m a.
unfold get.
left.
exists (m a). trivial.
Qed.
intros m a.
unfold get.
left.
exists (m a). trivial.
Qed.
Definition emp : tmap
:= fun _ => zero.
Lemma emp_sem
: forall a : A, get emp a = zero.
Proof.
intros; unfold get, emp; trivial.
Qed.
intros; unfold get, emp; trivial.
Qed.
Definition sig (a : A) (b : B)
:= fun a' => if beq a a' then b else zero.
Lemma sig_sem
: forall (a a' : A) (b : B),
get (sig a b) a' =
match (beq a a') with
| true => b
| false => zero
end.
get (sig a b) a' =
match (beq a a') with
| true => b
| false => zero
end.
Proof.
unfold get, sig. intros a a' b.
destruct (eq_dec a a').
rewrite e; trivial.
rewrite (@neq_beq_false a a'); auto.
Qed.
unfold get, sig. intros a a' b.
destruct (eq_dec a a').
rewrite e; trivial.
rewrite (@neq_beq_false a a'); auto.
Qed.
Definition upd (m : tmap) (a : A) (b : B) : tmap
:= fun a' => if (beq a a') then b else get m a'.
Lemma upd_sem
: forall m a a' b,
get (upd m a b) a' =
match (beq a a') with
| true => b
| false => get m a'
end.
get (upd m a b) a' =
match (beq a a') with
| true => b
| false => get m a'
end.
intros.
unfold get.
unfold upd.
unfold get.
trivial.
Qed.
unfold get.
unfold upd.
unfold get.
trivial.
Qed.
Lemma extensionality
: forall (m1 m2 : tmap),
(forall a, get m1 a = get m2 a) -> m1 = m2.
(forall a, get m1 a = get m2 a) -> m1 = m2.
Proof.
unfold get.
apply functional_extensionality.
Qed.
unfold get.
apply functional_extensionality.
Qed.
Definition lookup (m : tmap) (a : A) (b : B)
:= get m a = b.
Lemma emp_zero
: forall a, emp a = zero.
Proof.
intros.
unfold emp.
trivial.
Qed.
intros.
unfold emp.
trivial.
Qed.
Lemma get_upd_eq
: forall (m : tmap) a v, (upd m a v) a = v.
Proof.
intros.
unfold upd.
assert (beq a a= true).
apply eq_beq_true. trivial.
rewrite H. trivial.
Qed.
intros.
unfold upd.
assert (beq a a= true).
apply eq_beq_true. trivial.
rewrite H. trivial.
Qed.
Lemma get_upd_eq2
: forall (m : tmap) a1 a2 v, a1 = a2 -> (upd m a1 v) a2 = v.
Proof.
intros.
unfold upd.
assert (beq a a= true).
apply eq_beq_true. trivial.
rewrite H. trivial.
Qed.
intros.
unfold upd.
assert (beq a a= true).
apply eq_beq_true. trivial.
rewrite H. trivial.
Qed.
Lemma get_upd_ne
: forall (m : tmap) a a' v, a' <> a -> (upd m a v) a' = m a'.
Proof.
intros.
unfold upd.
assert (beq a a' = false). apply neq_beq_false. auto.
rewrite H0. unfold get. trivial.
Qed.
intros.
unfold upd.
assert (beq a a' = false). apply neq_beq_false. auto.
rewrite H0. unfold get. trivial.
Qed.
Hint Extern 1 => match goal with
| [ H : emp _ = _ |- _ ] =>
rewrite emp_zero in H; discriminate
end.
| [ H : emp _ = _ |- _ ] =>
rewrite emp_zero in H; discriminate
end.
Hint Rewrite get_upd_eq get_upd_ne using congruence.
Ltac destruct_get
:= match goal with
| H: context [ get ?m ?a ] |- _ => destruct (get m a); destruct_get
| |- context [ get ?m ?a ] => destruct (get m a); destruct_get
| _ => idtac
end.
| H: context [ get ?m ?a ] |- _ => destruct (get m a); destruct_get
| |- context [ get ?m ?a ] => destruct (get m a); destruct_get
| _ => idtac
end.
Notation "$0" := (emp 0).
Unset Implicit Arguments.
Unset Implicit Arguments.
AbsModel.v
Require Export Lists.List.
Require Export Types.
Require Export Types.
Set Implicit Arguments.
Definition TEventList(TEvent: Type): Type
:= list TEvent.
Record TContract(TState: Type): Type
:= mk_contract {
w_a: address; (* contract address *)
w_st: TState; (* contract storage state *)
}.
w_a: address; (* contract address *)
w_st: TState; (* contract storage state *)
}.
Record TMessage(Tmcall: Type): Type
:= mk_msg {
m_sender: address; (* msg.sender *)
m_func: Tmcall; (* function name and arguments *)
m_val: value; (* msg.value *)
}.
m_sender: address; (* msg.sender *)
m_func: Tmcall; (* function name and arguments *)
m_val: value; (* msg.value *)
}.
Record TEnv : Type
:= mk_env {
env_time: time; (* timestamp *)
env_bhash: uint256 (* block hash *)
}.
env_time: time; (* timestamp *)
env_bhash: uint256 (* block hash *)
}.
TMap.v
Set Implicit Arguments.
Require Export Coq.Logic.FunctionalExtensionality.
Require Export Coq.Logic.FunctionalExtensionality.
Class BEq A
:= {
beq : A -> A -> bool;
beq_true_eq: forall a a' : A, beq a a' = true -> a = a';
beq_false_neq : forall a a' : A, beq a a' = false -> a <> a';
eq_beq_true : forall a a' : A, a = a' -> beq a a' = true;
neq_beq_false : forall a a' : A, a <> a' -> beq a a' = false
}.
beq : A -> A -> bool;
beq_true_eq: forall a a' : A, beq a a' = true -> a = a';
beq_false_neq : forall a a' : A, beq a a' = false -> a <> a';
eq_beq_true : forall a a' : A, a = a' -> beq a a' = true;
neq_beq_false : forall a a' : A, a <> a' -> beq a a' = false
}.
Class BZero A `{BEq A} : Type
:= {zero: A;}.
Section BoolEq.
Context `{A: Type}.
Context `{BEq A}.
Lemma beq_dec
: forall (a a': A), beq a a' = true \/ beq a a' = false.
Proof.
intros.
destruct (beq a a').
left. trivial.
right. trivial.
Qed.
intros.
destruct (beq a a').
left. trivial.
right. trivial.
Qed.
Lemma beq_sym
: forall (a a': A) b,
beq a a' = b -> beq a' a = b.
beq a a' = b -> beq a' a = b.
Proof.
intros.
remember (beq a a') as Ha.
assert (beq a a' = Ha). auto.
destruct Ha.
rewrite <- H0. apply eq_beq_true.
apply beq_true_eq in H1. auto.
rewrite <-H0. apply neq_beq_false.
apply beq_false_neq in H1. auto.
Qed.
intros.
remember (beq a a') as Ha.
assert (beq a a' = Ha). auto.
destruct Ha.
rewrite <- H0. apply eq_beq_true.
apply beq_true_eq in H1. auto.
rewrite <-H0. apply neq_beq_false.
apply beq_false_neq in H1. auto.
Qed.
Lemma beq_refl
: forall m, beq m m = true.
Proof.
intros.
apply eq_beq_true. trivial.
Qed.
intros.
apply eq_beq_true. trivial.
Qed.
Lemma beq_trans
: forall m n k, beq m n = true
-> beq n k = true
-> beq m k = true.
-> beq n k = true
-> beq m k = true.
Proof.
intros.
apply beq_true_eq in H0.
apply beq_true_eq in H1.
apply eq_beq_true. rewrite H0. rewrite <- H1. trivial.
Qed.
intros.
apply beq_true_eq in H0.
apply beq_true_eq in H1.
apply eq_beq_true. rewrite H0. rewrite <- H1. trivial.
Qed.
Lemma beq_sym2
: forall m n, beq m n = beq n m.
Proof.
intros.
remember (beq n m) as Hnm.
assert (beq n m = Hnm). auto.
destruct Hnm.
apply beq_true_eq in H0.
apply eq_beq_true. auto.
apply beq_false_neq in H0.
apply neq_beq_false. auto.
Qed.
intros.
remember (beq n m) as Hnm.
assert (beq n m = Hnm). auto.
destruct Hnm.
apply beq_true_eq in H0.
apply eq_beq_true. auto.
apply beq_false_neq in H0.
apply neq_beq_false. auto.
Qed.
End BoolEq.
Ltac simplbeq
:= match goal with
(* beq rewrite directly *)
| [H : beq ?x ?y = ?f |- context [(beq ?x ?y)]] => rewrite H; simplbeq
| [H : beq ?x ?y = ?f, H0 : context [(beq ?x ?y)] |- _ ] => rewrite H in H0; simplbeq
(* beq_refl *)
| [ |- context [(beq ?x ?x)] ] => rewrite (beq_refl x); simplbeq
| [H : context [(beq ?x ?x)] |- _ ] => rewrite (beq_refl x) in H; simplbeq
(* beq_sym *)
| [ H : beq ?x ?y = ?b |- context [(beq ?y ?x)] ] => rewrite (beq_sym x y H); simplbeq
| [H : beq ?x ?y = ?b, H0 : context [(beq ?y ?x)] |- _ ] => rewrite (beq_sym x y H) in H0; simplbeq
| [ H : ?x <> ?y |- context [(beq ?x ?y)] ] => rewrite (neq_beq_false x y H); simplbeq
| [ H : ?x <> ?y, H0 : context [(beq ?x ?y)] |- _ ] => rewrite (neq_beq_false x y H) in H0; simplbeq
| [ H : ?y <> ?x |- context [(beq ?x ?y)] ] => rewrite (neq_beq_false x y (sym_not_eq H)); simplbeq
| [ H : ?y <> ?x, H0 : context [(beq ?x ?y)] |- _ ] => rewrite (neq_beq_false x y (sym_not_eq H)) in H0; simplbeq
(* beq rewrite directly *)
| [H : beq ?x ?y = true |- ?x =?y] => apply beq_true_eq; simplbeq
| [H : beq ?x ?y = true |- ?y =?x] => apply eq_sym; apply beq_true_eq; simplbeq
| [H : beq ?x ?y = false |- ?x <> ?y] => apply beq_false_neq; simplbeq
| [H : beq ?x ?y = false |- ?y <> ?x] => apply not_eq_sym; apply beq_false_neq; simplbeq
| [H : beq ?x ?y = ?f, H0 : context [(beq ?x ?y)] |- _ ] => rewrite H in H0; simplbeq
| [H : ?x = ?x |- _ ] => clear H; simplbeq
| [H : true = false |- _ ] => discriminate H
| [H : false = true |- _ ] => discriminate H
| _ => idtac
end.
(* beq rewrite directly *)
| [H : beq ?x ?y = ?f |- context [(beq ?x ?y)]] => rewrite H; simplbeq
| [H : beq ?x ?y = ?f, H0 : context [(beq ?x ?y)] |- _ ] => rewrite H in H0; simplbeq
(* beq_refl *)
| [ |- context [(beq ?x ?x)] ] => rewrite (beq_refl x); simplbeq
| [H : context [(beq ?x ?x)] |- _ ] => rewrite (beq_refl x) in H; simplbeq
(* beq_sym *)
| [ H : beq ?x ?y = ?b |- context [(beq ?y ?x)] ] => rewrite (beq_sym x y H); simplbeq
| [H : beq ?x ?y = ?b, H0 : context [(beq ?y ?x)] |- _ ] => rewrite (beq_sym x y H) in H0; simplbeq
| [ H : ?x <> ?y |- context [(beq ?x ?y)] ] => rewrite (neq_beq_false x y H); simplbeq
| [ H : ?x <> ?y, H0 : context [(beq ?x ?y)] |- _ ] => rewrite (neq_beq_false x y H) in H0; simplbeq
| [ H : ?y <> ?x |- context [(beq ?x ?y)] ] => rewrite (neq_beq_false x y (sym_not_eq H)); simplbeq
| [ H : ?y <> ?x, H0 : context [(beq ?x ?y)] |- _ ] => rewrite (neq_beq_false x y (sym_not_eq H)) in H0; simplbeq
(* beq rewrite directly *)
| [H : beq ?x ?y = true |- ?x =?y] => apply beq_true_eq; simplbeq
| [H : beq ?x ?y = true |- ?y =?x] => apply eq_sym; apply beq_true_eq; simplbeq
| [H : beq ?x ?y = false |- ?x <> ?y] => apply beq_false_neq; simplbeq
| [H : beq ?x ?y = false |- ?y <> ?x] => apply not_eq_sym; apply beq_false_neq; simplbeq
| [H : beq ?x ?y = ?f, H0 : context [(beq ?x ?y)] |- _ ] => rewrite H in H0; simplbeq
| [H : ?x = ?x |- _ ] => clear H; simplbeq
| [H : true = false |- _ ] => discriminate H
| [H : false = true |- _ ] => discriminate H
| _ => idtac
end.
Ltac decbeq x y
:= let Hb := fresh "Hb" in
(destruct (beq_dec x y) as [Hb | Hb]; simplbeq).
(destruct (beq_dec x y) as [Hb | Hb]; simplbeq).
Ltac beq_elimH H
:=
match goal with
| H : beq ?a ?b = true |- _ => generalize (beq_true_eq a b H); clear H; intro H
| H : beq ?a ?b = false |- _ => generalize (beq_false_neq a b H); clear H; intro H
| _ => fail 1 "not beq found"
end.
match goal with
| H : beq ?a ?b = true |- _ => generalize (beq_true_eq a b H); clear H; intro H
| H : beq ?a ?b = false |- _ => generalize (beq_false_neq a b H); clear H; intro H
| _ => fail 1 "not beq found"
end.
Ltac beq_intro
:=
match goal with
| |- beq ?a ?b = true => apply (eq_beq_true a b)
| |- beq ?a ?b = false => apply (neq_beq_false a b)
| _ => fail 1 "the goal is not bnat"
end.
match goal with
| |- beq ?a ?b = true => apply (eq_beq_true a b)
| |- beq ?a ?b = false => apply (neq_beq_false a b)
| _ => fail 1 "the goal is not bnat"
end.
Ltac beq_solve
:= beq_elim; beq_intro; auto with arith.
Ltac beq_rewrite t
:=
match t with
| beq ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [beq_solve | rewrite Hb; clear Hb])
| _ =>
match type of t with
| beq ?x ?y = true => rewrite (beq_true_eq x y t)
| _ => rewrite t
end
end.
match t with
| beq ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [beq_solve | rewrite Hb; clear Hb])
| _ =>
match type of t with
| beq ?x ?y = true => rewrite (beq_true_eq x y t)
| _ => rewrite t
end
end.
Ltac beq_rewriteH t H
:=
match t with
| beq ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [beq_solve | rewrite Hb in H; clear Hb])
| _ =>
match type of t with
| beq ?x ?y = true => rewrite (beq_true_eq x y t) in H
| _ => rewrite t in H
end
end.
match t with
| beq ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [beq_solve | rewrite Hb in H; clear Hb])
| _ =>
match type of t with
| beq ?x ?y = true => rewrite (beq_true_eq x y t) in H
| _ => rewrite t in H
end
end.
Tactic Notation "rewb" constr (t)
:= beq_rewrite t.
Tactic Notation "rewb" constr (t) "in" hyp (H)
:= beq_rewrite t H.
Section TMAP.
Context `{A: Type}.
Context `{B: Type}.
Context `{BEq A}.
Context `{BZero B}.
Definition tmap
:= A -> B.
Definition tmap_emp : tmap
:= fun _ => zero.
Definition tmap_sig (a : A) (b : B)
:= fun a' => if beq a a' then b else zero.
(* Definition tmap_get (m : tmap) (a : A) := m a. *)
Definition tmap_upd (m : tmap) (a : A) (b : B) : tmap
:= fun a' => if (beq a a') then b else m a'.
Lemma tmap_extensionality
: forall (m1 m2 : tmap), (forall a, m1 a = m2 a) -> m1 = m2.
Proof.
apply functional_extensionality.
Qed.
apply functional_extensionality.
Qed.
Lemma tmap_emp_zero
: forall a, tmap_emp a = zero.
Proof.
intros.
unfold tmap_emp.
trivial.
Qed.
intros.
unfold tmap_emp.
trivial.
Qed.
Lemma tmap_get_upd_eq
: forall (m : tmap) a v,
(tmap_upd m a v) a = v.
(tmap_upd m a v) a = v.
Proof.
intros.
unfold tmap_upd.
assert (beq a a = true). apply beq_refl.
rewrite H2. trivial.
Qed.
intros.
unfold tmap_upd.
assert (beq a a = true). apply beq_refl.
rewrite H2. trivial.
Qed.
Lemma tmap_upd_m_eq
: forall (m : tmap) a, (tmap_upd m a (m a)) = m.
Proof.
intros m a.
remember (tmap_upd m a (m a)) as Hma.
apply tmap_extensionality.
rewrite HeqHma.
intros.
unfold tmap_upd.
remember (beq a a0) as Ha.
assert (beq a a0 = Ha). auto.
destruct Ha. apply beq_true_eq in H2. rewrite H2. trivial.
trivial.
Qed.
intros m a.
remember (tmap_upd m a (m a)) as Hma.
apply tmap_extensionality.
rewrite HeqHma.
intros.
unfold tmap_upd.
remember (beq a a0) as Ha.
assert (beq a a0 = Ha). auto.
destruct Ha. apply beq_true_eq in H2. rewrite H2. trivial.
trivial.
Qed.
Lemma tmap_get_upd_eq2
: forall (m : tmap) a1 a2 v, beq a1 a2 = true -> (tmap_upd m a1 v) a2 = v.
Proof.
intros.
apply beq_true_eq in H2.
rewrite H2.
apply tmap_get_upd_eq.
Qed.
intros.
apply beq_true_eq in H2.
rewrite H2.
apply tmap_get_upd_eq.
Qed.
Lemma tmap_get_upd_ne
: forall (m : tmap) a a' v, beq a a' = false -> (tmap_upd m a v) a' = m a'.
Proof.
intros.
unfold tmap_upd.
rewrite H2.
trivial.
Qed.
intros.
unfold tmap_upd.
rewrite H2.
trivial.
Qed.
Lemma tmap_upd_upd_ne
: forall (m : tmap) a a' v v', beq a a' = false -> tmap_upd (tmap_upd m a v) a' v' = tmap_upd (tmap_upd m a' v') a v.
Proof.
intros.
unfold tmap_upd.
apply tmap_extensionality.
intro a0.
remember (beq a' a0) as Ha1.
remember (beq a a0) as Ha2.
assert (beq a' a0 = Ha1). auto.
assert (beq a a0 = Ha2). auto.
destruct Ha1.
destruct Ha2.
assert (beq a a' = true).
assert (beq a0 a' = true). apply beq_sym. apply H3.
generalize H5. apply beq_trans. apply H4.
rewrite H5 in H2. inversion H2.
trivial.
destruct Ha2.
trivial.
trivial.
Qed.
intros.
unfold tmap_upd.
apply tmap_extensionality.
intro a0.
remember (beq a' a0) as Ha1.
remember (beq a a0) as Ha2.
assert (beq a' a0 = Ha1). auto.
assert (beq a a0 = Ha2). auto.
destruct Ha1.
destruct Ha2.
assert (beq a a' = true).
assert (beq a0 a' = true). apply beq_sym. apply H3.
generalize H5. apply beq_trans. apply H4.
rewrite H5 in H2. inversion H2.
trivial.
destruct Ha2.
trivial.
trivial.
Qed.
Lemma tmap_upd_upd_eq
: forall (m : tmap) a v v', tmap_upd (tmap_upd m a v) a v' = tmap_upd m a v'.
Proof.
intros.
unfold tmap_upd.
apply tmap_extensionality.
intros a0.
destruct (beq a a0).
trivial.
trivial.
Qed.
intros.
unfold tmap_upd.
apply tmap_extensionality.
intros a0.
destruct (beq a a0).
trivial.
trivial.
Qed.
Lemma tmap_upd_upd_eq2
: forall (m : tmap) a a' v v', beq a a' = true -> tmap_upd (tmap_upd m a v) a' v' = tmap_upd m a' v'.
Proof.
intros.
apply beq_true_eq in H2.
rewrite <- H2.
apply tmap_upd_upd_eq.
Qed.
intros.
apply beq_true_eq in H2.
rewrite <- H2.
apply tmap_upd_upd_eq.
Qed.
Hint Extern 1 => match goal with
| [ H : tmap_emp _ = _ |- _ ] =>
rewrite tmap_emp_zero in H; discriminate
end.
| [ H : tmap_emp _ = _ |- _ ] =>
rewrite tmap_emp_zero in H; discriminate
end.
Hint Rewrite tmap_get_upd_eq tmap_get_upd_ne using congruence.
End TMAP.
Require Export Bool.
Ltac beq_destructH H pat
:=
let H0 := fresh "H" in
(rename H into H0;
match type of (H0) with
| (andb ?a ?b = true) => destruct (andb_prop a b H0) as pat; clear H0
| (orb ?a ?b = true) => destruct (orb_prop a b H0) as pat; clear H0
| _ => fail "not destructable"
end).
let H0 := fresh "H" in
(rename H into H0;
match type of (H0) with
| (andb ?a ?b = true) => destruct (andb_prop a b H0) as pat; clear H0
| (orb ?a ?b = true) => destruct (orb_prop a b H0) as pat; clear H0
| _ => fail "not destructable"
end).
Tactic Notation "desb" hyp (H) "as" simple_intropattern (pat)
:= beq_destructH H pat.
Ltac simplb
:=
match goal with
(* beq rewrite directly *)
| [H : negb ?x = true |- _ ] => apply (proj1 (negb_true_iff _)) in H; simplb
| [H : negb ?x = false |- _ ] => apply (proj1 (negb_false_iff _)) in H; simplb
| _ => idtac
end.
match goal with
(* beq rewrite directly *)
| [H : negb ?x = true |- _ ] => apply (proj1 (negb_true_iff _)) in H; simplb
| [H : negb ?x = false |- _ ] => apply (proj1 (negb_false_iff _)) in H; simplb
| _ => idtac
end.
Ltac tmap_simpl
:=
match goal with
| [ |- context [(tmap_upd ?m ?a1 ?v) ?a1]] => rewrite (tmap_get_upd_eq m a1 v); auto; tmap_simpl
| [ H: context [(tmap_upd ?m ?a1 ?v) ?a1] |- _ ]=> rewrite (tmap_get_upd_eq m a1 v) in H; auto; tmap_simpl
| [H : beq ?a1 ?a2 = true |- context [(tmap_upd ?m ?a1 ?v) ?a2]] => rewrite (tmap_get_upd_eq2 m a1 a2 v); auto; tmap_simpl
| [H : beq ?a2 ?a1 = true |- context [(tmap_upd ?m ?a1 ?v) ?a2]] => rewrite (tmap_get_upd_eq2 m a1 a2 v (beq_sym a2 a1 H)); auto; tmap_simpl
| [H : beq ?a1 ?a2 = true, H1: context [(tmap_upd ?m ?a1 ?v) ?a2] |- _ ]=> rewrite (tmap_get_upd_eq2 m a1 a2 v) in H1; auto; tmap_simpl
| [H : beq ?a2 ?a1 = true, H1: context [(tmap_upd ?m ?a1 ?v) ?a2] |- _ ]=> rewrite (tmap_get_upd_eq2 m a1 a2 v (beq_sym a2 a1 H)) in H1; auto; tmap_simpl
| [H : beq ?a1 ?a2 = false |- context [(tmap_upd ?m ?a1 ?v) ?a2]] => rewrite (tmap_get_upd_ne m a1 a2 v H); auto; tmap_simpl
| [H : beq ?a2 ?a1 = false |- context [(tmap_upd ?m ?a1 ?v) ?a2]] => rewrite (tmap_get_upd_ne m a1 a2 v (beq_sym a2 a1 H)); auto; tmap_simpl
| [H : beq ?a1 ?a2 = false, H1: context [(tmap_upd ?m ?a1 ?v) ?a2] |- _ ] => rewrite (tmap_get_upd_ne m a1 a2 v H) in H1; auto; tmap_simpl
| [H : beq ?a2 ?a1 = false, H1: context [(tmap_upd ?m ?a1 ?v) ?a2] |- _ ] => rewrite (tmap_get_upd_ne m a1 a2 v (beq_sym a2 a1 H)) in H1; auto; tmap_simpl
(* upd_upd_eq *)
| [H : beq ?a1 ?a2 = true |- context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a2 ?v2]] => rewrite (tmap_upd_upd_eq2 m a1 a2 v1 v2 H); auto; tmap_simpl
| [H : beq ?a2 ?a1 = true |- context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a2 ?v2]] => rewrite (tmap_upd_upd_eq2 m a1 a2 v1 v2 (beq_sym a2 a1 H)); auto; tmap_simpl
| [H : beq ?a1 ?a2 = true, H1: context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a2 ?v2] |- _ ]=> rewrite (tmap_upd_upd_eq2 m a1 a2 v1 v2) in H1; auto; tmap_simpl
| [H : beq ?a2 ?a1 = true, H1: context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a2 ?v2] |- _ ]=> rewrite (tmap_upd_upd_eq2 m a1 a2 v1 v2 (beq_sym a2 a1 H)) in H1; auto; tmap_simpl
| [ |- context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a1 ?v2]] => rewrite (tmap_upd_upd_eq m a1 v1 v2); auto; tmap_simpl
| [H : context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a1 ?v2] |- _ ]=> rewrite (tmap_upd_upd_eq m a1 v1 v2) in H; auto; tmap_simpl
(* upd_meq *)
| [ |- context [tmap_upd ?m ?a (?m ?a)]] => rewrite (tmap_upd_m_eq m a); auto; tmap_simpl
| [ H : context [tmap_upd ?m ?a (?m ?a)] |- _ ] => rewrite (tmap_upd_m_eq m a) in H; auto; tmap_simpl
(* tmap_emp *)
| [ H : context [tmap_emp _ ] |- _ ] => rewrite tmap_emp_zero in H; tmap_simpl
| [ |- context [tmap_emp _ ] ] => rewrite tmap_emp_zero; tmap_simpl
| _ => idtac
end.
match goal with
| [ |- context [(tmap_upd ?m ?a1 ?v) ?a1]] => rewrite (tmap_get_upd_eq m a1 v); auto; tmap_simpl
| [ H: context [(tmap_upd ?m ?a1 ?v) ?a1] |- _ ]=> rewrite (tmap_get_upd_eq m a1 v) in H; auto; tmap_simpl
| [H : beq ?a1 ?a2 = true |- context [(tmap_upd ?m ?a1 ?v) ?a2]] => rewrite (tmap_get_upd_eq2 m a1 a2 v); auto; tmap_simpl
| [H : beq ?a2 ?a1 = true |- context [(tmap_upd ?m ?a1 ?v) ?a2]] => rewrite (tmap_get_upd_eq2 m a1 a2 v (beq_sym a2 a1 H)); auto; tmap_simpl
| [H : beq ?a1 ?a2 = true, H1: context [(tmap_upd ?m ?a1 ?v) ?a2] |- _ ]=> rewrite (tmap_get_upd_eq2 m a1 a2 v) in H1; auto; tmap_simpl
| [H : beq ?a2 ?a1 = true, H1: context [(tmap_upd ?m ?a1 ?v) ?a2] |- _ ]=> rewrite (tmap_get_upd_eq2 m a1 a2 v (beq_sym a2 a1 H)) in H1; auto; tmap_simpl
| [H : beq ?a1 ?a2 = false |- context [(tmap_upd ?m ?a1 ?v) ?a2]] => rewrite (tmap_get_upd_ne m a1 a2 v H); auto; tmap_simpl
| [H : beq ?a2 ?a1 = false |- context [(tmap_upd ?m ?a1 ?v) ?a2]] => rewrite (tmap_get_upd_ne m a1 a2 v (beq_sym a2 a1 H)); auto; tmap_simpl
| [H : beq ?a1 ?a2 = false, H1: context [(tmap_upd ?m ?a1 ?v) ?a2] |- _ ] => rewrite (tmap_get_upd_ne m a1 a2 v H) in H1; auto; tmap_simpl
| [H : beq ?a2 ?a1 = false, H1: context [(tmap_upd ?m ?a1 ?v) ?a2] |- _ ] => rewrite (tmap_get_upd_ne m a1 a2 v (beq_sym a2 a1 H)) in H1; auto; tmap_simpl
(* upd_upd_eq *)
| [H : beq ?a1 ?a2 = true |- context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a2 ?v2]] => rewrite (tmap_upd_upd_eq2 m a1 a2 v1 v2 H); auto; tmap_simpl
| [H : beq ?a2 ?a1 = true |- context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a2 ?v2]] => rewrite (tmap_upd_upd_eq2 m a1 a2 v1 v2 (beq_sym a2 a1 H)); auto; tmap_simpl
| [H : beq ?a1 ?a2 = true, H1: context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a2 ?v2] |- _ ]=> rewrite (tmap_upd_upd_eq2 m a1 a2 v1 v2) in H1; auto; tmap_simpl
| [H : beq ?a2 ?a1 = true, H1: context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a2 ?v2] |- _ ]=> rewrite (tmap_upd_upd_eq2 m a1 a2 v1 v2 (beq_sym a2 a1 H)) in H1; auto; tmap_simpl
| [ |- context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a1 ?v2]] => rewrite (tmap_upd_upd_eq m a1 v1 v2); auto; tmap_simpl
| [H : context [tmap_upd (tmap_upd ?m ?a1 ?v1) ?a1 ?v2] |- _ ]=> rewrite (tmap_upd_upd_eq m a1 v1 v2) in H; auto; tmap_simpl
(* upd_meq *)
| [ |- context [tmap_upd ?m ?a (?m ?a)]] => rewrite (tmap_upd_m_eq m a); auto; tmap_simpl
| [ H : context [tmap_upd ?m ?a (?m ?a)] |- _ ] => rewrite (tmap_upd_m_eq m a) in H; auto; tmap_simpl
(* tmap_emp *)
| [ H : context [tmap_emp _ ] |- _ ] => rewrite tmap_emp_zero in H; tmap_simpl
| [ |- context [tmap_emp _ ] ] => rewrite tmap_emp_zero; tmap_simpl
| _ => idtac
end.
Tactic Notation "simpltm"
:= tmap_simpl.
Notation "$0"
:= (tmap_emp).
Notation "m $+ { k <- v }"
:= (tmap_upd m k v) (at level 50, left associativity).
Unset Implicit Arguments.
BNat.v
Require Export Bool.
Require Import Arith.
Require Import Arith.
Definition A
:= nat.
Definition B
:= nat.
Definition zero
:= 0.
Theorem nat_eq_dec
: forall a b : nat, {a = b} + {a <> b}.
Proof. intros; compare a b; auto. Qed.
blt
Fixpoint blt_nat (n m : nat) {struct n} : bool
:=
match n, m with
| O, O => false
| O, S _ => true
| S _, O => false
| S n', S m' => blt_nat n' m'
end.
match n, m with
| O, O => false
| O, S _ => true
| S _, O => false
| S n', S m' => blt_nat n' m'
end.
Lemma blt_irrefl
: forall a : nat, blt_nat a a = false.
Proof.
induction a; simpl; auto.
Qed.
induction a; simpl; auto.
Qed.
Lemma blt_irrefl_Prop
: forall a : nat, ~ (blt_nat a a = true).
Proof.
induction a; simpl; auto.
Qed.
induction a; simpl; auto.
Qed.
Lemma blt_asym
: forall a b : nat, blt_nat a b = true -> blt_nat b a = false.
Proof.
double induction a b; simpl; intros; auto.
Qed.
double induction a b; simpl; intros; auto.
Qed.
Lemma blt_O_Sn
: forall n : nat, blt_nat O (S n) = true.
Proof.
induction n; simpl; auto.
Qed.
induction n; simpl; auto.
Qed.
Lemma blt_n_O
: forall n, blt_nat n O = false.
Proof.
induction n; simpl; auto.
Qed.
induction n; simpl; auto.
Qed.
Lemma not_blt_n_O
: forall n : nat, ~ (blt_nat n 0 = true).
Proof.
induction n; simpl; auto.
Qed.
induction n; simpl; auto.
Qed.
Lemma blt_true_lt
: forall a b : nat, blt_nat a b = true -> a < b.
Proof.
double induction a b; simpl; intros;
auto with arith; try discriminate.
Qed.
double induction a b; simpl; intros;
auto with arith; try discriminate.
Qed.
Lemma blt_false_le
: forall n m, blt_nat n m = false -> m <= n.
Proof.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
Lemma le_blt_false
: forall n m, n <= m -> blt_nat m n = false.
Proof.
double induction n m; simpl; intros;
auto with arith.
destruct (lt_n_O _ H0).
Qed.
double induction n m; simpl; intros;
auto with arith.
destruct (lt_n_O _ H0).
Qed.
Lemma lt_blt_true
: forall a b : nat, a < b -> blt_nat a b = true.
Proof.
double induction a b; simpl; intros;
auto with arith.
destruct (lt_irrefl 0 H).
destruct (lt_n_O (S n) H0).
Qed.
double induction a b; simpl; intros;
auto with arith.
destruct (lt_irrefl 0 H).
destruct (lt_n_O (S n) H0).
Qed.
Lemma blt_n_Sn
: forall n : nat, blt_nat n (S n) = true.
Proof.
induction n; simpl; intros; auto with arith.
Qed.
induction n; simpl; intros; auto with arith.
Qed.
Lemma blt_S_eq
: forall a b, blt_nat a b = blt_nat (S a) (S b).
Proof.
trivial.
Qed.
trivial.
Qed.
Lemma blt_n_Sm
: forall n m, blt_nat n m = true -> blt_nat n (S m) = true.
Proof.
double induction n m; simpl; intros; auto with arith.
discriminate.
Qed
double induction n m; simpl; intros; auto with arith.
discriminate.
Qed
Lemma blt_n_mk
: forall n m k, blt_nat n m = true -> blt_nat n (m + k) = true.
Proof.
double induction n m; simpl; intros; auto with arith.
discriminate.
Qed
double induction n m; simpl; intros; auto with arith.
discriminate.
Qed
Lemma blt_n_km
: forall n m k, blt_nat n m = true -> blt_nat n (k + m) = true.
Proof.
double induction n m; simpl; intros;
auto with arith; try discriminate.
replace (k + (S n0)) with ((S n0) + k);
[idtac | auto with arith].
simpl. trivial.
replace (k + (S n0)) with ((S n0) + k);
[idtac | auto with arith].
simpl.
replace (n0 + k) with (k + n0);
[idtac | auto with arith].
apply H0; trivial.
Qed.
double induction n m; simpl; intros;
auto with arith; try discriminate.
replace (k + (S n0)) with ((S n0) + k);
[idtac | auto with arith].
simpl. trivial.
replace (k + (S n0)) with ((S n0) + k);
[idtac | auto with arith].
simpl.
replace (n0 + k) with (k + n0);
[idtac | auto with arith].
apply H0; trivial.
Qed.
Lemma blt_nat_dec
: forall a b, {blt_nat a b = true} + {blt_nat a b = false}.
Proof.
double induction a b; simpl; intros; try tauto || auto.
Qed.
double induction a b; simpl; intros; try tauto || auto.
Qed.
ble
Definition ble_nat (n m : nat) : bool
:=
match blt_nat m n with
| true => false
| false => true
end.
match blt_nat m n with
| true => false
| false => true
end.
beq
Fixpoint beq_nat (n m : nat) {struct n} : bool
:=
match n, m with
| O, O => true
| O, S _ => false
| S _, O => false
| S n1, S m1 => beq_nat n1 m1
end.
match n, m with
| O, O => true
| O, S _ => false
| S _, O => false
| S n1, S m1 => beq_nat n1 m1
end.
Lemma beq_refl
: forall m, beq_nat m m = true.
Proof.
induction m; simpl; intros; auto.
Qed.
induction m; simpl; intros; auto.
Qed.
Lemma beq_trans
: forall m n k, beq_nat m n = true
-> beq_nat n k = true
-> beq_nat m k = true.
-> beq_nat n k = true
-> beq_nat m k = true.
Proof.
induction m; induction n; destruct k;
simpl; intros; discriminate || auto.
eapply IHm; eauto.
Qed.
induction m; induction n; destruct k;
simpl; intros; discriminate || auto.
eapply IHm; eauto.
Qed.
Lemma beq_sym
: forall m n b, beq_nat m n = b -> beq_nat n m = b.
Proof.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
Lemma beq_sym2
: forall m n, beq_nat m n = beq_nat n m.
Proof.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
Lemma beq_true_eq
: forall n m, beq_nat n m = true -> n = m.
Proof.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
Lemma beq_false_neq
: forall n m, beq_nat n m = false -> ~ (n = m).
Proof.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
Lemma eq_beq_true
: forall n m, n = m
-> beq_nat n m = true.
Proof.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
double induction n m; simpl; intros;
auto with arith; discriminate.
Qed.
Lemma neq_beq_false
: forall n m, ~ (n = m) -> beq_nat n m = false.
Proof.
double induction n m; simpl; intros;
auto with arith.
destruct (H (refl_equal _)).
Qed.
double induction n m; simpl; intros;
auto with arith.
destruct (H (refl_equal _)).
Qed.
Lemma beq_nat_dec
: forall a b,
{beq_nat a b = true} + {beq_nat a b = false}.
{beq_nat a b = true} + {beq_nat a b = false}.
Proof.
double induction a b; simpl; intros; try tauto || auto.
Qed.
double induction a b; simpl; intros; try tauto || auto.
Qed.
?
Lemma blt_t_beq_f
: forall m n, blt_nat m n = true -> beq_nat m n = false.
Proof.
double induction n m; simpl; intros; auto with arith.
Qed.
double induction n m; simpl; intros; auto with arith.
Qed.
Lemma bgt_t_beq_f
: forall m n, blt_nat n m = true -> beq_nat m n = false.
Proof.
double induction m n; simpl; intros; auto with arith.
Qed.
double induction m n; simpl; intros; auto with arith.
Qed.
Lemma beq_t_blt_f
: forall m n, beq_nat m n = true -> blt_nat m n = false.
Proof.
double induction m n; simpl; intros; auto with arith.
Qed.
double induction m n; simpl; intros; auto with arith.
Qed.
Lemma beq_t_bgt_f
: forall m n, beq_nat m n = true -> blt_nat n m = false.
Proof.
double induction n m; simpl; intros; auto with arith.
Qed.
double induction n m; simpl; intros; auto with arith.
Qed.
Lemma blt_S_dec
: forall n m,
blt_nat n (S m) = true
-> blt_nat n m = true \/ beq_nat n m = true.
blt_nat n (S m) = true
-> blt_nat n m = true \/ beq_nat n m = true.
Proof.
intros n m H.
assert (Hx:=blt_true_lt _ _ H).
apply lt_n_Sm_le in Hx.
apply le_lt_or_eq_iff in Hx.
destruct Hx.
left.
apply lt_blt_true; trivial.
right.
apply eq_beq_true; trivial.
Qed.
intros n m H.
assert (Hx:=blt_true_lt _ _ H).
apply lt_n_Sm_le in Hx.
apply le_lt_or_eq_iff in Hx.
destruct Hx.
left.
apply lt_blt_true; trivial.
right.
apply eq_beq_true; trivial.
Qed.
max
Definition max_nat (m n : nat) : nat
:= if blt_nat m n then n else m.
Lemma max_nat_elim_l
: forall m n : nat, m <= max_nat m n.
Proof.
unfold max_nat; intros m n.
destruct (blt_nat_dec m n) as [Hb | Hb]; rewrite Hb.
assert (Hb' := blt_true_lt m n Hb).
auto with arith.
auto with arith.
Qed.
unfold max_nat; intros m n.
destruct (blt_nat_dec m n) as [Hb | Hb]; rewrite Hb.
assert (Hb' := blt_true_lt m n Hb).
auto with arith.
auto with arith.
Qed.
Lemma max_nat_elim_r
: forall m n : nat, n <= max_nat m n.
Proof.
unfold max_nat; intros m n.
destruct (blt_nat_dec m n) as [Hb | Hb]; rewrite Hb.
auto with arith.
assert (Hb' := blt_false_le m n Hb).
auto with arith.
Qed.
unfold max_nat; intros m n.
destruct (blt_nat_dec m n) as [Hb | Hb]; rewrite Hb.
auto with arith.
assert (Hb' := blt_false_le m n Hb).
auto with arith.
Qed.
Lemma ble_minus
: forall (x y : nat),
x <= y ->
forall (z: nat),
y <= z ->
y - x <= z - x.
x <= y ->
forall (z: nat),
y <= z ->
y - x <= z - x.
Proof.
induction x; induction y; induction z; try auto with arith; intros.
- inversion H0.
- simpl. apply IHx; auto with arith.
Qed.
induction x; induction y; induction z; try auto with arith; intros.
- inversion H0.
- simpl. apply IHx; auto with arith.
Qed.
Ltac rewrite_bnat t
:=
match type of t with
| blt_nat ?a ?b = ?c => rewrite t
| beq_nat ?a ?b = ?c => rewrite t
end.
match type of t with
| blt_nat ?a ?b = ?c => rewrite t
| beq_nat ?a ?b = ?c => rewrite t
end.
Ltac rewrite_bnat_H t H
:=
match type of t with
| blt_nat ?a ?b = ?c => rewrite t in H
| beq_nat ?a ?b = ?c => rewrite t in H
end.
match type of t with
| blt_nat ?a ?b = ?c => rewrite t in H
| beq_nat ?a ?b = ?c => rewrite t in H
end.
Ltac rewrite_bnat_all t
:=
match goal with
| |- context[(blt_nat ?a ?b)] => rewrite_bnat t; rewrite_bnat_all t
| H : context[(blt_nat ?a ?b)] |- _ => rewrite_bnat_H t H; rewrite_bnat_all t
| |- context[(beq_nat ?a ?b)] => rewrite_bnat t; rewrite_bnat_all t
| H : context[(beq_nat ?a ?b)] |- _ => rewrite_bnat_H t H; rewrite_bnat_all t
| _ => idtac
end.
match goal with
| |- context[(blt_nat ?a ?b)] => rewrite_bnat t; rewrite_bnat_all t
| H : context[(blt_nat ?a ?b)] |- _ => rewrite_bnat_H t H; rewrite_bnat_all t
| |- context[(beq_nat ?a ?b)] => rewrite_bnat t; rewrite_bnat_all t
| H : context[(beq_nat ?a ?b)] |- _ => rewrite_bnat_H t H; rewrite_bnat_all t
| _ => idtac
end.
Ltac simplbnat
:=
match goal with
(* blt rewrite directly *)
| [H : blt_nat ?x ?y = ?f |- context [(blt_nat ?x ?y)]] => rewrite H; simplbnat
| [H : blt_nat ?x ?y = ?f, H0 : context [(blt_nat ?x ?y)] |- _ ] => rewrite H in H0; simplbnat
(* beq rewrite directly *)
| [H : beq_nat ?x ?y = ?f |- context [(beq_nat ?x ?y)]] => rewrite H; simplbnat
| [H : beq_nat ?x ?y = ?f, H0 : context [(beq_nat ?x ?y)] |- _ ] => rewrite H in H0; simplbnat
(* blt -> beq *)
| [H : blt_nat ?x ?y = true |- context[(beq_nat ?x ?y)]] => rewrite (blt_t_beq_f x y H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context[(beq_nat ?x ?y)] |- _ ] => rewrite (blt_t_beq_f x y H) in H0; simplbnat
(* bgt -> beq *)
| [H : blt_nat ?y ?x = true |- context[(beq_nat ?x ?y)]] => rewrite (bgt_t_beq_f x y H); simplbnat
| [H : blt_nat ?y ?x = true, H0 : context[(beq_nat ?x ?y)] |- _ ] => rewrite (bgt_t_beq_f x y H) in H0; simplbnat
(* beq -> blt *)
| [H : beq_nat ?y ?x = true |- context[(blt_nat ?x ?y)]] => rewrite (beq_t_blt_f x y H); simplbnat
| [H : beq_nat ?y ?x = true, H0 : context[(blt_nat ?x ?y)] |- _ ] => rewrite (beq_t_blt_f x y H) in H0; simplbnat
(* beq -> bgt *)
| [H : beq_nat ?y ?x = true |- context[(blt_nat ?y ?x)]] => rewrite (beq_t_bgt_f x y H); simplbnat
| [H : beq_nat ?y ?x = true, H0 : context[(blt_nat ?y ?x)] |- _ ] => rewrite (beq_t_bgt_f x y H) in H0; simplbnat
(* blt_irrefl *)
| [ |- context [blt_nat ?x ?x]] => rewrite (blt_irrefl x); simplbnat
| [H : context [blt_nat ?x ?x] |- _ ] => rewrite (blt_irrefl x) in H; simplbnat
(* blt_asym *)
| [H : blt_nat ?x ?y = true |- context [blt_nat ?y ?x]] => rewrite (blt_asym x y H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context [blt_nat ?y ?x] |- _ ] => rewrite (blt_asym x y H) in H0; simplbnat
(* blt_O_Sn *)
| [ |- context [(blt_nat O (S ?x))]] => rewrite (blt_O_Sn x); simplbnat
| [H : context [(blt_nat O (S ?x))] |- _ ] => rewrite (blt_O_Sn x) in H; simplbnat
(* blt_n_O *)
| [ |- context [(blt_nat ?x O)]] =>rewrite (blt_n_O x); simplbnat
| [H : context [(blt_nat ?x O)] |- _ ] => rewrite (blt_n_O x) in H; simplbnat
(* blt_n_Sn *)
| [ |- context [(blt_nat ?x (S ?x))]] => rewrite (blt_n_Sn x); simplbnat
| [H : context [(blt_nat ?x (S ?x))] |- _ ] => rewrite (blt_n_Sn x) in H; simplbnat
(* blt_S_eq *)
| [ |- context [(blt_nat (S ?x) (S ?y))]] => rewrite <- (blt_S_eq x y); simplbnat
| [H : context [(blt_nat (S ?x) (S ?y))] |- _ ] => rewrite <- (blt_S_eq x y) in H; simplbnat
(* blt_n_Sm *)
| [H : blt_nat ?x ?y = true |- context [(blt_nat ?x (S ?y))]] => rewrite (blt_n_Sm x y H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context [(blt_nat ?x (S ?y))] |- _ ] => rewrite <- (blt_n_Sm x y H) in H0; simplbnat
(* blt_n_mk *)
| [H : blt_nat ?x ?y = true |- context [(blt_nat ?x (?y + ?k))]] => rewrite (blt_n_mk x y k H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context [(blt_nat ?x (?y + ?k))] |- _ ] => rewrite <- (blt_n_mk x y k H) in H0; simplbnat
(* blt_n_km *)
| [H : blt_nat ?x ?y = true |- context [(blt_nat ?x (?k + ?y))]] => rewrite (blt_n_km x y k H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context [(blt_nat ?x (?k + ?y))] |- _ ] => rewrite <- (blt_n_km x y k H) in H0; simplbnat
(* beq_refl *)
| [ |- context [(beq_nat ?x ?x)] ] => rewrite (beq_refl x); simplbnat
| [H : context [(beq_nat ?x ?x)] |- _ ] => rewrite (beq_refl x) in H; simplbnat
(* beq_sym *)
| [ H : beq_nat ?x ?y = ?b |- context [(beq_nat ?y ?x)] ] => rewrite (beq_sym x y b H); simplbnat
| [H : beq_nat ?x ?y = ?b, H0 : context [(beq_nat ?y ?x)] |- _ ] => rewrite (beq_sym x y b H) in H0; simplbnat
| [ H : ?x <> ?y |- context [(beq_nat ?x ?y)] ] => rewrite (neq_beq_false x y H); simplbnat
| [ H : ?x <> ?y, H0 : context [(beq_nat ?x ?y)] |- _ ] => rewrite (neq_beq_false x y H) in H0; simplbnat
| [ H : ?y <> ?x |- context [(beq_nat ?x ?y)] ] => rewrite (neq_beq_false x y (sym_not_eq H)); simplbnat
| [ H : ?y <> ?x, H0 : context [(beq_nat ?x ?y)] |- _ ] => rewrite (neq_beq_false x y (sym_not_eq H)) in H0; simplbnat
| [H : ?x = ?x |- _ ] => clear H; simplbnat
| [H : true = false |- _ ] => discriminate H
| [H : false = true |- _ ] => discriminate H
| _ => idtac
end.
match goal with
(* blt rewrite directly *)
| [H : blt_nat ?x ?y = ?f |- context [(blt_nat ?x ?y)]] => rewrite H; simplbnat
| [H : blt_nat ?x ?y = ?f, H0 : context [(blt_nat ?x ?y)] |- _ ] => rewrite H in H0; simplbnat
(* beq rewrite directly *)
| [H : beq_nat ?x ?y = ?f |- context [(beq_nat ?x ?y)]] => rewrite H; simplbnat
| [H : beq_nat ?x ?y = ?f, H0 : context [(beq_nat ?x ?y)] |- _ ] => rewrite H in H0; simplbnat
(* blt -> beq *)
| [H : blt_nat ?x ?y = true |- context[(beq_nat ?x ?y)]] => rewrite (blt_t_beq_f x y H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context[(beq_nat ?x ?y)] |- _ ] => rewrite (blt_t_beq_f x y H) in H0; simplbnat
(* bgt -> beq *)
| [H : blt_nat ?y ?x = true |- context[(beq_nat ?x ?y)]] => rewrite (bgt_t_beq_f x y H); simplbnat
| [H : blt_nat ?y ?x = true, H0 : context[(beq_nat ?x ?y)] |- _ ] => rewrite (bgt_t_beq_f x y H) in H0; simplbnat
(* beq -> blt *)
| [H : beq_nat ?y ?x = true |- context[(blt_nat ?x ?y)]] => rewrite (beq_t_blt_f x y H); simplbnat
| [H : beq_nat ?y ?x = true, H0 : context[(blt_nat ?x ?y)] |- _ ] => rewrite (beq_t_blt_f x y H) in H0; simplbnat
(* beq -> bgt *)
| [H : beq_nat ?y ?x = true |- context[(blt_nat ?y ?x)]] => rewrite (beq_t_bgt_f x y H); simplbnat
| [H : beq_nat ?y ?x = true, H0 : context[(blt_nat ?y ?x)] |- _ ] => rewrite (beq_t_bgt_f x y H) in H0; simplbnat
(* blt_irrefl *)
| [ |- context [blt_nat ?x ?x]] => rewrite (blt_irrefl x); simplbnat
| [H : context [blt_nat ?x ?x] |- _ ] => rewrite (blt_irrefl x) in H; simplbnat
(* blt_asym *)
| [H : blt_nat ?x ?y = true |- context [blt_nat ?y ?x]] => rewrite (blt_asym x y H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context [blt_nat ?y ?x] |- _ ] => rewrite (blt_asym x y H) in H0; simplbnat
(* blt_O_Sn *)
| [ |- context [(blt_nat O (S ?x))]] => rewrite (blt_O_Sn x); simplbnat
| [H : context [(blt_nat O (S ?x))] |- _ ] => rewrite (blt_O_Sn x) in H; simplbnat
(* blt_n_O *)
| [ |- context [(blt_nat ?x O)]] =>rewrite (blt_n_O x); simplbnat
| [H : context [(blt_nat ?x O)] |- _ ] => rewrite (blt_n_O x) in H; simplbnat
(* blt_n_Sn *)
| [ |- context [(blt_nat ?x (S ?x))]] => rewrite (blt_n_Sn x); simplbnat
| [H : context [(blt_nat ?x (S ?x))] |- _ ] => rewrite (blt_n_Sn x) in H; simplbnat
(* blt_S_eq *)
| [ |- context [(blt_nat (S ?x) (S ?y))]] => rewrite <- (blt_S_eq x y); simplbnat
| [H : context [(blt_nat (S ?x) (S ?y))] |- _ ] => rewrite <- (blt_S_eq x y) in H; simplbnat
(* blt_n_Sm *)
| [H : blt_nat ?x ?y = true |- context [(blt_nat ?x (S ?y))]] => rewrite (blt_n_Sm x y H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context [(blt_nat ?x (S ?y))] |- _ ] => rewrite <- (blt_n_Sm x y H) in H0; simplbnat
(* blt_n_mk *)
| [H : blt_nat ?x ?y = true |- context [(blt_nat ?x (?y + ?k))]] => rewrite (blt_n_mk x y k H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context [(blt_nat ?x (?y + ?k))] |- _ ] => rewrite <- (blt_n_mk x y k H) in H0; simplbnat
(* blt_n_km *)
| [H : blt_nat ?x ?y = true |- context [(blt_nat ?x (?k + ?y))]] => rewrite (blt_n_km x y k H); simplbnat
| [H : blt_nat ?x ?y = true, H0 : context [(blt_nat ?x (?k + ?y))] |- _ ] => rewrite <- (blt_n_km x y k H) in H0; simplbnat
(* beq_refl *)
| [ |- context [(beq_nat ?x ?x)] ] => rewrite (beq_refl x); simplbnat
| [H : context [(beq_nat ?x ?x)] |- _ ] => rewrite (beq_refl x) in H; simplbnat
(* beq_sym *)
| [ H : beq_nat ?x ?y = ?b |- context [(beq_nat ?y ?x)] ] => rewrite (beq_sym x y b H); simplbnat
| [H : beq_nat ?x ?y = ?b, H0 : context [(beq_nat ?y ?x)] |- _ ] => rewrite (beq_sym x y b H) in H0; simplbnat
| [ H : ?x <> ?y |- context [(beq_nat ?x ?y)] ] => rewrite (neq_beq_false x y H); simplbnat
| [ H : ?x <> ?y, H0 : context [(beq_nat ?x ?y)] |- _ ] => rewrite (neq_beq_false x y H) in H0; simplbnat
| [ H : ?y <> ?x |- context [(beq_nat ?x ?y)] ] => rewrite (neq_beq_false x y (sym_not_eq H)); simplbnat
| [ H : ?y <> ?x, H0 : context [(beq_nat ?x ?y)] |- _ ] => rewrite (neq_beq_false x y (sym_not_eq H)) in H0; simplbnat
| [H : ?x = ?x |- _ ] => clear H; simplbnat
| [H : true = false |- _ ] => discriminate H
| [H : false = true |- _ ] => discriminate H
| _ => idtac
end.
Tactic Notation "bnat simpl"
:= simplbnat.
Ltac desbnatH H
:=
match goal with
| H : blt_nat ?a ?b = true |- _ => generalize (blt_true_lt a b H); clear H; intro H
| H : blt_nat ?a ?b = false |- _ => generalize (blt_false_le a b H); clear H; intro H
| H : beq_nat ?a ?b = true |- _ => generalize (beq_true_eq a b H); clear H; intro H
| H : beq_nat ?a ?b = false |- _ => generalize (beq_false_neq a b H); clear H; intro H
| _ => fail 1 "not bnat found"
end.
match goal with
| H : blt_nat ?a ?b = true |- _ => generalize (blt_true_lt a b H); clear H; intro H
| H : blt_nat ?a ?b = false |- _ => generalize (blt_false_le a b H); clear H; intro H
| H : beq_nat ?a ?b = true |- _ => generalize (beq_true_eq a b H); clear H; intro H
| H : beq_nat ?a ?b = false |- _ => generalize (beq_false_neq a b H); clear H; intro H
| _ => fail 1 "not bnat found"
end.
Ltac desbnat
:=
match goal with
| H : blt_nat ?a ?b = true |- _ => generalize (blt_true_lt a b H); clear H; intro H; desbnat
| H : blt_nat ?a ?b = false |- _ => generalize (blt_false_le a b H); clear H; intro H; desbnat
| H : beq_nat ?a ?b = true |- _ => generalize (beq_true_eq a b H); clear H; intro H; desbnat
| H : beq_nat ?a ?b = false |- _ => generalize (beq_false_neq a b H); clear H; intro H; desbnat
| _ => idtac
end.
match goal with
| H : blt_nat ?a ?b = true |- _ => generalize (blt_true_lt a b H); clear H; intro H; desbnat
| H : blt_nat ?a ?b = false |- _ => generalize (blt_false_le a b H); clear H; intro H; desbnat
| H : beq_nat ?a ?b = true |- _ => generalize (beq_true_eq a b H); clear H; intro H; desbnat
| H : beq_nat ?a ?b = false |- _ => generalize (beq_false_neq a b H); clear H; intro H; desbnat
| _ => idtac
end.
Ltac conbnat
:=
match goal with
| |- blt_nat ?a ?b = true => apply (lt_blt_true a b)
| |- blt_nat ?a ?b = false => apply (le_blt_false b a)
| |- beq_nat ?a ?b = true => apply (eq_beq_true a b)
| |- beq_nat ?a ?b = false => apply (neq_beq_false a b)
| _ => fail 1 "the goal is not bnat"
end.
match goal with
| |- blt_nat ?a ?b = true => apply (lt_blt_true a b)
| |- blt_nat ?a ?b = false => apply (le_blt_false b a)
| |- beq_nat ?a ?b = true => apply (eq_beq_true a b)
| |- beq_nat ?a ?b = false => apply (neq_beq_false a b)
| _ => fail 1 "the goal is not bnat"
end.
Ltac solvebnat
:= desbnat; conbnat; auto with arith.
Tactic Notation "rewbnat" constr (t)
:=
match t with
| beq_nat ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [solvebnat | rewrite Hb; clear Hb])
| blt_nat ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [solvebnat | rewrite Hb; clear Hb])
| _ => match type of t with
| beq_nat ?x ?y = true => rewrite (beq_true_eq x y t)
| _ => rewrite t
end
end.
match t with
| beq_nat ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [solvebnat | rewrite Hb; clear Hb])
| blt_nat ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [solvebnat | rewrite Hb; clear Hb])
| _ => match type of t with
| beq_nat ?x ?y = true => rewrite (beq_true_eq x y t)
| _ => rewrite t
end
end.
Tactic Notation "rewbnat" constr (t) "in" hyp (H)
:=
match t with
| beq_nat ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [solvebnat | rewrite Hb in H; clear Hb])
| blt_nat ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [solvebnat | rewrite Hb in H; clear Hb])
| _ =>
match type of t with
| beq_nat ?x ?y = true => rewrite (beq_true_eq x y t) in H
| _ => rewrite t in H
end
end.
match t with
| beq_nat ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [solvebnat | rewrite Hb in H; clear Hb])
| blt_nat ?x ?y = ?f => let Hb := fresh "Hb" in (assert (Hb : t); [solvebnat | rewrite Hb in H; clear Hb])
| _ =>
match type of t with
| beq_nat ?x ?y = true => rewrite (beq_true_eq x y t) in H
| _ => rewrite t in H
end
end.
Tactic Notation "assertbnat" constr (t)
:=
let Hb := fresh "Hb" in (
match t with
| beq_nat ?x ?y = ?f => (assert (Hb : t); [solvebnat | idtac])
| blt_nat ?x ?y = ?f => (assert (Hb : t); [solvebnat | idtac])
| _ => fail 1 "t must be a blt_nat or beq_nat equation"
end).
let Hb := fresh "Hb" in (
match t with
| beq_nat ?x ?y = ?f => (assert (Hb : t); [solvebnat | idtac])
| blt_nat ?x ?y = ?f => (assert (Hb : t); [solvebnat | idtac])
| _ => fail 1 "t must be a blt_nat or beq_nat equation"
end).
Ltac discribnat
:=
desbnat; subst;
match goal with
| H : ?x <> ?x |- _ => destruct (H (refl_equal x))
| H : ?x = ?y |- _ => discriminate
| H : ?x < ?x |- _ => destruct (lt_irrefl x H)
| H : ?x < O |- _ => destruct (lt_n_O x H)
| H : beq_nat ?x ?x = false |- _ => desbnatH H; destruct (H (refl_equal x))
| _ => elimtype False; auto with arith || fail 1 "no discriminatable hypothesis"
end.
desbnat; subst;
match goal with
| H : ?x <> ?x |- _ => destruct (H (refl_equal x))
| H : ?x = ?y |- _ => discriminate
| H : ?x < ?x |- _ => destruct (lt_irrefl x H)
| H : ?x < O |- _ => destruct (lt_n_O x H)
| H : beq_nat ?x ?x = false |- _ => desbnatH H; destruct (H (refl_equal x))
| _ => elimtype False; auto with arith || fail 1 "no discriminatable hypothesis"
end.
Ltac substbnat_all
:= desbnat; subst.
Ltac substbnat_one f
:= desbnat; subst f.
Tactic Notation "substbnat"
:= substbnat_all.
Tactic Notation "substbnat" constr (f)
:= substbnat_one f.
Ltac decbeqnat x y
:= let Hb := fresh "Hb" in (destruct (beq_nat_dec x y) as [Hb | Hb]; simplbnat).
Ltac decbltnat x y
:= let Hb := fresh "Hb" in (destruct (blt_nat_dec x y) as [Hb | Hb]; simplbnat).
Mapping.v
Require Export Types.
Require Export BNat.
Require Export TMap.
Require Export Nat.
Require Export BNat.
Require Export TMap.
Require Export Nat.
Definition a2v
:= @tmap address value.
Definition aa2v
:= @tmap (prod address address) value.
Instance address_Domain : BEq address
:=
{
beq := BNat.beq_nat;
beq_true_eq := BNat.beq_true_eq;
beq_false_neq := BNat.beq_false_neq;
eq_beq_true := BNat.eq_beq_true;
neq_beq_false := BNat.neq_beq_false;
}.
{
beq := BNat.beq_nat;
beq_true_eq := BNat.beq_true_eq;
beq_false_neq := BNat.beq_false_neq;
eq_beq_true := BNat.eq_beq_true;
neq_beq_false := BNat.neq_beq_false;
}.
Instance value_Range : BZero
:=
{
zero := (0: value);
}.
{
zero := (0: value);
}.
Definition beq_addrx2 (a1 a2: (prod address address)): bool
:=
match a1, a2 with
| (x1, y1), (x2, y2) => andb (beq_nat x1 x2) (beq_nat y1 y2)
end.
match a1, a2 with
| (x1, y1), (x2, y2) => andb (beq_nat x1 x2) (beq_nat y1 y2)
end.
Instance addressx2_Domain : BEq (prod address address)
:=
{
beq a a' := beq_addrx2 a a';
}.
{
beq a a' := beq_addrx2 a a';
}.
Proof.
unfold beq_addrx2.
intros [a1 a2] [a3 a4].
intros.
unfold andb in H.
decbeqnat a1 a3.
rewbnat H.
rewbnat Hb.
trivial.
intros [a1 a2] [a3 a4].
intros.
unfold beq_addrx2 in H.
unfold andb in H.
decbeqnat a1 a3.
rewbnat Hb.
intro Hf.
inversion Hf;subst.
simplbnat.
intro Hf.
inversion Hf; subst.
simplbnat.
intros [a1 a2] [a3 a4].
intros.
unfold beq_addrx2.
inversion H;subst.
unfold andb.
simplbnat.
trivial.
intros [a1 a2] [a3 a4].
intros.
unfold beq_addrx2.
unfold andb.
decbeqnat a1 a3.
rewbnat Hb in H.
decbeqnat a2 a4.
rewbnat Hb0 in H.
destruct (H (eq_refl _)).
trivial.
trivial.
Defined.
unfold beq_addrx2.
intros [a1 a2] [a3 a4].
intros.
unfold andb in H.
decbeqnat a1 a3.
rewbnat H.
rewbnat Hb.
trivial.
intros [a1 a2] [a3 a4].
intros.
unfold beq_addrx2 in H.
unfold andb in H.
decbeqnat a1 a3.
rewbnat Hb.
intro Hf.
inversion Hf;subst.
simplbnat.
intro Hf.
inversion Hf; subst.
simplbnat.
intros [a1 a2] [a3 a4].
intros.
unfold beq_addrx2.
inversion H;subst.
unfold andb.
simplbnat.
trivial.
intros [a1 a2] [a3 a4].
intros.
unfold beq_addrx2.
unfold andb.
decbeqnat a1 a3.
rewbnat Hb in H.
decbeqnat a2 a4.
rewbnat Hb0 in H.
destruct (H (eq_refl _)).
trivial.
trivial.
Defined.
Opaque beq.
Require Import Omega.
Definition plus_with_overflow (lhs: value) (rhs: value)
:=
if (blt_nat (MAX_UINT256 - rhs) lhs)
then (if (beq_nat rhs 0)
then lhs
else (lhs + rhs - MAX_UINT256 - 1))
else (lhs + rhs).
if (blt_nat (MAX_UINT256 - rhs) lhs)
then (if (beq_nat rhs 0)
then lhs
else (lhs + rhs - MAX_UINT256 - 1))
else (lhs + rhs).
Lemma plus_safe_lt
: forall (x: value) (y: value), x <= MAX_UINT256 - y -> plus_with_overflow x y = x + y.
Proof.
intros.
unfold plus_with_overflow.
assert (H1 : blt_nat (MAX_UINT256 - y) x = false).
apply le_blt_false; trivial.
rewrite H1; trivial.
Qed.
intros.
unfold plus_with_overflow.
assert (H1 : blt_nat (MAX_UINT256 - y) x = false).
apply le_blt_false; trivial.
rewrite H1; trivial.
Qed.
Lemma plus_safe_lhs0
: forall (x: value) (y: value), x = 0 -> plus_with_overflow x y = x + y.
Proof.
intros.
unfold plus_with_overflow.
rewrite H; simpl.
assert(Ht: blt_nat (MAX_UINT256 - y) 0 = false).
simplbnat; trivial.
rewrite Ht; trivial.
Qed.
intros.
unfold plus_with_overflow.
rewrite H; simpl.
assert(Ht: blt_nat (MAX_UINT256 - y) 0 = false).
simplbnat; trivial.
rewrite Ht; trivial.
Qed.
Lemma plus_safe_rhs0
: forall (x: value) (y: value), y = 0 -> plus_with_overflow x y = x + y.
Proof.
intros.
unfold plus_with_overflow.
rewrite H; simpl.
destruct (blt_nat_dec (MAX_UINT256 - 0) x); rewrite e; trivial.
Qed.
intros.
unfold plus_with_overflow.
rewrite H; simpl.
destruct (blt_nat_dec (MAX_UINT256 - 0) x); rewrite e; trivial.
Qed.
Definition minus_with_underflow (lhs: value) (rhs: value)
:= if (blt_nat lhs rhs) then (lhs + MAX_UINT256 + 1 - rhs) else (lhs - rhs).
Lemma minus_safe
: forall (x: value) (y: value), x >= y -> minus_with_underflow x y = x - y.
Proof.
intros.
unfold minus_with_underflow.
assert (H1 : blt_nat x y = false).
apply le_blt_false; trivial.
rewrite H1; trivial.
Qed.
intros.
unfold minus_with_underflow.
assert (H1 : blt_nat x y = false).
apply le_blt_false; trivial.
rewrite H1; trivial.
Qed.
Lemma minus_plus_safe
: forall (x y : value), x <= MAX_UINT256 -> x >= y -> plus_with_overflow (minus_with_underflow x y) y = x.
Proof.
intros x y Hhi Hlo.
rewrite (minus_safe _ _ Hlo).
assert (y <= x). auto with arith.
assert (x - y <= MAX_UINT256 - y). apply ble_minus; auto.
rewrite (plus_safe_lt _ _ H0).
Admitted.
intros x y Hhi Hlo.
rewrite (minus_safe _ _ Hlo).
assert (y <= x). auto with arith.
assert (x - y <= MAX_UINT256 - y). apply ble_minus; auto.
rewrite (plus_safe_lt _ _ H0).
Admitted.
Definition a2v_upd_inc (m: a2v) (a: address) (v:value)
:= @tmap_upd address value address_Domain m a (plus_with_overflow (m a) v).
Definition a2v_upd_dec (m: a2v) (a: address) (v:value)
:= @tmap_upd address value address_Domain m a (minus_with_underflow (m a) v).
Definition aa2v_upd_2 (m: aa2v) (a1: address) (a2: address) (v:value)
:= @tmap_upd (prod address address) value addressx2_Domain m (a1, a2) v.
Definition aa2v_upd_inc (m: aa2v) (a1: address) (a2: address) (v:value)
:= @tmap_upd (prod address address) value addressx2_Domain m (a1, a2) (plus_with_overflow (m (a1, a2)) v).
Definition aa2v_upd_dec (m: aa2v) (a1: address) (a2: address) (v:value)
:= @tmap_upd (prod address address) value addressx2_Domain m (a1, a2) (minus_with_underflow (m (a1, a2)) v).
Notation "m $+ { k , k' <- v }"
:= (aa2v_upd_2 m k k' v) (at level 50, left associativity).
Notation "m $+ { k <- += v }"
:= (a2v_upd_inc m k v) (at level 50, left associativity).
Notation "m $+ { k <- -= v }"
:= (a2v_upd_dec m k v) (at level 50, left associativity).
Notation "m $+ { k , k' <- += v }"
:= (aa2v_upd_inc m k k' v) (at level 50, left associativity).
Notation "m $+ { k , k' <- -= v }"
:= (aa2v_upd_dec m k k' v) (at level 50, left associativity).
Lemma a2v_dec_inc_id
: forall (m: a2v) (a: address) (v: value),
m a <= MAX_UINT256 ->
m a >= v ->
m = m $+ { a <- -= v } $+ { a <- += v }.
m a <= MAX_UINT256 ->
m a >= v ->
m = m $+ { a <- -= v } $+ { a <- += v }.
Proof.
intros m a v Hhi Hlo.
unfold a2v_upd_inc, a2v_upd_dec, tmap_upd.
apply tmap_extensionality.
intros a'. destruct (beq_dec a a').
- (* a = a' *)
rewrite Nat.eqb_eq in H. subst a.
rewrite (beq_refl _).
rewrite (minus_plus_safe _ _ Hhi Hlo).
reflexivity.
- (* a <> a' *)
rewrite H.
reflexivity.
Qed.
intros m a v Hhi Hlo.
unfold a2v_upd_inc, a2v_upd_dec, tmap_upd.
apply tmap_extensionality.
intros a'. destruct (beq_dec a a').
- (* a = a' *)
rewrite Nat.eqb_eq in H. subst a.
rewrite (beq_refl _).
rewrite (minus_plus_safe _ _ Hhi Hlo).
reflexivity.
- (* a <> a' *)
rewrite H.
reflexivity.
Qed.
Spec.v
Require Export Model.
Require Export Lists.List.
Require Export Lists.List.
Record Spec: Type
:=
mk_spec {
spec_require: state -> Prop;
spec_events: state -> eventlist -> Prop;
spec_trans: state -> state -> Prop
}.
mk_spec {
spec_require: state -> Prop;
spec_events: state -> eventlist -> Prop;
spec_trans: state -> state -> Prop
}.
Definition funcspec_EIP20(_initialAmount: uint256)(_tokenName: string)(_decimalUnits: uint8)(_tokenSymbol: string)
:=
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* No require in this function. *)
(fun S : state => True)
(* Models an EIP20 event here. *)
(fun S E => E = ev_EIP20 (m_sender msg) _initialAmount _tokenName _decimalUnits _tokenSymbol :: nil)
(* State transition: *)
(fun S S' : state =>
(* totalSupply = _initialAmount; // Update total supply *)
st_totalSupply S' = _initialAmount /\
(* name = _tokenName; // Set the name for display purposes *)
st_name S' = _tokenName /\
(* decimals = _decimalUnits; // Amount of decimals for display purposes *)
st_decimals S' = _decimalUnits /\
(* symbol = _tokenSymbol; // Set the symbol for display purposes *)
st_symbol S' = _tokenSymbol /\
(* balances[msg.sender] = _initialAmount; // Give the creator all initial tokens *)
st_balances S' = $0 $+ {m_sender msg <- _initialAmount } /\
(* Init to all zero. *)
st_allowed S' = $0
)
).
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* No require in this function. *)
(fun S : state => True)
(* Models an EIP20 event here. *)
(fun S E => E = ev_EIP20 (m_sender msg) _initialAmount _tokenName _decimalUnits _tokenSymbol :: nil)
(* State transition: *)
(fun S S' : state =>
(* totalSupply = _initialAmount; // Update total supply *)
st_totalSupply S' = _initialAmount /\
(* name = _tokenName; // Set the name for display purposes *)
st_name S' = _tokenName /\
(* decimals = _decimalUnits; // Amount of decimals for display purposes *)
st_decimals S' = _decimalUnits /\
(* symbol = _tokenSymbol; // Set the symbol for display purposes *)
st_symbol S' = _tokenSymbol /\
(* balances[msg.sender] = _initialAmount; // Give the creator all initial tokens *)
st_balances S' = $0 $+ {m_sender msg <- _initialAmount } /\
(* Init to all zero. *)
st_allowed S' = $0
)
).
Definition funcspec_transfer(to: address)(value: value)
:=
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* require(balances[msg.sender] >= _value); *)
(fun S : state =>
(st_balances S (m_sender msg )) >= value /\
(* require(msg.sender == _to || balances[_to] <= MAX_UINT256 - _value); *)
((m_sender msg = to) \/ (m_sender msg <> to /\ st_balances S to <= MAX_UINT256 - value)))
(* emit Transfer(msg.sender, _to, _value); *)
(* return True; *)
(fun S E => E = (ev_Transfer (m_sender msg) (m_sender msg) to value) :: (ev_return _ True) :: nil)
(* State transition: *)
(fun S S' : state =>
(* Unchanged. *)
st_totalSupply S' = st_totalSupply S /\
st_name S' = st_name S /\
st_decimals S' = st_decimals S /\
st_symbol S' = st_symbol S /\
(* balances[msg.sender] -= _value; *)
st_balances S' = (st_balances S) $+{ (m_sender msg) <- -= value }
(* balances[_to] += _value; *)
$+{ to <- += value }
(* Unchanged. *)
/\ st_allowed S' = st_allowed S)
).
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* require(balances[msg.sender] >= _value); *)
(fun S : state =>
(st_balances S (m_sender msg )) >= value /\
(* require(msg.sender == _to || balances[_to] <= MAX_UINT256 - _value); *)
((m_sender msg = to) \/ (m_sender msg <> to /\ st_balances S to <= MAX_UINT256 - value)))
(* emit Transfer(msg.sender, _to, _value); *)
(* return True; *)
(fun S E => E = (ev_Transfer (m_sender msg) (m_sender msg) to value) :: (ev_return _ True) :: nil)
(* State transition: *)
(fun S S' : state =>
(* Unchanged. *)
st_totalSupply S' = st_totalSupply S /\
st_name S' = st_name S /\
st_decimals S' = st_decimals S /\
st_symbol S' = st_symbol S /\
(* balances[msg.sender] -= _value; *)
st_balances S' = (st_balances S) $+{ (m_sender msg) <- -= value }
(* balances[_to] += _value; *)
$+{ to <- += value }
(* Unchanged. *)
/\ st_allowed S' = st_allowed S)
).
Definition funcspec_transferFrom_1(from: address)(to: address)(value: value)
:=
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(fun S : state =>
(* require(balances[_from] >= _value); *)
st_balances S from >= value /\
(* require(_from == _to || balances[_to] <= MAX_UINT256 - _value); *)
((from = to) \/ (from <> to /\ st_balances S to <= MAX_UINT256 - value)) /\
(* require(allowance >= _value); *)
st_allowed S (from, m_sender msg) >= value /\
(* allowance < MAX_UINT256 *)
st_allowed S (from, m_sender msg) < MAX_UINT256
)
(* emit Transfer(_from, _to, _value); *)
(* return True; *)
(fun S E => E = (ev_Transfer (m_sender msg) from to value) :: (ev_return _ True) :: nil)
(* State transition: *)
(fun S S' : state =>
(* Unchanged. *)
st_totalSupply S' = st_totalSupply S /\
st_name S' = st_name S /\
st_decimals S' = st_decimals S /\
st_symbol S' = st_symbol S /\
(* balances[_from] -= _value; *)
st_balances S' = (st_balances S) $+{ from <- -= value }
(* balances[_to] += _value; *)
$+{ to <- += value } /\
(* allowed[_from][msg.sender] -= _value; *)
st_allowed S' = (st_allowed S) $+{ from, m_sender msg <- -= value }
)
).
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(fun S : state =>
(* require(balances[_from] >= _value); *)
st_balances S from >= value /\
(* require(_from == _to || balances[_to] <= MAX_UINT256 - _value); *)
((from = to) \/ (from <> to /\ st_balances S to <= MAX_UINT256 - value)) /\
(* require(allowance >= _value); *)
st_allowed S (from, m_sender msg) >= value /\
(* allowance < MAX_UINT256 *)
st_allowed S (from, m_sender msg) < MAX_UINT256
)
(* emit Transfer(_from, _to, _value); *)
(* return True; *)
(fun S E => E = (ev_Transfer (m_sender msg) from to value) :: (ev_return _ True) :: nil)
(* State transition: *)
(fun S S' : state =>
(* Unchanged. *)
st_totalSupply S' = st_totalSupply S /\
st_name S' = st_name S /\
st_decimals S' = st_decimals S /\
st_symbol S' = st_symbol S /\
(* balances[_from] -= _value; *)
st_balances S' = (st_balances S) $+{ from <- -= value }
(* balances[_to] += _value; *)
$+{ to <- += value } /\
(* allowed[_from][msg.sender] -= _value; *)
st_allowed S' = (st_allowed S) $+{ from, m_sender msg <- -= value }
)
).
Definition funcspec_transferFrom_2(from: address)(to: address)(value: value)
:=
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(fun S : state =>
(* require(balances[_from] >= _value); *)
st_balances S from >= value /\
(* require(_from == _to || balances[_to] <= MAX_UINT256 - _value); *)
((from = to) \/ (from <> to /\ st_balances S to <= MAX_UINT256 - value)) /\
(* require(allowance >= _value); *)
st_allowed S (from, m_sender msg) >= value /\
(* allowance = MAX_UINT256 *)
st_allowed S (from, m_sender msg) = MAX_UINT256)
(* emit Transfer(_from, _to, _value); *)
(* return True; *)
(fun S E => E = (ev_Transfer (m_sender msg) from to value) :: (ev_return _ True) :: nil)
(* State transition: *)
(fun S S' : state =>
(* Unchanged. *)
st_totalSupply S' = st_totalSupply S /\
st_name S' = st_name S /\
st_decimals S' = st_decimals S /\
st_symbol S' = st_symbol S /\
(* balances[_from] -= _value; *)
st_balances S' = (st_balances S) $+{ from <- -= value }
(* balances[_to] += _value; *)
$+{ to <- += value } /\
(* Unchanged. *)
st_allowed S' = st_allowed S
)
).
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(fun S : state =>
(* require(balances[_from] >= _value); *)
st_balances S from >= value /\
(* require(_from == _to || balances[_to] <= MAX_UINT256 - _value); *)
((from = to) \/ (from <> to /\ st_balances S to <= MAX_UINT256 - value)) /\
(* require(allowance >= _value); *)
st_allowed S (from, m_sender msg) >= value /\
(* allowance = MAX_UINT256 *)
st_allowed S (from, m_sender msg) = MAX_UINT256)
(* emit Transfer(_from, _to, _value); *)
(* return True; *)
(fun S E => E = (ev_Transfer (m_sender msg) from to value) :: (ev_return _ True) :: nil)
(* State transition: *)
(fun S S' : state =>
(* Unchanged. *)
st_totalSupply S' = st_totalSupply S /\
st_name S' = st_name S /\
st_decimals S' = st_decimals S /\
st_symbol S' = st_symbol S /\
(* balances[_from] -= _value; *)
st_balances S' = (st_balances S) $+{ from <- -= value }
(* balances[_to] += _value; *)
$+{ to <- += value } /\
(* Unchanged. *)
st_allowed S' = st_allowed S
)
).
Definition funcspec_balanceOf(owner: address)
:=
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* No requirement *)
(fun S : state => True)
(* return balances[_owner]; *)
(fun S E => E = (ev_return _ (st_balances S owner)) :: nil)
(* Unchanged. *)
(fun S S' : state => S = S')
).
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* No requirement *)
(fun S : state => True)
(* return balances[_owner]; *)
(fun S E => E = (ev_return _ (st_balances S owner)) :: nil)
(* Unchanged. *)
(fun S S' : state => S = S')
).
Definition funcspec_approve(spender: address)(value: value)
:=
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* No requirement *)
(fun S : state => True)
(* emit Approval(msg.sender, _spender, _value); *)
(* return True; *)
(fun S E => E = (ev_Approval (m_sender msg) (m_sender msg) spender value) :: (ev_return _ True) :: nil)
(* State transition: *)
(fun S S' : state =>
(* Unchanged. *)
st_totalSupply S' = st_totalSupply S /\
st_name S' = st_name S /\
st_decimals S' = st_decimals S /\
st_symbol S' = st_symbol S /\
st_balances S' = st_balances S /\
(* allowed[msg.sender][_spender] = _value; *)
st_allowed S' = (st_allowed S) $+{ m_sender msg, spender <- value}
)
).
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* No requirement *)
(fun S : state => True)
(* emit Approval(msg.sender, _spender, _value); *)
(* return True; *)
(fun S E => E = (ev_Approval (m_sender msg) (m_sender msg) spender value) :: (ev_return _ True) :: nil)
(* State transition: *)
(fun S S' : state =>
(* Unchanged. *)
st_totalSupply S' = st_totalSupply S /\
st_name S' = st_name S /\
st_decimals S' = st_decimals S /\
st_symbol S' = st_symbol S /\
st_balances S' = st_balances S /\
(* allowed[msg.sender][_spender] = _value; *)
st_allowed S' = (st_allowed S) $+{ m_sender msg, spender <- value}
)
).
Definition funcspec_allowance (owner: address) (spender: address)
:=
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* No requirement *)
(fun S : state => True)
(* return allowed[_owner][_spender]; *)
(fun S E => E = (ev_return _ (st_allowed S (owner, spender))) :: nil)
(* Unchanged. *)
(fun S S' : state => S' = S)
).
fun (this: address) (env: env) (msg: message) =>
(mk_spec
(* No requirement *)
(fun S : state => True)
(* return allowed[_owner][_spender]; *)
(fun S E => E = (ev_return _ (st_allowed S (owner, spender))) :: nil)
(* Unchanged. *)
(fun S S' : state => S' = S)
).
Inductive create : env -> message -> contract -> eventlist -> Prop
:=
| create_EIP20 : forall env msg S C E sender ia name dec sym spec preP evP postP,
msg = mk_msg sender (mc_EIP20 ia name dec sym) 0
-> spec = funcspec_EIP20 ia name dec sym (w_a C) env msg
-> ia <= MAX_UINT256
-> preP = spec_require spec
-> evP = spec_events spec
-> postP = spec_trans spec
-> evP S E /\ postP S (w_st C)
-> create env msg C E.
| create_EIP20 : forall env msg S C E sender ia name dec sym spec preP evP postP,
msg = mk_msg sender (mc_EIP20 ia name dec sym) 0
-> spec = funcspec_EIP20 ia name dec sym (w_a C) env msg
-> ia <= MAX_UINT256
-> preP = spec_require spec
-> evP = spec_events spec
-> postP = spec_trans spec
-> evP S E /\ postP S (w_st C)
-> create env msg C E.
Inductive step : env -> contract -> message -> contract -> eventlist -> Prop
:=
| step_transfer: forall env msg C C' E' sender to v spec preP evP postP,
w_a C = w_a C'
-> msg = mk_msg sender (mc_transfer to v) 0
-> spec = funcspec_transfer to v (w_a C) env msg
-> preP = spec_require spec
-> evP = spec_events spec
-> postP = spec_trans spec
-> preP (w_st C) /\ evP (w_st C) E' /\ postP (w_st C) (w_st C')
-> step env C msg C' E'
| step_transferFrom_1 : forall env sender msg from to v spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_transferFrom from to v) 0
-> spec = funcspec_transferFrom_1 from to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
| step_transferFrom_2 : forall env sender msg from to v spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_transferFrom from to v) 0
-> spec = funcspec_transferFrom_2 from to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
| step_balanceOf : forall env sender msg owner spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_balanceOf owner) 0
-> spec = funcspec_balanceOf owner (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
| step_approve : forall env sender msg spender v spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_approve spender v) 0
-> spec = funcspec_approve spender v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
| step_allowance : forall env sender msg owner spender spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_allowance owner spender) 0
-> spec = funcspec_allowance owner spender (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
.
| step_transfer: forall env msg C C' E' sender to v spec preP evP postP,
w_a C = w_a C'
-> msg = mk_msg sender (mc_transfer to v) 0
-> spec = funcspec_transfer to v (w_a C) env msg
-> preP = spec_require spec
-> evP = spec_events spec
-> postP = spec_trans spec
-> preP (w_st C) /\ evP (w_st C) E' /\ postP (w_st C) (w_st C')
-> step env C msg C' E'
| step_transferFrom_1 : forall env sender msg from to v spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_transferFrom from to v) 0
-> spec = funcspec_transferFrom_1 from to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
| step_transferFrom_2 : forall env sender msg from to v spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_transferFrom from to v) 0
-> spec = funcspec_transferFrom_2 from to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
| step_balanceOf : forall env sender msg owner spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_balanceOf owner) 0
-> spec = funcspec_balanceOf owner (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
| step_approve : forall env sender msg spender v spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_approve spender v) 0
-> spec = funcspec_approve spender v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
| step_allowance : forall env sender msg owner spender spec C C' E' ,
w_a C = w_a C'
-> msg = mk_msg sender (mc_allowance owner spender) 0
-> spec = funcspec_allowance owner spender (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> step env C msg C' E'
.
Definition env_step (env1: env) (env2: env) : Prop
:= env_time env2 >= env_time env1 /\ env_bhash env2 <> env_bhash env1.
Fixpoint steps (env: env) (C: contract) (ml: list message) (env': Model.env) (C': contract) (E: eventlist) :Prop
:= match ml with
| nil => C' = C /\ E = nil /\ env = env'
| cons msg ml => exists env'', exists C'', exists E'', exists E',
step env C msg C'' E'' /\ steps env'' C'' ml env' C' E'
/\ E = E'' ++ E'
/\ env_step env env''
end.
| nil => C' = C /\ E = nil /\ env = env'
| cons msg ml => exists env'', exists C'', exists E'', exists E',
step env C msg C'' E'' /\ steps env'' C'' ml env' C' E'
/\ E = E'' ++ E'
/\ env_step env env''
end.
Definition run (env: env) (C: contract) (ml: list message) (C': contract) (E: eventlist) :Prop
:=
exists env',
steps env C ml env' C' E.
exists env',
steps env C ml env' C' E.
Model.v
Require Export LibEx.
Require Export Lists.List.
Require Export ZArith.
Require Export Integers.
Require Export String.
Require Export Types.
Require Export Mapping.
Require Export AbsModel.
Require Export Lists.List.
Require Export ZArith.
Require Export Integers.
Require Export String.
Require Export Types.
Require Export Mapping.
Require Export AbsModel.
Record state : Type
:=
mk_st {
st_symbol: string;
st_name: string;
st_decimals: uint8;
st_totalSupply: uint256;
st_balances: a2v;
st_allowed: aa2v;
}.
mk_st {
st_symbol: string;
st_name: string;
st_decimals: uint8;
st_totalSupply: uint256;
st_balances: a2v;
st_allowed: aa2v;
}.
Inductive event : Type
:=
(* ERC20 events *)
| ev_Transfer (a: address) (from: address) (to: address) (v: value): event
| ev_Approval (a: address) (owner: address) (spender: address) (v: value): event
| ev_EIP20 (a: address) (_initialAmount: uint256) (_tokenName: string)
(_decimalUnits: uint8) (_tokenSymbol: string) : event
(* Return event that models the return value *)
| ev_return (A: Type) (ret: A) : event
| ev_revert (this: address)
.
(* ERC20 events *)
| ev_Transfer (a: address) (from: address) (to: address) (v: value): event
| ev_Approval (a: address) (owner: address) (spender: address) (v: value): event
| ev_EIP20 (a: address) (_initialAmount: uint256) (_tokenName: string)
(_decimalUnits: uint8) (_tokenSymbol: string) : event
(* Return event that models the return value *)
| ev_return (A: Type) (ret: A) : event
| ev_revert (this: address)
.
Definition eventlist
:= TEventList event.
Definition env
:= TEnv.
Definition contract
:= TContract state.
Inductive mcall : Type
:=
| mc_EIP20 (ia: uint256) (name: string) (dec: uint8) (sym: string) : mcall
| mc_fallback: mcall
| mc_balanceOf (owner: address): mcall
| mc_transfer (to: address) (v: value): mcall
| mc_transferFrom (from: address) (to: address) (v: value): mcall
| mc_approve (spender: address) (v: value): mcall
| mc_allowance (owner: address) (spender: value): mcall
| mc_EIP20 (ia: uint256) (name: string) (dec: uint8) (sym: string) : mcall
| mc_fallback: mcall
| mc_balanceOf (owner: address): mcall
| mc_transfer (to: address) (v: value): mcall
| mc_transferFrom (from: address) (to: address) (v: value): mcall
| mc_approve (spender: address) (v: value): mcall
| mc_allowance (owner: address) (spender: value): mcall
Definition message
:= TMessage mcall.
DSL.v
Require Import Arith.
Require Import Nat.
Require Import String.
Open Scope string_scope.
Require Import Nat.
Require Import String.
Open Scope string_scope.
Require Import Model.
Delimit Scope dsl_scope with dsl.
Inductive PrimitiveStmt
:=
| DSL_require (cond: state -> env -> message -> bool)
| DSL_emit (evt: state -> env -> message -> event)
| DSL_balances_upd_inc (addr: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_balances_upd_dec (addr: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_balances_upd (addr: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_allowed_upd_inc (from: state -> env -> message -> address)(to: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_allowed_upd_dec (from: state -> env -> message -> address)(to: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_allowed_upd (from: state -> env -> message -> address)(to: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_totalSupply_upd (expr: state -> env -> message -> uint256)
| DSL_name_upd (expr: state -> env -> message -> string)
| DSL_decimals_upd (expr: state -> env -> message -> uint8)
| DSL_symbol_upd (expr: state -> env -> message -> string)
| DSL_return (T: Type) (expr: state -> env -> message -> T)
| DSL_ctor
| DSL_nop.
| DSL_require (cond: state -> env -> message -> bool)
| DSL_emit (evt: state -> env -> message -> event)
| DSL_balances_upd_inc (addr: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_balances_upd_dec (addr: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_balances_upd (addr: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_allowed_upd_inc (from: state -> env -> message -> address)(to: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_allowed_upd_dec (from: state -> env -> message -> address)(to: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_allowed_upd (from: state -> env -> message -> address)(to: state -> env -> message -> address)(expr: state -> env -> message -> uint256)
| DSL_totalSupply_upd (expr: state -> env -> message -> uint256)
| DSL_name_upd (expr: state -> env -> message -> string)
| DSL_decimals_upd (expr: state -> env -> message -> uint8)
| DSL_symbol_upd (expr: state -> env -> message -> string)
| DSL_return (T: Type) (expr: state -> env -> message -> T)
| DSL_ctor
| DSL_nop.
Arguments DSL_return [T].
Inductive Stmt
:=
| DSL_prim (stmt: PrimitiveStmt)
| DSL_if (cond: state -> env -> message -> bool) (then_stmt: Stmt) (else_stmt: Stmt)
| DSL_seq (stmt: Stmt) (stmt': Stmt).
| DSL_prim (stmt: PrimitiveStmt)
| DSL_if (cond: state -> env -> message -> bool) (then_stmt: Stmt) (else_stmt: Stmt)
| DSL_seq (stmt: Stmt) (stmt': Stmt).
Record Result: Type
:=
mk_result {
ret_st: state; (* ending state *)
ret_evts: eventlist; (* generated events *)
ret_stopped: bool; (* does the execution have to stop? *)
}.
mk_result {
ret_st: state; (* ending state *)
ret_evts: eventlist; (* generated events *)
ret_stopped: bool; (* does the execution have to stop? *)
}.
Definition Next (st: state) (evts: eventlist) : Result
:= mk_result st evts false.
Definition Stop (st: state) (evts: eventlist) : Result
:= mk_result st evts true.
Fixpoint dsl_exec_prim
(stmt: PrimitiveStmt)
(st0: state)
(st: state)
(env: env) (msg: message) (this: address)
(evts: eventlist): Result
(stmt: PrimitiveStmt)
(st0: state)
(st: state)
(env: env) (msg: message) (this: address)
(evts: eventlist): Result
:=
match stmt with
| DSL_require cond =>
if cond st env msg then
Next st evts
else
Stop st0 (ev_revert this :: nil)
| DSL_emit evt =>
Next st (evts ++ (evt st env msg :: nil))
| DSL_return expr =>
Stop st (evts ++ (ev_return _ (expr st env msg) :: nil))
| DSL_balances_upd_inc addr expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(a2v_upd_inc (st_balances st) (addr st env msg) (expr st env msg))
(st_allowed st))
evts
| DSL_balances_upd_dec addr expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(a2v_upd_dec (st_balances st) (addr st env msg) (expr st env msg))
(st_allowed st))
evts
| DSL_balances_upd addr expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st $+ { (addr st env msg) <- (expr st env msg) })
(st_allowed st))
evts
| DSL_allowed_upd_inc from to expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(aa2v_upd_inc (st_allowed st) (from st env msg) (to st env msg) (expr st env msg)))
evts
| DSL_allowed_upd_dec from to expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(aa2v_upd_dec (st_allowed st) (from st env msg) (to st env msg) (expr st env msg)))
evts
| DSL_allowed_upd from to expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(aa2v_upd_2 (st_allowed st) (from st env msg) (to st env msg) (expr st env msg)))
evts
| DSL_totalSupply_upd expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(expr st env msg)
(st_balances st)
(st_allowed st))
evts
| DSL_name_upd expr =>
Next (mk_st (st_symbol st)
(expr st env msg)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(st_allowed st))
evts
| DSL_decimals_upd expr =>
Next (mk_st (st_symbol st)
(st_name st)
(expr st env msg)
(st_totalSupply st)
(st_balances st)
(st_allowed st))
evts
| DSL_symbol_upd expr =>
Next (mk_st (expr st env msg)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(st_allowed st))
evts
| DSL_ctor =>
Next st
(evts ++ (ev_EIP20 (m_sender msg)
(st_totalSupply st)
(st_name st)
(st_decimals st)
(st_symbol st) :: nil))
| DSL_nop =>
Next st evts
end.
match stmt with
| DSL_require cond =>
if cond st env msg then
Next st evts
else
Stop st0 (ev_revert this :: nil)
| DSL_emit evt =>
Next st (evts ++ (evt st env msg :: nil))
| DSL_return expr =>
Stop st (evts ++ (ev_return _ (expr st env msg) :: nil))
| DSL_balances_upd_inc addr expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(a2v_upd_inc (st_balances st) (addr st env msg) (expr st env msg))
(st_allowed st))
evts
| DSL_balances_upd_dec addr expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(a2v_upd_dec (st_balances st) (addr st env msg) (expr st env msg))
(st_allowed st))
evts
| DSL_balances_upd addr expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st $+ { (addr st env msg) <- (expr st env msg) })
(st_allowed st))
evts
| DSL_allowed_upd_inc from to expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(aa2v_upd_inc (st_allowed st) (from st env msg) (to st env msg) (expr st env msg)))
evts
| DSL_allowed_upd_dec from to expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(aa2v_upd_dec (st_allowed st) (from st env msg) (to st env msg) (expr st env msg)))
evts
| DSL_allowed_upd from to expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(aa2v_upd_2 (st_allowed st) (from st env msg) (to st env msg) (expr st env msg)))
evts
| DSL_totalSupply_upd expr =>
Next (mk_st (st_symbol st)
(st_name st)
(st_decimals st)
(expr st env msg)
(st_balances st)
(st_allowed st))
evts
| DSL_name_upd expr =>
Next (mk_st (st_symbol st)
(expr st env msg)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(st_allowed st))
evts
| DSL_decimals_upd expr =>
Next (mk_st (st_symbol st)
(st_name st)
(expr st env msg)
(st_totalSupply st)
(st_balances st)
(st_allowed st))
evts
| DSL_symbol_upd expr =>
Next (mk_st (expr st env msg)
(st_name st)
(st_decimals st)
(st_totalSupply st)
(st_balances st)
(st_allowed st))
evts
| DSL_ctor =>
Next st
(evts ++ (ev_EIP20 (m_sender msg)
(st_totalSupply st)
(st_name st)
(st_decimals st)
(st_symbol st) :: nil))
| DSL_nop =>
Next st evts
end.
Fixpoint dsl_exec
(stmt: Stmt)
(st0: state)
(st: state)
(env: env) (msg: message) (this: address)
(evts: eventlist) {struct stmt}: Result
(stmt: Stmt)
(st0: state)
(st: state)
(env: env) (msg: message) (this: address)
(evts: eventlist) {struct stmt}: Result
:=
match stmt with
| DSL_prim stmt' =>
dsl_exec_prim stmt' st0 st env msg this evts
| DSL_if cond then_stmt else_stmt =>
if cond st env msg then
dsl_exec then_stmt st0 st env msg this evts
else
dsl_exec else_stmt st0 st env msg this evts
| DSL_seq stmt stmt' =>
match dsl_exec stmt st0 st env msg this evts with
| mk_result st'' evts'' stopped =>
if stopped then
mk_result st'' evts'' stopped
else
dsl_exec stmt' st0 st'' env msg this evts''
end
end.
match stmt with
| DSL_prim stmt' =>
dsl_exec_prim stmt' st0 st env msg this evts
| DSL_if cond then_stmt else_stmt =>
if cond st env msg then
dsl_exec then_stmt st0 st env msg this evts
else
dsl_exec else_stmt st0 st env msg this evts
| DSL_seq stmt stmt' =>
match dsl_exec stmt st0 st env msg this evts with
| mk_result st'' evts'' stopped =>
if stopped then
mk_result st'' evts'' stopped
else
dsl_exec stmt' st0 st'' env msg this evts''
end
end.
Notation "'symbol'"
:= (fun (st: state) (env: env) (msg: message) => st_symbol st) : dsl_scope.
Notation "'name'"
:= (fun (st: state) (env: env) (msg: message) => st_name st) : dsl_scope.
Notation "'decimals'"
:= (fun (st: state) (env: env) (msg: message) => st_decimals st) : dsl_scope.
Notation "'totalSupply'"
:= (fun (st: state) (env: env) (msg: message) => st_totalSupply st) : dsl_scope.
Notation "'balances'"
:= (fun (st: state) (env: env) (msg: message) => st_balances st) : dsl_scope.
Notation "'balances' '[' addr ']'"
:= (fun (st: state) (env: env) (msg: message) =>
((balances%dsl st env msg) (addr st env msg))) : dsl_scope.
((balances%dsl st env msg) (addr st env msg))) : dsl_scope.
Notation "'allowed'"
:= (fun (st: state) (env: env) (msg: message) => st_allowed st) : dsl_scope.
Notation "'allowed' '[' from ']' '[' to ']'"
Notation "'Transfer' '(' from ',' to ',' value ')'"
Notation "'Approval' '(' owner ',' spender ',' value ')'"
dsl
Definition dsl_ge
:= fun x y (st: state) (env: env) (msg: message) =>
(negb (ltb (x st env msg) (y st env msg))).
(negb (ltb (x st env msg) (y st env msg))).
Infix ">=" := dsl_ge : dsl_scope.
Definition dsl_lt
:= fun x y (st: state) (env: env) (msg: message) =>
ltb (x st env msg) (y st env msg).
ltb (x st env msg) (y st env msg).
Infix "<" := dsl_lt : dsl_scope.
Definition dsl_le
:= fun x y (st: state) (env: env) (msg: message) =>
Nat.leb (x st env msg) (y st env msg).
Nat.leb (x st env msg) (y st env msg).
Infix "<=" := dsl_le : dsl_scope.
Definition dsl_eq
fun x y (st: state) (env: env) (msg: message) =>
(Nat.eqb (x st env msg) (y st env msg)).
(Nat.eqb (x st env msg) (y st env msg)).
Infix "==" := dsl_eq (at level 70): dsl_scope.
Definition dsl_add
fun x y (st: state) (env: env) (msg: message) =>
(x st env msg) + (y st env msg).
(x st env msg) + (y st env msg).
Infix "+" := dsl_add : dsl_scope.
Definition dsl_sub
fun x y (st: state) (env: env) (msg: message) =>
(x st env msg) - (y st env msg).
(x st env msg) - (y st env msg).
Infix "-" := dsl_sub : dsl_scope.
Definition dsl_or
fun x y (st: state) (env: env) (msg: message) =>
(orb (x st env msg) (y st env msg)).
(orb (x st env msg) (y st env msg)).
Infix "||" := dsl_or : dsl_scope.
Notation "'msg.sender'"
(fun (st: state) (env: env) (msg: message) =>
m_sender msg) : dsl_scope.
m_sender msg) : dsl_scope.
Definition otrue
:= true.
Definition ofalse
:= false.
Notation "'true'"
:= (fun (st: state) (env: env) (msg: message) => True) : dsl_scope.
Notation "'false'"
:= (fun (st: state) (env: env) (msg: message) => False) : dsl_scope.
DSL语句封装
Notation "'require' '(' cond ')'"
(DSL_require cond) (at level 200) : dsl_scope.
...
Require Import Spec.
Section dsl_transfer_from.
Open Scope dsl_scope.
Open Scope dsl_scope.
Context `{from: state -> env -> message -> address}.
Context `{_from: address}.
Context `{to: state -> env -> message -> address}.
Context `{_to: address}.
Context `{value: state -> env -> message -> uint256}.
Context `{_value: uint256}.
Context `{max_uint256: state -> env -> message -> uint256}.
Context `{from_immutable: forall st env msg, from st env msg = _from}.
Context `{to_immutable: forall st env msg, to st env msg = _to}.
Context `{value_immutable: forall st env msg, value st env msg = _value}.
Context `{max_uint256_immutable: forall st env msg, max_uint256 st env msg = MAX_UINT256}.
Definition transferFrom_dsl : Stmt
:=
(@uint256 allowance = allowed[from][msg.sender] ;
@require(balances[from] >= value) ;
@require((from == to) || (balances[to] <= max_uint256 - value)) ;
@require(allowance >= value) ;
@balances[from] -= value ;
@balances[to] += value ;
@if (allowance < max_uint256) {
(@allowed[from][msg.sender] -= value)
} else {
(@nop)
} ;
(@emit Transfer(from, to, value)) ;
(@return true)).
(@uint256 allowance = allowed[from][msg.sender] ;
@require(balances[from] >= value) ;
@require((from == to) || (balances[to] <= max_uint256 - value)) ;
@require(allowance >= value) ;
@balances[from] -= value ;
@balances[to] += value ;
@if (allowance < max_uint256) {
(@allowed[from][msg.sender] -= value)
} else {
(@nop)
} ;
(@emit Transfer(from, to, value)) ;
(@return true)).
Lemma nat_nooverflow_dsl_nooverflow
:
forall (m: state -> a2v) st env msg,
(_from = _to \/ (_from <> _to /\ (m st _to <= MAX_UINT256 - _value)))%nat ->
((from == to) ||
((fun st env msg => m st (to st env msg)) <= max_uint256 - value))%dsl st env msg = otrue.
forall (m: state -> a2v) st env msg,
(_from = _to \/ (_from <> _to /\ (m st _to <= MAX_UINT256 - _value)))%nat ->
((from == to) ||
((fun st env msg => m st (to st env msg)) <= max_uint256 - value))%dsl st env msg = otrue.
Proof.
intros m st env msg Hnat.
unfold "=="%dsl, "<="%dsl, "||"%dsl, "||"%bool, "-"%dsl.
rewrite (from_immutable st env msg),
(to_immutable st env msg),
(value_immutable st env msg),
(max_uint256_immutable st env msg).
destruct Hnat.
- rewrite H. rewrite (Nat.eqb_refl _). reflexivity.
- destruct H as [Hneq Hle].
apply Nat.eqb_neq in Hneq. rewrite Hneq.
apply Nat.leb_le in Hle. exact Hle.
Qed.
intros m st env msg Hnat.
unfold "=="%dsl, "<="%dsl, "||"%dsl, "||"%bool, "-"%dsl.
rewrite (from_immutable st env msg),
(to_immutable st env msg),
(value_immutable st env msg),
(max_uint256_immutable st env msg).
destruct Hnat.
- rewrite H. rewrite (Nat.eqb_refl _). reflexivity.
- destruct H as [Hneq Hle].
apply Nat.eqb_neq in Hneq. rewrite Hneq.
apply Nat.leb_le in Hle. exact Hle.
Qed.
Lemma transferFrom_dsl_sat_spec_1
:
forall st env msg this,
spec_require (funcspec_transferFrom_1 _from _to _value this env msg) st ->
forall st0 result,
dsl_exec transferFrom_dsl st0 st env msg this nil = result ->
spec_trans (funcspec_transferFrom_1 _from _to _value this env msg) st (ret_st result) /\
spec_events (funcspec_transferFrom_1 _from _to _value this env msg) (ret_st result) (ret_evts result).
forall st env msg this,
spec_require (funcspec_transferFrom_1 _from _to _value this env msg) st ->
forall st0 result,
dsl_exec transferFrom_dsl st0 st env msg this nil = result ->
spec_trans (funcspec_transferFrom_1 _from _to _value this env msg) st (ret_st result) /\
spec_events (funcspec_transferFrom_1 _from _to _value this env msg) (ret_st result) (ret_evts result).
Proof.
intros st env msg this Hreq st0 result Hexec.
simpl in Hreq.
destruct Hreq as [Hreq_blncs_lo [Hreq_blncs_hi [Hreq_allwd_lo Hreq_allwd_hi]]].
apply Nat.leb_le in Hreq_blncs_lo.
generalize (nat_nooverflow_dsl_nooverflow _ st env msg Hreq_blncs_hi).
clear Hreq_blncs_hi. intros Hreq_blncs_hi.
apply Nat.leb_le in Hreq_allwd_lo.
apply Nat.ltb_lt in Hreq_allwd_hi.
simpl in Hexec.
unfold ">="%dsl in Hexec.
rewrite (Nat.ltb_antisym _ _) in Hexec.
rewrite (value_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_blncs_lo in Hexec.
simpl in Hexec.
rewrite Hreq_blncs_hi in Hexec.
simpl in Hexec.
rewrite (Nat.ltb_antisym _ _) in Hexec.
rewrite (value_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_allwd_lo in Hexec.
simpl in Hexec.
unfold "<"%dsl in Hexec; simpl in Hexec.
rewrite (max_uint256_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_allwd_hi in Hexec.
simpl in Hexec.
unfold funcspec_transferFrom_1.
rewrite <- Hexec.
repeat rewrite (value_immutable _ _ _).
repeat rewrite (from_immutable _ _ _).
repeat rewrite (to_immutable _ _ _).
repeat (split; auto).
Qed.
intros st env msg this Hreq st0 result Hexec.
simpl in Hreq.
destruct Hreq as [Hreq_blncs_lo [Hreq_blncs_hi [Hreq_allwd_lo Hreq_allwd_hi]]].
apply Nat.leb_le in Hreq_blncs_lo.
generalize (nat_nooverflow_dsl_nooverflow _ st env msg Hreq_blncs_hi).
clear Hreq_blncs_hi. intros Hreq_blncs_hi.
apply Nat.leb_le in Hreq_allwd_lo.
apply Nat.ltb_lt in Hreq_allwd_hi.
simpl in Hexec.
unfold ">="%dsl in Hexec.
rewrite (Nat.ltb_antisym _ _) in Hexec.
rewrite (value_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_blncs_lo in Hexec.
simpl in Hexec.
rewrite Hreq_blncs_hi in Hexec.
simpl in Hexec.
rewrite (Nat.ltb_antisym _ _) in Hexec.
rewrite (value_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_allwd_lo in Hexec.
simpl in Hexec.
unfold "<"%dsl in Hexec; simpl in Hexec.
rewrite (max_uint256_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_allwd_hi in Hexec.
simpl in Hexec.
unfold funcspec_transferFrom_1.
rewrite <- Hexec.
repeat rewrite (value_immutable _ _ _).
repeat rewrite (from_immutable _ _ _).
repeat rewrite (to_immutable _ _ _).
repeat (split; auto).
Qed.
Lemma transferFrom_dsl_sat_spec_2
forall st env msg this,
spec_require (funcspec_transferFrom_2 _from _to _value this env msg) st ->
forall st0 result,
dsl_exec transferFrom_dsl st0 st env msg this nil = result ->
spec_trans (funcspec_transferFrom_2 _from _to _value this env msg) st (ret_st result) /\
spec_events (funcspec_transferFrom_2 _from _to _value this env msg) (ret_st result) (ret_evts result).
spec_require (funcspec_transferFrom_2 _from _to _value this env msg) st ->
forall st0 result,
dsl_exec transferFrom_dsl st0 st env msg this nil = result ->
spec_trans (funcspec_transferFrom_2 _from _to _value this env msg) st (ret_st result) /\
spec_events (funcspec_transferFrom_2 _from _to _value this env msg) (ret_st result) (ret_evts result).
Proof.
intros st env msg this Hreq st0 result Hexec.
simpl in Hreq. destruct Hreq as [Hreq_blncs_lo [Hreq_blncs_hi [Hreq_allwd_lo Hreq_allwd_hi]]].
generalize (nat_nooverflow_dsl_nooverflow _ st env msg Hreq_blncs_hi).
clear Hreq_blncs_hi. intros Hreq_blncs_hi.
apply Nat.leb_le in Hreq_blncs_lo.
apply Nat.leb_le in Hreq_allwd_lo.
simpl in Hexec.
unfold ">="%dsl in Hexec.
rewrite (Nat.ltb_antisym _ _) in Hexec.
rewrite (value_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_blncs_lo in Hexec.
simpl in Hexec.
rewrite Hreq_blncs_hi in Hexec.
simpl in Hexec.
rewrite (Nat.ltb_antisym _ _) in Hexec.
rewrite (value_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_allwd_lo in Hexec.
simpl in Hexec.
unfold "<"%dsl in Hexec; simpl in Hexec.
rewrite (max_uint256_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_allwd_hi in Hexec.
rewrite (Nat.ltb_irrefl _) in Hexec.
simpl in Hexec.
unfold funcspec_transferFrom_2.
rewrite <- Hexec.
repeat rewrite (value_immutable _ _ _).
repeat rewrite (from_immutable _ _ _).
repeat rewrite (to_immutable _ _ _).
repeat (split; auto).
Qed.
intros st env msg this Hreq st0 result Hexec.
simpl in Hreq. destruct Hreq as [Hreq_blncs_lo [Hreq_blncs_hi [Hreq_allwd_lo Hreq_allwd_hi]]].
generalize (nat_nooverflow_dsl_nooverflow _ st env msg Hreq_blncs_hi).
clear Hreq_blncs_hi. intros Hreq_blncs_hi.
apply Nat.leb_le in Hreq_blncs_lo.
apply Nat.leb_le in Hreq_allwd_lo.
simpl in Hexec.
unfold ">="%dsl in Hexec.
rewrite (Nat.ltb_antisym _ _) in Hexec.
rewrite (value_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_blncs_lo in Hexec.
simpl in Hexec.
rewrite Hreq_blncs_hi in Hexec.
simpl in Hexec.
rewrite (Nat.ltb_antisym _ _) in Hexec.
rewrite (value_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_allwd_lo in Hexec.
simpl in Hexec.
unfold "<"%dsl in Hexec; simpl in Hexec.
rewrite (max_uint256_immutable _ _ _) in Hexec.
rewrite (from_immutable _ _ _) in Hexec.
rewrite Hreq_allwd_hi in Hexec.
rewrite (Nat.ltb_irrefl _) in Hexec.
simpl in Hexec.
unfold funcspec_transferFrom_2.
rewrite <- Hexec.
repeat rewrite (value_immutable _ _ _).
repeat rewrite (from_immutable _ _ _).
repeat rewrite (to_immutable _ _ _).
repeat (split; auto).
Qed.
Close Scope dsl_scope.
End dsl_transfer_from.
End dsl_transfer_from.
Section dsl_transfer.
Open Scope dsl_scope.
Open Scope dsl_scope.
Context `{to: state -> env -> message -> address}.
Context `{_to: address}.
Context `{value: state -> env -> message -> uint256}.
Context `{_value: uint256}.
Context `{max_uint256: state -> env -> message -> uint256}.
Context `{to_immutable: forall st env msg, to st env msg = _to}.
Context `{value_immutable: forall st env msg, value st env msg = _value}.
Context `{max_uint256_immutable: forall st env msg, max_uint256 st env msg = MAX_UINT256}.
Definition transfer_dsl : Stmt
:=
(@require(balances[msg.sender] >= value) ;
@require((msg.sender == to) || (balances[to] <= max_uint256 - value)) ;
@balances[msg.sender] -= value ;
@balances[to] += value ;
(@emit Transfer(msg.sender, to, value)) ;
(@return true)
).
(@require(balances[msg.sender] >= value) ;
@require((msg.sender == to) || (balances[to] <= max_uint256 - value)) ;
@balances[msg.sender] -= value ;
@balances[to] += value ;
(@emit Transfer(msg.sender, to, value)) ;
(@return true)
).
Lemma nat_nooverflow_dsl_nooverflow'
Lemma transfer_dsl_sat_spec
Close Scope dsl_scope.
End dsl_transfer.
End dsl_transfer.
... ...
Prop.v
Require Export Lists.List.
Require Import Model.
Require Import Spec.
Require Export Arith.
Require Import Model.
Require Import Spec.
Require Export Arith.
Inductive Sum : (@tmap address value) -> value -> Prop
:=
| Sum_emp : Sum tmap_emp 0
| Sum_add : forall m v a' v',
Sum m v
-> m a' = 0
-> Sum (m $+ {a' <- v'}) (v + v')
| Sum_del : forall m v a',
Sum m v
-> Sum (m $+ {a' <- 0}) (v - (m a')).
| Sum_emp : Sum tmap_emp 0
| Sum_add : forall m v a' v',
Sum m v
-> m a' = 0
-> Sum (m $+ {a' <- v'}) (v + v')
| Sum_del : forall m v a',
Sum m v
-> Sum (m $+ {a' <- 0}) (v - (m a')).
Lemma address_dec
: forall (a1 a2: address), {a1 = a2} + {a1 <> a2}.
Proof.
intros.
remember (beq a1 a2) as Ha.
assert (beq a1 a2 = Ha). auto.
destruct Ha.
beq_elimH H. left. apply H.
right.
simplbeq.
trivial.
Qed.
intros.
remember (beq a1 a2) as Ha.
assert (beq a1 a2 = Ha). auto.
destruct Ha.
beq_elimH H. left. apply H.
right.
simplbeq.
trivial.
Qed.
Lemma Sum_dec2
: forall m t a,
Sum m t
-> Sum (m $+ {a <- -= m a}) (t - m a).
Sum m t
-> Sum (m $+ {a <- -= m a}) (t - m a).
Proof.
unfold a2v_upd_dec.
intros.
assert (Ht : minus_with_underflow (m a) (m a) = 0).
assert (Ht1 : 0 = (m a) - (m a)).
auto with arith.
rewrite Ht1.
apply minus_safe; auto.
rewrite Ht.
apply Sum_del; trivial.
Qed.
unfold a2v_upd_dec.
intros.
assert (Ht : minus_with_underflow (m a) (m a) = 0).
assert (Ht1 : 0 = (m a) - (m a)).
auto with arith.
rewrite Ht1.
apply minus_safe; auto.
rewrite Ht.
apply Sum_del; trivial.
Qed.
Fixpoint sum (m: @tmap address value) (al: list address) : value
:=
match al with
| nil => 0
| cons a al' => (m a) + sum m al'
end.
match al with
| nil => 0
| cons a al' => (m a) + sum m al'
end.
Open Scope list_scope.
Section List.
Context `{A: Type}.
Context `{BEq A}.
Fixpoint list_in (a: A) (al: list A) : bool
:=
match al with
| nil => false
| cons a' al' => if beq a a' then true
else list_in a al'
end.
match al with
| nil => false
| cons a' al' => if beq a a' then true
else list_in a al'
end.
Fixpoint no_repeat (al: list A) : bool
:=
match al with
| nil => true
| cons a' al' => andb (negb (list_in a' al')) (no_repeat al')
end.
match al with
| nil => true
| cons a' al' => andb (negb (list_in a' al')) (no_repeat al')
end.
End List.
Opaque beq.
Opaque beq.
Opaque beq.
Lemma sum_emp
: forall al, sum $0 al = 0.
Proof.
intros.
induction al.
simpl. trivial.
simpl. apply IHal.
Qed.
intros.
induction al.
simpl. trivial.
simpl. apply IHal.
Qed.
Lemma sum_add_cons
: forall (al : list address) m (a: address),
list_in a al = false
-> no_repeat al = true
-> m a + sum m al = sum m (a :: al).
list_in a al = false
-> no_repeat al = true
-> m a + sum m al = sum m (a :: al).
Proof.
induction al.
intros m a Hin Hnr.
simpl.
trivial.
intros m a' Hin' Hnr'.
assert (Hnin : list_in a' al = false).
simpl in Hin'.
decbeq a' a.
trivial.
substH IHal with (IHal m a' Hnin).
simpl.
simpl in IHal.
omega.
Qed.
induction al.
intros m a Hin Hnr.
simpl.
trivial.
intros m a' Hin' Hnr'.
assert (Hnin : list_in a' al = false).
simpl in Hin'.
decbeq a' a.
trivial.
substH IHal with (IHal m a' Hnin).
simpl.
simpl in IHal.
omega.
Qed.
Lemma sum_del_none
: forall al m a,
list_in a al = false
-> no_repeat al = true
-> sum (m $+ {a <- 0}) al = sum m al.
list_in a al = false
-> no_repeat al = true
-> sum (m $+ {a <- 0}) al = sum m al.
Proof.
induction al.
intros m a Hin Hnr.
simpl.
trivial.
intros m a' Hin' Hnr.
simpl in Hin'.
simpl.
decbeq a a'; tmap_simpl.
simpl in Hnr.
desb Hnr as [Hnr1 Hnr2].
rewrite (IHal m a' Hin' Hnr2).
trivial.
Qed.
induction al.
intros m a Hin Hnr.
simpl.
trivial.
intros m a' Hin' Hnr.
simpl in Hin'.
simpl.
decbeq a a'; tmap_simpl.
simpl in Hnr.
desb Hnr as [Hnr1 Hnr2].
rewrite (IHal m a' Hin' Hnr2).
trivial.
Qed.
Lemma sum_del_any
: forall al m a,
list_in a al = true
-> no_repeat al = true
-> m a + sum (m $+ {a <- 0}) al = sum m al.
list_in a al = true
-> no_repeat al = true
-> m a + sum (m $+ {a <- 0}) al = sum m al.
Proof.
induction al.
intros m a Hin Hnr.
simpl in Hin.
discriminate.
intros m a' Hin' Hnr.
simpl in Hin'.
destruct (beq_dec a a').
simplbeq.
simpl.
simpl in Hnr.
desb Hnr as [Hnr1 Hnr2].
simpltm.
assert (a = a').
beq_elimH H.
trivial.
subst a'.
simplb.
rewrite sum_del_none; trivial.
simpl.
simplbeq.
tmap_simpl.
simpl in Hnr.
desb Hnr as [Hnr1 Hnr2].
rewrite <- (IHal m a' Hin' Hnr2).
omega.
Qed.
induction al.
intros m a Hin Hnr.
simpl in Hin.
discriminate.
intros m a' Hin' Hnr.
simpl in Hin'.
destruct (beq_dec a a').
simplbeq.
simpl.
simpl in Hnr.
desb Hnr as [Hnr1 Hnr2].
simpltm.
assert (a = a').
beq_elimH H.
trivial.
subst a'.
simplb.
rewrite sum_del_none; trivial.
simpl.
simplbeq.
tmap_simpl.
simpl in Hnr.
desb Hnr as [Hnr1 Hnr2].
rewrite <- (IHal m a' Hin' Hnr2).
omega.
Qed.
Lemma minus_minus
forall t a b,
t - a - b = t - (a + b).
t - a - b = t - (a + b).
Lemma sum_add_not_in
forall al m a v,
list_in a al = false
-> no_repeat al = true
-> sum (m $+ {a <- v}) al = sum m al.
list_in a al = false
-> no_repeat al = true
-> sum (m $+ {a <- v}) al = sum m al.
Proof.
induction al.
intros m a v Hin Hnr.
simpl.
trivial.
intros m a' v' Hin' Hnr.
simpl in Hin'.
simpl in Hnr.
desb Hnr as [Hnr1 Hnr2].
simplb.
decbeq a a'; tmap_simpl.
simpl.
simpltm.
Qed.
induction al.
intros m a v Hin Hnr.
simpl.
trivial.
intros m a' v' Hin' Hnr.
simpl in Hin'.
simpl in Hnr.
desb Hnr as [Hnr1 Hnr2].
simplb.
decbeq a a'; tmap_simpl.
simpl.
simpltm.
Qed.
Lemma sum_add_in
: forall al m a v,
list_in a al = true
-> no_repeat al = true
-> m a = 0
-> sum (m $+ {a <- v}) al = sum m al + v.
list_in a al = true
-> no_repeat al = true
-> m a = 0
-> sum (m $+ {a <- v}) al = sum m al + v.
Lemma Sum_ge_strong
: forall m t,
Sum m t
-> forall a al,
list_in a al = false
-> no_repeat al = true
-> t >= m a + sum m al.
Sum m t
-> forall a al,
list_in a al = false
-> no_repeat al = true
-> t >= m a + sum m al.
Lemma Sum_ge
: forall m a t,
Sum m t
-> t >= m a.
Sum m t
-> t >= m a.
Lemma Sum_ge_2
: forall m a a' t,
Sum m t
-> beq a a' = false
-> t >= m a + m a'.
Sum m t
-> beq a a' = false
-> t >= m a + m a'.
Lemma Sum_sig
:
forall m a t,
m = $0 $+ { a <- t }
-> Sum m t.
forall m a t,
m = $0 $+ { a <- t }
-> Sum m t.
Ltac arith_rewrite t
:=
let H := fresh "Harith" in
match t with
| ?x = ?y => assert (H: t); [auto with arith; try omega | rewrite H; clear H]
end.
let H := fresh "Harith" in
match t with
| ?x = ?y => assert (H: t); [auto with arith; try omega | rewrite H; clear H]
end.
Lemma Sum_dec
: forall m t a (v: value),
Sum m t
-> m a >= v
-> Sum (m $+ {a <- -= v}) (t - v).
Sum m t
-> m a >= v
-> Sum (m $+ {a <- -= v}) (t - v).
Lemma Sum_inc
: forall m t a (v: value),
Sum m t
-> m a <= MAX_UINT256 - v
-> Sum (m $+ {a <- += v}) (t + v).
Sum m t
-> m a <= MAX_UINT256 - v
-> Sum (m $+ {a <- += v}) (t + v).
Lemma a2v_upd_inc_zero
forall m a,
m $+ {a <- += 0} = m.
m $+ {a <- += 0} = m.
Lemma a2v_upd_dec_zero
: forall m a,
m $+ {a <- -= 0} = m.
m $+ {a <- -= 0} = m.
Lemma Sum_transfer
: forall m t a1 a2 v m',
Sum m t
-> m a1 >= v
-> m a2 <= MAX_UINT256 - v
-> m' = m $+{a1 <- -= v} $+{a2 <- += v}
-> Sum m' t.
Sum m t
-> m a1 >= v
-> m a2 <= MAX_UINT256 - v
-> m' = m $+{a1 <- -= v} $+{a2 <- += v}
-> Sum m' t.
Definition assert_genesis_event (e: event) (E: eventlist) : Prop
:=
match E with
| nil => False
| cons e' E => e = e'
end.
match E with
| nil => False
| cons e' E => e = e'
end.
Lemma assert_genesis_event_app
: forall e E E',
assert_genesis_event e E
-> assert_genesis_event e (E ++ E').
assert_genesis_event e E
-> assert_genesis_event e (E ++ E').
Definition INV (env: env) (S: state) (E: eventlist) : Prop
:=
let blncs := st_balances S in
(* balances not overflow *)
(forall a, blncs a <= MAX_UINT256) /\
(* totalSupply preserves *)
exists total,
total = st_totalSupply S
/\ Sum blncs total
/\ exists creator, exists name, exists decimals, exists sym,
assert_genesis_event (ev_EIP20 creator total name decimals sym) E.
let blncs := st_balances S in
(* balances not overflow *)
(forall a, blncs a <= MAX_UINT256) /\
(* totalSupply preserves *)
exists total,
total = st_totalSupply S
/\ Sum blncs total
/\ exists creator, exists name, exists decimals, exists sym,
assert_genesis_event (ev_EIP20 creator total name decimals sym) E.
Theorem step_INV
: forall this env msg S E env' S' E',
step env (mk_contract this S) msg (mk_contract this S') E'
-> env_step env env'
-> INV env S E
-> INV env' S' (E ++ E').
step env (mk_contract this S) msg (mk_contract this S') E'
-> env_step env env'
-> INV env S E
-> INV env' S' (E ++ E').
Proof.
intros this env msg S E env' S' E'.
intros Hstep Henv' HI.
destruct HI as [Hblncs [total [Htotal [Htv [creator [name [decimals [sym Hassert]]]]]]]].
inversion_clear Hstep.
(* case: transfer *)
- unfold funcspec_transfer in H1.
subst spec preP evP postP.
simpl in *.
subst msg.
simpl in H5.
destruct H5 as [[Hx1a Hx1b] [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 [Hx7 Hx8]]]]]]].
destruct Hx1b.
+ (* msg.sender == to *)
subst sender.
rewrite <- (a2v_dec_inc_id _ _ _ (Hblncs to) Hx1a) in Hx7.
rewrite <- Hx7 in *.
split; auto.
exists total.
repeat split; subst; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
+ (* msg.sender != to *)
destruct H0 as [Hsender Hof].
split.
* (* no overflow *)
rewrite Hx7.
intros.
destruct (beq_dec a to).
{
(* a == to *)
rewrite Nat.eqb_eq in H0.
subst a.
apply neq_beq_false in Hsender.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_upd_upd_ne _ _ _ _ _ Hsender).
rewrite (tmap_get_upd_ne _ _ _ _ Hsender).
rewrite (tmap_get_upd_eq _ _ _).
rewrite (tmap_get_upd_ne _ _ _ _ Hsender).
rewrite (plus_safe_lt _ _ Hof).
generalize(Hblncs sender). intros. omega.
}
{
(* a <> to *)
apply beq_sym in H0.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_get_upd_ne _ _ _ _ H0).
destruct (beq_dec a sender).
- (* a == sender *)
rewrite Nat.eqb_eq in H1.
subst a.
rewrite (tmap_get_upd_eq _ _ _).
rewrite (minus_safe _ _ Hx1a).
generalize (Hblncs sender). intros. omega.
- (* a <> sender *)
apply beq_sym in H1.
rewrite (tmap_get_upd_ne _ _ _ _ H1).
generalize (Hblncs a). intros. omega.
}
* (* totalSupply preserves *)
exists total.
rewrite <- Htotal in *.
repeat split; auto.
{
apply (Sum_transfer (st_balances S) total
sender to v (st_balances S'));
auto with arith.
}
{
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
}
(* case: transferFrom-1 *)
- unfold funcspec_transferFrom_1 in H1.
subst spec.
simpl in *.
destruct H2 as [[Hx1a [Hx1b [Hx1c Hx1d]]] [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 [Hx7 Hx8]]]]]]].
destruct Hx1b.
+ (* from = to *)
subst from.
rewrite <- (a2v_dec_inc_id _ _ _ (Hblncs to) Hx1a) in Hx7.
rewrite <- Hx7 in *.
split; auto.
exists total.
repeat split; subst; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
+ (* from <> to *)
destruct H1 as [Hfrom Hof].
split.
* (* no overflow *)
rewrite Hx7.
intros.
destruct (beq_dec a to).
{
(* a == to *)
rewrite Nat.eqb_eq in H1.
subst a.
apply neq_beq_false in Hfrom.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_upd_upd_ne _ _ _ _ _ Hfrom).
rewrite (tmap_get_upd_ne _ _ _ _ Hfrom).
rewrite (tmap_get_upd_eq _ _ _).
rewrite (tmap_get_upd_ne _ _ _ _ Hfrom).
rewrite (plus_safe_lt _ _ Hof).
generalize(Hblncs from). intros. omega.
}
{
(* a <> to *)
apply beq_sym in H1.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_get_upd_ne _ _ _ _ H1).
destruct (beq_dec a from).
- (* a == from *)
rewrite Nat.eqb_eq in H2.
subst a.
rewrite (tmap_get_upd_eq _ _ _).
rewrite (minus_safe _ _ Hx1a).
generalize (Hblncs from). intros. omega.
- (* a <> sender *)
apply beq_sym in H2.
rewrite (tmap_get_upd_ne _ _ _ _ H2).
generalize (Hblncs a). intros. omega.
}
* (* totalSupply preserves *)
exists total.
rewrite <- Htotal in *.
repeat split; auto.
{
apply (Sum_transfer (st_balances S) total
from to v (st_balances S'));
auto with arith.
}
{
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
}
(* case: transferFrom-2 *)
- unfold funcspec_transferFrom_2 in H1.
subst spec.
simpl in *.
destruct H2 as [[Hx1a [Hx1b [Hx1c Hx1d]]] [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 [Hx7 Hx8]]]]]]].
destruct Hx1b.
+ (* from = to *)
subst from.
rewrite <- (a2v_dec_inc_id _ _ _ (Hblncs to) Hx1a) in Hx7.
rewrite <- Hx7 in *.
split; auto.
exists total.
repeat split; subst; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
+ (* from <> to *)
destruct H1 as [Hfrom Hof].
split.
* (* no overflow *)
rewrite Hx7.
intros.
destruct (beq_dec a to).
{
(* a == to *)
rewrite Nat.eqb_eq in H1.
subst a.
apply neq_beq_false in Hfrom.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_upd_upd_ne _ _ _ _ _ Hfrom).
rewrite (tmap_get_upd_ne _ _ _ _ Hfrom).
rewrite (tmap_get_upd_eq _ _ _).
rewrite (tmap_get_upd_ne _ _ _ _ Hfrom).
rewrite (plus_safe_lt _ _ Hof).
generalize(Hblncs from). intros. omega.
}
{
(* a <> to *)
apply beq_sym in H1.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_get_upd_ne _ _ _ _ H1).
destruct (beq_dec a from).
- (* a == from *)
rewrite Nat.eqb_eq in H2.
subst a.
rewrite (tmap_get_upd_eq _ _ _).
rewrite (minus_safe _ _ Hx1a).
generalize (Hblncs from). intros. omega.
- (* a <> sender *)
apply beq_sym in H2.
rewrite (tmap_get_upd_ne _ _ _ _ H2).
generalize (Hblncs a). intros. omega.
}
* (* totalSupply preserves *)
exists total.
rewrite <- Htotal in *.
repeat split; auto.
{
apply (Sum_transfer (st_balances S) total
from to v (st_balances S'));
auto with arith.
}
{
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
}
(* case: balanceOf *)
- unfold funcspec_balanceOf in H2.
subst spec.
simpl in *.
destruct H2 as [Hx1 [Hx2 Hx3]].
subst S.
split; auto.
exists total.
simpl.
repeat split; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
(* case: approve *)
- unfold funcspec_approve in H1.
subst spec.
simpl in *.
destruct H2 as [Hx1 [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 [Hx7 Hx8]]]]]]].
rewrite <- Hx7 in *.
split; auto.
exists total.
rewrite Hx3 in *.
rewrite Hx7 in *.
repeat split; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
(* case: allowance *)
- unfold funcspec_allowance in H1.
subst spec.
simpl in *.
destruct H2 as [Hx1 [Hx2 Hx3]].
subst S'.
split; auto.
exists total.
simpl.
repeat split; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
Qed.
intros this env msg S E env' S' E'.
intros Hstep Henv' HI.
destruct HI as [Hblncs [total [Htotal [Htv [creator [name [decimals [sym Hassert]]]]]]]].
inversion_clear Hstep.
(* case: transfer *)
- unfold funcspec_transfer in H1.
subst spec preP evP postP.
simpl in *.
subst msg.
simpl in H5.
destruct H5 as [[Hx1a Hx1b] [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 [Hx7 Hx8]]]]]]].
destruct Hx1b.
+ (* msg.sender == to *)
subst sender.
rewrite <- (a2v_dec_inc_id _ _ _ (Hblncs to) Hx1a) in Hx7.
rewrite <- Hx7 in *.
split; auto.
exists total.
repeat split; subst; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
+ (* msg.sender != to *)
destruct H0 as [Hsender Hof].
split.
* (* no overflow *)
rewrite Hx7.
intros.
destruct (beq_dec a to).
{
(* a == to *)
rewrite Nat.eqb_eq in H0.
subst a.
apply neq_beq_false in Hsender.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_upd_upd_ne _ _ _ _ _ Hsender).
rewrite (tmap_get_upd_ne _ _ _ _ Hsender).
rewrite (tmap_get_upd_eq _ _ _).
rewrite (tmap_get_upd_ne _ _ _ _ Hsender).
rewrite (plus_safe_lt _ _ Hof).
generalize(Hblncs sender). intros. omega.
}
{
(* a <> to *)
apply beq_sym in H0.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_get_upd_ne _ _ _ _ H0).
destruct (beq_dec a sender).
- (* a == sender *)
rewrite Nat.eqb_eq in H1.
subst a.
rewrite (tmap_get_upd_eq _ _ _).
rewrite (minus_safe _ _ Hx1a).
generalize (Hblncs sender). intros. omega.
- (* a <> sender *)
apply beq_sym in H1.
rewrite (tmap_get_upd_ne _ _ _ _ H1).
generalize (Hblncs a). intros. omega.
}
* (* totalSupply preserves *)
exists total.
rewrite <- Htotal in *.
repeat split; auto.
{
apply (Sum_transfer (st_balances S) total
sender to v (st_balances S'));
auto with arith.
}
{
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
}
(* case: transferFrom-1 *)
- unfold funcspec_transferFrom_1 in H1.
subst spec.
simpl in *.
destruct H2 as [[Hx1a [Hx1b [Hx1c Hx1d]]] [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 [Hx7 Hx8]]]]]]].
destruct Hx1b.
+ (* from = to *)
subst from.
rewrite <- (a2v_dec_inc_id _ _ _ (Hblncs to) Hx1a) in Hx7.
rewrite <- Hx7 in *.
split; auto.
exists total.
repeat split; subst; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
+ (* from <> to *)
destruct H1 as [Hfrom Hof].
split.
* (* no overflow *)
rewrite Hx7.
intros.
destruct (beq_dec a to).
{
(* a == to *)
rewrite Nat.eqb_eq in H1.
subst a.
apply neq_beq_false in Hfrom.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_upd_upd_ne _ _ _ _ _ Hfrom).
rewrite (tmap_get_upd_ne _ _ _ _ Hfrom).
rewrite (tmap_get_upd_eq _ _ _).
rewrite (tmap_get_upd_ne _ _ _ _ Hfrom).
rewrite (plus_safe_lt _ _ Hof).
generalize(Hblncs from). intros. omega.
}
{
(* a <> to *)
apply beq_sym in H1.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_get_upd_ne _ _ _ _ H1).
destruct (beq_dec a from).
- (* a == from *)
rewrite Nat.eqb_eq in H2.
subst a.
rewrite (tmap_get_upd_eq _ _ _).
rewrite (minus_safe _ _ Hx1a).
generalize (Hblncs from). intros. omega.
- (* a <> sender *)
apply beq_sym in H2.
rewrite (tmap_get_upd_ne _ _ _ _ H2).
generalize (Hblncs a). intros. omega.
}
* (* totalSupply preserves *)
exists total.
rewrite <- Htotal in *.
repeat split; auto.
{
apply (Sum_transfer (st_balances S) total
from to v (st_balances S'));
auto with arith.
}
{
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
}
(* case: transferFrom-2 *)
- unfold funcspec_transferFrom_2 in H1.
subst spec.
simpl in *.
destruct H2 as [[Hx1a [Hx1b [Hx1c Hx1d]]] [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 [Hx7 Hx8]]]]]]].
destruct Hx1b.
+ (* from = to *)
subst from.
rewrite <- (a2v_dec_inc_id _ _ _ (Hblncs to) Hx1a) in Hx7.
rewrite <- Hx7 in *.
split; auto.
exists total.
repeat split; subst; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
+ (* from <> to *)
destruct H1 as [Hfrom Hof].
split.
* (* no overflow *)
rewrite Hx7.
intros.
destruct (beq_dec a to).
{
(* a == to *)
rewrite Nat.eqb_eq in H1.
subst a.
apply neq_beq_false in Hfrom.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_upd_upd_ne _ _ _ _ _ Hfrom).
rewrite (tmap_get_upd_ne _ _ _ _ Hfrom).
rewrite (tmap_get_upd_eq _ _ _).
rewrite (tmap_get_upd_ne _ _ _ _ Hfrom).
rewrite (plus_safe_lt _ _ Hof).
generalize(Hblncs from). intros. omega.
}
{
(* a <> to *)
apply beq_sym in H1.
unfold a2v_upd_inc, a2v_upd_dec.
rewrite (tmap_get_upd_ne _ _ _ _ H1).
destruct (beq_dec a from).
- (* a == from *)
rewrite Nat.eqb_eq in H2.
subst a.
rewrite (tmap_get_upd_eq _ _ _).
rewrite (minus_safe _ _ Hx1a).
generalize (Hblncs from). intros. omega.
- (* a <> sender *)
apply beq_sym in H2.
rewrite (tmap_get_upd_ne _ _ _ _ H2).
generalize (Hblncs a). intros. omega.
}
* (* totalSupply preserves *)
exists total.
rewrite <- Htotal in *.
repeat split; auto.
{
apply (Sum_transfer (st_balances S) total
from to v (st_balances S'));
auto with arith.
}
{
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
}
(* case: balanceOf *)
- unfold funcspec_balanceOf in H2.
subst spec.
simpl in *.
destruct H2 as [Hx1 [Hx2 Hx3]].
subst S.
split; auto.
exists total.
simpl.
repeat split; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
(* case: approve *)
- unfold funcspec_approve in H1.
subst spec.
simpl in *.
destruct H2 as [Hx1 [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 [Hx7 Hx8]]]]]]].
rewrite <- Hx7 in *.
split; auto.
exists total.
rewrite Hx3 in *.
rewrite Hx7 in *.
repeat split; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
(* case: allowance *)
- unfold funcspec_allowance in H1.
subst spec.
simpl in *.
destruct H2 as [Hx1 [Hx2 Hx3]].
subst S'.
split; auto.
exists total.
simpl.
repeat split; auto.
exists creator. exists name. exists decimals. exists sym.
apply assert_genesis_event_app; auto.
Qed.
Theorem create_INV
: forall env0 env msg C E,
create env0 msg C E
-> env_step env0 env
-> INV env (w_st C) E.
create env0 msg C E
-> env_step env0 env
-> INV env (w_st C) E.
Proof.
intros.
inversion_clear H.
subst spec preP evP postP; simpl.
unfold funcspec_EIP20 in H7.
simpl in H7.
destruct H7 as [Hx1 [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 Hx7]]]]]].
unfold INV.
split.
- (* no overflow initially *)
subst.
rewrite Hx6. clear Hx6. simpl.
intros a.
destruct (beq_dec sender a).
+ (* a = sender *)
apply Nat.eqb_eq in H. subst a.
rewrite (tmap_get_upd_eq _ _ _).
auto.
+ (* a <> sender *)
rewrite (tmap_get_upd_ne _ _ _ _ H).
rewrite (tmap_emp_zero _).
unfold TMap.zero.
unfold value_Range.
omega.
- (* totalSupply preserves *)
exists ia.
repeat split; auto.
+ apply Sum_sig in Hx6.
trivial.
+ exists sender. exists name. exists dec. exists sym.
unfold assert_genesis_event.
rewrite Hx1.
rewrite H1.
simpl.
trivial.
Qed.
intros.
inversion_clear H.
subst spec preP evP postP; simpl.
unfold funcspec_EIP20 in H7.
simpl in H7.
destruct H7 as [Hx1 [Hx2 [Hx3 [Hx4 [Hx5 [Hx6 Hx7]]]]]].
unfold INV.
split.
- (* no overflow initially *)
subst.
rewrite Hx6. clear Hx6. simpl.
intros a.
destruct (beq_dec sender a).
+ (* a = sender *)
apply Nat.eqb_eq in H. subst a.
rewrite (tmap_get_upd_eq _ _ _).
auto.
+ (* a <> sender *)
rewrite (tmap_get_upd_ne _ _ _ _ H).
rewrite (tmap_emp_zero _).
unfold TMap.zero.
unfold value_Range.
omega.
- (* totalSupply preserves *)
exists ia.
repeat split; auto.
+ apply Sum_sig in Hx6.
trivial.
+ exists sender. exists name. exists dec. exists sym.
unfold assert_genesis_event.
rewrite Hx1.
rewrite H1.
simpl.
trivial.
Qed.
Lemma step_contract_address_constant
: forall env C msg C' E',
step env C msg C' E'
-> w_a C = w_a C'.
step env C msg C' E'
-> w_a C = w_a C'.
Lemma steps_INV
: forall ml env C E,
INV env (w_st C) E
-> forall env' C' E', steps env C ml env' C' E'
-> INV env' (w_st C') (E ++ E').
INV env (w_st C) E
-> forall env' C' E', steps env C ml env' C' E'
-> INV env' (w_st C') (E ++ E').
Lemma INV_implies_totalSupply_fixed
:
forall env S E,
INV env S E
-> Sum (st_balances S) (st_totalSupply S).
forall env S E,
INV env S E
-> Sum (st_balances S) (st_totalSupply S).
Theorem Property_totalSupply_equal_to_sum_balances
:
forall env0 env msg ml C E C' E',
create env0 msg C E
-> env_step env0 env
-> run env C ml C' E'
-> Sum (st_balances (w_st C')) (st_totalSupply (w_st C')).
forall env0 env msg ml C E C' E',
create env0 msg C E
-> env_step env0 env
-> run env C ml C' E'
-> Sum (st_balances (w_st C')) (st_totalSupply (w_st C')).
Theorem Property_totalSupply_fixed_transfer
:
forall env C C' E' msg to v spec preP evP postP,
spec = funcspec_transfer to v (w_a C) env msg
-> preP = spec_require spec
-> evP = spec_events spec
-> postP = spec_trans spec
-> preP (w_st C) /\ evP (w_st C) E' /\ postP (w_st C) (w_st C')
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
forall env C C' E' msg to v spec preP evP postP,
spec = funcspec_transfer to v (w_a C) env msg
-> preP = spec_require spec
-> evP = spec_events spec
-> postP = spec_trans spec
-> preP (w_st C) /\ evP (w_st C) E' /\ postP (w_st C) (w_st C')
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
Lemma INV_step_total_Supply_fixed
:
forall env C C' E' msg ,
step env C msg C' E'
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
forall env C C' E' msg ,
step env C msg C' E'
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
Theorem Property_totalSupply_fixed_after_initialization
:
forall env0 env msg C E C' E',
create env0 msg C E
-> step env C msg C' E'
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
forall env0 env msg C E C' E',
create env0 msg C E
-> step env C msg C' E'
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
Lemma INV_steps_total_supply_fixed
:
forall ml env0 C0 C E env,
steps env0 C0 ml env C E
-> (st_totalSupply (w_st C0)) = (st_totalSupply (w_st C)).
forall ml env0 C0 C E env,
steps env0 C0 ml env C E
-> (st_totalSupply (w_st C0)) = (st_totalSupply (w_st C)).
Theorem Property_totalSupply_fixed_after_initialization1
:
forall env0 env msg ml C E C' E',
create env0 msg C E
-> run env C ml C' E'
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
forall env0 env msg ml C E C' E',
create env0 msg C E
-> run env C ml C' E'
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
Theorem Property_totalSupply_fixed_delegate_transfer1
:
forall env C C' E' from msg to v spec,
spec = funcspec_transferFrom_1 from to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
forall env C C' E' from msg to v spec,
spec = funcspec_transferFrom_1 from to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
Theorem Property_totalSupply_fixed_delegate_transfer2
:
forall env C C' E' from msg to v spec,
spec = funcspec_transferFrom_2 from to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
forall env C C' E' from msg to v spec,
spec = funcspec_transferFrom_2 from to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\ (spec_events spec) (w_st C) E' /\ (spec_trans spec) (w_st C) (w_st C')
-> (st_totalSupply (w_st C)) = (st_totalSupply (w_st C')).
Theorem Property_from_to_balances_change
:
forall env C C' E' to addr msg v spec,
spec = funcspec_transfer to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\
(spec_events spec) (w_st C) E' /\
(spec_trans spec) (w_st C) (w_st C')
-> m_sender msg <> to
-> m_sender msg <> addr
-> to <> addr
-> (st_balances (w_st C') to = (st_balances (w_st C) to) + v)
/\ (st_balances (w_st C') (m_sender msg) = (st_balances (w_st C) (m_sender msg)) - v)
/\ st_balances (w_st C') addr = st_balances (w_st C) addr.
forall env C C' E' to addr msg v spec,
spec = funcspec_transfer to v (w_a C) env msg
-> (spec_require spec) (w_st C) /\
(spec_events spec) (w_st C) E' /\
(spec_trans spec) (w_st C) (w_st C')
-> m_sender msg <> to
-> m_sender msg <> addr
-> to <> addr
-> (st_balances (w_st C') to = (st_balances (w_st C) to) + v)
/\ (st_balances (w_st C') (m_sender msg) = (st_balances (w_st C) (m_sender msg)) - v)
/\ st_balances (w_st C') addr = st_balances (w_st C) addr.
Proof.
intros env C C' E' to addr msg v spec Hspec_def Hspec Hsender HsenderA HtoA.
unfold funcspec_transfer in Hspec_def.
subst spec. simpl in Hspec.
destruct Hspec as [Hof [_ [_ [_ [_ [_ [Hblncs _]]]]]]].
rewrite Hblncs in *. clear Hblncs.
apply neq_beq_false in Hsender.
apply neq_beq_false in HsenderA.
apply neq_beq_false in HtoA.
unfold a2v_upd_dec. unfold a2v_upd_inc.
destruct Hof as [Hlo Hhi].
destruct Hhi.
rewrite H in Hsender.
rewrite beq_refl in Hsender.
inversion Hsender.
destruct H as [_ Hhi].
split.
- rewrite (tmap_get_upd_eq _ _ _).
rewrite (tmap_get_upd_ne _ _ _ _ Hsender).
apply plus_safe_lt; auto.
- split.
+ apply beq_sym in Hsender.
rewrite (tmap_get_upd_ne _ _ _ _ Hsender).
rewrite (tmap_get_upd_eq _ _ _).
apply minus_safe; auto.
+ apply beq_sym in Hsender.
rewrite (tmap_get_upd_ne _ _ _ _ HtoA).
rewrite (tmap_get_upd_ne _ _ _ _ HsenderA).
auto.
Qed.
intros env C C' E' to addr msg v spec Hspec_def Hspec Hsender HsenderA HtoA.
unfold funcspec_transfer in Hspec_def.
subst spec. simpl in Hspec.
destruct Hspec as [Hof [_ [_ [_ [_ [_ [Hblncs _]]]]]]].
rewrite Hblncs in *. clear Hblncs.
apply neq_beq_false in Hsender.
apply neq_beq_false in HsenderA.
apply neq_beq_false in HtoA.
unfold a2v_upd_dec. unfold a2v_upd_inc.
destruct Hof as [Hlo Hhi].
destruct Hhi.
rewrite H in Hsender.
rewrite beq_refl in Hsender.
inversion Hsender.
destruct H as [_ Hhi].
split.
- rewrite (tmap_get_upd_eq _ _ _).
rewrite (tmap_get_upd_ne _ _ _ _ Hsender).
apply plus_safe_lt; auto.
- split.
+ apply beq_sym in Hsender.
rewrite (tmap_get_upd_ne _ _ _ _ Hsender).
rewrite (tmap_get_upd_eq _ _ _).
apply minus_safe; auto.
+ apply beq_sym in Hsender.
rewrite (tmap_get_upd_ne _ _ _ _ HtoA).
rewrite (tmap_get_upd_ne _ _ _ _ HsenderA).
auto.
Qed.
0 条评论
下一页