Proof-Oriented Programming in F*

Proof-oriented Programming in F*
How to customize F* to your own program logic
Aseem Rastogi
Microsoft Research
(Joint work with my collaborators: https://project-everest.github.io/people/)
Talk outline
F* overview
Introduction to F* by examples
Indexed effects in F* (a.k.a. customize F* for your own program logic)
What is F*
https://www.fstar-lang.org
A functional programming language
Like OCaml, F#, Haskell
F* programs can be compiled to OCaml and F# by-default*
 
Expressive type system based on dependent type
theory (like proof assistants Coq, Lean, Agda, Idris, …)
 
SMT-based semi-automation
(like program verifiers Dafny, Why3, …)
 
Meta-programming and tactics for interactive proofs
(like Coq, Lean, Isabelle, …)
A first example
type
 list (a:Type) =
  | Nil  : list a
  | Cons : a -> list a -> list a
//[1; 2]
Cons 1 (Cons 2 Nil)
 
let
 
rec
 length (l:list a) =
  
match
 l 
with
  | [] -> 0
  | _::tl -> 1 + length tl
//append [1] [2] = [1; 2]
let
 
rec
 append (l1 l2:list a) = …
 
let
 
rec
 length_append (l1 l2:list a)
  : 
Lemma
 (
ensures
 length (append l1 l2) = length l1 + length l2)
  = 
match
 l1 
with
     | [] -> ()
     | _::tl -> length_append tl l2
Behind the scenes
F* Landscape
Embedded
domain-
specific
languages
Interfacing
with existing
toolchains
Logical
foundations
of programs
and proofs
F* and friends
EverParse
HACL*
Vale
EverCrypt
QUIC
Veritas
mitls …
More than 600,000 lines of F*
Under Continuous Integration
Built several times a day
Proofs for Billions of Unsuspecting Users
High-value domains:
Fintech, verifiable
computing, …
 
Verita
s
Wysteria
Automated parsing
untrusted data with
proofs
in Hyper-V/VMSwitch
Verified
cryptography in
the Linux kernel
Quic transport,
MSQuic in Windows,
Verified crypto in
Firefox, mbedTLS,
Signal in Wasm,
Wireguard, …
Verified Merkle
trees for Enterprise
blockchains
DICE
An upcoming TCG
standard for boot
firmware (e.g. in IoT)
Basic types, functions as first-class values, lambdas
type 
empty =
type 
unit = ()
type 
bool = true | false
let
 incr (x:int) : int = x + 1
let
 apply_twice (f:a -> a) (x:a) = f (f x)
let
 add_2 (x:int) : int = apply_twice incr x
let
 add_4 (x:int) : int = apply_twice (fun x -> x + 2) x  
//lambdas
Inductive types, pattern matching, recursion
type
 list (a:Type) =
  | Nil  : list a
  | Cons : a -> list a -> list a
//[1; 2]
Cons 1 (Cons 2 Nil)
let
 
rec
 map (f:a -> b) (l:list a)
  : list b
  = 
match
 l 
with
    | [] -> []
    | hd::tl -> f hd :: map f tl
Semantic termination checking
let
 
rec
 map (f:a -> b) (l:list a)
  : list b
  = 
match
 l 
with
    | [] -> []
    | hd::tl -> f hd :: map f tl
Semantic termination checking
Based on well-founded ordering ( 
<<
 )
-
a:nat << b:nat
 if 
a < b
-
Inductive subterm ordering
-
hd << Cons hd tl
  and  
tl << Cons hd tl
-
User-defined well-founded relations
-
Primitive support for lexicographic ordering
 
let
 
rec
 ackermann (m n : nat)
  : nat (decreases %[m;n])
  = if m=0 then n+1
    else if n=0 then ackermann (m-1) 1
    else ackermann (m-1) (ackermann m (n-1))
Refinement types
 
type 
nat = x:int{x >= 0}
type 
pos = x:int{x > 0}
 
type 
monotonic = f:int -> int{
  forall x y. (x <= y) 
=> (f x <= f y)
}
 
//coercive
let 
f (x:int) : nat =
  
if
 x >= 0 
then
 x
  
else
 0
 
x:t{phi}
where  
x
  may occur free in  
phi
Intuition: values of type  
t
  that satisfy  
phi
Dependent function types
let 
incr (x:int) : y:int{y > x} = x + 1
let rec
 sum (x:nat) : y:nat{y >= x} =
  
if
 x = 0 
then
 0
  
else
 x + sum (x-1)
 
//writing specifications using dependent types
let
 
rec
 length_append (l1 l2:list a)
  : 
Lemma
 (
ensures
 length (append l1 l2) = length l1 + length l2)
  = 
match
 l1 
with
     | [] -> ()
     | _::tl -> length_append tl l2
Proofs by Induction
//writing specifications using dependent types
let
 
rec
 length_append (l1 l2:list a)
  : 
Lemma
 (
ensures
 length (append l1 l2) = length l1 + length l2)
  = 
match
 l1 
with
     | [] -> ()
     | _::tl -> length_append tl l2  
//invoke Induction Hypothesis
 
Proof by induction on list l1:
 
Base case, l1 = []
  L.H.S. = length (append [] l2) = length l2
  R.H.S. = length [] + length l2 = length l2
 
Inductive case: l1 = hd::tl       Induction Hypothesis: length (append tl l2) = length tl + length l2
  L.H.S. = length (append hd::tl l2) = length (hd::append tl l2) = 1+length (append tl l2)  //apply I.H. at this step
            = 1+length tl+length l2 = length l1+length l2 = R.H.S.
Effectful programming and proving
 
So far, we have seen side-effects free, terminating functions o
f type  
a -> b
 
What about programming and proving with effects?
State, exception, I/O, non-determinism, …
 
 
Indexed effects: a user-extensible effect system in F*
 
Based on modeling effects using monads (Wadler, Moggi, …)
 
 
 
Computation types
In general functions have types:    x:
a -> M b is
Type  
(M b is)
  is called a computation type
M
 is an effect label, upper-bound on the effect of the function
Effects are arranged in an ordering
is
  are the effect indices, may encode effect-specific program logic
Primitive effects 
Pure
 and 
Div
 
Pure a pre post 
where   
pre : prop  
and     
post : a -> prop
 
    A side-effect free computation that if called when 
pre
 holds,
    terminates, and returns a result of type 
a
 s.t. 
post a
 holds
 
Div a pre post    
Similar, but the computation may diverge
 
 
Tot a =def= Pure a True (fun _ -> True)
 
a -> b =def= a -> Tot b
 
a -> 
Lemma
 pre post =def= a -> Pure unit pre (fun _ -> post)
Modeling effects using monads
 
Choose a representation for effectful functions
Define two combinators that obey monadic laws:
return
 : turn a pure value into an effectful computation
bind
     : compose two effectful computations
Define basic actions
 
type
 st (a:Type) = int -> a * int
 
let
 return (x:a) = fun s -> s, x
 
let
 bind (f:st a) (g:a -> st b) : st b = 
fun
 s0 ->
  
let
 s1, x = f s0 
in
  (g x) s1
 
let
 get () : st int = 
fun
 s -> s, s
let
 put (s:int) : st unit = 
fun
 _ -> (), s
Programming with monads
 
type
 st (a:Type) = int -> a * int
let
 return (x:a) = 
fun
 s -> s, x
let
 bind (f:st a) (g:a -> st b) : st b = 
fun
 s0 ->
  
let
 s1, x = f s0 
in
  (g x) s1
let
 get () : st int = 
fun
 s -> s, s
let
 put (s:int) : st unit = 
fun
 _ -> (), s
 
 
let
 incr () : st int = bind (get ()) (fun s -> bind (put (s+1)) (fun _ -> return s)))
 
