<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="../../../unit.xsl"?>
<KIVSPEC name="CASM">
<SPECBODY>
<external/>
asm specification 
   comment: definition of an ASM for the concrete level of the Mondex
   refinement. Only parts of this ASM (STARTFROM#, REQ# etc.) are used 
   in the definitions of concrete operations of the Mondex refinement. 
   Proving ASM refinement directly is future work and may require
   small corrections to the ASM definition.;
   using <a href="../../../specs/set-nat/export/unit.xml">set-nat</a> <a href="../../../specs/genname/export/unit.xml">genname</a> 
         <a href="../../../specs/initether/export/unit.xml">initether</a> <a href="../../../specs/status/export/unit.xml">status</a> 
         <a href="../../../specs/set-PayDetails/export/unit.xml">set-PayDetails</a> 
         <a href="../../../specs/messagelist/export/unit.xml">messagelist</a>
   declaration 

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

      <syn>final state</syn>
      msgl = []

      <syn>CSTEP# </syn>
       <syn>choose</syn>  receiver <syn>with</syn> authentic(receiver) <syn>in </syn>
        <syn>let</syn> msg = hd msgl <syn>in </syn>
         msgl := tl msgl <syn>seq</syn>
         COP#


      <syn>COP# </syn>
         <syn>IGNORE#</syn> ∨ 
         <syn>ABORT#</syn> ∨ 
         <syn>INCREASE#</syn> ∨ 
         <syn>if</syn> isStartFrom(msg) <syn>then</syn> 
          ABORT# ∨ 
          ABORT# <syn>seq</syn> STARTFROM#
         <syn>else</syn> <syn>if</syn> isStartTo(msg) <syn>then</syn>
          ABORT# ∨ 
          ABORT# <syn>seq</syn> STARTTO#
         <syn>else</syn> <syn>if</syn> isreq(msg) ∧ status(receiver) = epr <syn>then</syn> REQ#
         <syn>else</syn> <syn>if</syn> isval(msg) ∧ status(receiver) = epv <syn>then</syn> VAL#
         <syn>else</syn> <syn>if</syn> isack(msg) ∧ status(receiver) = epa <syn>then</syn> ACK#
         <syn>else</syn> ABORT# 
       <syn>seq</syn> LOSEMSG#

         
      <syn>LOSEMSG</syn>#
       <syn>choose</syn> newether <syn>with</syn> newether ⊆ ether ++ outmsg <syn>in</syn> 
        ether := newether

      <syn>IGNORE#</syn>
       outmsg := ⊥

      <syn>INCREASE#</syn>
       <syn>choose</syn> n <syn>with</syn> nextSeqNo(receiver) ≤ n <syn>in</syn> 
         nextSeqNo(receiver) := n <syn>seq</syn> 
         outmsg := ⊥

      <syn>STRICTINCREASE#</syn>
       <syn>choose</syn> n <syn>with</syn> nextSeqNo(receiver) &lt; n <syn>in</syn> 
        nextSeqNo(receiver) := n

      <syn>LOGIFNEEDED#</syn>
       <syn>if</syn> status(receiver) = epa ∨ status(receiver) = epv <syn>then</syn> 
        exLog(receiver) := exLog(receiver) ++ pdAuth(receiver)

      <syn>ABORT#</syn>
       LOGIFNEEDED# <syn>seq</syn>
       status(receiver) := idle <syn>seq</syn> 
       INCREASE#(receiver; nextSeqNo, outmsg) <syn>seq</syn> 
       outmsg := ⊥

      <syn>STARTFROM#</syn>
       <syn>let</syn> msgna = msg .name, 
           value = msg .value, 
           msgno = msg .nextSeqNo
       <syn>in</syn> 
        <syn>if</syn> msg ∈ ether ∧ 
           authentic(msgna) ∧ 
           receiver ≠ msgna ∧ 
           value ≤ balance(receiver) ∧ 
           status(receiver) = idle
        <syn>then</syn> 
         pdAuth(receiver) := mkpd(receiver, nextSeqNo(receiver), msgna, msgno, value)
         status(receiver) := epr
         outmsg := ⊥ <syn>seq</syn> 
         STRICTINCREASE#
        <syn>else</syn> 
         IGNORE#


      <syn>STARTTO</syn>#
       <syn>let</syn> msgna = msg .name, 
           value = msg .value, 
           msgno = msg .nextSeqNo
       <syn>in</syn> 
        <syn>if</syn> msg ∈ ether ∧ 
           authentic(msgna) ∧ 
           receiver ≠ msgna ∧ 
           status(receiver) = idle
        <syn>then</syn>
         pdAuth(receiver) := mkpd(msgna, msgno, receiver, nextSeqNo(receiver), value)
         status(receiver) := epv <syn>seq</syn>
         outmsg := req(pdAuth(receiver)) <syn>seq</syn>
         STRICTINCREASE#
        <syn>else</syn>
         IGNORE# ∨ ABORT#

      <syn>REQ</syn># 
       <syn>if</syn> msg ∈ ether ∧ 
          msg = req(pdAuth(receiver))
       <syn>then</syn> 
        balance(receiver) := balance(receiver) - pdAuth(receiver) .value 
        status(receiver) := epa 
        outmsg := val(pdAuth(receiver))
       <syn>else</syn> IGNORE#

      <syn>VAL</syn>#
       <syn>if</syn> msg ∈ ether ∧ 
          msg = val(pdAuth(receiver))
       <syn>then</syn> 
        balance(receiver) := balance(receiver) + pdAuth(receiver) .value
        status(receiver) := idle
        outmsg := ack(pdAuth(receiver))
       <syn>else</syn> IGNORE#

      <syn>ACK</syn># 
       <syn>if</syn> msg ∈ ether ∧ 
          msg = ack(pdAuth(receiver))
       <syn>then</syn> 
        status(receiver) := idle
        outmsg := ⊥
       <syn>else</syn> IGNORE#

end asm specification</SPECBODY>

<SPECBODY>
<internal/>asm specification 
   comment: definition of an ASM for the concrete level of the Mondex
   refinement. Only parts of this ASM (STARTFROM#, REQ# etc.) are used 
   in the definitions of concrete operations of the Mondex refinement. 
   Proving ASM refinement directly is future work and may require
   small corrections to the ASM definition.;
   using <a href="../../../specs/set-nat/export/unit.xml">set-nat</a> <a href="../../../specs/genname/export/unit.xml">genname</a> 
         <a href="../../../specs/initether/export/unit.xml">initether</a> <a href="../../../specs/status/export/unit.xml">status</a> 
         <a href="../../../specs/set-PayDetails/export/unit.xml">set-PayDetails</a> 
         <a href="../../../specs/messagelist/export/unit.xml">messagelist</a>
    target 
         procedures 
            CASM#   : (name → nat) × (name → PayDetailsSet) × (name → status) × (name → nat) × (name → PayDetails) × messageset × message × 
                      messagelist nonfunctional indeterministic;
            CSTEP#   : (name → nat) × (name → PayDetailsSet) × (name → status) × (name → nat) × (name → PayDetails) × messageset × message × 
                       messagelist nonfunctional indeterministic;
            COP#  name × message : (name → nat) × (name → PayDetailsSet) × (name → status) × (name → nat) × (name → PayDetails) × messageset × message nonfunctional indeterministic;
            LOSEMSG#  message : messageset nonfunctional indeterministic;
            IGNORE#   : message;
            INCREASE#  name : (name → nat) × message nonfunctional indeterministic;
            STRICTINCREASE#  name : (name → nat) nonfunctional indeterministic;
            LOGIFNEEDED#  name × (name → status) × (name → PayDetails) : (name → PayDetailsSet) nonfunctional;
            ABORT#  name × (name → PayDetails) : (name → PayDetailsSet) × (name → status) × (name → nat) × message nonfunctional indeterministic;
            STARTFROM#  message × name × (name → nat) × messageset : (name → PayDetailsSet) × (name → status) × (name → nat) × (name → PayDetails) × 
                                                                     message nonfunctional indeterministic;
            STARTTO#  message × name × messageset : (name → PayDetailsSet) × (name → status) × (name → nat) × (name → PayDetails) × message nonfunctional indeterministic;
            REQ#  message × name × (name → PayDetails) × messageset : (name → nat) × (name → status) × message nonfunctional indeterministic;
            VAL#  message × name × (name → PayDetails) × messageset : (name → nat) × (name → status) × message nonfunctional indeterministic;
            ACK#  message × name × (name → PayDetails) × messageset : (name → status) × message nonfunctional indeterministic;
         variables 
            balance : name → nat; 
            exLog : name → PayDetailsSet; 
            status : name → status; 
            nextSeqNo : name → nat; 
            pdAuth : name → PayDetails; 
            ether, newether : messageset; 
            msgno, value : nat; 
            msgna, receiver : name; 
            messages : messageset; 
            msg, outmsg : message; 
   declaration 
      asm
      : CASM# (var balance, exLog, status, nextSeqNo, pdAuth, ether, outmsg, msgl)
          begin 
             exLog := λ na. ∅, ether := {λ msg. isStartTo(msg)}  ∪ {λ msg. isStartFrom(msg)}  ∪ {⊥} , status := λ na. idle ; 
             while msgl ≠ [] do CSTEP#(; balance, exLog, status, nextSeqNo, pdAuth, ether, outmsg, msgl)
          end;
      CSTEP# (var balance, exLog, status, nextSeqNo, pdAuth, ether, outmsg, msgl)
        begin 
           var  receiver
           with authentic(receiver)
           in var msg = hd msgl in begin 
                                      msgl := tl msgl ; COP#(receiver, msg; balance, exLog, status, nextSeqNo, pdAuth, ether, outmsg)
                                   end
        end;
      COP# (receiver, msg; var balance, exLog, status, nextSeqNo, pdAuth, ether, outmsg)
        begin 
           IGNORE#(; outmsg) ∨ 
           begin 
              ABORT#(receiver, pdAuth; exLog, status, nextSeqNo, outmsg) ∨ 
              begin 
                 INCREASE#(receiver; nextSeqNo, outmsg) ∨ 
                 if isStartFrom(msg)
                 then begin 
                         ABORT#(receiver, pdAuth; exLog, status, nextSeqNo, outmsg) ∨ 
                         begin 
                            ABORT#(receiver, pdAuth; exLog, status, nextSeqNo, outmsg) ; 
                            STARTFROM#(msg, receiver, balance, ether; exLog, status, nextSeqNo, pdAuth, outmsg)
                         end
                      end
                 else if isStartTo(msg)
                      then begin 
                              ABORT#(receiver, pdAuth; exLog, status, nextSeqNo, outmsg) ∨ 
                              begin 
                                 ABORT#(receiver, pdAuth; exLog, status, nextSeqNo, outmsg) ; 
                                 STARTTO#(msg, receiver, ether; exLog, status, nextSeqNo, pdAuth, outmsg)
                              end
                           end
                      else if isreq(msg) ∧ status(receiver) = epr
                           then REQ#(msg, receiver, pdAuth, ether; balance, status, outmsg)
                           else if isval(msg) ∧ status(receiver) = epv
                                then VAL#(msg, receiver, pdAuth, ether; balance, status, outmsg)
                                else if isack(msg) ∧ status(receiver) = epa
                                     then ACK#(msg, receiver, pdAuth, ether; status, outmsg)
                                     else ABORT#(receiver, pdAuth; exLog, status, nextSeqNo, outmsg)
              end
           end ; 
           LOSEMSG#(outmsg; ether)
        end;
      LOSEMSG# (outmsg; var ether)
        begin 
           var  newether with newether ⊆ ether ++ outmsg in ether := newether
        end;
      IGNORE# (var outmsg)
        begin 
           outmsg := ⊥
        end;
      INCREASE# (receiver; var nextSeqNo, outmsg)
        begin 
           var  n with nextSeqNo(receiver) ≤ n in nextSeqNo(receiver) := n ; outmsg := ⊥
        end;
      STRICTINCREASE# (receiver; var nextSeqNo)
        begin 
           var  n with nextSeqNo(receiver) &lt; n in nextSeqNo(receiver) := n
        end;
      LOGIFNEEDED# (receiver, status, pdAuth; var exLog)
        begin 
           if status(receiver) = epa ∨ status(receiver) = epv
           then exLog(receiver) := exLog(receiver) ++ pdAuth(receiver)
        end;
      ABORT# (receiver, pdAuth; var exLog, status, nextSeqNo, outmsg)
        begin 
           LOGIFNEEDED#(receiver, status, pdAuth; exLog) ; status(receiver) := idle ; INCREASE#(receiver; nextSeqNo, outmsg) ; outmsg := ⊥
        end;
      STARTFROM# (msg, receiver, balance, ether; var exLog, status, nextSeqNo, pdAuth, outmsg)
        begin 
           var msgna = msg .name, value = msg .value, msgno = msg .nextSeqNo
           in if msg ∈ ether ∧ authentic(msgna) ∧ receiver ≠ msgna ∧ value ≤ balance(receiver) ∧ status(receiver) = idle
              then begin 
                      pdAuth(receiver) := mkpd(receiver, nextSeqNo(receiver), msgna, msgno, value), status(receiver) := epr, outmsg := ⊥ ; 
                      STRICTINCREASE#(receiver; nextSeqNo)
                   end
              else begin 
                      IGNORE#(; outmsg) ∨ ABORT#(receiver, pdAuth; exLog, status, nextSeqNo, outmsg)
                   end
        end;
      STARTTO# (msg, receiver, ether; var exLog, status, nextSeqNo, pdAuth, outmsg)
        begin 
           var msgna = msg .name, value = msg .value, msgno = msg .nextSeqNo
           in if msg ∈ ether ∧ authentic(msgna) ∧ receiver ≠ msgna ∧ status(receiver) = idle
              then begin 
                      pdAuth(receiver) := mkpd(msgna, msgno, receiver, nextSeqNo(receiver), value), status(receiver) := epv ; 
                      outmsg := req(pdAuth(receiver)) ; 
                      STRICTINCREASE#(receiver; nextSeqNo)
                   end
              else begin 
                      IGNORE#(; outmsg) ∨ ABORT#(receiver, pdAuth; exLog, status, nextSeqNo, outmsg)
                   end
        end;
      REQ# (msg, receiver, pdAuth, ether; var balance, status, outmsg)
        begin 
           if msg ∈ ether ∧ msg = req(pdAuth(receiver))
           then balance(receiver) := balance(receiver) - pdAuth(receiver) .value, status(receiver) := epa, outmsg := val(pdAuth(receiver))
           else IGNORE#(; outmsg)
        end;
      VAL# (msg, receiver, pdAuth, ether; var balance, status, outmsg)
        begin 
           if msg ∈ ether ∧ msg = val(pdAuth(receiver))
           then balance(receiver) := balance(receiver) + pdAuth(receiver) .value, status(receiver) := idle, outmsg := ack(pdAuth(receiver))
           else IGNORE#(; outmsg)
        end;
      ACK# (msg, receiver, pdAuth, ether; var status, outmsg)
        begin 
           if msg ∈ ether ∧ msg = ack(pdAuth(receiver))
           then status(receiver) := idle, outmsg := ⊥
           else IGNORE#(; outmsg)
        end;
end asm specification</SPECBODY></KIVSPEC>
