Revision 5cef9de483f78c5ea88da20516bf1e5c4208ea49 authored by Pierre-Yves Strub on 18 March 2017, 11:25:57 UTC, committed by Pierre-Yves Strub on 18 March 2017, 11:25:57 UTC
1 parent b4427d7
Plug_and_Pray_example.ec
require import Distr.
require import Real.
require import Int.
import EuclDiv.
require import Pair.
require Plug_and_Pray.
const q : int.
axiom q_pos : q > 0.
module type Orcl = {
fun query(n : int) : int
}.
module type Adv(O : Orcl) = {
fun run() : bool {*}
}.
module G0(AF : Adv) = {
var b : bool
var k : int
module O = {
fun query(n : int) : int = {
var k_ : int;
k = n;
return k_;
}
}
module A = AF(O)
fun main(x : unit) : unit = {
k = 0;
b = A.run();
(* This is an artificial way to ensure that 0 <= k < q.
Usually, this would be enforced in the oracle, e.g.,
by stopping to answer (and increasing the counter)
after q queries. *)
k = `|k %% q|;
}
}.
module G1(AF : Adv) = {
var b : bool
var k : int
var i : int
module O = {
fun query(n : int) : int = {
var k_ : int;
k = n;
return k_;
}
}
module A = AF(O)
fun main(x : unit) : unit = {
i = $(Distr.Dinter.dinter 0 (q -1));
k = 0;
b = A.run();
k = `|k %% q|;
}
}.
clone import Plug_and_Pray as PnP with
type tres <- unit, type tin <- unit, op bound <- q.
(*
We first apply the general Lemma that yields
1 / q * Pr[ G0 : Ev] = Pr[ G0; i=$[0..q-1] : Ev /\ i = G0.k]
where ``G0; i=$[0..q-1]'' is expressed as an application of the
``Guess'' functor and we use an if-then-else to ensure that
G0.k is in [0..q-1].
*)
lemma Bound_aux &m (A <: Adv):
(1%r/q%r) * Pr[ G0(A).main(()) @ &m : G0.b ]
= Pr[ Guess(G0(A)).main(()) @ &m : G0.b /\ (fst res) = if G0.k >= 0 && G0.k < q then G0.k else 0 ].
proof.
print axiom PBound.
cut := PBound &m (G0(A))
(lambda g u, let (b,k_,g_a_) = g in b)
(lambda g u, let (b_,k,g_a_) = g in 1)
tt.
trivial.
qed.
(*
We now transfer the previous lemma to G0 and G1 by relating
Guess(G0) with G1.
*)
lemma Bound &m (A <: Adv{G1,G0}):
(1%r/q%r) * Pr[ G0(A).main(tt) @ &m : G0.b ]
= Pr[ G1(A).main(tt) @ &m : G1.b /\ G1.k = G1.i].
proof.
rewrite (Bound_aux &m A).
(* we also prove the postcondition 0 <= G1.k < q *)
equiv_deno (_ : true ==> G0.b{1} = G1.b{2} /\ fst(res){1} = G1.i{2} /\ G0.k{1} = G1.k{2} /\
G1.k{2} >= 0 /\ G1.k{2} < q) => //.
fun.
swap {2} 1 3.
inline G0(A).main.
rnd.
sp; wp.
call (_:true); skip; smt.
by smt.
qed.
Computing file changes ...