<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="../../../unit.xsl"?>
<KIVSPEC name="simple-BASM">
<SPECBODY>
<external/>asm specification 
   comment: approximate specification of the intermediate level
            of the Mondex case study as an ASM: we take
            messages directly from the ether instead of from an input
            list (+ check whether in ether).  Also we do not
            group operations (e.g. ABORT with STARTFROM) since there
            is no need to do so: an ASM can execute ABORT
            by its own decision, and must not read an input
            in doing so. IGNORE operations as present in
            the original operations have been dropped too 
            for the same reason.;
   using <a href="../../../specs/set-nat/export/unit.xml">set-nat</a> <a href="../../../specs/genname/export/unit.xml">genname</a> 
         <a href="../../../specs/status/export/unit.xml">status</a> <a href="../../../specs/set-message/export/unit.xml">set-message</a> 
         <a href="../../../specs/set-PayDetails/export/unit.xml">set-PayDetails</a>

      <syn>initial state</syn>
            exLog := λ na. ∅ 
            ether := {λ msg. isStartTo(msg)}  ∪ {λ msg. isStartFrom(msg)}  ∪ {⊥}  
            state := λ na. idle 
             
      <syn>final state</syn>
            ether = ∅ 


      <syn>BSTEP</syn># 
           <syn>choose</syn>  msg, fail?, receiver
           <syn>with</syn> (msg ∈ ether ∧ authentic(receiver))
           <syn>in</syn> 
                 <syn>if</syn> isStartTo(msg) ∧ state(receiver) = idle
                 <syn>then</syn> STARTTO#
                 <syn>else</syn> <syn>if</syn> isStartFrom(msg) ∧ state(receiver) = idle
                 <syn>then</syn> STARTFROM#
                 <syn>else</syn> <syn>if</syn> isreq(msg) ∧ state(receiver) = epr
                 <syn>then</syn> REQ#
                 <syn>else</syn> <syn>if</syn> isval(msg) ∧ state(receiver) = epv
                 <syn>then</syn> VAL#
                 <syn>else</syn> <syn>if</syn> isack(msg) ∧ state(receiver) = epa
                 <syn>then</syn> ACK#
                 <syn>else</syn> ABORT#
                 <syn>seq</syn> ether := ether ++ outmsg

      <syn>ABORT</syn>#
           <syn>choose</syn>  n
           <syn>with</syn> nextSeqNo(receiver) ≤ n
           <syn>in</syn> 
                 <syn>if</syn> state(receiver) = epa ∨ state(receiver) = epv
                 <syn>then</syn> exLog(receiver) := exLog(receiver) ++ pdAuth(receiver) <syn>seq</syn>
                 state(receiver) := idle 
                 nextSeqNo(receiver) := n
                 outmsg := ⊥


      <syn>STARTFROM</syn># 
           <syn>let</syn> msgna = msg .name, value = msg .value, msgno = msg .nextSeqNo
           <syn>in</syn> <syn>if</syn> authentic(msgna) ∧ ¬ fail? ∧ receiver ≠ msgna ∧ value ≤ balance(receiver)
              <syn>then</syn> <syn>choose</syn>  n
                   <syn>with</syn> nextSeqNo(receiver) &lt; n
                   <syn>in</syn> begin 
                         pdAuth(receiver) := mkpd(receiver, nextSeqNo(receiver), msgna, msgno, value) 
                         state(receiver) := epr <syn>seq</syn> 
                         nextSeqNo(receiver) := n 
                         outmsg := ⊥
              <syn>else</syn> outmsg := ⊥

      <syn>STARTTO</syn># 
           <syn>let</syn> msgna = msg .name, value = msg .value, msgno = msg .nextSeqNo
           <syn>in</syn> <syn>if</syn> authentic(msgna) ∧ ¬ fail? ∧ receiver ≠ msgna
              <syn>then </syn> <syn>choose</syn>  n
                   <syn>with</syn> nextSeqNo(receiver) &lt; n
                   <syn>in</syn> 
                         pdAuth(receiver) := mkpd(msgna, msgno, receiver, nextSeqNo(receiver), value) 
                         state(receiver) := epv <syn>seq</syn> 
                         outmsg := req(pdAuth(receiver)) 
                         nextSeqNo(receiver) := n
              <syn>else</syn> outmsg := ⊥

      <syn>REQ</syn># 
           <syn>if</syn> msg = req(pdAuth(receiver)) ∧ ¬ fail?
           <syn>then</syn> 
                   balance(receiver) := balance(receiver) - pdAuth(receiver) .value 
                   state(receiver) := epa <syn> seq </syn>
                   outmsg := val(pdAuth(receiver))
           <syn>else</syn> outmsg := ⊥

      <syn>VAL</syn># 
           <syn>if</syn> msg = val(pdAuth(receiver)) ∧ ¬ fail?
           <syn>then</syn> balance(receiver) := balance(receiver) + pdAuth(receiver) .value 
                           state(receiver) := idle 
                           outmsg := ack(pdAuth(receiver))
           <syn>else</syn> outmsg := ⊥

      <syn>ACK</syn># 
           <syn>if</syn> msg = ack(pdAuth(receiver)) ∧ ¬ fail?
           <syn>then</syn> 
                state(receiver) := idle 
                outmsg := ⊥
           <syn>else</syn> outmsg := ⊥