//with shorthand
let
 incr () : st int =
  s 
<- get ();
  put (s+1);;
  return s
Proving with monads
type
 st (a:Type) is = ...
Indexed monads : indices encode reasoning principles
Several of them in the literature (graded monads, parameterized monads, …)
Indexed effects in F* : A unifying framework for programming and proving with
indexed monads and combinations thereof
Example: Reasoning for stateful computations
Examples
FStar/Sec1.GST.fst at master · FStarLang/FStar (github.com)
FStar/HoareST.fst at master · FStarLang/FStar (github.com)
FStar/examples/layeredeffects at master · FStarLang/FStar (github.com)
Indexed effects
Indexed effects in F* : A unifying framework for programming and proving with
indexed monads and combinations thereof
Abstraction
Composition (via lifts and layering)
Primitive syntax (
let
in
)
Seamless integration with rest of F*
Inductive types, recursion, termination checking, refinement types, … for free!
Customize F* to your own program logic!
Indexed effects in action
https://www.fstar-lang.org/papers/indexedeffects/
Steel,
 embedding of Concurrent Separation Logic in F*, based on indexed effects
The indices are separation logic pre- and post assertions
A variant has two additional indices for Hoare-style pre- and post
Described in our ICFP’20 and ICFP’21 papers
Meta-programming and tactics framework in F*
Meta-programs are F* programs in the TAC indexed effect
See ulib/FStar.Tactics.Effect.fsti
DY*: Bhargavan et al., Euro S&P’21, based on a state and exception indexed effect
https://github.com/reprosec/dolev-yao-star
Slide Note
Embed
Share

