Section PedersenHiding.
Variable A_State : Set.
Variable A1 : GroupElement -> Comp (nat * nat * A_State).
Hypothesis A1_wf : forall p, well_formed_comp (A1 p).
Variable A2 : A_State -> GroupElement -> Comp bool.
Hypothesis A2_wf :
forall s c, well_formed_comp (A2 s c).
Definition PedersenHiding_G0 :=
a <-$ [ 0  .. order);
[v1, v2, s_A] <-$3 A1 (g^a);
b <-$ {0,1};
v <- (if b then v1 else v2);
z <-$
(r <-$ [ 0  .. order);
ret (g^a)^r);
b' <-$ A2 s_A (g ^ v * z);
ret eqb b b'.
Definition PedersenHiding_G1 :=
a <-$ [ 0  .. order);
[v1, v2, s_A] <-$3 A1 (g^a);
b <-$ {0,1};
v <- (if b then v1 else v2);
z <-$
(x <-$ RndGrpElem;
ret (g ^ v * x));
b' <-$ A2 s_A z;
ret eqb b b'.
Definition PedersenHiding_G2 :=
a <-$ [ 0  .. order);
[v1, v2, s_A] <-$3 A1 (g^a);
b <-$ {0,1};
x <-$ RndGrpElem;
b' <-$ A2 s_A x;
ret eqb b b'.
Definition PedersenHiding_G3 :=
a <-$ [ 0  .. order);
[v1, v2, s_A] <-$3 A1 (g^a);
x <-$ RndGrpElem;
b' <-$ A2 s_A x;
b <-$ {0,1};
ret eqb b b'.
unfold HidingCommit_G, PedersenSetup, PedersenCommit, PedersenHiding_G0.
repeat (inline_first; comp_skip; comp_simp).
Qed.
unfold PedersenHiding_G0, PedersenHiding_G1.
do 3 (inline_first; comp_skip; comp_simp).
comp_inline_r.
comp_skip.
symmetry.
eapply comp_spec_eq_impl_eq.
apply group_OTP_exp.
comp_simp.
intuition.
Qed.
unfold PedersenHiding_G1, PedersenHiding_G2.
do 3 (inline_first; comp_skip; comp_simp).
comp_skip.
symmetry.
eapply comp_spec_eq_impl_eq.
eapply group_OTP_l.
Qed.
unfold PedersenHiding_G2, PedersenHiding_G3.
do 2 (inline_first; comp_skip; comp_simp).
comp_swap_l.
comp_skip.
comp_swap_l.
comp_skip.
Qed.

Theorem PedersenHiding_G3_half :
Pr[PedersenHiding_G3] == 1/2.