diff --git a/Project2.fst b/Project2.fst index 28bd3fa..cfc7f54 100644 --- a/Project2.fst +++ b/Project2.fst @@ -93,8 +93,8 @@ let rec wellformed (cs: callstack) = (* Type for the outcome of a single execution step: either the execution terminated (Stop) as a final state is reached or further execution steps are possible *) noeq type step_outcome = - | Stop : (cs: callstack) -> step_outcome - | Next : (cs: callstack) -> step_outcome + | Stop : (cs: callstack{wellformed cs}) -> step_outcome + | Next : (cs: callstack{wellformed cs}) -> step_outcome (* Auxiliary function for applying the effects of terminated states to the underneath execution states *) val apply_returneffects: (ts: terstate) -> (rs: regstate{isCallState rs}) -> Tot regstate @@ -118,41 +118,41 @@ let step te cs = if gas < 1 then Next (Ter ExcState ps) else match (getOpcode code pc, stack) with - | (ADD, a::b::stack') -> Next (Exec(((gas-1, pc+1, mem, (a+b):: stack'), (actor, input, code), gs)::ps)) + | (ADD, a::b::stack') -> Next (Exec(((gas-1, pc+1, mem, (a+b):: stack'), (actor, input, code), gs) :: ps)) | (AND, a::b::stack') -> let c = (if a > 0 && b > 0 then 1 else 0) in - Next (Exec(((gas-1, pc+1, mem, c::stack'), (actor, input, code), gs)::ps)) + Next (Exec(((gas-1, pc+1, mem, c::stack'), (actor, input, code), gs) :: ps)) | (LE, a::b::stack') -> let c = (if a <= b then 1 else 0) in - Next (Exec(((gas-1, pc+1, mem, c::stack'), (actor, input, code), gs)::ps)) + Next (Exec(((gas-1, pc+1, mem, c::stack'), (actor, input, code), gs) :: ps)) | (PUSH x, stack') -> Next (Exec(((gas-1, pc+1, mem, x::stack'), (actor, input, code), gs)::ps)) - | (POP, x::stack') -> Next (Exec(((gas-1, pc+1, mem, stack') (actor, input, code), gs)::ps)) + | (POP, x::stack') -> Next (Exec(((gas-1, pc+1, mem, stack'), (actor, input, code), gs) :: ps)) | (MSTORE, p::v::stack') -> Next (Exec(((gas-1, pc+1, update mem p v, stack'), (actor, input, code), gs)::ps)) | (MLOAD, p::stack') -> let v = (mem p) in - Next (Exec(((gas-1, pc+1, mem, v::stack'), (actor, input, code), gs')::ps)) + Next (Exec(((gas-1, pc+1, mem, v::stack'), (actor, input, code), gs)::ps)) | (SSTORE, p::v::stack') -> let acc = (let (bal, stor, code) = gs actor in (bal, update stor p v, code)) in let gs' = update gs actor acc in Next (Exec(((gas-1, pc+1, mem, stack'), (actor, input, code), gs')::ps)) | (SLOAD, v::stack') -> Next (Exec(((gas-1, pc+1, mem, (let (bal, stor, code) = gs actor in stor v)::stack'), (actor, input, code), gs)::ps)) | (BALANCE, a::stack') -> let (bal, _, _) = (gs a) in - Next (Exec(((gas-1, pc+1, mem, bal::stack'), (actor, input, code), gs')::ps)) + Next (Exec(((gas-1, pc+1, mem, bal::stack'), (actor, input, code), gs)::ps)) | (ADDRESS, stack') -> Next (Exec(((gas-1, pc+1, mem, actor::stack'), (actor, input, code), gs)::ps)) | (INPUT, stack') -> Next (Exec(((gas-1, pc+1, mem, input::stack'), (actor, input, code), gs)::ps)) | (GAS, stack') -> Next (Exec(((gas-1, pc+1, mem, gas::stack'), (actor, input, code), gs)::ps)) | (JUMP i, stack') -> Next (Exec((((gas-1, i, mem, stack'), (actor, input, code), gs))::ps)) | (JUMPI i, b::stack') -> let j = (if b = 0 then pc+1 else i) in - Next (Exec((((gas-1, j, mem, stack'), (actor, input, code), gs))::ps)) + Next (Exec((((gas-1, j, mem, stack'), (actor, input, code), gs))::ps)) | (RETURN, v::stack') -> Next (Ter (HaltState gs v (gas-1)) ps) | (STOP, stack') -> Next (Ter (HaltState gs 0 (gas-1)) ps) | (TIMESTAMP, stack') -> Next (Exec(((gas-1, pc+1, mem, te::stack'), (actor, input, code), gs)::ps)) | (CALL, to::v::inp::resaddr::stack') -> let (bal, _, _) = gs actor in if bal < v then Next (Ter ExcState ps) else - if v < 0 then Next (Ter ExcState ps) else - let to_acc = (let (bal, stor, code) = gs to in (bal+v, stor, code)) in - let actor_acc = (let (bal, stor, code) = gs actor in (bal-v, stor, code)) in - let gs' = update (update gs to to_acc) actor actor_acc in - let mu' = (gas-1, 0, (fun x -> 0), []) in - let env' = (to, inp, (let (_, _, code) = (gs to) in code)) in - let old_ex_state = ((gas, pc, mem, to::v::inp::resaddr::stack'), (actor, input, code), gs) in - Next (Exec((mu', env', gs')::(old_ex_state::ps))) + if v < 0 then Next (Ter ExcState ps) else + let to_acc = (let (bal, stor, code) = gs to in (bal+v, stor, code)) in + let actor_acc = (let (bal, stor, code) = gs actor in (bal-v, stor, code)) in + let gs' = update (update gs to to_acc) actor actor_acc in + let mu' = (gas-1, 0, (fun x -> 0), []) in + let env' = (to, inp, (let (_, _, code) = (gs to) in code)) in + let old_ex_state = ((gas, pc, mem, to::v::inp::resaddr::stack'), (actor, input, code), gs) in + Next (Exec((mu', env', gs')::(old_ex_state::ps))) | _ -> Next (Ter ExcState ps) (* A simple wrapper for the step function that removes the execution outcome *) @@ -177,8 +177,8 @@ let rec nsteps n te cs = val gas: plaincallstack -> Tot nat let gas cs = match cs with - | (((gas, _, _, _), _, _)::_) -> gas - | _ -> 0 + | (((gas, _, _, _), _, _)::_) -> gas + | _ -> 0 val getDecArgList: (cs: callstack {wellformed cs}) -> Tot (list nat) let getDecArgList (cs: callstack {wellformed cs}) = @@ -226,7 +226,11 @@ let rec nsteps_stop n te cs = if n = 0 then () else nsteps_stop (n-1) te (step_simp te cs) (* Prove that if a call stack does not change within one step then it must be final. Formulate first the Lemma and then prove it *) -(* val progress: *) +val progress: (te:tenv) -> (cs: callstack{wellformed cs}) -> + Lemma (requires (cs == step_simp te cs)) + (ensures (isFinal cs)) +let rec progress te cs = + () (* 3.4: Uniqueness of callstack *) @@ -256,8 +260,7 @@ let rec callstacks_unique n te cs cs' = val exception_prop: (te:tenv) -> (ps:plaincallstack) -> Lemma (requires (wellformed (Ter ExcState ps))) (ensures (nsteps (op_Multiply 2 (length ps)) te (Ter ExcState ps) == (Ter ExcState []))) -let rec exception_prop te ps = - match ps with - | [] -> () - | _ :: ps' -> exception_prop te ps' +let rec exception_prop te ps = match ps with + | [] -> () + | _ :: ps' -> exception_prop te ps'