Learn how to customize F* to tailor to your program logic with insights from Aseem Rastogi from Microsoft Research. Delve into the world of F* programming, a functional language akin to OCaml and Haskell, featuring advanced type systems and interactive proof capabilities. Discover examples, details on indexed effects, and the landscape of F* in verified assembly code, domain-specific languages, and more.

  • F*
  • Proof-Oriented
  • Customization
  • Functional Programming
  • Programming Language

Uploaded on Sep 25, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. Proof-oriented Programming in F* How to customize F* to your own program logic Aseem Rastogi Microsoft Research (Joint work with my collaborators: https://project-everest.github.io/people/)

  2. Talk outline F* overview Introduction to F* by examples Indexed effects in F* (a.k.a. customize F* for your own program logic)

  3. What is F* https://www.fstar-lang.org A functional programming language Like OCaml, F#, Haskell F* programs can be compiled to OCaml and F# by-default* Expressive type system based on dependent type theory (like proof assistants Coq, Lean, Agda, Idris, ) Meta-programming and tactics for interactive proofs (like Coq, Lean, Isabelle, ) SMT-based semi-automation (like program verifiers Dafny, Why3, )

  4. A first example type list (a:Type) = let rec length (l:list a) = | Nil : list a match l with | Cons : a -> list a -> list a | [] -> 0 | _::tl -> 1 + length tl //[1; 2] Cons 1 (Cons 2 Nil) //append [1] [2] = [1; 2] let rec append (l1 l2:list a) = let rec length_append (l1 l2:list a) : Lemma (ensures length (append l1 l2) = length l1 + length l2) = match l1 with | [] -> () | _::tl -> length_append tl l2

  5. Behind the scenes ? ? Typing derivation

  6. F* Landscape Verified assembly code Verified C programs Vale Low* Embedded domain- specific languages Concurrency and distribution with separation logic Steel Verified parser generator Logical foundations of programs and proofs Interfacing with existing toolchains X86 C OCaml, F#, Rust? WebAssembly Assembly

  7. F* and friends EverParse HACL* Vale EverCrypt QUIC Veritas mitls More than 600,000 lines of F* Under Continuous Integration Built several times a day

  8. Proofs for Billions of Unsuspecting Users Automated parsing untrusted data with proofs in Hyper-V/VMSwitch DICE Verita s Wysteria An upcoming TCG standard for boot firmware (e.g. in IoT) Cloud infrastructure Verified cryptography in the Linux kernel Verified Merkle trees for Enterprise blockchains Secure communications MSQuic in Windows, Verified crypto in Firefox, mbedTLS, Signal in Wasm, Wireguard, Quic transport, High-value domains: Fintech, verifiable computing,

  9. Basic types, functions as first-class values, lambdas type empty = type unit = () type bool = true | false let incr (x:int) : int = x + 1 let apply_twice (f:a -> a) (x:a) = f (f x) let add_2 (x:int) : int = apply_twice incr x let add_4 (x:int) : int = apply_twice (fun x -> x + 2) x //lambdas

  10. Inductive types, pattern matching, recursion type list (a:Type) = | Nil : list a | Cons : a -> list a -> list a //[1; 2] Cons 1 (Cons 2 Nil) let rec map (f:a -> b) (l:list a) : list b = match l with | [] -> [] | hd::tl -> f hd :: map f tl

  11. Semantic termination checking Semantic termination checking Based on well-founded ordering ( << ) let rec map (f:a -> b) (l:list a) : list b - a:nat << b:nat if a < b = match l with | [] -> [] - Inductive subterm ordering - hd << Cons hd tl and tl << Cons hd tl | hd::tl -> f hd :: map f tl - User-defined well-founded relations - Primitive support for lexicographic ordering let rec ackermann (m n : nat) : nat (decreases %[m;n]) = if m=0 then n+1 else if n=0 then ackermann (m-1) 1 else ackermann (m-1) (ackermann m (n-1))

  12. Refinement types type nat = x:int{x >= 0} x:t{phi} type pos = x:int{x > 0} where x may occur free in phi type monotonic = f:int -> int{ Intuition: values of type t that satisfy phi forall x y. (x <= y) => (f x <= f y) } //coercive let f (x:int) : nat = if x >= 0 then x else 0

  13. Dependent function types let incr (x:int) : y:int{y > x} = x + 1 let rec sum (x:nat) : y:nat{y >= x} = if x = 0 then 0 else x + sum (x-1) //writing specifications using dependent types let rec length_append (l1 l2:list a) : Lemma (ensures length (append l1 l2) = length l1 + length l2) = match l1 with | [] -> () | _::tl -> length_append tl l2

  14. Proofs by Induction //writing specifications using dependent types let rec length_append (l1 l2:list a) : Lemma (ensures length (append l1 l2) = length l1 + length l2) = match l1 with | [] -> () | _::tl -> length_append tl l2 //invoke Induction Hypothesis Proof by induction on list l1: Base case, l1 = [] L.H.S. = length (append [] l2) = length l2 R.H.S. = length [] + length l2 = length l2 Inductive case: l1 = hd::tl Induction Hypothesis: length (append tl l2) = length tl + length l2 L.H.S. = length (append hd::tl l2) = length (hd::append tl l2) = 1+length (append tl l2) //apply I.H. at this step = 1+length tl+length l2 = length l1+length l2 = R.H.S.

  15. Effectful programming and proving So far, we have seen side-effects free, terminating functions of type a -> b What about programming and proving with effects? State, exception, I/O, non-determinism, Indexed effects: a user-extensible effect system in F* Based on modeling effects using monads (Wadler, Moggi, )

  16. Computation types In general functions have types: x:a -> M b is Type (M b is) is called a computation type M is an effect label, upper-bound on the effect of the function Effects are arranged in an ordering is are the effect indices, may encode effect-specific program logic

  17. Primitive effects Pure and Div Pure a pre post where pre : prop and post : a -> prop A side-effect free computation that if called when pre holds, terminates, and returns a result of type a s.t. post a holds Div a pre post Similar, but the computation may diverge Tot a =def= Pure a True (fun _ -> True) a -> b =def= a -> Tot b a -> Lemma pre post =def= a -> Pure unit pre (fun _ -> post)

  18. Modeling effects using monads Choose a representation for effectful functions Define two combinators that obey monadic laws: return : turn a pure value into an effectful computation bind : compose two effectful computations Define basic actions type st (a:Type) = int -> a * int let return (x:a) = fun s -> s, x let bind (f:st a) (g:a -> st b) : st b = fun s0 -> let s1, x = f s0 in (g x) s1 let get () : st int = fun s -> s, s let put (s:int) : st unit = fun _ -> (), s

  19. Programming with monads type st (a:Type) = int -> a * int let return (x:a) = fun s -> s, x let bind (f:st a) (g:a -> st b) : st b = fun s0 -> let s1, x = f s0 in (g x) s1 let get () : st int = fun s -> s, s let put (s:int) : st unit = fun _ -> (), s let incr () : st int = bind (get ()) (fun s -> bind (put (s+1)) (fun _ -> return s))) //with shorthand let incr () : st int = s <- get (); put (s+1);; return s

  20. Proving with monads type st (a:Type) is = ... Indexed monads : indices encode reasoning principles Several of them in the literature (graded monads, parameterized monads, ) Indexed effects in F* : A unifying framework for programming and proving with indexed monads and combinations thereof Example: Reasoning for stateful computations

  21. Examples FStar/Sec1.GST.fst at master FStarLang/FStar (github.com) FStar/HoareST.fst at master FStarLang/FStar (github.com) FStar/examples/layeredeffects at master FStarLang/FStar (github.com)

  22. Indexed effects Indexed effects in F* : A unifying framework for programming and proving with indexed monads and combinations thereof Abstraction Composition (via lifts and layering) Primitive syntax (let in) Seamless integration with rest of F* Inductive types, recursion, termination checking, refinement types, for free! Customize F* to your own program logic!

  23. Indexed effects in action https://www.fstar-lang.org/papers/indexedeffects/ Steel, embedding of Concurrent Separation Logic in F*, based on indexed effects The indices are separation logic pre- and post assertions A variant has two additional indices for Hoare-style pre- and post Described in our ICFP 20 and ICFP 21 papers Meta-programming and tactics framework in F* Meta-programs are F* programs in the TAC indexed effect See ulib/FStar.Tactics.Effect.fsti DY*: Bhargavan et al., Euro S&P 21, based on a state and exception indexed effect https://github.com/reprosec/dolev-yao-star

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#