• Aucun résultat trouvé

Spy Game – Verifying a Local Generic Solver in Iris

N/A
N/A
Protected

Academic year: 2022

Partager "Spy Game – Verifying a Local Generic Solver in Iris"

Copied!
43
0
0

Texte intégral

(1)

Spy Game – Verifying a Local Generic Solver in Iris

Paulo Em´ılio de Vilhena, Jacques-Henri Jourdan, Franc¸ois Pottier

January 22, 2020

(2)

When is a function constant?

Consider a program “f” that behaves extensionally.

Is it possible to dynamicallydetect that “f” is aconstant function?

What if “f” is defined onlazy integersinstead?

f : int - > int

(3)

When is a function constant?

Consider a program “f” that behaves extensionally.

Is it possible to dynamicallydetect that “f” is aconstant function? No.

What if “f” is defined onlazy integersinstead?

t y p e l a z y _ i n t = u n i t - > int f : l a z y _ i n t - > int

(4)

Approximate solution

Idea: “If fdoesnotuse its argument, then it must be constant.”

t y p e l a z y _ i n t = u n i t - > int

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = let r = ref t r u e in

let spy : l a z y _ i n t =

fun () - > r := f a l s e ; 0 in

let _ = f spy in

! r

We refer to this programming technique asspying.

Can we verify the correctness ofis_constant?

(5)

Approximate solution

Idea: “If fdoesnotuse its argument, then it must be constant.”

t y p e l a z y _ i n t = u n i t - > int

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = let r = ref t r u e in

let spy : l a z y _ i n t =

fun () - > r := f a l s e ; 0 in

let _ = f spy in

! r

We refer to this programming technique asspying.

Can we verify the correctness ofis_constant?

(6)

Approximate solution

Idea: “If fdoesnotuse its argument, then it must be constant.”

t y p e l a z y _ i n t = u n i t - > int

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = let r = ref t r u e in

let spy : l a z y _ i n t =

fun () - > r := f a l s e ; 0 in

let _ = f spy in

! r

We refer to this programming technique asspying.

Can we verify the correctness ofis_constant?

(7)

Approximate solution

Idea: “If fdoesnotuse its argument, then it must be constant.”

t y p e l a z y _ i n t = u n i t - > int

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = let r = ref t r u e in

let spy : l a z y _ i n t =

fun () - > r := f a l s e ; 0 in

let _ = f spy in

! r

We refer to this programming technique asspying.

Can we verify the correctness ofis_constant?

(8)

Approximate solution

Idea: “If fdoesnotuse its argument, then it must be constant.”

t y p e l a z y _ i n t = u n i t - > int

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = let r = ref t r u e in

let spy : l a z y _ i n t =

fun () - > r := f a l s e ; 0 in

let _ = f spy in

! r

We refer to this programming technique asspying.

Can we verify the correctness ofis_constant?

(9)

Approximate solution

Idea: “If fdoesnotuse its argument, then it must be constant.”

t y p e l a z y _ i n t = u n i t - > int

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = let r = ref t r u e in

let spy : l a z y _ i n t =

fun () - > r := f a l s e ; 0 in

let _ = f spy in

! r

We refer to this programming technique asspying.

Can we verify the correctness ofis_constant?

(10)

Approximate solution

Idea: “If fdoesnotuse its argument, then it must be constant.”

t y p e l a z y _ i n t = u n i t - > int

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = let r = ref t r u e in

let spy : l a z y _ i n t =

fun () - > r := f a l s e ; 0 in

let _ = f spy in

! r

We refer to this programming technique asspying.

Can we verify the correctness ofis_constant?

(11)

Motivation

Why is this a relevant question?

Spying has never been verifiedin separation logic.

Spying is used in real-worldfixed point computationalgorithms.

In the rest of this talk

Explain and verify spying usingIris – an expressive separation logic.

By the end, we will have the key ideasto verify is_constant!

These same ideas allow verifying fixed point computation algorithms.

(12)