end asm specification</SPECBODY>

<SPECBODY>
<internal/>asm specification 
   comment: approximate specification of the intermediate level
            of the Mondex case study as an ASM: we take
            messages directly from the ether instead of from an input
            list (+ check whether in ether).  Also we do not
            group operations (e.g. ABORT with STARTFROM) since there
            is no need to do so: an ASM can execute ABORT
            by its own decision, and must not read an input
            in doing so. IGNORE operations as present in
            the original operations have been dropped too 
            for the same reason.;
   using <a href="../../../specs/set-nat/export/unit.xml">set-nat</a> <a href="../../../specs/genname/export/unit.xml">genname</a> 
         <a href="../../../specs/status/export/unit.xml">status</a> <a href="../../../specs/set-message/export/unit.xml">set-message</a> 
         <a href="../../../specs/set-PayDetails/export/unit.xml">set-PayDetails</a>
    target 
         procedures 
            BASM#   : (name → nat) × (name → PayDetailsSet) × (name → status) × (name → nat) × (name → PayDetails) × messageset × message nonfunctional indeterministic;
            BSTEP#   : (name → nat) × (name → PayDetailsSet) × (name → status) × (name → nat) × (name → PayDetails) × messageset × message nonfunctional indeterministic;
            ABORT#  name × (name → PayDetails) : (name → PayDetailsSet) × (name → status) × (name → nat) × message nonfunctional indeterministic;
            STARTFROM#  message × bool × name × (name → nat) : (name → status) × (name → nat) × (name → PayDetails) × message nonfunctional indeterministic;
            STARTTO#  message × bool × name : (name → status) × (name → nat) × (name → PayDetails) × message nonfunctional indeterministic;
            REQ#  message × name × bool × (name → PayDetails) : (name → nat) × (name → status) × message nonfunctional;
            VAL#  message × name × bool × (name → PayDetails) : (name → nat) × (name → status) × message nonfunctional;
            ACK#  message × name × bool × (name → PayDetails) : (name → status) × message nonfunctional;
         variables 
            balance : name → nat; 
            exLog : name → PayDetailsSet; 
            state : name → status; 
            nextSeqNo : name → nat; 
            pdAuth : name → PayDetails; 
            ether, newether : messageset; 
            fail?, fin : bool; 
            msgno, value : nat; 
            msgna, receiver : name; 
            messages : messageset; 
            msg, outmsg : message; 
   declaration 
      asm
      : BASM# (var balance, exLog, state, nextSeqNo, pdAuth, ether, outmsg)
          begin 
             exLog := λ na. ∅, ether := {λ msg. isStartTo(msg)}  ∪ {λ msg. isStartFrom(msg)}  ∪ {⊥} , state := λ na. idle ; 
             while ether ≠ ∅ do BSTEP#(; balance, exLog, state, nextSeqNo, pdAuth, ether, outmsg)
          end;
      BSTEP# (var balance, exLog, state, nextSeqNo, pdAuth, ether, outmsg)
        begin 
           var  msg, fail?, receiver
           with (msg ∈ ether ∧ authentic(receiver))
           in begin 
                 if isStartTo(msg) ∧ state(receiver) = idle
                 then STARTTO#(msg, fail?, receiver; state, nextSeqNo, pdAuth, outmsg)
                 else if isStartFrom(msg) ∧ state(receiver) = idle
                      then STARTFROM#(msg, fail?, receiver, balance; state, nextSeqNo, pdAuth, outmsg)
                      else if isreq(msg) ∧ state(receiver) = epr
                           then REQ#(msg, receiver, fail?, pdAuth; balance, state, outmsg)
                           else if isval(msg) ∧ state(receiver) = epv
                                then VAL#(msg, receiver, fail?, pdAuth; balance, state, outmsg)
                                else if isack(msg) ∧ state(receiver) = epa
                                     then ACK#(msg, receiver, fail?, pdAuth; state, outmsg)
                                     else ABORT#(receiver, pdAuth; exLog, state, nextSeqNo, outmsg) ; 
                 ether := ether ++ outmsg
              end
        end;
      ABORT# (receiver, pdAuth; var exLog, state, nextSeqNo, outmsg)
        begin 
           var  n
           with nextSeqNo(receiver) ≤ n
           in begin 
                 if state(receiver) = epa ∨ state(receiver) = epv
                 then exLog(receiver) := exLog(receiver) ++ pdAuth(receiver) ; 
                 state(receiver) := idle, nextSeqNo(receiver) := n, outmsg := ⊥
              end
        end;
      STARTFROM# (msg, fail?, receiver, balance; var state, nextSeqNo, pdAuth, outmsg)
        begin 
           var msgna = msg .name, value = msg .value, msgno = msg .nextSeqNo
           in if authentic(msgna) ∧ ¬ fail? ∧ receiver ≠ msgna ∧ value ≤ balance(receiver)
              then var  n
                   with nextSeqNo(receiver) &lt; n
                   in begin 
                         pdAuth(receiver) := mkpd(receiver, nextSeqNo(receiver), msgna, msgno, value), state(receiver) := epr ; 
                         nextSeqNo(receiver) := n, outmsg := ⊥
                      end
              else outmsg := ⊥
        end;
      STARTTO# (msg, fail?, receiver; var state, nextSeqNo, pdAuth, outmsg)
        begin 
           var msgna = msg .name, value = msg .value, msgno = msg .nextSeqNo
           in if authentic(msgna) ∧ ¬ fail? ∧ receiver ≠ msgna
              then var  n
                   with nextSeqNo(receiver) &lt; n
                   in begin 
                         pdAuth(receiver) := mkpd(msgna, msgno, receiver, nextSeqNo(receiver), value), state(receiver) := epv ; 
                         outmsg := req(pdAuth(receiver)), nextSeqNo(receiver) := n
                      end
              else outmsg := ⊥
        end;
      REQ# (msg, receiver, fail?, pdAuth; var balance, state, outmsg)
        begin 
           if msg = req(pdAuth(receiver)) ∧ ¬ fail?
           then begin 
                   balance(receiver) := balance(receiver) - pdAuth(receiver) .value, state(receiver) := epa ; outmsg := val(pdAuth(receiver))
                end
           else outmsg := ⊥
        end;
      VAL# (msg, receiver, fail?, pdAuth; var balance, state, outmsg)
        begin 
           if msg = val(pdAuth(receiver)) ∧ ¬ fail?
           then balance(receiver) := balance(receiver) + pdAuth(receiver) .value, state(receiver) := idle, outmsg := ack(pdAuth(receiver))
           else outmsg := ⊥
        end;
      ACK# (msg, receiver, fail?, pdAuth; var state, outmsg)
        begin 
           if msg = ack(pdAuth(receiver)) ∧ ¬ fail?
           then state(receiver) := idle, outmsg := ⊥
           else outmsg := ⊥
        end;
end asm specification</SPECBODY></KIVSPEC>
