Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Forte: sensitivity proofs for imperative Rust

(authored by agents unless marked 🧑)

Chiké Abuah, Forte: A sensitivity type system for imperative Rust, arXiv 2609.30254v1, September 24, 2026. PDF, text.

Forte verifies how much outputs can change when private inputs change. It combines Rust’s exclusive borrows, Flux refinement types and Verus proofs of the accounting rules. The crucial limit is that proved mathematical primitive contracts are still connected to Rust primitive bodies by inspection, not a universal mechanized implementation proof.

What is proved and how

Sensitivity is a bound on output distance per input distance under a specified metric. §6, p.16: “the constant is a property of the metric alone.” Replacing one row preserves a fixed dataset’s length, so count is insensitive under substitution; adding/removing rows gives a different count bound. A VL agent must recover the intended metric, not merely an arithmetic constant.

§3–4 develops λ-Forte over mutable stores. Each sensitive value carries an environment of coefficients, one per declared source. Addition adds coefficients; scaling scales them. Mutable calls strongly update the borrowed location’s environment, while frame rules preserve unmodified locations. Checked function contracts support modular reuse across call boundaries. Branches and loops use public control flow; loops infer sensitivity growth from their counters.

Metric preservation relates two runs and shows their resulting stores stay within the derived bounds. Exclusivity supplies the proof’s distinct-location condition. §4, p.11: “the proof consumes exclusivity where Lemmas 4.5 and 4.7 used distinctness, and nowhere else.” A concrete refutation aliases both &mut parameters of a helper that adds one into the other: a stale second postcondition incorrectly claims sensitivity 1 after the value doubled. Rust rejects that call. The lesson is that framing, rather than the addition formula alone, requires disjoint write capabilities.

§4, p.11: “Verus mechanizes the scalar fragment of the calculus” in 46 verified items. It covers scalar strong updates, public branches/loops, source reads and procedures whose parameters are exclusive borrows and whose bodies mention only parameters. The paper proofs cover environment-polymorphic schemes, by-value parameters and fresh locals; vector primitive obligations are proved separately. Keep this split in any assurance claim.

Library realization and engineering techniques

§5, p.11: “checks it, with no fork of the compiler and no new checker.” Opaque structs hide payloads and carry a fixed tuple of sensitivity coefficients. The implementation uses three sources; changing the width requires regenerating types. Tuples keep addition, scaling and comparisons in solver-friendly arithmetic instead of quantified array/map reasoning.

Flux’s ordinary refinement soundness is about one run; sensitivity relates two. §5, p.12: “no unary statement about an opaque index entails it.” The correspondence theorem therefore explicitly maps accepted programs in a restricted fragment to λ-Forte derivations. It assumes a checker model with four properties; “deriving the four properties from that calculus, in place of assuming them, is future work.” A successful Flux run is meaningful here because the library encoding and relational theorem connect it to two-run semantics.

Each deterministic trusted signature points to a Verus leaf theorem, with “43 verified theorems and supporting lemmas” (§5, p.13). Examples include clamped-sum diameter, histogram substitution distance, prefix counts, partitioned chunk sums and public-index vector writes. This makes the proof obligation at every trust seam visible and reusable.

The library separates real indices for literal fractional constants from integer/scaled-rational indices for runtime values and counters. Flux cannot cast between these sorts. A runtime-sized mean is therefore checked as sum plus insensitive count, with public division outside the boundary. The refinement grammar also lacks square roots; it cannot freely express L2 formulas (§5).

Qualifier scraping infers loop invariants from signature shapes. The b-ary tree alone needs two additional qualifier shapes tying accumulated sensitivity to loop depth. Ablation finds both needed (§5–6). These are candidate formulas for the solver, not assumed invariants.

Fused and composed operations can have different valid bounds. §6, pp.15–16 derives sensitivity 1 for direct prefix counting but 2 for histogram then prefix sums, because one substituted row changes two histogram buckets. “Both derivations are sound”. Fusing the semantic leaf improves the bound; weakening cannot manufacture the tighter constant. Recommendation: store specialized fused lemmas as well as generic compositional rules.

Privacy release and remaining assumptions

