Documentation

GaudisCrypt.Lib.RO.OneWayness_GameHop.GuessExperiment

OneWayness GameHop: Guess Experiment Framework #

This module provides the abstract guessing-game machinery that abstracts both the win and bad events in the OW chain. Used by both Game 1's bad-event reduction and Game 2's win-event reduction.

Core combinators #

Bounds #

Schema (per-game correspondence) #

Game 2's body fits directly. Game 1's needs the bridges in Game1.lean to convert to Game 1' form.

Generic guessing-game combinators #

The framework for cryptographic guess-game reductions. loop_n is a plain bounded loop; guess_experiment is the unifying "n+1 attempts to hit a uniform target" game.

noncomputable def guess_experiment {T s : Type} (env : GaudisCrypt.ProgramDenotation s Unit) (sample_target : GaudisCrypt.ProgramDenotation s T) (target_var : GaudisCrypt.Lens T s) (matched_var : GaudisCrypt.Lens Bool s) (body final : T → GaudisCrypt.ProgramDenotation s Unit) (n : ℕ) :

A generic "guess the uniform target" experiment.

The key generalization vs prior versions: the body and final iterations are parameterized by the target t. Each iteration can use the bound target directly in match-checks (no state extracts required). This unifies two shapes of match-check that arise in OW:

  • Input-side match (Game 1 bad): lazy_query_tracked already tracks input matches internally via chal_x_queried_gh; the body doesn't need an explicit match-check (it ignores its target param).
  • Output-side match (Game 2 win-bound): body explicitly does if y_val = t then set matched_var true using bound y_val and t.

Returns the matched flag's final value (Bool). Cryptographic reductions relate ow_game_*'s win/bad events to the matched flag via specialized bridges.

Equations
  • One or more equations did not get rendered due to their size.
