The transferBy calculus #
The generic "sliding coupling" relation between programs:
ProgramDenotation.transferBy c p qholds when the coupling programc(think:convert, filling in a lazily sampled random-oracle table) slides from afterpto beforeq, preservingp's value:(p >>= fun a => c >>= fun _ => pure a) = (c >>= fun _ => q).Closure combinators:
transferBy_pure,transferBy_bind,transferBy_while_loop(Kleene/ωSup argument),transferBy_zoom(lifting along a lens into a larger state).Reflexivity from commutation:
transferBy_refl_of_commuteand its footprint formtransferBy_refl_of_inFootprint_compl— a program whose probabilistic footprint avoidsc's footprint transfers to itself.transferBy_comm_contis the converse direction (self-transfer gives commutation in continuation-passing form).Consequences at the
wp/marginal level:transferBy_wp_invariant,transferBy_wp_value,transferBy_marginal_invariant,transferBy_value_marginal— forc-invariant (resp. state-blind) postconditions, transfer gives wp-equality and equal output marginals.
The lazy/eager random-oracle transfer (ProgramDenotation.transfer in
GaudisCrypt.Lib.RO.TransferConvert) is transferBy convert; its
ProcedureState variant (Stable/Loc in
GaudisCrypt.Lib.RO.TransferInstantiate) is transferBy convertL.
Generic transfer: c slides from after p to before q, preserving the value.
Equations
- c.transferBy p q = ((do let a ← p c pure a) = do c q)
Instances For
Monad-law combinators #
pure transfers to itself.
transferBy chains under >>=.
For Unit-valued programs the transfer is a plain bind equation:
p; c = c; q.
Converse of transferBy_unit_bind: a plain bind equation between
Unit-valued programs is a transfer.
zoom lifts transferBy: a state-level transfer becomes a zoomed one.
Reflexivity from commutation #
Self-transfer from pair-output commutation with c.
Continuation form of the transfer: c slides past p in front of any
continuation k, turning p into q. At p = q this says a
self-transferring program commutes with c (the converse direction of
transferBy_refl_of_commute).
Self-transfer from footprint disjointness: a program whose probabilistic
footprint avoids c's footprint commutes with c
(commute_of_disjoint_footprint), so transfers to itself. The ᶜ-form makes
the disjointness hypothesis le_refl.
Closure under while_loop (Kleene/ωSup argument) #
Couple every finite iterate of the two loops via an intermediate whileBy_Ψ
whose else-branch is c (representing "loop terminates, then couple"), then
take the ωSup.
transferBy is preserved by while_loop. If the condition transfers to
itself (e.g. by transferBy_refl_of_inFootprint_compl) and the body
transfers, then the two loops transfer.
Consequences at the wp and marginal level #
Transfer at the wp level for c-invariant postconditions: if the post
F is invariant under running c (in the wp sense), then transfer +
absorption give wp-equality of p and q on F at any starting state.
Transfer at the wp level for value-only postconditions: for
G : α → ENNReal, the wps of p and q against fun aσ => G aσ.1 agree,
given transfer, absorption, and that c is a probability (mass 1).
Value marginal: SubProb-level statement of the transfer.
Marginal at the (value × c-invariant projection) level: instead of
projecting to just the value, additionally include any state projection
h : s → β that is invariant under running c (in the wp sense).