This repository contains the Rocq formalization for two related papers:
- "Lawyer: Modular Obligations-Based Liveness Reasoning in Higher-Order Impredicative Concurrent Separation Logic", OOPSLA'26 - a program logic for proving (un)fair termination of concurrent higher-order programs.
- "Verifying wait-freedom for concurrent higher-order programs", ECOOP'26 - extends Lawyer to establish wait-freedom of concurrent higher-order programs.
The wait-freedom development is built as an extension of the Lawyer project.
Both rely on Trillium framework; however, the wait-freedom extension requires a fork of Trillium (namely, its' trillium_wfree branch) with a generalized adequacy theorem and weakest precondition; the Lawyer development still works with that fork.
This document describes both developments together, since most of the Rocq implementation is shared.
There are also artifacts available for each of the papers:
fairness/- general definitions of traces and fairness, as well as various utility filesheap_lang/- definition and reasoning rules for the programming language being usedlawyer/examples/- case studies for Lawyerobligations/- implementation of the obligations-based reasoningnonblocking/- wait-freedom extension of Lawyer. Most of it resides in this folder directly, except for:tokens/- adaptation to the restricted wait-freedomlogrel/- definitions and theorems about logical relationsexamples/- case studies on wait-freedom
check/- collection of the end resultscheck.v- end results for Lawyercheck_wfree.v- end results for the wait-freedom extension
First, install opam according to the instructions for your operating system. We used the version 2.1.2.
Then clone the sources into lawyer folder.
Then execute the following.
# create a new opam environment
opam switch create lawyer-env 5.4.0
# switch into the new environment
eval $(opam env --switch=lawyer-env)
# set up repository for Rocq packages
opam repo add coq-released https://coq.inria.fr/opam/released
# set up repository with the Trillium extension
opam repo add logsem-opam https://github.com/logsem/opam
# move into the Lawyer directory
cd lawyer/
# install all dependencies of Lawyer
opam install . --deps-only
# build Lawyer; adjust the number of jobs as needed
make -j 5
-
Build the project as described above.
-
Open
check/check.vfor Lawyer results, orcheck/check_wfree.vfor wait-freedom results, with an editor of choice. In each file, the definitionresultsis a tuple collecting the proofs of progress properties of all corresponding case studies. -
Step through every line of this file.
-
The last
Print Assumptionsline prints all the axioms that the listed theorems rely on. Processing it might take a while.The used axioms will be listed at the bottom of the output. Check that only the following axioms are used:
RelationalChoice.relational_choiceClassicalUniqueChoice.dependent_unique_choiceClassical_Prop.classicclassical.PropExtclassical.FunExtclassical.Choice
-
No-Obligations Model (Fig. 1) It can be viewed simply as a subset of the Obligations Model with restricted state and transitions. Namely, No-Obligations Model corresponds to choosing Level to be the empty set (see Appendix C). Therefore, we do not provide a separate Rocq definition of No-Obligations Model.
-
Example programs Each example program from Section 2.1 has a subfolder X in
lawyer/examples/. Inside of it, theX.vfile contains the verification of the program, andX_adequacy.vproves the meta-level property about the execution of that program.- Statically-known bound (Fig. 2):
const_term/subfolder. The proved property is execution time being linear wrt. the value of N argument. - Runtime-determined Bound (Fig. 3):
rt_bound/subfolder. The proved property is termination under fair scheduler (since internally it uses a blockingnondetfunction). - Delaying example (Fig. 4):
lf_counter/subfolder. The proved property is termination under any scheduler.
- Statically-known bound (Fig. 2):
- Definition of Obligations Model (Fig. 5):
lawyer/obligations/obligations_model.v- OM parameters:
ObligationsParamstypeclass - OM state:
ProgressStaterecord. Note that "fuel" component of the state is named "ps_cps", and the "barrel" resource in logic is called "cp". Well-formedness condition is defined inlawyer/obligations/obligations_wf.v, recordom_st_wf. - OM transitions: definition
om_trans - OM as a Trillium model: definition
ObligationsModel
- OM parameters:
- Example programs
Similarly to the above, the results are located in the subfolders of
lawyer/examples/. The property we prove for these examples is termination under fair scheduler.- Blocking example (Fig. 6):
nondet/subfolder, see specificallynondet/nondet_adequacy.v, theoremnondet_pre_allocated_termination. - Fork example (Fig. 7):
nondet/subfolder.
- Blocking example (Fig. 6):
-
General trace-related definitions: defined in the Trillium fork; see the
README.mdin it -
Operational semantics of our language (Fig. 8):
heap_lang/lang.v -
Refinement relation (definitions 1, 2 and 3). Our implementation of refinement proceeds slightly differently compared to the paper presentation.
- The state relation in paper (Definition 1) consists of two parts: sameThreads and liveThreads. Contrary, the Rocq version (
lawyer/obligations/obligations_adequacy.v, definitionobls_st_rel) only includes the latter. Indeed, sameThreads is not explicitly used for proving termination, which is the main purpose of the refinement we establish. However, sameThreads is used to establish the refinement (lawyer/obligations/obligations_adequacy.v, proof of lemmano_obls_live_tids) as a part of proving AlwaysHolds. Therefore, we keep this condition as a part of trace interpretation (seelawyer/obligations/obligations_em.v, definitionthreads_own_obls). - The finite trace refinement in paper (Definition 2) is defined by placing restrictions on every transition in both traces.
Contrary, the Rocq implementation proceeds in two steps.
- We start by defining the notion of "valid evolution step" (
lawyer/obligations/obligations_em.v, definitionobls_valid_evolution_step) that intuitively captures the "lock-step" relation between physical and model steps. - Then, we show that the proof of weakest precondition implies intensional refinement (see Trillium paper for definition) of the specific relation on pairs of physical and model traces. Namely, the last transitions of such traces must form a valid evolution step.
- Then, we show that this intensional refinement in fact implies the refinement from Definition 3 (minus the sameThreads part discussed above).
- We start by defining the notion of "valid evolution step" (
See
heap_lang/simulation_adequacy.v, comment inside ofstrong_simulation_adequacy_traces_multiplelemma that discusses points 2 and 3 above. - The state relation in paper (Definition 1) consists of two parts: sameThreads and liveThreads. Contrary, the Rocq version (
-
Relative image-finiteness of refinement relation (Lemma 2.1):
lawyer/obligations/obligations_adequacy.v, lemmaobls_sim_rel_FB. -
General trace fairness (definition 4):
fairness/fairness.v, definitionfair_by'. Also see the lemmafair_by'_weakly_fairin the same file for equivalence with more common notion of weak fairness. Then, notion of fair execution is given byfair_ex. "Obligations-fair" traces are defined inlawyer/obligations/obligations_model.v, definitionobls_trace_fair. -
Transporting of execution fairness to the model trace (Lemma 2.2):
lawyer/obligations/obligations_adequacy.v, lemmaexec_om_fairness_preserved -
Termination of obligations-fair OM traces (Lemma 2.3):
lawyer/obligations/obls_termination.v, theoremobls_fair_trace_terminate
- Verification of
nondetexample:lawyer/examples/nondet/nondet.v - Definitions of OM resources (Fig. 9), OU (along with its iterated version) and related lemmas (Fig. 10):
lawyer/obligations/obligations_resources.v - Two-step program logic and model updates:
lawyer/program_logic.v. In particular, the rule trillium-step-nval-simpl corresponds to the lemmasswp_MU_wp. - sswp and rules for it:
lawyer/program_logic.v(adapted from Fairneris project):heap_lang/sswp_logic.v
The case study is located in lawyer/examples/ticketlock/.
Code for ticketlock implementation and top-level program can be found inn ticketlock.v and client.v correspondingly.
The final result stating the fair termination of the closed program is located in closed_adequacy.v.
- BOU definition and related lemmas (Fig. 14): see
lawyer/obligations/obligations_resources.v. - The rule MU-OM-nofork:
lawyer/obligations/obligations_logic.v, lemmaBOU_AMU. Throughout the development, we use theAMUmodality, which can be thought of as simplyMU.
- Sequential fair lock specification (Fig. 15):
lawyer/examples/ticketlock/releasing_lock.v, recordReleasingFairLock.
- Proof that ticketlock satisfies the sequential lock specification for any choice of spec's parameters satisfying a number of restrictions:
lawyer/examples/ticketlock/ticketlock_releasing.v, definitionRFL_FL_TL'. - Verification of ticketlock implementation against the logically atomic specification:
lawyer/examples/ticketlock/ticketlock.v, see in particularTL_FL. - Derivation of the sequential specification for a wrapper over logically atomic implementation:
lawyer/examples/ticketlock/releasing_lock.v, see in particularRFL_FL.
Verification of the top-level program on top of the sequential lock specification: lawyer/examples/ticketlock/client.v, theorem client_spec.
- Well-formedness of obligations states:
lawyer/obligations/obligations_wf.v, recordom_st_wf. - OM starting state (definition 6):
lawyer/obligations/obligations_em.v, definitioninit_om_state.
- Full adequacy theorem of Lawyer:
lawyer/obligations/obligations_adequacy.v, lemmaobls_terminates_impl_multiple. - Specialized adequacy theorem (Theorem B.1): lemma
obls_terminates_impl_paper.
- Termination of all OM traces when Level is the empty set (Corollary C.1):
lawyer/obligations/unfair_termination.v, lemmaalways_term_wo_lvls. - Termination within constant time when Level is the empty set and Degree is singleton (Corollary C.2):
lawyer/obligations/unfair_termination.v, lemmaalways_terminates_within_bound.
Operational semantics of our language (Fig. 8 and 16): heap_lang/lang.v.
The mechanization mentions prophecy variables, but they are never used throughout the development.
Full form of Lawyer rules (Fig. 17) can be found in lawyer/program_logic.v (rules connecting wp with sswp and MU) and lawyer/obligations/obligations_logic.v (rules connecting MU with BOU).
- "Total" atomic updates (Definition 7):
lawyer/examples/ticketlock/obls_atomic.v, definitionTAU. - "Total" logically atomic triples:
lawyer/examples/ticketlock/obls_atomic.v, definitionsTLATandTLAT_RRfor different kinds of "wait clauses" used in underlyingTAU - Logically atomic fair lock specification (Fig. 18):
lawyer/examples/ticketlock/fair_lock.v, recordFairLock.
Verification of the top-level program on top of the sequential lock specification: lawyer/examples/ticketlock/client.v, theorem client_spec.
- Two implementations of parallel composition operator and rules for them:
lawyer/examples/par.v, definitionsparandpar_sym, along withpar_specandpar_sym_speclemmas. Moreover, the case study inlawyer/examples/nondet/(nondet_par.v, nondet_par_adequacy.v)is a version of nondet implementation that uses parallel composition. - A program consisting of two threads that increment the shared counter in turns, up to a certain bound, waiting for each others' turn:
lawyer/examples/eo_fin/(eo_fin.v, eo_fin_adequacy.v) - Program illustrating the concurrent use of two locks:
lawyer/examples/ticketlock/(two_locks, two_locks_adequacy).v
- General definitions and lemmas about traces:
trillium/traces/*.v
- Operational semantics of our language (Figure 3):
heap_lang/lang.v - Calls and returns (Definition 1):
lawyer/nonblocking/trace_context.v, definitionscall_atandreturn_at
Note that the former explictly mentions the call argument, whereas the definition in the paper existentially quantifies over it. - Eventual return of calls (Definition 2):
lawyer/nonblocking/wfree_traces.v, definitionalways_returns_strong
Note that it is additionally parameterized with:- stuckness bit (thus covering the possibly-stuck definition)
- predicate on the call argument. This parameter is always set to an always true predicate and thus can be ignored.
- Call fairness ("schedUntilRet"):
lawyer/nonblocking/wfree_traces.v, definitionfair_call_strong - Client validity:
lawyer/nonblocking/logrel/valid_client.v, definitionvalid_client - Wait-freedom (Definition 3):
lawyer/nonblocking/wfree_traces.v, definitionwait_free_strong
Again, it is parameterized by a stuckness bit and an unused predicate on call arguments.
- Lawyer specification of wait-freedom (Definition 4):
lawyer/nonblocking/om_wfree_inst.v, recordWaitFreeSpec
Note the following:- This specification explicitly mentions an invariant that should be established from the starting configuration and which is assumed by both Hoare triples.
In contrast, Definition 4 does not mention a module invariant explicitly and rather allows to take a viewshift from starting configuration before proving the Hoare triples.
However, viewshifts allow establishing invariants, and the proofs in the paper (Sec. 4) proceed exactly by establishing a module invariant.
See Iris Lecture Notes, Sec 4.3 "Abstract Data Types" for the discussion on these specification styles. - Parameter
Pcan be ignored - The amount of fuel consumed by the operation is determined by the fuel function
wfs_F, mentioned in Sec. 5.1 - We prohibit the wait-free operation from forking using the forking bit. For that, we use our variation of Trillium weakest precondition defined in
trillium/bi/weakestpre.v.
- This specification explicitly mentions an invariant that should be established from the starting configuration and which is assumed by both Hoare triples.
- Wait-freedom adequacy theorem (Theorem 5):
lawyer/nonblocking/wfree_adequacy.v, theoremwfree_is_wait_free
Again, it is parameterized by a stuckness bit, and the unused predicate on call arguments is set to be always true.
It also explicitly requires the value representing the wait-free operation to be a lambda-expression.
We do not mechanize the proofs presented in this section, as they are only used for explaining the Iris logic and not for establishing wait-freedom of incr (which is done in Section 4).
The specifications and proofs are standard and explained in e.g., Iris Lecture Notes.
- Verification of the wait-freedom specification for the counter example:
lawyer/nonblocking/examples/counter/counter.v, definitioncounter_WF_spec
Note that we use the two-step logic of Lawyer to verify the Lawyer triples.
In this logic, verifying every step amounts to applying two rules: one for the physical execution step and one for the model step.
The former rules (e.g.wp_faa) are listed inheap_lang/sswp_logic.v, whereas the latter are implicitly applied by tactics such asMU_by_burn_cp. - Wait-freedom of counter example:
lawyer/nonblocking/examples/counter/counter_adequacy.v - The degree parameter of fuel is always set to the lowest degree
d0of our Obligations Model instantiation: seewfs_specinWaitFreeSpeclocated inlawyer/nonblocking/om_wfree_inst.v - The fraction parameter of phase is always set to
1/2: see the Hoare triple inwait_free_method_genlocated inlawyer/nonblocking/om_wfree_inst.v NoInfExecLawyer triple for wait-freedom:lawyer/nonblocking/om_wfree_inst.v, definitionwait_free_method_gen
Ignore thePandQparameters.PresInvtriple for wait-freedom: defined directly as value interpretation (see Sec. 6.2)
-
Stuckness variations of definitions related to wait-freedom (Definitions 6 and those mentioned below it): they are specific cases of definitions used for Section 2.1 with stuckness bit set to
MaybeStuck. -
Adequacy theorem for possibly-stuck wait-freedom: instantiation of
lawyer/nonblocking/wfree_adequacy.v, theoremwfree_is_wait_freewith stuckness bit set toMaybeStuck. -
Modular verification of
list_map:lawyer/nonblocking/examples/list_map/list_map.vlist_mapimplementation (Figure 6a):hl_list_map_cur.- Modular proof of specification:
hlm_WF_fix_spec_unsafe. Note that we verify wait-freedom for eta-expandedhl_list_map_cur fdue to the lambda-expression restriction (mentioned above).
-
Possibly-stuck wait-fredom of
list_map (incr l):lawyer/nonblocking/examples/list_map/list_map_adequacy.v. -
Fuel function:
wfs_Fcomponent ofWaitFreeSpec.
Note that throughout the restricted wait-freedom development we use multisets of operations instead of lists.
-
Implementation of the queue algorithm (Figure 7) in our language is scattered across multiple files in
lawyer/nonblocking/examples/queue:dequeuer/dequeue.v, definitiondequeuedequeuer/read_head_dequeuer.v, definitionread_head_dequeuerdequeuer/dequeuer_thread.v, definitiondequeuer_threadenqueuer/enqueue.v, definitionenqueueenqueuer/read_head.v, definitionread_head_enqueuerenqueuer/enqueuer_thread.v, definitionenqueuer_thread
-
Restricted wait-freedom (Definition 7):
lawyer/nonblocking/wfree_traces.v, definitionwait_free_restr. -
Exclusion of forks:
lawyer/nonblocking/logrel/valid_client.v, definitionno_forks. -
Specification of restricted wait-freedom (Definition 8):
lawyer/nonblocking/tokens/om_wfree_inst_tokens.v, definitionWaitFreeSpecToken. -
Definition and lemmas about tokens resource algebra:
lawyer/nonblocking/tokens/tokens_ra.v -
Adequacy theorem for restricted wait-freedom (Theorem 9):
lawyer/nonblocking/tokens/wfree_adequacy_tokens.v, theoremwfree_token_is_wait_free_restr. -
Restricted wait-freedom of the queue algorithm:
lawyer/nonblocking/examples/queue/simple_queue_adequacy.v
-
Reduction to proving termination: it is scattered across multiple lemmas used to prove
wfree_is_wait_freementioned above.
In particular, see the lemmas inWFAdequacysection which fixes the parameters of an infinite call. -
Definition of progress resource:
trillium/trillium/program_logic/adequacy_cond.v, recordProgressResource. Note that it is additionally parameterized with stuckness and forking bits (and list of postconditions mentioned in the appendix). -
Conditional adequacy theorem of Trillium (Theorem 10):
trillium/trillium/program_logic/simulation_adequacy_em_cond.v,theorem
PR_strong_simulation_adequacy_traces_multiple. -
Refinement relation for wait-freedom:
lawyer/nonblocking/wfree_adequacy_lib.v, definitionobls_sim_rel_wfree
- Expression relation:
lawyer/nonblocking/logrel/logrel.v, definitioninterp_expr - Value relation (Definition 11):
lawyer/nonblocking/logrel/logrel.v, definitioninterp - Fundamental theorem (Theorem 12):
lawyer/nonblocking/logrel/fundamental.v, theoremfundamental - Robust safety of the wait-free operation (Theorem 13):
lawyer/nonblocking/wfree_adequacy.v, definitioninit_wptp_wfree
- Definition of progress resource for wait-fredom:
lawyer/nonblocking/pr_wfree.v, definitionpr_pr_wfree. - Definition of the
infCallPrefixpredicate:lawyer/nonblocking/wfree_traces.v, definitionfits_inf_call. - Proof of the progress resource laws:
lawyer/nonblocking/pr_wfree.v, definitionPR_wfree.
- "Wait-freedom" of a simple sequential program:
lawyer/nonblocking/examples/mk_ref/(mk_ref, mk_ref_adequacy).v - Variations of above definitions and theorems for restricted wait-freedom:
lawyer/nonblocking/tokens/*.v.
In particular:- Extension of trace intepretation for physical WP that keeps track of method tokens:
pwp_ext.v - Logical relation and fundamental theorem for token-based specifications:
logrel_tok.vandfundamental_tok.v - Lifting of a stronger specification to one required by token-based FTLR:
op_spec_lifting.v, lemmalift_spec - Progress resource for restricted wait-freedom:
pr_wfree_tokens.v
- Extension of trace intepretation for physical WP that keeps track of method tokens: