Seed-Based Forking Lemma (Bellare-Neven) #
The forking lemma is a key tool in provable security. The seeded variant in this file
(seededFork) mechanizes the original Bellare-Neven construction (CCS 2006): pre-sample every
oracle response into a QuerySeed, run the adversary deterministically against that seed, then
re-run it against a seed that has been modified at the chosen fork point.
seededFork returns OracleComp spec (Option (α × α)) with explicit matching on
success/failure. The seeded replay uses seededOracle via StateT, and generateSeed
produces the initial seed as a ProbComp lifted into spec.
The companion file VCVio/CryptoFoundations/ReplayFork.lean provides the replay variant,
which only pre-samples the forked oracle family and answers ambient randomness live; it is the
natural choice for reductions like Fiat-Shamir EUF-CMA whose adversaries make both kinds of
queries.
Bundles the inputs to the forking lemma.
- main : OracleComp spec α
- queryBound : ι → ℕ
- js : List ι
Instances For
The forking operation: run main with a random seed, then re-run it with the seed modified
at the s-th query to oracle i (where s = cf x₁), checking that both runs agree on cf.
Returns none (failure) when:
cf x₁ = none(adversary did not choose a fork point)- the re-sampled oracle response equals the original (no useful fork)
cf x₂ ≠ cf x₁(the second run chose a different fork point)
Instances For
The deterministic core of seededFork with the random seed and replacement value already fixed.
Runs main once against seed, checks whether the fork-index selector cf fires, and if so
replays main against a modified seed where the (cf x₁)-th answer to oracle i is replaced
by u. Returns the pair (x₁, x₂) when both runs agree on the fork index.
The only remaining randomness comes from main's own oracle queries that fall outside the
seed (i.e. queries beyond the budget qb).
Instances For
When the seed has at least qb t pre-generated answers for each oracle t, running main
against the seed makes zero live oracle queries (every query is answered from the seed).
After truncating the seed at query index s for oracle i and inserting a fresh answer u,
the replayed run can make at most qb i - (s + 1) live queries, all to oracle i.
All other oracle families remain fully covered by the seed.
seededForkWithSeedValue makes at most qb i live queries, all to oracle i.
The first seeded run is query-free (covered by the seed); the replay after the fork point uses
at most the remaining i-budget. The bound holds regardless of which fork index cf returns.
The expected unit-cost query count of seededForkWithSeedValue, averaged over the randomly
sampled seed and replacement value, is at most qb i.
Total expected query work of one fork attempt. The LHS decomposes as three terms:
- Seed generation:
∑ j in js, qb j * sampleCost juniform-oracle calls to build the seed. - Replacement sample:
sampleCost icalls to sample one fresh value at the forked oraclei. - Replay queries: at most
qb ilive queries during the replayed execution.
The RHS is their sum: (∑ j in js, qb j * sampleCost j) + sampleCost i + qb i.
If seededFork succeeds (returns some), both runs agree on the fork index.
On seededFork support, first-projection success equals old pair-style success event.
Key bound of the forking lemma: the probability that both runs succeed with fork point s
is at least Pr[cf(main) = s]² - Pr[cf(main) = s] / |Range i|.
The standard forking-lemma precondition is itself a valid probability bound.
Main forking lemma: the failure probability is bounded by 1 - acc * (acc / q - 1/h).
Forking-lemma lower bound, packaged directly as the success-event probability.
Bellare-Neven seeded forking bound in its canonical acc² / q − acc / h shape, where
acc = ∑ₛ Pr[= some s | cf <$> main], q = qb i + 1, and h = |spec.Range i|.
This is the aggregated bound that appears as Lemma 1 of Bellare-Neven (CCS'06): summing the
per-index lower bound over all fork points and applying Cauchy-Schwarz reshapes the product
form delivered by le_probEvent_isSome_seededFork into the familiar ratio form. Algebraically
the two statements are equal (modulo ENNReal.mul_sub under the finiteness of acc); this
lemma exposes the ratio form as a public API so that downstream callers can match the
textbook presentation directly.