Specification of is_constant

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = let r = ref t r u e in

let spy () = r := f a l s e ; 0 in let _ = f spy in ! r

The specification is a Hoare triple:

{f implements φ}

is constant f

{b.b =true ⇒ ∃c.∀m. φ(m) =c}

“x computes m” is sugar for {true} x () {y.y =m}

“f implements φ” is sugar for

∀x,m.{x computes m} f x {y.y =φ(m)}

(13)

Intuition

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = (* A s s u m p t i o n : f i m p l e m e n t s φ *) let r = ref t r u e in

let spy () = r := f a l s e ; 0 in

let _ = f spy in

! r

At a first glimpse, the code suggests an intuitive idea:

“Ifrcontains true, then φis a constant function.”

The assertion becomes true only after“f spy”. It is notan invariant.

(14)

Intuition

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = (* A s s u m p t i o n : f i m p l e m e n t s φ *) let r = ref t r u e in

let spy () = r := f a l s e ; 0 in

let _ = f spy in

! r

At a first glimpse, the code suggests an intuitive idea:

“Ifrcontains true, then φis a constant function.”

The assertion becomes true only after“f spy”. It is notan invariant.

(15)

Intuition

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = (* A s s u m p t i o n : f i m p l e m e n t s φ *) let r = ref t r u e in

let spy () = r := f a l s e ; 0 in

let _ = f spy in

! r

At a first glimpse, the code suggests an intuitive idea:

“Ifrcontains true, then φis a constant function.”

The assertion becomes true only after“f spy”. It is notan invariant.

(16)

Intuition

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = (* A s s u m p t i o n : f i m p l e m e n t s φ *) let r = ref t r u e in

let spy () = r := f a l s e ; 0 in

let _ = f spy in

! r

At a first glimpse, the code suggests an intuitive idea:

“Ifrcontains true, then φis a constant function.”

The assertion becomes true only after“f spy”. It is notan invariant.

(17)

Intuition

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = (* A s s u m p t i o n : f i m p l e m e n t s φ *) let r = ref t r u e in

let spy () = r := f a l s e ; 0 in

let _ = f spy in

! r

At a first glimpse, the code suggests an intuitive idea:

“Ifrcontains true, then φis a constant function.”

The assertion becomes true only after“f spy”. It is notan invariant.

(18)

Insight 1

let i s _ c o n s t a n t ( f : l a z y _ i n t - > int ) = (* A s s u m p t i o n : f i m p l e m e n t s φ *) let r = ref t r u e in

let spy () = r := f a l s e ; 0 in

let _ = f spy in

! r

A better candidate invariant mentions how many times fcalls spy:

“#(calls) =#(past calls)+#(future calls) and

if rcontainstrue then #(past calls) = 0.”

To name the number of futurecalls, we needprophecy counters.

(19)

Prophecy Counters

They are ghostcode; they do not exist at runtime.

Implemented using Iris’s prophecy variables (Jung et al. 2020).

{true}

prophCounter() {p.∃n.p n}

{p n}

prophDecr p

{().0<np (n−1)}

{p n}

prophZero p {().n= 0}

Intuition

(20)

The Invariant

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ;

! r

The operationprophCounter () yields a natural numbern.

Because we use prophDecr insidespy andprophZero at the end, n is the number of times spywillbe called!

n =#(calls)

(21)

The Invariant

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ;

! r

Informal:

“#(calls) =#(past calls)+#(futurecalls) and

ifrcontains true then #(past calls) = 0.”

Inv(r,p,n) = ∃(k : nat) (l : nat) (b : bool).

(22)

The Invariant

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ;

! r

At the end, by exploiting the invariant, we obtain:

r7→b ∗ (b =true⇒n= 0)

“If rcontainstrue, thenspy has never been called.”

But how to prove that φis constant from there?

(23)

The Invariant

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ;

! r

At the end, by exploiting the invariant, we obtain:

r7→b ∗ (b =true⇒n= 0)

“If rcontainstrue, thenspy has never been called.”

(24)