Instances For

    Collector-game route to the bound. #

    ALTERNATIVE architectural approach: introduce a collector version of guess_experiment that:

    The bound on the collector is then a one-line application of "uniform sample ∈ finite list of length ≤ n+1 has probability ≤ (n+1)/|T|". The deferred-sampling content becomes a single equivalence proof guess_experiment ≤ guess_experiment_collector.

    Interim form of guess_experiment: same as the collector but with the target sampled FIRST (like guess_experiment) instead of last.

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      theorem guess_experiment_le_interim_assumption {T : Type} [Fintype T] [Nonempty T] [DecidableEq T] (env : GaudisCrypt.ProgramDenotation state Unit) (target_var : GaudisCrypt.Lens T state) (matched_var : GaudisCrypt.Lens Bool state) (queries_list_var : GaudisCrypt.Lens (List T) state) (body final : T → GaudisCrypt.ProgramDenotation state Unit) (body_recording final_recording : GaudisCrypt.ProgramDenotation state Unit) (n : ℕ) (h_correspondence : ∀ (σ' : state) (t : T), (do GaudisCrypt.ProgramDenotation.set target_var t GaudisCrypt.ProgramDenotation.set matched_var false GaudisCrypt.loop_n n (body t) final t GaudisCrypt.ProgramDenotation.get matched_var).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ' ≤ (do GaudisCrypt.ProgramDenotation.set queries_list_var [] GaudisCrypt.loop_n n body_recording final_recording let qs ← GaudisCrypt.ProgramDenotation.get queries_list_var GaudisCrypt.ProgramDenotation.set matched_var (decide (t ∈ qs)) GaudisCrypt.ProgramDenotation.get matched_var).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ') (σ : state) :
      (guess_experiment env GaudisCrypt.ProgramDenotation.uniform target_var matched_var body final n).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ ≤ (guess_experiment_interim env queries_list_var matched_var body_recording final_recording n).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ

      Generic bound: guess_experiment.wp ≤ guess_experiment_interim.wp (with sample_target = ProgramDenotation.uniform).

      The cryptographic content is in h_correspondence: a per-state bound that the LHS's matched-fire after the loop+final is at most the RHS's t ∈ qs after recording+final_recording. This bound must be discharged at each instantiation — the proof here just peels the common env and uniform t prefix.

      theorem schema_inner_equation {T : Type} [DecidableEq T] (target_var : GaudisCrypt.Lens T state) (matched_var : GaudisCrypt.Lens Bool state) (queries_list_var : GaudisCrypt.Lens (List T) state) [GaudisCrypt.disjoint matched_var queries_list_var] [GaudisCrypt.disjoint matched_var target_var] [GaudisCrypt.disjoint queries_list_var target_var] (q_body q_final : GaudisCrypt.ProgramDenotation state T) (h_q_body_matched : q_body.inFootprint matched_var.footprintᶜ) (h_q_body_qs : q_body.inFootprint queries_list_var.footprintᶜ) (h_q_body_target : q_body.inFootprint target_var.footprintᶜ) (h_q_final_matched : q_final.inFootprint matched_var.footprintᶜ) (h_q_final_qs : q_final.inFootprint queries_list_var.footprintᶜ) (h_q_final_target : q_final.inFootprint target_var.footprintᶜ) (n : ℕ) (σ' : state) (t : T) :
      (do GaudisCrypt.ProgramDenotation.set target_var t GaudisCrypt.ProgramDenotation.set matched_var false GaudisCrypt.loop_n n do let a ← q_body if a = t then GaudisCrypt.ProgramDenotation.set matched_var true else pure () do let a ← q_final if a = t then GaudisCrypt.ProgramDenotation.set matched_var true else pure () GaudisCrypt.ProgramDenotation.get matched_var).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ' = (do GaudisCrypt.ProgramDenotation.set queries_list_var [] GaudisCrypt.loop_n n do let a ← q_body let qs ← GaudisCrypt.ProgramDenotation.get queries_list_var GaudisCrypt.ProgramDenotation.set queries_list_var (qs ++ [a]) do let a ← q_final let qs ← GaudisCrypt.ProgramDenotation.get queries_list_var GaudisCrypt.ProgramDenotation.set queries_list_var (qs ++ [a]) let qs ← GaudisCrypt.ProgramDenotation.get queries_list_var GaudisCrypt.ProgramDenotation.set matched_var (decide (t ∈ qs)) GaudisCrypt.ProgramDenotation.get matched_var).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ'

      Schema's inner per-σ', t equation: the per-σ', t correspondence that guess_experiment_le_interim_via_schema uses to discharge the h_correspondence of guess_experiment_le_interim_assumption.

      Proved relationally: this is PRHLSchema.schema_inner_equation_prhl (PlonkLean/PRHL/Clients/SchemaInnerEquation.lean), one synchronized loop invariant matched₁ = (t ∈ qs₂) in the pRHL calculus. The former unary proof (~280 lines plus ~700 lines of private support lemmas, maxHeartbeats 1600000) was removed in favor of it.

      Reusable for other game-level proofs (e.g., game_1_correspondence) that need the inner equation directly without going through the full schema.

      theorem guess_experiment_le_interim_via_schema {T : Type} [Fintype T] [Nonempty T] [DecidableEq T] (env : GaudisCrypt.ProgramDenotation state Unit) (target_var : GaudisCrypt.Lens T state) (matched_var : GaudisCrypt.Lens Bool state) (queries_list_var : GaudisCrypt.Lens (List T) state) [GaudisCrypt.disjoint matched_var queries_list_var] [GaudisCrypt.disjoint matched_var target_var] [GaudisCrypt.disjoint queries_list_var target_var] (q_body q_final : GaudisCrypt.ProgramDenotation state T) (h_q_body_matched : q_body.inFootprint matched_var.footprintᶜ) (h_q_body_qs : q_body.inFootprint queries_list_var.footprintᶜ) (h_q_body_target : q_body.inFootprint target_var.footprintᶜ) (h_q_final_matched : q_final.inFootprint matched_var.footprintᶜ) (h_q_final_qs : q_final.inFootprint queries_list_var.footprintᶜ) (h_q_final_target : q_final.inFootprint target_var.footprintᶜ) (body final : T → GaudisCrypt.ProgramDenotation state Unit) (body_recording final_recording : GaudisCrypt.ProgramDenotation state Unit) (h_body : ∀ (t : T), body t = do let a ← q_body if a = t then GaudisCrypt.ProgramDenotation.set matched_var true else pure ()) (h_body_recording : body_recording = do let a ← q_body let qs ← GaudisCrypt.ProgramDenotation.get queries_list_var GaudisCrypt.ProgramDenotation.set queries_list_var (qs ++ [a])) (h_final : ∀ (t : T), final t = do let a ← q_final if a = t then GaudisCrypt.ProgramDenotation.set matched_var true else pure ()) (h_final_recording : final_recording = do let a ← q_final let qs ← GaudisCrypt.ProgramDenotation.get queries_list_var GaudisCrypt.ProgramDenotation.set queries_list_var (qs ++ [a])) (n : ℕ) (σ : state) :
      (guess_experiment env GaudisCrypt.ProgramDenotation.uniform target_var matched_var body final n).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ ≤ (guess_experiment_interim env queries_list_var matched_var body_recording final_recording n).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ

      Schema-based correspondence: when body and body_recording both decompose as q >>= ... for some shared "query" subprogram q, with body's tail being a match-check against t and body_recording's tail appending to queries_list_var, the per-state correspondence (the h_correspondence hypothesis of guess_experiment_le_interim_assumption) is provable structurally via schema_inner_equation.

      q_body and q_final are the shared subprograms for the loop and the final iteration respectively. They may differ (e.g., body does adv query via oracle_input, final does response check via ow_response).

      theorem guess_experiment_interim_wp_bound {T : Type} [Fintype T] [Nonempty T] [DecidableEq T] (env : GaudisCrypt.ProgramDenotation state Unit) (queries_list_var : GaudisCrypt.Lens (List T) state) (matched_var : GaudisCrypt.Lens Bool state) [GaudisCrypt.disjoint queries_list_var matched_var] (body_recording final_recording : GaudisCrypt.ProgramDenotation state Unit) (n : ℕ) (h_qs_length_le : ∀ (σ : state), (do env GaudisCrypt.ProgramDenotation.set queries_list_var [] GaudisCrypt.loop_n n body_recording final_recording).wp (fun (aσ : Unit × state) => ↑(queries_list_var.get aσ.2).length / ↑(Fintype.card T)) σ ≤ ↑(n + 1) / ↑(Fintype.card T)) (σ : state) :
      (guess_experiment_interim env queries_list_var matched_var body_recording final_recording n).wp (fun (bσ : Bool × state) => if bσ.1 = true then 1 else 0) σ ≤ (↑n + 1) / ↑(Fintype.card T)

      Interim wp bound: by interim = collector + collector bound. Generic.

      Helpers for length-bound proofs #

      theorem ProgramDenotation.wp_qs_length_preserved_of_inFootprint {T : Type} [DecidableEq T] (qs_var : GaudisCrypt.Lens (List T) state) {α : Type} (p : GaudisCrypt.ProgramDenotation state α) (h_p : p.inFootprint qs_var.footprintᶜ) (σ : state) :
      p.wp (fun (aσ : α × state) => ↑(qs_var.get aσ.2).length) σ ≤ ↑(qs_var.get σ).length

      For a program p that doesn't write to qs_var, the expected list length at output is bounded by the initial length (up to mass ≤ 1).