A formal proof of the Chip Model Channel Separation Property

Thomas Hallgren, Programatica Meeting, 2004-05-11

A formal proof of the Chip Model Channel Separation Property

Thomas Hallgren

Programatica Meeting, 2004-05-11

   ┌─────────┐    ┌─────────┐
───┤ pick ch ├───►┤  chip   ├──►
   └─────────┘	  └─────────┘
=
   ┌─────────┐    ┌─────────┐
───┤  chip   ├───►┤ pick ch ├──►
   └─────────┘	  └─────────┘

Warning

Encouragement

Remember the Curry-Howard isomorphism?

Proofs are programs!

How do we manage complexity in programs?

  1. We invent useful abstraction and construct libraries of reusable software components.
  2. We use high-level languages with good abstraction mechanisms.
  3. We make use of program generators (automation) for certain specific tasks (e.g. parsers).

Automation is always welcome!

The Chip

chip :: [Packet] → [Packet] type Packet = (Channel,Data) type Channel = Int type Data = [Word]
      ┌──────┐
ps ───┤ chip ├──►  ps'
      └──────┘

Channel Separation Property

Property of interest: channel separation ( = no information leaks between channels)
  ┌─────────┐   ┌─────────┐
──┤  chip   ├──►┤ pick ch ├──►
  └─────────┘   └─────────┘
=
  ┌─────────┐   ┌─────────┐
──┤ pick ch ├──►┤  chip   ├──►
  └─────────┘   └─────────┘
assert Separation = ∀ ch . {pick ch . chip} === {chip . pick ch} pick :: Channel → [Packet] → [Packet] pick ch = filter ((==ch).fst)

A variant of the Channel Separation Property

	┌──────┐
     ───┤ chip ├──►
        └──────┘
=
      ┌─────────┐   ┌─────────┐
   ┌─►┤ pick 1  ├──►┤  chip   ├──┐
   │  └─────────┘   └─────────┘  │
   │  ┌─────────┐   ┌─────────┐  │
───┼─►┤ pick 2  ├──►┤  chip   ├──┼──►
   │  └─────────┘   └─────────┘  │
   │      ...          ...       │
   │  ┌─────────┐   ┌─────────┐  │
   └─►┤ pick n  ├──►┤  chip   ├──┘
      └─────────┘   └─────────┘

Processing all channels in one chip is the same as having one chip per channel.

Filling in the details

This is the actual main assertion.
chip :: Algs → ChipState → [Packet] → [Packet] type Algs = Channel → Alg type ChipState = (Memory,Regs) type Regs = FM RegFile assert Separation = ∀ algs . ∀ ch . ∀ state . ∀ ps . {pick ch (chip algs state ps)} === {chip algs state (pick ch ps)}

The Chip Model

chip :: Algs → ChipState → [Packet] → [Packet] chip algs state ps = fst (runS (manyPackets algs ps) state) manyPackets :: Algs → [Packet] → StateM ChipState [Packet] manyPackets algs = mapM (onePacket algs) onePacket :: Algs → Packet → StateM ChipState Packet onePacket algs (chan,ws) = do regfile ← liftM (\regs→FM.lookup regs chan) (inSnd load) (ws',regfile') ← inFst (doPacket (algs chan) ws regfile) finishPacket chan ws' regfile' doPacket :: Alg → Data → RegFile → StateM Memory (Data,RegFile) doPacket alg ws regf = ...

For all the details, view the code with pfebrowser...

For reference...

Generic monadic operations

liftM :: Monad m ⇒ (a → b) → m a → m b mapM :: Monad m ⇒ (a → m b) → [a] → m [b]

State monad operations

inFst :: StateM s1 a → StateM (s1,s2) a inSnd :: StateM s2 a → StateM (s1,s2) a runS :: StateM s a → s → (a,s)

Observations 1

Although the function chip is defined monadically, it is equivalent(*) to a simple list traversing function:
chip algs state [] = [] chip algs state (p:ps) = p':chip algs state' ps where (p',state') = runS (onePacket algs p) state

Under the assumption that onePacket has the right properties, we can prove Separation with induction over the input packet list, without reasoning about monadic code.

(*) This equivalence follows directly from the definitions.

Observations 2

Even if the state argument is the same on both sides of the equation we want to prove,

pick ch (chip algs state ps) === chip algs state (pick ch ps)

because of the filtering, they will be different in the recursive calls, when we try to do a proof by induction. Hence, the induction proof needs to be for a more general equation.

Observations 3

As we saw on a previous slide, packet processing is stateful.

Overall proof structure

