Counting Queries Made by a Computation #
This file defines a simulation oracle countingOracle for counting the number of queries made
while running the computation. The count is represented by a function from oracle indices to
counts, allowing each oracle to be tracked individually.
Tracking individually is not necessary, but gives tighter security bounds in some cases. It also allows for generating things like seed values for a computation more tightly.
Wrap an oracle implementation to accumulate cost in a WriterT ω layer.
The cost function costFn assigns a cost value to each oracle query.
Cost is accumulated before the implementation runs, so failed queries are still costed.
Side-channel trace instrumentation.
withCost doubles as automatic side-channel instrumentation: given any
OracleComp spec α and a cost function costFn : spec.Domain → ω,
(simulateQ (base.withCost costFn) oa).run produces m (α × ω) without
modifying the computation's source code. The cost function encodes the
observation model:
fun _ => ()(constant-time): every query looks identical to the observer.fun t => queryLabel t(typed): the observer sees which oracle was queried but not the arguments or results.
This is the preferred approach when the observation model is "every oracle
query is visible." For observations at non-query points (e.g. pure-computation
timing), use the explicit observe / runObs API from ObservationOracle.
Instances For
Cost-tracking preserves failure probability: for any base monad m with HasEvalSPMF,
wrapping an oracle implementation with withCost does not change the probability of failure.
When every query costs the monoid identity 1, the trace is always 1,
so withCost is a no-op up to pairing with 1.
EvalDist Bridge for withCost #
These lemmas connect the result-marginal distribution of a withCost-instrumented
computation to the distribution of the uninstrumented computation, enabling direct
probability-level reasoning about traced computations.
Wrap an oracle implementation to count queries in a WriterT (QueryCount ι) layer.
Counting happens before the implementation runs, so failed queries are still counted.
This is a special case of withCost where the cost function is QueryCount.single.
Instances For
Oracle with arbitrary cost tracking. The cost is accumulated in a WriterT ω layer
while preserving the original oracle behavior.
Instances For
Oracle for counting the number of queries made by a computation. The count is stored as a function from oracle indices to counts, to give finer grained information about the count.
Instances For
Specialization of QueryImpl.probFailure_run_simulateQ_withCost to countingOracle.
Specialization of QueryImpl.NeverFail_run_simulateQ_withCost_iff to countingOracle.
Compatibility helper matching old state-style counting semantics:
simulate with zero initial count, then offset by qc.
Instances For
We can always reduce simulation with counting to start with 0,
and add the initial count back at the end.
Reduce membership in support of simulation with counting to simulation starting from 0.