Documentation

CatCryptCore.Tactics.Invariant

Invariant Tactics #

This file provides tactics for working with invariants in relational proofs, including proving invariant preservation and extracting relation hypotheses.

Main tactics #

Heap agreement modulo location sets #

Implementation Notes #

ssprove_invariant #

The ssprove_invariant tactic tries the following strategies in order:

  1. trueInv_IsInvariant - trivial invariant that always holds
  2. heap_agree_IsInvariant - heap agreement on specified locations
  3. IsInvariant_inv_conj - conjunction of invariant with semi-invariant
  4. andInv_IsInvariant - conjunction of two invariants
  5. User-provided assumptions

ssprove_rem_rel #

The ssprove_rem_rel tactic extracts information from location couplings:

When both rem_lhs l v and syncsAt l hold, we can derive rem_rhs l v.

References #

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
Instances For

    Preservation rules for heap_agree_except #

    theorem CatCrypt.Relational.heap_agree_except_sample (L : Finset ) (α : Type u_1) [Fintype α] [Nonempty α] :
    rHoare (heap_agree_except L) (Core.SPComp.sample α) (Core.SPComp.sample α) fun (a₁ : α) (h₁ : Core.Heap) (a₂ : α) (h₂ : Core.Heap) => heap_agree_except L h₁ h₂ a₁ = a₂

    Sampling preserves heap_agree_except (sampling doesn't touch the heap).

    theorem CatCrypt.Relational.heap_agree_except_get (L : Finset ) ( : Core.Location) (hℓ : .idL) :
    rHoare (heap_agree_except L) (Core.SPComp.get ) (Core.SPComp.get ) fun (a₁ : .ty) (h₁ : Core.Heap) (a₂ : .ty) (h₂ : Core.Heap) => heap_agree_except L h₁ h₂ a₁ = a₂

    Getting from a location not in L gives equal values.

    theorem CatCrypt.Relational.heap_agree_except_set_in (L : Finset ) ( : Core.Location) (hℓ : .id L) (v₁ v₂ : .ty) :
    rHoare (heap_agree_except L) (Core.SPComp.set v₁) (Core.SPComp.set v₂) fun (x : Unit) (h₁ : Core.Heap) (x_1 : Unit) (h₂ : Core.Heap) => heap_agree_except L h₁ h₂

    Setting a location IN L (private state) with arbitrary values preserves the invariant.

    theorem CatCrypt.Relational.heap_agree_except_set_same (L : Finset ) ( : Core.Location) (v : .ty) :
    rHoare (heap_agree_except L) (Core.SPComp.set v) (Core.SPComp.set v) fun (x : Unit) (h₁ : Core.Heap) (x_1 : Unit) (h₂ : Core.Heap) => heap_agree_except L h₁ h₂

    Setting the same value on both sides preserves the invariant (for any location).

    theorem CatCrypt.Relational.heap_agree_except_get_any (L : Finset ) ( : Core.Location) :
    rHoare (heap_agree_except L) (Core.SPComp.get ) (Core.SPComp.get ) fun (x : .ty) (h₁ : Core.Heap) (x_1 : .ty) (h₂ : Core.Heap) => heap_agree_except L h₁ h₂

    Getting from any location preserves the invariant.

    theorem CatCrypt.Relational.heap_agree_except_ret {α : Type u_1} (L : Finset ) (a : α) :
    rHoare (heap_agree_except L) (pure a) (pure a) fun (x : α) (h₁ : Core.Heap) (x_1 : α) (h₂ : Core.Heap) => heap_agree_except L h₁ h₂

    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:

    1. trueInv_IsInvariant - the trivial invariant
    2. heap_agree_IsInvariant - heap agreement invariants
    3. IsInvariant_inv_conj - conjunction with semi-invariants (recursive)
    4. andInv_IsInvariant - conjunction of invariants
    5. Type class inference
    6. 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
    Instances For

      ssprove_invariant! is a more aggressive version that uses decide for decidable goals.

      Equations
      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
        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 v and syncsAt l, derive h₀.get l = h₁.get l and h₁.get l = v
          • From rem_rhs l v and syncsAt l, derive h₀.get l = h₁.get l and h₀.get l = v
          • From rem_lhs l v alone, derive h₀.get l = v
          • From rem_rhs l v alone, derive h₁.get l = v
          • From syncsAt l alone, derive h₀.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
          Instances For

            ssprove_rem_rel_intro introduces and names the extracted relations.

            This variant names the derived hypotheses for later use.

            Equations
            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:

              1. Writes that "undo" previous changes
              2. Writes that establish a synchronized state
              3. 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
              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
                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
                    Instances For

                      ssprove_extract_sync l extracts synchronization information for location l.

                      Equations
                      Instances For

                        Configuration #

                        Configuration for invariant tactics

                        • autoLocality : Bool

                          Whether to automatically apply locality

                        • splitAnd : Bool

                          Whether to split conjunction invariants

                        • maxDepth :

                          Maximum depth for recursive tactics

                        • unfoldDefs : Bool

                          Whether to unfold definitions aggressively

                        Instances For

                          Simp Lemmas for Invariant Reasoning #