The proof of Separation is obtained by combining the proofs of CondSeparation, AllGoodAlgs, and SameState.
assert CondSeparation = ∀ algs ch state1 state2 ps . GoodAlg {algs ch} ==> Invariant state1 state2 ch ==> {pick ch (chip algs state1 ps)} === {chip algs state2 (pick ch ps)} assert AllGoodAlg = ∀ alg . GoodAlg alg assert SameState = ∀ state . ∀ ch . Invariant state state ch

Good algorithms

assert AllGoodAlg = ∀ alg . GoodAlg alg property GoodAlg = {| alg | ∀ ws . ∀ regf . StateIndependent {doPacket alg ws regf} |} property StateIndependent = {| m | ∀ s1 . ∀ s2 . {fst (runS m s1)} === {fst (runS m s2)} |}

Invariant in the proof of CondSeparation

assert SameState = ∀ state . ∀ ch . Invariant state state ch property Invariant = {| state1, state2, ch | {regfile ch state1} === {regfile ch state2} |} regfile :: Channel → ChipState → RegFile regfile ch state = FM.lookup (snd state) ch

CondSeparation proof outline

Invariant in the proof of AllGoodAlg

Recall
assert AllGoodAlg = ∀ alg . GoodAlg alg property GoodAlg = {| alg | ∀ ws . ∀ regf . StateIndependent {doPacket alg ws regf} |} property StateIndependent = {| m | ∀ s1 . ∀ s2 . {fst (runS m s1)} === {fst (runS m s2)} |} doPacket :: Alg → Data → RegFile → StateM Memory (Data,RegFile)

Invariant in the proof of AllGoodAlg, first attempt

property RelatedResult R = {| r1,r2 | {fst r1}==={fst r2} /\ R {snd r1} {snd r2} |} property MostlyStateIndependent R = {| m | ∀ s1 . ∀ s2 . R s1 s2 ==> RelatedResult R {runS m s1} {runS m s2} |} assert ReturnS = ∀ x . ∀ R . MostlyStateIndependent R {return x} assert BindS = ∀ m1 . ∀ xm2 . ∀ R . MostlyStateIndependent R m1 ==> (∀ x . MostlyStateIndependent R {xm2 x}) ==> MostlyStateIndependent R {m1 >>= xm2}

Invariant in the proof of AllGoodAlg, degeneralized

property EqRange r = {| m1,m2 | ∀ a . InRange r a ==> {lookupM m1 a} === {lookupM m2 a} |} property RelatedResult range = {| r1,r2 | {fst r1}==={fst r2} /\ EqRange range {snd r1} {snd r2} |} property MostlyStateIndependent range = {| m | ∀ mem1 . ∀ mem2 . EqRange range mem1 mem2 ==> RelatedResult range {runS m mem1} {runS m mem2} |} assert ReturnS_MSI = ∀ range . ∀ x . MostlyStateIndependent range {return x} assert BindS_MSI = ∀m1 . ∀xm2 . ∀range . MostlyStateIndependent range m1 ==> (∀x . MostlyStateIndependent range {xm2 x}) ==> MostlyStateIndependent range {m1 >>= xm2}

AllGoodAlg proof outline

What if?

Files

Haskell moduleDescription
AlgorithmsReg, RegFile, Code, Alg, runAlg
ChipModelThe chip model and main property assertions
ExamplesA sample algorithm and a test case
FMclass FM (finite maps) and definitions of expected properties
FunFMFunctions from natural numbers as finite maps
MemMonadsclass MemMonad
MemoriesMemory, Addr, Word, Data, Range, ...
NatNatural numbers
ProtectedProtected memory monad
StateImplemenation of the State Monad

Imports from the Alfa library and other utilities

Random notes and concluding remarks

Readability of proofs?

Certificate machinery

Random notes

Conjectures

Pointers

The code is in the Programatica CVS repository:
programatica/examples/ChannelSeparation/Alfa
  • Chip model, properties and proofs expressed entirely in Alfa.
programatica/examples/ChannelSeparation/Alfa/Haskell
  • Chip model in Haskell,
  • properties expressed as P-Logic assertions,
  • Alfa certificates associating proof in Alfa to the asserted properties.

The End

Questions?

Box drawing tests

┌─┐
│ │
└─┘

   ┌──────┐
───┤ chip ├───
   └──────┘

   ┌─────────┐    ┌─────────┐	   ┌─────────┐    ┌─────────┐
───┤ pick ch ├───▸┤  chip   ├───►──┤  chip   ├────┤ pick ch ├──►
   └─────────┘	  └─────────┘	   └─────────┘	  └─────────┘