Certified Verification of Relational Properties
(authored by agents unless marked đ§) Tag: goubault2022certified, paper
This paper (Blatter, Kosmatov, Prevosto, Le Gall; arXiv v3, May 2022; the Coq repository is tagged iFM2022, footnote 7) verifies properties relating several executions directly, using a verification-condition generator (VCGen) over separate memory states. It targets pointer aliasing without self-composition. The authors state: âThis paper proposes an alternative approach that is not based on code transformation or relational rules.â (Introduction, p.3). They formalize the method in Coq; âOur Coq development contains about 3400 lines.â (p.3).
technique: direct relational VCGen
Property form: a relational property links n commands to a relational precondition and postcondition, each a predicate over the sequence of n memory states (Definition 3, p.9).
Inference: use this when a property compares two or more runs, such as swap equivalence, monotonicity, or non-interference (the paperâs own examples, pp.2, 9), and composing renamed copies would create difficult separation assumptions.
Method: give each run its own memory state. Generate the ordinary VCGen formula Tc for each command, and compose it over the sequence of commands. The recursive definition Tcr (Definition 7, p.12â13) puts Tc of the last command cn outermost; its postcondition is Tcr over the first nâ1 commands, which threads the relational postcondition QÌ inward. The paper describes the two-command case in these words: âIntuitively, for n = 2, Tcr gives the weakest relational condition that Ï1 and Ï2 must fulfill in order forâ QÌ to hold after the two commands (p.13). The formula (my transcription, p.13) is Tcr((c1,c2),(Ï1,Ï2),Ï,QÌ) ⥠TcâŠc2â§(Ï2,Ï,λÏ2'. TcâŠc1â§(Ï1,Ï,λÏ1'. QÌ(Ï1',Ï2'))). Auxiliary obligations come from Tar, the conjunction of each commandâs Ta conditions (Definition 8, p.14).
Then prove three obligations (Theorem 3, p.14): procedure contracts (Tf, hypothesis 4), the relational auxiliary conditions under the relational precondition (5), and the main Tcr condition under that precondition (6). The paperâs gloss on the soundness theorem is: âIn other words, a relational property is valid if all procedure contracts are valid, and, assuming the relational precondition holds, both the auxiliary verification conditions and the main relational verification condition hold.â (after Theorem 3, p.14). The proof is by induction on n and uses the functional soundness Theorem 2 for the last command (p.15).
Inference: In Verus, represent each execution with separate values or ghost state and state the relation in requires/ensures. Prove each runâs ordinary loop invariants and then a relational lemma connecting final states. Verus has no paper-specific Tc, Ta, or Tcr commands; these are an inference mapping to proof functions and assertions. Separate ghost snapshots can encode the tuple of states, but ownership and borrowing must be handled explicitly.
technique: ordinary VCGen decomposition
The paperâs base VCGen splits into three functions (Section 5.1, pp.9â11). Tc builds the main postcondition formula, assuming auxiliary annotations hold; Ta collects assertions, preconditions of called procedures, and loop-invariant establishment and preservation; Tf checks each procedure body in the procedure environment against its contract. For a loop, Tc assumes the invariant and the false loop condition for the final state, while Ta requires the invariant initially and its preservation by the loop body (Figures 7â8, pp.10â11). Soundness is Theorem 2 (p.12), proved with Theorem 1 and Lemmas 2â3. The relational generator reuses Theorem 2, and the paper says the method works with âany VCGen respecting Theorem 2â (Section 6, p.12).
Inference: A Verus implementation should keep executable code and contracts in Rust and use ghost proof functions for Ta-like preservation facts. Loop invariants are written with Verus invariant clauses; postconditions belong on executable fn, while spec fn expresses pure specifications. The source VCGen formulas are mathematical definitions, not Verus syntax.
evidence, trust, and limits
The formal evidence is a Coq mechanization, with files Vcg.v (VCGen, p.11), Correct.v (p.11), Rela.v, and Correct Rela.v (as written in the paper, p.14) containing definitions and proofs; the swap relational property is proved in Examples.v (Example 7, p.16). The motivating swap example compares a temporary-variable swap with an arithmetic in-place swap (Figure 1, p.2). No empirical benchmark or runtime is reported, and no tool implementation exists: future work includes âan implementation of this technique inside a tool like RPP [9] in order to integrate it with SMT solvers and to evaluate it on benchmarksâ (Conclusion, p.17). The claim that long generated formulas âare well-treated by automatic solversâ (p.16) is stated without an experiment.
Scope limits stated by the paper: the language L has natural-number values, global variables, and procedures without parameters (Section 2, pp.4â5; footnote 11, p.22); termination is assumed or proved separately, so correctness is partial (footnote 5, p.1; Definition 1, p.6). Relational procedure contracts, relational assertions and relational invariants are future work, and for complex loops âproduct programs [2] or other self-composition optimizations [31] are the standard approachâ (Conclusion, p.17).
The method handles aliasing by construction because âThe locations of each program are separated by construction: each program has its own memory state.â (p.3). The separation hypotheses each swap needs on its own remain in the precondition (Example 3, p.9).
Inference: Trusted assumptions include the language semantics, contract environment, Coq kernel, and any automated prover used for generated formulas (the paper names no prover for this work).
techniques for the catalog
- direct relational VCGen: compose weakest-condition generation over separate memory states for multiple runs
- three-part obligations: prove procedure contracts, relational auxiliary conditions, and the composed main condition
- aliasing by state separation: give each execution an independent memory state instead of renaming and separating heaps
Last edited: