Documentation

VCVio.OracleComp.QueryTracking.Unpredictability

ROM Unpredictability and Collision Win Bounds #

Fresh query uniformity, cache preimage bounds, and the collision-based win probability theorem.

Unpredictability #

HasUnpredictableSample samples β packages "the probability of any specific outcome of samples : ProbComp α is at most β". It is the abstract handle through which downstream collision bounds ingest min-entropy of a sample distribution without re-deriving uniform-sample arithmetic at each call site.

Instances:

The TV-distance "programming collision" bound that consumes this typeclass lives downstream in VCVio/ProgramLogic/Relational/ProgrammingOracle.lean (see programming_collision_bound and its qP * qH * β repackaging), keeping the relational theorem in the ProgramLogic layer while the unpredictability primitive stays here in QueryTracking.

Unpredictability #

theorem OracleComp.probOutput_fresh_cachingOracle_query {ι : Type} [DecidableEq ι] {spec' : OracleSpec ι} [spec'.Fintype] [spec'.Inhabited] (t : spec'.Domain) (u : spec'.Range t) (cache₀ : spec'.QueryCache) (hfresh : cache₀ t = none) :
Pr[= (u, cache₀.cacheQuery t u) | (OracleSpec.cachingOracle t).run cache₀] = (↑(Fintype.card (spec'.Range t)))⁻¹

Fresh query uniformity: querying cachingOracle at an uncached point yields each value with probability 1/|C|.

theorem OracleComp.probEvent_unqueried_match_le {ι : Type} [DecidableEq ι] {spec' : OracleSpec ι} [spec'.Fintype] [spec'.Inhabited] {α : Type} {t : } (oa : OracleComp spec' α) (_hbound : oa.IsPerIndexQueryBound fun (x : ι) => t) (predict : spec'.Domain) (_target : spec'.Range predict) :
(probEvent ((simulateQ OracleSpec.cachingOracle oa).run ) fun (z : α × spec'.QueryCache) => z.2 predict = none) * (↑(Fintype.card (spec'.Range predict)))⁻¹ (↑(Fintype.card (spec'.Range predict)))⁻¹

WARNING: trivially true. The proof uses only probEvent_le_one; the query bound hbound and target are completely unused. The conclusion Pr[...] * |C|⁻¹ ≤ |C|⁻¹ holds for any computation regardless of how many queries it makes.

A meaningful unpredictability bound should use hbound to establish that the queried point is fresh, giving a tight 1/|C| bound on the probability of guessing the ROM output.

theorem OracleComp.probEvent_cache_has_value_le_of_unique_preimage {ι : Type} [DecidableEq ι] {spec : OracleSpec ι} [spec.DecidableEq] [spec.Fintype] [spec.Inhabited] {α : Type} [Inhabited ι] (oa : OracleComp spec α) (n : ) (hbound : oa.IsTotalQueryBound n) (hrange : ∀ (t : ι), Fintype.card (spec.Range default) Fintype.card (spec.Range t)) (v₀ : spec.Range default) (cache₀ : spec.QueryCache) (hunique_v₀ : ∀ (t₀ t₁ : spec.Domain) (v₁ : spec.Range t₀) (v₂ : spec.Range t₁), cache₀ t₀ = some v₁cache₀ t₁ = some v₂v₁ v₀v₂ v₀t₀ = t₁) :
(probEvent ((simulateQ OracleSpec.cachingOracle oa).run cache₀) fun (z : α × spec.QueryCache) => ∃ (t₀ : spec.Domain) (v : spec.Range t₀), z.2 t₀ = some v cache₀ t₀ = none v v₀) n * (↑(Fintype.card (spec.Range default)))⁻¹

Cache preimage bound: if the initial cache contains at most one preimage of a target value v₀, then the probability that simulateQ cachingOracle oa creates a fresh cache entry equal to v₀ is at most n / |C|, where n is the total query bound. Each cache miss is a fresh uniform draw, so a union bound over the at most n misses gives the result.

This is the reusable ROM lemma for the extractability "fresh target hit" case.

theorem OracleComp.probEvent_cache_has_value_le_of_noCollision {ι : Type} [DecidableEq ι] {spec : OracleSpec ι} [spec.DecidableEq] [spec.Fintype] [spec.Inhabited] {α : Type} [Inhabited ι] (oa : OracleComp spec α) (n : ) (hbound : oa.IsTotalQueryBound n) (hrange : ∀ (t : ι), Fintype.card (spec.Range default) Fintype.card (spec.Range t)) (v₀ : spec.Range default) (cache₀ : spec.QueryCache) (hno : ¬CacheHasCollision cache₀) :
(probEvent ((simulateQ OracleSpec.cachingOracle oa).run cache₀) fun (z : α × spec.QueryCache) => ∃ (t₀ : spec.Domain) (v : spec.Range t₀), z.2 t₀ = some v cache₀ t₀ = none v v₀) n * (↑(Fintype.card (spec.Range default)))⁻¹

Special case of probEvent_cache_has_value_le_of_unique_preimage when the initial cache contains at most one preimage of v₀ because the cache is collision-free.

theorem OracleComp.probEvent_cache_has_value_le {ι : Type} [DecidableEq ι] {spec : OracleSpec ι} [spec.DecidableEq] [spec.Fintype] [spec.Inhabited] {α : Type} [Inhabited ι] (oa : OracleComp spec α) (n : ) (hbound : oa.IsTotalQueryBound n) (hrange : ∀ (t : ι), Fintype.card (spec.Range default) Fintype.card (spec.Range t)) (v₀ : spec.Range default) (cache₀ : spec.QueryCache) (hno_v₀ : ∀ (t₀ : spec.Domain) (v : spec.Range t₀), cache₀ t₀ = some v¬v v₀) :
(probEvent ((simulateQ OracleSpec.cachingOracle oa).run cache₀) fun (z : α × spec.QueryCache) => ∃ (t₀ : spec.Domain) (v : spec.Range t₀), z.2 t₀ = some v cache₀ t₀ = none v v₀) n * (↑(Fintype.card (spec.Range default)))⁻¹

Special case of probEvent_cache_has_value_le_of_unique_preimage when the initial cache contains no preimage of v₀.

Collision-Based Win Bound #

theorem OracleComp.probEvent_collision_win_le {ι : Type} [DecidableEq ι] {spec : OracleSpec ι} [spec.DecidableEq] [spec.Fintype] [spec.Inhabited] {α : Type} {t : } [Inhabited ι] [Unique ι] (oa : OracleComp spec α) (win : α × spec.QueryCacheProp) (hbound : oa.IsPerIndexQueryBound fun (x : ι) => t) (hC : 0 < Fintype.card (spec.Range default)) (hrange : ∀ (t : ι), Fintype.card (spec.Range default) Fintype.card (spec.Range t)) (hwin : zsupport ((simulateQ OracleSpec.cachingOracle oa).run ), win zCacheHasCollision z.2) :

WARNING: vacuously true. The [Unique ι] hypothesis means ι has exactly one element, but CacheHasCollision (used via probEvent_cacheCollision_le_birthday') requires two distinct oracle indices t₁ ≠ t₂ : ι, which is impossible when ι is unique. The event CacheHasCollision z.2 is therefore always false, making the bound trivially 0 ≤ ....

For a useful single-oracle collision bound, state it over LogHasCollision (which checks for equal outputs on distinct inputs within the same oracle index) rather than CacheHasCollision (which requires distinct indices).

HasUnpredictableSample #

structure OracleComp.HasUnpredictableSample {α : Type} (samples : ProbComp α) (β : ENNReal) :

A probabilistic computation samples : ProbComp α is β-unpredictable if every specific outcome occurs with probability at most β. This is the standard "min-entropy at level log₂(1/β)" notion, packaged as a structured proposition so that downstream collision bounds can ingest it generically.

Equivalent to ∀ x, Pr[= x | samples] ≤ β; the structure shape lets it serve as the canonical abstract hypothesis for "values drawn from samples are hard to guess".

Instances For
    theorem OracleComp.hasUnpredictableSample_iff {α : Type} (samples : ProbComp α) (β : ENNReal) :
    HasUnpredictableSample samples β ∀ (x : α), Pr[= x | samples] β
    theorem OracleComp.HasUnpredictableSample.mono {α : Type} {samples : ProbComp α} {β β' : ENNReal} (h : HasUnpredictableSample samples β) ( : β β') :

    Monotonicity in the bound: a β-unpredictable sample is also β'-unpredictable for any β' ≥ β.

    $ᵗ α is (|α|)⁻¹-unpredictable for any nonempty Fintype.

    Sanity check: uniform sampling reproduces the canonical 1/|α| shape #

    For a β-unpredictable sampling distribution from a fintype, the per-sample bound matches (Fintype.card α)⁻¹ exactly when samples = $ᵗ α. This pins the textbook "uniform draw from α has min-entropy log₂|α|" arithmetic so downstream collision bounds can substitute β = 1/|α| algebraically.