Invariant Tactics #
This file provides tactics for working with invariants in relational proofs, including proving invariant preservation and extracting relation hypotheses.
Main tactics #
ssprove_invariant- prove IsInvariant goals using common patternsssprove_invariant_step- discharge per-operation invariant preservation goalsssprove_rem_rel- extract hypotheses from remembered/synchronized valuesssprove_restore- restore invariant after writes
Heap agreement modulo location sets #
heap_agree_except- heaps agree except on a set of locations (useful for proving that operations on private state don't affect the invariant)- Preservation rules for sample, get, set operations
Implementation Notes #
ssprove_invariant #
The ssprove_invariant tactic tries the following strategies in order:
trueInv_IsInvariant- trivial invariant that always holdsheap_agree_IsInvariant- heap agreement on specified locationsIsInvariant_inv_conj- conjunction of invariant with semi-invariantandInv_IsInvariant- conjunction of two invariants- User-provided assumptions
ssprove_rem_rel #
The ssprove_rem_rel tactic extracts information from location couplings:
rem_lhs l v- the left heap has value v at location lrem_rhs l v- the right heap has value v at location lsyncsAt l- both heaps have the same value at location l
When both rem_lhs l v and syncsAt l hold, we can derive rem_rhs l v.
References #
- SSProve: theories/Crypt/package/pkg_user_util.v
- SSProve: theories/Crypt/package/pkg_invariants.v
- EasyCrypt:
auto/sp/wpfor invariant preservation
Heap Agreement Modulo Locations #
These definitions and lemmas support proving that operations on private state don't break an invariant on shared state. This is the key pattern for crypto proofs where packages have disjoint state.
Heap equivalence modulo a set of location IDs. Two heaps agree except possibly at locations in L.
This is the "frame" invariant: L represents the "private" locations that may differ, and everything else must be equal.
Equations
- CatCrypt.Relational.heap_agree_except L h₁ h₂ = ∀ (ℓ : CatCrypt.Core.Location), ℓ.id ∉ L → h₁.get ℓ = h₂.get ℓ
Instances For
Preservation rules for heap_agree_except #
Sampling preserves heap_agree_except (sampling doesn't touch the heap).
Getting from a location not in L gives equal values.
Setting a location IN L (private state) with arbitrary values preserves the invariant.
Setting the same value on both sides preserves the invariant (for any location).
Getting from any location preserves the invariant.
Pure/return preserves the invariant.
ssprove_invariant Tactic #
ssprove_invariant is a tactic for proving IsInvariant goals.
The tactic attempts to prove that a predicate is a valid invariant by trying:
trueInv_IsInvariant- the trivial invariantheap_agree_IsInvariant- heap agreement invariantsIsInvariant_inv_conj- conjunction with semi-invariants (recursive)andInv_IsInvariant- conjunction of invariants- Type class inference
- Direct assumptions
Example:
-- Proving that trueInv is an invariant
example : IsInvariant L₀ L₁ trueInv := by ssprove_invariant
-- Proving that heap_agree is an invariant
example : IsInvariant L L (heap_agree L) := by ssprove_invariant
-- Proving conjunction invariants
example [IsInvariant L₀ L₁ inv] [SemiInvariant L₀ L₁ sinv] :
IsInvariant L₀ L₁ (inv ⋊ sinv) := by ssprove_invariant
Equations
- CatCrypt.Tactics.tacticSsprove_invariant = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_invariant 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_invariant" false)
Instances For
ssprove_invariant! is a more aggressive version that uses decide for decidable goals.
Equations
- CatCrypt.Tactics.tacticSsprove_invariant! = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_invariant! 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_invariant!" false)
Instances For
ssprove_invariant_step discharges per-operation invariant preservation goals
for heap_agree_except.
This tactic tries all preservation rules for heap_agree_except:
- Sample (always preserves)
- Get (always preserves)
- Set on private location (arbitrary values)
- Set on shared location (same value)
- Sync and ret rules
Example:
-- Given goal: rHoare (heap_agree_except L) (SPComp.sample α) (SPComp.sample α) Ψ
ssprove_invariant_step
Equations
- CatCrypt.Tactics.tacticSsprove_invariant_step = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_invariant_step 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_invariant_step" false)
Instances For
ssprove_rem_rel Tactic #
ssprove_rem_rel extracts relation hypotheses from remembered values and syncs.
Given hypotheses about rem_lhs, rem_rhs, and syncsAt, this tactic
derives additional hypotheses about the relationship between heap values.
Key derivations:
- From
rem_lhs l vandsyncsAt l, deriveh₀.get l = h₁.get landh₁.get l = v - From
rem_rhs l vandsyncsAt l, deriveh₀.get l = h₁.get landh₀.get l = v - From
rem_lhs l valone, deriveh₀.get l = v - From
rem_rhs l valone, deriveh₁.get l = v - From
syncsAt lalone, deriveh₀.get l = h₁.get l
Example:
example (hrem : rem_lhs l v h₀ h₁) (hsync : syncsAt l h₀ h₁) : h₁.get l = v := by
ssprove_rem_rel
Equations
- CatCrypt.Tactics.tacticSsprove_rem_rel = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_rem_rel 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_rem_rel" false)
Instances For
ssprove_rem_rel_intro introduces and names the extracted relations.
This variant names the derived hypotheses for later use.
Equations
- CatCrypt.Tactics.tacticSsprove_rem_rel_intro = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_rem_rel_intro 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_rem_rel_intro" false)
Instances For
ssprove_restore Tactic #
ssprove_restore is a tactic for restoring an invariant after writes.
After a sequence of writes that may have temporarily broken the invariant, this tactic attempts to show that the final state satisfies the invariant.
Common patterns:
- Writes that "undo" previous changes
- Writes that establish a synchronized state
- Combining partial invariants
Example:
-- After setting the same value on both sides, syncsAt is restored
example : syncsAt l (h₀.set l v) (h₁.set l v) := by ssprove_restore
-- After writes that maintain invariant structure
example (hinv : inv h₀ h₁) : inv (h₀.set l v) (h₁.set l v) := by
ssprove_restore
Equations
- CatCrypt.Tactics.tacticSsprove_restore = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_restore 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_restore" false)
Instances For
ssprove_invariant_intro Tactic #
ssprove_invariant_intro introduces invariant hypotheses into context.
This is useful at the start of a relational proof to set up the invariant assumptions. It introduces the heap pair and the invariant hypothesis.
Example:
theorem example : rHoare inv c₁ c₂ post := by
ssprove_invariant_intro
-- Now have: h₀ h₁ : Heap, hinv : inv h₀ h₁
Equations
- CatCrypt.Tactics.tacticSsprove_invariant_intro = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_invariant_intro 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_invariant_intro" false)
Instances For
ssprove_invariant_intro_named h₀ h₁ hinv introduces with specific names.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Helper Tactics #
ssprove_split_inv splits a conjunction invariant into its components.
Equations
- CatCrypt.Tactics.tacticSsprove_split_inv = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_split_inv 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_split_inv" false)
Instances For
ssprove_extract_sync l extracts synchronization information for location l.
Equations
- CatCrypt.Tactics.tacticSsprove_extract_sync = Lean.ParserDescr.node `CatCrypt.Tactics.tacticSsprove_extract_sync 1024 (Lean.ParserDescr.nonReservedSymbol "ssprove_extract_sync" false)