diff options
author | Jason Gross <jgross@mit.edu> | 2016-05-24 11:46:01 -0400 |
---|---|---|
committer | Jason Gross <jgross@mit.edu> | 2016-05-24 11:46:01 -0400 |
commit | 324e99b1b8d057c00eea0b5133057e75adc821e3 (patch) | |
tree | 770f9f22efa0419a94250ff76b672bd2c6fa3946 /src/Specific | |
parent | de5416133dc67dcd2729d4c7448991ab2672782a (diff) |
Fix some issues in Ed25519 tactics
- Use replace rather than refine to speed up [Defined] and make the
tactics easier to read
- Use [apply f_equal] in place of [reflexivity] for unknown presumably
arcane reasons to satisfy Coq's unifier
- Factor out some tactics into tactic scripts
- Write a lemma to pull functions out of [Let_In]
- Fix autoindentation in emacs by wrapping [Let_In_unRep] in parentheses
(probably a ProofGeneral regexp gone wrong)
- Write a kludgy tactic to unfold [proj1_sig] only when applied to
[exist]
(Pair programming with Andres)
Diffstat (limited to 'src/Specific')
-rw-r--r-- | src/Specific/Ed25519.v | 197 |
1 files changed, 112 insertions, 85 deletions
diff --git a/src/Specific/Ed25519.v b/src/Specific/Ed25519.v index 3db14f057..6e61d0ae2 100644 --- a/src/Specific/Ed25519.v +++ b/src/Specific/Ed25519.v @@ -168,7 +168,7 @@ Definition enc'_correct : @enc (@E.point curve25519params) _ _ = (fun x => enc' clear; abstract (cbv [Let_In]; reflexivity) | ] - end. + end. Local Ltac replace_let_in_with_Let_In := repeat match goal with | [ |- context G[let x := ?y in @?z x] ] @@ -197,10 +197,10 @@ Section Ed25519Frep. Axiom FRepInv : FRep -> FRep. Axiom FRepInv_correct : forall x, inv (rep2F x)%F = rep2F (FRepInv x). - + Axiom FSRepPow : FRep -> SRep -> FRep. Axiom FSRepPow_correct : forall x n, (rep2F x ^ rep2S n)%F = rep2F (FSRepPow x n). - + Axiom FRepOpp : FRep -> FRep. Axiom FRepOpp_correct : forall x, opp (rep2F x) = rep2F (FRepOpp x). @@ -214,26 +214,34 @@ Section Ed25519Frep. Axiom FRep2wire : FRep -> word (b-1). Axiom FRep2wire_correct : forall x, FRep2wire x = @enc _ _ FqEncoding (rep2F x). - + Lemma unfoldDiv : forall {m} (x y:F m), (x/y = x * inv y)%F. Proof. unfold div. congruence. Qed. - + Definition rep2E (r:FRep * FRep * FRep * FRep) : extended := match r with (((x, y), z), t) => mkExtended (rep2F x) (rep2F y) (rep2F z) (rep2F t) end. - + Lemma if_map : forall {T U} (f:T->U) (b:bool) (x y:T), (if b then f x else f y) = f (if b then x else y). Proof. destruct b; trivial. Qed. - + Create HintDb FRepOperations discriminated. Hint Rewrite FRepMul_correct FRepAdd_correct FRepSub_correct FRepInv_correct FSRepPow_correct FRepOpp_correct : FRepOperations. - + Local Ltac Let_In_unRep := match goal with | [ |- appcontext G[Let_In (unRep ?x) ?f] ] => change (Let_In (unRep x) f) with (Let_In x (fun y => f (unRep y))); cbv beta end. - + + + (** TODO: Move me *) + Lemma pull_Let_In {B C} (f : B -> C) A (v : A) (b : A -> B) + : Let_In v (fun v' => f (b v')) = f (Let_In v b). + Proof. + reflexivity. + Qed. + Lemma unifiedAddM1Rep_sig : forall a b : FRep * FRep * FRep * FRep, { unifiedAddM1Rep | rep2E unifiedAddM1Rep = unifiedAddM1' (rep2E a) (rep2E b) }. Proof. destruct a as [[[]]]; destruct b as [[[]]]. @@ -243,7 +251,7 @@ Section Ed25519Frep. end. unfold rep2E. cbv beta delta [unifiedAddM1']. pose proof (rcFOK twice_d) as H; rewrite <-H; clear H. (* XXX: this is a hack -- rewrite misresolves typeclasses? *) - + { etransitivity; [|replace_let_in_with_Let_In; reflexivity]. repeat ( autorewrite with FRepOperations; @@ -253,16 +261,17 @@ Section Ed25519Frep. change (LHS = (rep2E (((x, y), z), t))) end. reflexivity. } - + subst e. - reflexivity. (* FIXME: do not simpl the goal here, we want to keep the Let_In common subexpressions *) + Local Opaque Let_In. + repeat setoid_rewrite (pull_Let_In rep2E). + Local Transparent Let_In. + reflexivity. Defined. - - (*Eval simpl in (fun x1 y1 z1 t1 x2 y2 z2 t2 => proj1_sig (unifiedAddM1Rep_sig (((x1, y1), z1), t1) (((x2, y2), z2), t2))). (* TODO: remove after debugging the fixme three lines above *) *) - + Definition unifiedAddM1Rep (a b:FRep * FRep * FRep * FRep) : FRep * FRep * FRep * FRep := Eval hnf in proj1_sig (unifiedAddM1Rep_sig a b). Definition unifiedAddM1Rep_correct a b : rep2E (unifiedAddM1Rep a b) = unifiedAddM1' (rep2E a) (rep2E b) := Eval hnf in proj2_sig (unifiedAddM1Rep_sig a b). - + Definition rep2T (P:FRep * FRep) := (rep2F (fst P), rep2F (snd P)). Definition erep2trep (P:FRep * FRep * FRep * FRep) := Let_In P (fun P => Let_In (FRepInv (snd (fst P))) (fun iZ => (FRepMul (fst (fst (fst P))) iZ, FRepMul (snd (fst (fst P))) iZ))). Lemma erep2trep_correct : forall P, rep2T (erep2trep P) = extendedToTwisted (rep2E P). @@ -270,7 +279,38 @@ Section Ed25519Frep. unfold rep2T, rep2E, erep2trep, extendedToTwisted; destruct P as [[[]]]; simpl. rewrite !unfoldDiv, <-!FRepMul_correct, <-FRepInv_correct. reflexivity. Qed. - + + (** TODO: possibly move me, remove local *) + Local Ltac replace_option_match_with_option_rect := + idtac; + lazymatch goal with + | [ |- _ = ?RHS :> ?T ] + => lazymatch RHS with + | match ?a with None => ?N | Some x => @?S x end + => replace RHS with (option_rect (fun _ => T) S N a) by (destruct a; reflexivity) + end + end. + + (** TODO: Move me, remove Local *) + Definition proj1_sig_unmatched {A P} := @proj1_sig A P. + Definition proj1_sig_nounfold {A P} := @proj1_sig A P. + Definition proj1_sig_unfold {A P} := Eval cbv [proj1_sig] in @proj1_sig A P. + Local Ltac unfold_proj1_sig_exist := + (** Change the first [proj1_sig] into [proj1_sig_unmatched]; if it's applied to [exist], mark it as unfoldable, otherwise mark it as not unfoldable. Then repeat. Finally, unfold. *) + repeat (change @proj1_sig with @proj1_sig_unmatched at 1; + match goal with + | [ |- context[proj1_sig_unmatched (exist _ _ _)] ] + => change @proj1_sig_unmatched with @proj1_sig_unfold + | _ => change @proj1_sig_unmatched with @proj1_sig_nounfold + end); + (* [proj1_sig_nounfold] is a thin wrapper around [proj1_sig]; unfolding it restores [proj1_sig]. Unfolding [proj1_sig_nounfold] exposes the pattern match, which is reduced by ι. *) + cbv [proj1_sig_nounfold proj1_sig_unfold]. + + (** TODO: possibly move me, remove Local *) + Local Ltac reflexivity_when_unification_is_stupid_about_evars + := repeat first [ reflexivity + | apply f_equal ]. + Lemma sharper_verify : forall pk l msg sig, { verify | verify = ed25519_verify pk l msg sig}. Proof. eexists; intros. @@ -278,19 +318,14 @@ Section Ed25519Frep. ed25519params curve25519params EdDSA.E EdDSA.B EdDSA.b EdDSA.l EdDSA.H EdDSA.PointEncoding EdDSA.FlEncoding EdDSA.FqEncoding]. - + etransitivity. Focus 2. { repeat match goal with | [ |- ?x = ?x ] => reflexivity - | [ |- _ = match ?a with None => ?N | Some x => @?S x end :> ?T ] - => etransitivity; - [ - | refine (_ : option_rect (fun _ => T) _ N a = _); - let S' := match goal with |- option_rect _ ?S' _ _ = _ => S' end in - refine (option_rect (fun a' => option_rect (fun _ => T) S' N a' = match a' with None => N | Some x => S x end) - (fun x => _) _ a); intros; simpl @option_rect ]; - [ reflexivity | .. ] + | _ => replace_option_match_with_option_rect + | [ |- _ = option_rect _ _ _ _ ] + => eapply option_rect_Proper_nd; [ intro | reflexivity.. ] end. set_evars. rewrite<- E.point_eqb_correct. @@ -300,63 +335,60 @@ Section Ed25519Frep. let p2 := constr:(unifiedAddM1_rep eq_refl) in repeat match goal with | |- context [(_ * E.opp ?P)%E] => - rewrite <-(unExtendedPoint_mkExtendedPoint P); - rewrite negateExtended_correct; - rewrite <-p1 + rewrite <-(unExtendedPoint_mkExtendedPoint P); + rewrite negateExtended_correct; + rewrite <-p1 | |- context [(_ * ?P)%E] => - rewrite <-(unExtendedPoint_mkExtendedPoint P); - rewrite <-p1 + rewrite <-(unExtendedPoint_mkExtendedPoint P); + rewrite <-p1 | _ => rewrite p2 end; rewrite ?Znat.Z_nat_N, <-?Word.wordToN_nat; subst_evars; reflexivity. - } Unfocus. - + } Unfocus. + etransitivity. Focus 2. { lazymatch goal with |- _ = option_rect _ _ ?false ?dec => - symmetry; etransitivity; [|eapply (option_rect_option_map (fun (x:F _) => Z.to_N x) _ false dec)] + symmetry; etransitivity; [|eapply (option_rect_option_map (fun (x:F _) => Z.to_N x) _ false dec)] end. eapply option_rect_Proper_nd; [intro|reflexivity..]. match goal with | [ |- ?RHS = ?e ?v ] => let RHS' := (match eval pattern v in RHS with ?RHS' _ => RHS' end) in - unify e RHS' + unify e RHS' end. reflexivity. } Unfocus. rewrite <-decode_scalar_correct. - + etransitivity. Focus 2. { do 2 (eapply option_rect_Proper_nd; [intro|reflexivity..]). symmetry; apply decode_test_encode_test. } Unfocus. - + rewrite enc'_correct. cbv [unExtendedPoint unifiedAddM1 negateExtended scalarMultM1]. - (* Why does this take too long? - lazymatch goal with |- context [ proj1_sig ?x ] => - fail 5 - end. *) - unfold proj1_sig at 1 2. + unfold_proj1_sig_exist. + etransitivity. Focus 2. { do 2 (eapply option_rect_Proper_nd; [intro|reflexivity..]). set_evars. repeat match goal with | [ |- appcontext[@proj1_sig ?A ?P (@iter_op ?T ?f ?neutral ?T' ?testbit ?exp ?base ?bound)] ] - => erewrite (@iter_op_proj T _ _ (@proj1_sig _ _)) by reflexivity + => erewrite (@iter_op_proj T _ _ (@proj1_sig _ _)) by reflexivity end. subst_evars. reflexivity. } Unfocus. - + cbv [mkExtendedPoint E.zero]. - unfold proj1_sig at 1 2 3 5 6 7 8. + unfold_proj1_sig_exist. rewrite B_proj. - + etransitivity. Focus 2. { do 1 (eapply option_rect_Proper_nd; [intro|reflexivity..]). @@ -368,11 +400,11 @@ Section Ed25519Frep. match goal with | [ |- ?RHS = ?e ?v ] => let RHS' := (match eval pattern v in RHS with ?RHS' _ => RHS' end) in - unify e RHS' + unify e RHS' end. reflexivity. } Unfocus. - + cbv [dec PointEncoding point_encoding]. etransitivity. Focus 2. @@ -385,9 +417,9 @@ Section Ed25519Frep. Unfocus. reflexivity. } Unfocus. - + cbv iota beta delta [point_dec_coordinates sign_bit dec FqEncoding modular_word_encoding E.solve_for_x2 sqrt_mod_q]. - + etransitivity. Focus 2. { do 1 (eapply option_rect_Proper_nd; [|reflexivity..]). cbv beta delta [pointwise_relation]. intro. @@ -397,12 +429,12 @@ Section Ed25519Frep. lazymatch goal with | [ |- _ = ?term :> ?T ] => lazymatch term with (match ?a with None => ?N | Some x => @?S x end) - => let term' := constr:((option_rect (fun _ => T) S N) a) in - replace term with term' by reflexivity - end + => let term' := constr:((option_rect (fun _ => T) S N) a) in + replace term with term' by reflexivity + end end. - reflexivity. } Unfocus. reflexivity. } Unfocus. - + reflexivity. } Unfocus. reflexivity. } Unfocus. + etransitivity. Focus 2. { do 1 (eapply option_rect_Proper_nd; [cbv beta delta [pointwise_relation]; intro|reflexivity..]). @@ -411,7 +443,7 @@ Section Ed25519Frep. replace_let_in_with_Let_In. reflexivity. } Unfocus. - + etransitivity. Focus 2. { do 1 (eapply option_rect_Proper_nd; [cbv beta delta [pointwise_relation]; intro|reflexivity..]). @@ -427,8 +459,8 @@ Section Ed25519Frep. => apply Let_In_Proper_nd; [ reflexivity | cbv beta delta [pointwise_relation]; intro ] | [ |- ?LHS = option_rect ?P ?S ?N (if ?b then ?t else ?f) ] => transitivity (if b then option_rect P S N t else option_rect P S N f); - [ - | destruct b; reflexivity ] + [ + | destruct b; reflexivity ] | [ |- _ = if ?b then ?t else ?f ] => apply (f_equal2 (fun x y => if b then x else y)) | [ |- _ = false ] => reflexivity @@ -436,11 +468,11 @@ Section Ed25519Frep. end. reflexivity. } Unfocus. - + cbv iota beta delta [q d a]. rewrite wire2FRep_correct. - + etransitivity. Focus 2. { eapply option_rect_Proper_nd; [|reflexivity..]. cbv beta delta [pointwise_relation]. intro. @@ -455,15 +487,15 @@ Section Ed25519Frep. rewrite !unfoldDiv. rewrite !FRepInv_correct. rewrite !FRepMul_correct. - Let_In_unRep. - rewrite <-(rcSOK (Z.to_N (Ed25519.q / 8 + 1))). + (Let_In_unRep). + rewrite <- (rcSOK (Z.to_N (Ed25519.q / 8 + 1))). eapply Let_In_Proper_nd; [reflexivity|cbv beta delta [pointwise_relation]; intro]. etransitivity. Focus 2. eapply Let_In_Proper_nd; [|cbv beta delta [pointwise_relation]; intro;reflexivity]. { (* TODO: rewrite <-pow_nat_iter_op_correct. erewrite <-iter_op_spec. *) rewrite FSRepPow_correct. - Let_In_unRep. + (Let_In_unRep). etransitivity. Focus 2. eapply Let_In_Proper_nd; [reflexivity|cbv beta delta [pointwise_relation]; intro]. { set_evars. rewrite !F_pow_2_r. @@ -478,7 +510,7 @@ Section Ed25519Frep. reflexivity. } Unfocus. match goal with |- ?e = Let_In ?xval (fun x => rep2F (@?f x)) => change (e = rep2F (Let_In xval f)) end. reflexivity. } Unfocus. - Let_In_unRep. + (Let_In_unRep). eapply Let_In_Proper_nd; [reflexivity|cbv beta delta [pointwise_relation]; intro]. set_evars. rewrite !F_pow_2_r. @@ -488,17 +520,17 @@ Section Ed25519Frep. rewrite <-!FRep2wire_correct. subst_evars. lazymatch goal with |- _ = if ?b then ?t else ?f => apply (f_equal2 (fun x y => if b then x else y)) end; [|reflexivity]. - + set_evars. rewrite !FRepOpp_correct. rewrite (if_map rep2F). lazymatch goal with |- ?e = Let_In (rep2F ?x, rep2F ?y) (fun p => @?r p) => - change (e = Let_In (x, y) (fun p => r (rep2F (fst p), rep2F (snd p)))); cbv beta zeta + change (e = Let_In (x, y) (fun p => r (rep2F (fst p), rep2F (snd p)))); cbv beta zeta end. subst_evars. eapply Let_In_Proper_nd; [reflexivity|cbv beta delta [pointwise_relation]; intro]. - + set_evars; erewrite (f_equal2 (@weqb b)); subst_evars; [|reflexivity|symmetry]. Focus 2. { unfold twistedToExtended. rewrite F_mul_0_l. @@ -507,29 +539,24 @@ Section Ed25519Frep. rewrite <-(rcFOK 1%F). match goal with |- context [?x] => match x with (fst (proj1_sig B)) => rewrite <-(rcFOK x) end end. match goal with |- context [?x] => match x with (snd (proj1_sig B)) => rewrite <-(rcFOK x) end end. - autorewrite with FRepOperations. (* breaks reflexivity *) + autorewrite with FRepOperations. (* breaks reflexivity; use [reflexivity_when_unification_is_stupid_about_evars] instead *) + repeat match goal with |- appcontext [ ?E ] => - match E with (rep2F ?x, rep2F ?y, rep2F ?z, rep2F ?t) => - change E with (rep2E (((x, y), z), t)) - end - end. + match E with (rep2F ?x, rep2F ?y, rep2F ?z, rep2F ?t) => + change E with (rep2E (((x, y), z), t)) + end + end. lazymatch goal with |- context [?X] => lazymatch X with negateExtended' (rep2E ?E) => - replace X with (rep2E (((((FRepOpp (fst (fst (fst E)))), (snd (fst (fst E)))), (snd (fst E))), (FRepOpp (snd E))))) by (simpl; autorewrite with FRepOperations; reflexivity) - end end; simpl fst; simpl snd. (* we actually only want to simpl in the with clause *) + replace X with (rep2E (((((FRepOpp (fst (fst (fst E)))), (snd (fst (fst E)))), (snd (fst E))), (FRepOpp (snd E))))) by (simpl; autorewrite with FRepOperations; reflexivity) + end end; simpl fst; simpl snd. (* we actually only want to simpl in the with clause *) do 2 erewrite <- (fun x y z => iter_op_proj rep2E unifiedAddM1Rep unifiedAddM1' x y z N.testbit_nat) by apply unifiedAddM1Rep_correct. rewrite <-unifiedAddM1Rep_correct, <-erep2trep_correct; cbv beta delta [erep2trep]. - (* - reflexivity. } Unfocus. - (* - cbv beta iota delta - [iter_op test_and_op unifiedAddM1' extendedToTwisted twistedToExtended enc' snd - point_dec_coordinates PrimeFieldTheorems.sqrt_mod_q]. - *) + reflexivity_when_unification_is_stupid_about_evars. + } Unfocus. + reflexivity. } Unfocus. reflexivity. -*) - Admitted. - -End Ed25519Frep.
\ No newline at end of file + Defined. +End Ed25519Frep. |