Insight 2 – The link between n and φ

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ; ! r

“If spyis never called, it can pretend to compute an arbitrary integer.”

n= 0 =⇒ ∀m.{true}spy (){y.y =m}

Therefore

n = 0 =⇒

{f implements φ} f spy {c.

∀m.

c =φ(m)}

(25)

Insight 2 – The link between n and φ

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ; ! r

“If spyis never called, it can pretend to compute an arbitrary integer.”

n= 0 =⇒ ∀m.spy computes m

Therefore

n= 0 =⇒

{f implements φ} f spy {c.

∀m.

c =φ(m)}

(26)

Insight 2 – The link between n and φ

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ; ! r

“If spyis never called, it can pretend to compute an arbitrary integer.”

n= 0 =⇒ ∀m.spy computes m Therefore

n= 0 =⇒ ∀m.

{f implements φ}

f spy {c.

∀m.

c =φ(m)}

(27)

Insight 2 – The link between n and φ

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ; ! r

“If spyis never called, it can pretend to compute an arbitrary integer.”

n= 0 =⇒ ∀m.spy computes m Therefore

n= 0 =⇒ ∀m.

{f implements φ}

f spy

∀m.

(28)

Insight 2 – The link between n and φ

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in

let _ = f spy in p r o p h Z e r o p ; ! r

“If spyis never called, it can pretend to compute an arbitrary integer.”

n= 0 =⇒ ∀m.spy computes m Therefore

n= 0 =⇒

{f implements φ}

f spy {c.∀m.c =φ(m)}

(29)

Conjunction rule

Moving the quantifier is justified by arestricted conjunction rule:

∀x.{P}e {y.Q(x,y)} Qis pure {P}e0 {y.∀x.Q(x,y)}

wheree0 is a copy ofe instrumented withprophecy variables.

The proof in Iris is novel and is yet another use case of prophecies.

(30)

Combining the previous steps

let i s _ c o n s t a n t f = let r = ref t r u e in

let p = p r o p h C o u n t e r () in let spy () =

p r o p h D e c r p ; r := f a l s e ; 0 in let _ = f spy in

p r o p h Z e r o p ; ! r

“If rcontains true at the end, thenspyis never called.”

r7→b ∗ (b =true⇒n= 0)

“If spyis never called, then φis a constant function.”

n= 0 =⇒

{f implements φ}

f spy {c.∀m.c =φ(m)}

(31)

Summary

What we have seen so far

is_constant– an example of spying.

Proof sketch foris_constant.

How prophecy variables are used to handle spying.

A restricted conjunction rule.

For the rest of the talk

What is alocal generic solver.

Explain theconnection between spying and local generic solvers.

(32)

What is a Local Generic Solver?

A term coined by Fecht and Seidl (1999).

Asolver computes the least function “phi” that satisfies eqs phi = phi

where “eqs” is a user-supplied function.

Genericmeans it is parameterized with a user-defined partial order.

Localmeansphi is computed on demand and need not be defined everywhere.

(33)

API of a Local Generic Solver

t y p e v a l u a t i o n = v a r i a b l e - > p r o p e r t y

val lfp : ( v a l u a t i o n - > v a l u a t i o n ) - > v a l u a t i o n

A simpleexample is to compute Fibonacci:

t y p e v a l u a t i o n = int - > int

let eqs ( phi : v a l u a t i o n ) ( n : int ) =

if n <= 1 t h e n 1 e l s e phi ( n - 1) + phi ( n - 2) in

let fib = lfp eqs

(34)

Dependencies

“fibatndepends onfibat n - 1andn - 2.”

t y p e v a l u a t i o n = int - > int

let eqs ( phi : v a l u a t i o n ) (n: int ) =

if n <= 1 t h e n 1 e l s e phi (n - 1) + phi (n - 2) in

let fib = lfp eqs

Local generic solvers use dependencies for efficiency.

Dependencies are discovered at runtimevia spying.

(35)

Conclusion

What is in the paper

