Appendix D: Solutions for Chapter 33
This page collects solutions and editorial notes for the exercises in Chapter 33: Fiat-Shamir in the QROM. Compute and derivation exercises have worked solutions; open-ended exercises have an editorial note describing what a strong answer addresses.
The fuller versions of these routines are in the fiat_shamir_qrom package under solutions/ch33-fiat-shamir-qrom. From a clone of the companion repository, pytest tests/ch33 runs its suite. Appendix C has the setup.
Exercise 1
Section titled “Exercise 1”The chapter’s DFMS20-shaped model: , the corollary’s coefficient rounded and its additive challenge-space term dropped. Chapter 33 records that the dropped term is about at these parameters, so every width below is an output of the model and not a certified minimum.
With , . And . The bound gives , vastly greater than 1. A bound greater than 1 says only that the soundness error is at most a probability, which is true by definition. In that regime the bound carries no information and is vacuous.
To meet , we need , i.e. , so . With , is strictly greater than (by the tiny term). With , . Thus the minimum real has , and the smallest integer (or power-of-two) bit width that satisfies the strict inequality is 173.
So under the model the per-round challenge space must grow from to at least . By the model’s measure, the current is inadequate by 45 bits at the 128-bit PQ target.
import mathr, q_bits, k = 12, 80, 128loss_bits = 2 * r * (q_bits + 1) # (2q + 1)^{2r}, approximatedinteractive_bits = -128 * r # eps_interactive = |C|^{-r}needed = math.ceil(2 * math.log2(2 * 2 ** q_bits + 1) + k / r)print(loss_bits, interactive_bits, loss_bits + interactive_bits)print(needed, needed - 128)# ==> 1944 -1536 408# ==> 173 45Exercise 2
Section titled “Exercise 2”Plonky3’s Fiat-Shamir structure compiles two distinct interactions:
- Inner-layer FRI: placed in the FRI-based tier (Table 33.2’s FRI / BCS-based SNARK row). The Fiat-Shamir compilation here turns each FRI round’s verifier challenge into a hash of the transcript so far. The exercise asks for the chapter’s model, which Table 33.1 sets aside for this tier. Under that model the DFMS20-style loss for FRI is per-round, with the bound dominated by the number of FRI rounds ( for a degree bound , so at rate on a low-degree-extension (LDE) domain of size ).
- Outer-layer polynomial commitment interface: the polynomial-IOP rounds that use it are placed in the multi-round tier (Table 33.2’s multi-round FS row), while the commitment scheme itself, Merkle-FRI in the default configuration, stays in the FRI-based tier above. The polynomial-IOP layer compiles its rounds with a separate Fiat-Shamir transformation that consumes the inner-layer FRI’s output as one of its messages.
The two tiers are alternative ways for a false statement to be accepted, not two events that must both happen, so the interactive error adds: , a union bound over the polynomial-IOP check being fooled, the proximity test being fooled, and a Merkle opening being forged. A product would make a perfect proximity test erase the IOP’s own error, which is false. Chapter 34 Section 5.5 uses the same union-bound shape.
The chapter’s stipulated model then multiplies that sum once, over the compiled protocol’s total round count: . That inequality is the model’s and not DFMS20’s Corollary 13, which carries a different coefficient and an additive challenge-space term the model drops, so it is not a certified bound for Plonky3 or for any FRI pipeline. Under the model, each added round multiplies the loss factor by . Ch 33 itself sets FRI apart from this model (Table 33.1).
Exercise 3
Section titled “Exercise 3”The classical rewinder runs the prover twice with the same first message , for a nonce , and different challenges . That yields and , from which . The step that fails under quantum queries is the oracle-side fork. The rewinder needs the prover’s decisive query to in order to answer it differently on the second run. A quantum prover’s queries are in superposition, so finding that query means measuring it, and the measurement disturbs the state the second run would start from. Rewinding itself does have a quantum analogue: DFMS19’s extractor for the sigma protocol measures the response and rewinds on the measured state, with quantum computationally unique responses bounding the disturbance (Theorem 25). What has no direct quantum analogue is the classical extractor’s record-and-replay of oracle queries, which measure-and-reprogram replaces (Don et al., 2019).
Exercise 4
Section titled “Exercise 4”The exercise assumes an interactive soundness error holding against quantum dishonest provers, so the bound reads . That assumption is the premise, not a consequence of computational special soundness: the interactive prover the reduction produces is itself quantum, and DFMS19 records that in the quantum setting computational special soundness does not imply ordinary soundness (Don et al., 2019). Schnorr supplies the transcript algebra here and nothing more. At and that is , vastly larger than 1, so the bound is vacuous. A bound greater than 1 says only that the soundness error is at most a probability, which is true by definition. In that regime the bound carries no information.
For 80-bit PQ soundness: , so . is strictly greater than , so the minimum real bit width is strictly greater than , and the smallest integer (or power-of-two) that satisfies the strict inequality is 115. The toy has , so the challenge space must grow by approximately bits beyond the toy parameters. The integer form gives the same 105, which is what the block below computes. What the 115-bit width does not establish is that Schnorr is post-quantum secure at it: the compiled bound is only as good as the assumed quantum interactive error, and Schnorr’s own hardness assumption falls to Shor at any challenge width.
import mathq = 2 ** 16vacuous_bits = math.log2((2 * q + 1) ** 2 / 1013)csize_min_bits = math.ceil(math.log2((2 * q + 1) ** 2) + 80)growth = csize_min_bits - math.ceil(math.log2(1013))print(round(vacuous_bits, 2), vacuous_bits > 0)print(csize_min_bits, growth)# ==> 24.02 True# ==> 115 105