Section SigmaProtocol.
Variable R : Blist -> Blist -> bool.
Variable t : nat.
Variable (Commitment Response P_State : Set)
(P_commit : Blist -> Blist -> Comp (P_State * Commitment))
(V_challenge : Blist -> Commitment -> Comp (Bvector t))
(P_respond : P_State -> Bvector t -> Comp Response)
(V_accept :  Blist -> Commitment -> Bvector t -> Response -> bool).
Variable extract : Blist -> Commitment -> Bvector t -> Bvector t -> Response -> Response -> Comp Blist.
(* Also, extract must be efficient *)
Variable Commitment_EqDec : EqDec Commitment.
Variable Response_EqDec : EqDec Response.
Definition Protocol x w :=
[s_P, a] <-$2 P_commit x w;
e <-$ V_challenge x a;
z <-$ P_respond s_P e;
ret (a, e, z).
(* The ZK simulator *)
Variable M : Blist -> Bvector t -> Comp (Commitment * Response).
Definition G_S x :=
e <-$ {0, 1}^t;
[a, z] <-$2 M x e;
b <-$ ret (V_accept x a e z);
ret (b, (a, e, z)).
Definition G_P x w :=
[a, e, z] <-$3 Protocol x w;
b <-$ ret (V_accept x a e z);
ret (b, (a, e, z)).
Class SigmaProtocol
:= {
poly1 : nat -> nat;
w_length : forall x w, R x w = true -> (length w <= poly1 (length x))%nat;
completeness : forall x w,
R x w = true ->
Pr[[a, e, z] <-$3 Protocol x w; ret (V_accept x a e z)] == 1;
special_soundness : forall x a e e' z z',
e <> e' ->
(exists w, In (a, e, z) (getSupport (Protocol x w))) ->
(exists w, In (a, e', z') (getSupport (Protocol x w))) ->
V_accept x a e z = true ->
V_accept x a e' z' = true ->
Pr[w <-$ extract x a e e' z z'; ret (R x w)] == 1; (* Or perhaps just non-negligible *)
sHVZK : forall x w c,
evalDist (G_S x) (true, c) == evalDist (G_P x w) (true,c)
}.
End SigmaProtocol.
Ltac destruct_exists :=
match goal with
| [H : exists x, _ |- _ ] =>
destruct H
end.

Lemma getSupport_Bind_In : forall (A B : Set) (c : Comp B)(f : B -> Comp A) a,
In a (getSupport (Bind c f)) ->
exists b,
In b (getSupport c) /\
In a (getSupport (f b)).