Improvements to Iris’s prophecy variableAPI.

Proof of aconjunction rule.

Use of locks to make our code thread-safe.

Specification and proof ofmodulus, the general case of spying.

Specification and proof of alocal generic solver.

Limitations

We only provepartial correctness.

We do not prove deadlock-freedom.

(36)

Questions?

(37)

modulus

Spying is subsumed by a single combinator, modulus, so named by Longley (1999).

let m o d u l u s ff f = let xs = ref [] in let spy x =

xs := x :: ! xs ; f x

in

let c = ff spy in ( c , ! xs )

lfpuses modulus.

is_constantcan be written in terms ofmodulus.

(38)

modulus

Spying is subsumed by a single combinator, modulus, so named by Longley (1999).

let m o d u l u s ff f = let xs = ref [] in let spy x =

xs := x :: ! xs ; f x

in

let c = ff spy in ( c , ! xs )

let i s _ c o n s t a n t p r e d = let r = ref t r u e in let spy () =

r := f a l s e ; 0

in

let _ = p r e d spy in

! r

lfpuses modulus.

is_constantcan be written in terms ofmodulus.

(39)

modulus

Spying is subsumed by a single combinator, modulus, so named by Longley (1999).

let m o d u l u s ff f = let xs = ref [] in let spy x =

xs := x :: ! xs ; f x

in

let c = ff spy in ( c , ! xs )

let i s _ c o n s t a n t p r e d = let z e r o () = 0 in m a t c h

m o d u l u s p r e d z e r o w i t h

| _ , [] - > t r u e

| _ , _ :: _ - > f a l s e

lfpuses modulus.

is_constantcan be written in terms ofmodulus.

(40)

Conjunction rule

∀x.{P}e (){y.Q x y} Q is pure {P}withProph e{y.∀x.Q x y}

wherewithProph eis the program einstrumented with prophecies:

let w i t h P r o p h ( e : u n i t - > ’ a ) = let p = n e w P r o p h () in

let y = e () in r e s o l v e P r o p h p y ; y

(41)

Prophecy variables

Prophecy Allocation {true}

newProph() {p.∃zs.p zs}

Prophecy Assignment {p zs}

resolveProph p x ().∃zs.zs =x ::zs0p zs0

Prophecy Disposal {p zs} disposeProph p

{().zs = []}

Improvements

The operationdisposeProph is new.

(42)

Specification of Fix

∀eqsE.(E is monotone) ⇒

{eqs implements E}

lfp eqs

{phi.phi implements µE}¯

Remarks

Partial correctness: termination isnotguaranteed.

Possible deadlocks depending on the user implementation ofE.

(43)

Related work

Hofmann et al. (2010a) present a Coq proof of a local generic solver:

they model the solver as a computation in a state monad,

and they assume the client can be modeled as a strategy tree.

Why it is permitted to model the client in this way is the subject of two separate papers (Hofmann et al. 2010b; Bauer et al. 2013).

Références

Documents relatifs

This shows that the solver is safe (that is, combining it with valid user code cannot result in an illegal memory access or a data race) and correct (that is, it computes the

Same idea, but a prophecy variable must be used to name y ahead of time and allow the case split

This follows from Weinstein's results [10] on intersection of nearby Lagrange manifold and our case can be viewed as an extension of this

L’accès aux archives de la revue « Rendiconti del Seminario Matematico della Università di Padova » ( http://rendiconti.math.unipd.it/ ) implique l’accord avec les

Because I was using Kerberos authentication, I was able to log into cfs without typing a password; instead, my telnet client obtained a service principal from the Ticket

In this survey, we review known results and we present new results on Klee sets and Chebyshev centers with respect to Bregman distances.. Examples are provided and connections to

It can be shown that it is theoretically possible to obtain a maximal flow in a given network in at most | E | iterations, and that this may even be achieved using augmenting paths

New chapters include coverage of important topics like VoIP and EAP Coverage of cutting edge technologies like optical networking and storage Authored by Cisco Systems, worldwide