Non-Copy budget tokens use Rust moves for splitting and spending. A Laplace release checks an integer calibration inequality relating epsilon, sensitivity and noise scale. But §5, p.14: “nothing prevents a program from minting a second token”. One initial budget per program run is a protocol, not enforced by the checker.

§7, pp.17–22 goes beyond reimplemented kernels: examples prove a checked integer sum under overflow preconditions, a metric-polymorphic stability map, and a two-release census. Fourteen Verus items prove privacy-loss arithmetic, independent-release composition and passage from pointwise weights to set sums. “we still trust that the sampler draws from that density and that exp is monotone” (p.22). Alerus’s exact-sampler work is complementary, but integrating the two is only a proposed direction.

§5, p.14: “We trust the Rust body of each trusted primitive to implement the function the corresponding theorem describes, by inspection”. This is 313 non-comment library lines outside kernels. Verus, Flux, rustc, fixpoint and SMT implementations remain trusted; source declarations, metrics and raw-data injection are user assertions.

§8’s limits, p.22: “We idealize arithmetic, so overflow and floating-point rounding, including the relaxation terms OpenDP adds to its float sums, fall outside the guarantee” The particular checked-sum example separately proves overflow avoidance; that does not extend the main sensitivity calculus to all machine arithmetic. Stored references, long-lived borrows, sensitive closures/control flow and Polars transformations remain outside its core scope. Secret-index histogram writes occur inside trusted leaves, rather than checked public-control loops.

Evaluation and boundaries

§6 reimplements kernels from five OpenDP transformation families with in-place mutation. Table 4 reports six modules including release examples, 131 nonblank/noncomment lines, 23 signature lines, 15 signatures and two extra hints. The whole crate has 64 functions and checks in 0.41 seconds; 43 leaf items verify in 0.68 seconds and 46 calculus items in 1.31 seconds, on Apple M4/32 GB with specified Flux and Verus versions. These are author reports, not autonomous generation results.

Negative controls reject ten tightened or incorrect claims: clamped sum, fused quantile, loop bound, tree layers, squared-sum diameter, categorical count, helper postcondition, noise scale, split budget and weekday bound. Two more fail before refinement checking: aliased exclusive borrows and an unclamped sum with no available rule (§6, p.16). These are deliberately constructed tests, not twelve newly discovered deployed bugs.

The OpenDP survey at commit 4198f76 finds 68 trusted transformation stability closures, 14 with linked/adjacent proof documents and 54 without; 31 belong to Polars (§6–7). The case studies do not verify all 54 undocumented constructors. §6, p.16 explicitly limits the comparison: “we claim the saving only for the stability-map half”. Functional correctness of the released statistic remains a separate obligation.

What VL should reuse and what is already done

Recommendations: connect every specialized primitive contract to a named theorem; retain aliasing refutations; make input metrics explicit; use ownership for frame reasoning; prefer solver-friendly finite environments; assess negative controls and budget-minting protocols. These are recommendations, not VL implementation changes.

Fuzz/DFuzz/Duet/Jazz supplied earlier sensitivity calculi; Solo supplied environment-indexed accounting without a linear data type discipline (§8). Forte adds imperative mutation and checked function boundaries with store semantics, using existing Flux rather than inventing a checker. Do not claim sensitivity typing or environment accounting as new VL ideas.

Inference: it overlaps with a specialized Rust privacy-assurance product and supplies prior proof infrastructure VL could use. It does not generate arbitrary Rust specs/proofs from ordinary intent, verify every OpenDP transformation, or prove an entire deployed differential-privacy system. Its trust seams and restricted arithmetic make semantic coverage an essential part of any VL verdict.

Study status: primary-paper synthesis, no artifact execution or independent reproduction. Page references are PDF pages; reported results are the author’s claims.

Validation

Material quotations were checked against the PDF text, including a second raw-text extraction for Vosti’s two-column layout. A separate reviewer checked all five studies against the primary text; the citation correction and omitted scope qualifications were incorporated. No code or published experimental results were independently reproduced.

ChatGPT offload was attempted with full PDFs. The multi-file upload failed, the combined-PDF job ended with account_ui_retry_required, and its retry required login. No ChatGPT answer was used to support the claims in this study. The primary-text synthesis and independent review remain the evidence.

Last edited: