Oracle loops #
Scratch state and loop primitives for adversary-driven oracle protocols.
Scratch state:
want_more,oracle_input,oracle_output,adversary_result— the per-step variables shared between the adversary and the loop infrastructure. All disjoint fromrandom_oracle_state.The three oracle-loop variants, sharing the same body shape:
oracle_step— one iteration.oracle_loop_n—qiterations (static query budget).oracle_loop— unbounded iteration viawhile_loopandwant_more.
Their transfer /
inRange/ linear-bound / indicator-step lemmas.Key-level RO reasoning for
lazy_query inp >>= set oracle_output(the "deferred sampling" combinator).
Scratch state #
lazy_query + set oracle_output — the "deferred sampling" combinator #
The combined step "query the oracle on inp, store the result in
oracle_output" is the unit of work performed in every oracle-loop
body. We collect its key-level properties here.
Pushing convert past the let inp ← get oracle_input; let v ← lazy_query inp; set oracle_output v piece.
(lazy_query inp >>= set oracle_output) avoids any lens L disjoint from both
random_oracle_state and oracle_output (probabilistic footprint form).
(lazy_query inp >>= set oracle_output) preserves RO[k] for inp ≠ k.
More precisely, the wp can be strengthened with the RO[k]-preserved
condition.
Fine-grained RO commutativity: a write to RO[x] commutes with
(lazy_query inp >>= set oracle_output) when inp ≠ x. Writes to
different RO keys commute, and oracle_output is disjoint from RO.
Mechanical core of averaged-invariance MISS-case arguments.
Generic adversary + oracle loop primitives #
Both cr_loop_body/cr_loop (in CollisionResistance.lean) and
ow_loop_body/ow_loop (in OneWayness.lean) use the same shape:
"run the adversary, then perform one oracle call on whatever the adversary
wrote to oracle_input, storing the result in oracle_output." The
shared abstraction lives here. Game-specific files alias these.
One round of an adversary-and-query loop body. Generic over the adversary;
parameterised over the oracle so it can be instantiated to lazy_query or
random_oracle_query.
Equations
- oracle_step adv oracle = do adv let __do_lift ← GaudisCrypt.ProgramDenotation.get oracle_input let __do_lift ← oracle __do_lift GaudisCrypt.ProgramDenotation.set oracle_output __do_lift
Instances For
Run oracle_step adv oracle for q rounds.
Equations
- oracle_loop_n adv 0 x✝ = pure ()
- oracle_loop_n adv n.succ x✝ = do oracle_step adv x✝ oracle_loop_n adv n x✝
Instances For
Unbounded oracle_loop #
The while_loop variant: the adversary may continue indefinitely,
terminating by clearing want_more. Strictly more general than
oracle_loop_n (which fixes the query budget upfront). The lazy = eager
equivalence is proved in PlonkLean.RO.ROEquiv via the transfer
framework's while_loop closure law.
Unbounded "adversary + oracle call" loop. The adversary decides via
the want_more flag whether to continue or stop. Returns the value
of adversary_result.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The lazy form of oracle_loop's while-loop body.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The eager form of oracle_loop's while-loop body.
Equations
- One or more equations did not get rendered due to their size.
Instances For
oracle_step adv transfers from lazy to eager, provided adv is RO-disjoint.
(Countability-free; the inRange original was retired once all consumers moved to
inFootprint.)
oracle_loop_n adv q transfers from lazy to eager. (Countability-free; the inRange
original was retired once all consumers moved to inFootprint.)
Generic preservation: oracle_step adv avoids any lens L disjoint from
random_oracle_state, oracle_input, and oracle_output, provided the adversary avoids it.
Generic preservation lifted to the loop, by induction on q.
Linear-growth bound for oracle_loop_n. If a single body iteration
bumps the wp of f (against the state-projected post) by at most a
constant c, then q iterations bump it by at most q * c. Captures
the standard "loop accumulation" pattern used for both query-budget
bounds (e.g. each query bumps RO size by ≤ 1) and probability bounds
(e.g. each query has ≤ 1/N chance of producing a target value).
Generic per-query indicator step #
The "one lazy_query bumps a state-indicator f by at most the integrated
pointwise badness" pattern. Captures lazy_query_collision_step,
lazy_query_RO_size_step (in CollisionResistance.lean) and
lazy_query_useful_preimage_step (in OneWayness.lean).
Per-query indicator step (generic). If on every cache-miss, the new
fresh sample y at input x bumps f by at most bad x y σ, then the
wp of lazy_query x on the state-marginal of f is at most
f σ + (∑ y, bad x y σ) / |output|. Cache-hit case is trivial since
lazy_query is pure y_cache there (state unchanged).
Generic oracle-step indicator bump. One oracle_step adv bumps the
state-indicator f by at most c σ, given that:
(1) the adversary preserves f (in expectation),
(2) the adversary preserves c (in expectation),
(3) writes to oracle_output leave f unchanged,
(4) one lazy_query bumps f by at most c σ.
Captures the standard "Layer A + adv-preservation" pattern: a single loop body iteration bumps the indicator by the per-query amount, because the adversary alone preserves it. Used by both CR and OW for multiple indicators (collision, RO_size, useful_preimage).
Constant-c specialization of oracle_step_wp_indicator_bump. The
adversary trivially preserves a constant via ProgramDenotation.wp_const_le.
The static-budget oracle loop is the bounded loop combinator applied to a
single oracle step. Lets generic loop_n lemmas apply to oracle_loop_n.