(* Toy example using counter.

  This example was originally generated by GSVerif from the following processes:

      let P(d:channel,k:bitstring) =
        in(d,i:nat);
        out(c,h(i,k));
        out(d,i+1).

      let Q(d:channel,k:bitstring) =
        in(d,i:nat);
        in(c,y:bitstring);
        if h(i,k) = y
        then out(c,s); out(d,i+1)
        else out(d,i+1).

      process
        !
        new d:channel [precise];
        new k:bitstring;
        (
          ! P(d,k)
        | ! Q(d,k)
        | out(d,0)
        | ! in(d,x:nat); out(d,x)
        )

  GSVerif modifies a query F => \phi with F => \phi || \phi' where \phi' is a property
  that is always false. Instead of using this transformed query, we can declare the
  negation of \phi' as an axiom. See the paper on GSVerif (CSF'18) for more details
  on these properties.
*)

free c:channel.
free s:bitstring [private].

fun h(nat,bitstring):bitstring.

type stamp.

free id:stamp [private].

event Counter(channel,stamp,stamp,nat).

axiom i:nat,i1:nat,st:stamp,st1:stamp,st2:stamp,d:channel;
  event(Counter(d,st2,st,i1)) && event(Counter(d,st2,st,i)) ==> i1 = i;
  event(Counter(d,st2,st,i1)) && event(Counter(d,st2,st1,i1)) ==> st = st1.

query attacker(s).

process
  !
  new d:channel;
  new k:bitstring;
  (
    (
      !
      in(d,i:nat);
      new st[]:stamp;
      event Counter(d,id,st,i);
      out(c,h(i,k));
      out(d,i + 1)
    ) | (
      !
      in(d,i:nat);
      new st[]:stamp;
      event Counter(d,id,st,i);
      in(c,y:bitstring);
      if h(i,k) = y
      then
        out(c,s);
        out(d,i + 1)
      else
        out(d,i + 1)

    )
    | out(d,0)
    | ! in(d,x:nat); out(d,x)
  )

(* EXPECTPV
RESULT not attacker(s[]) is true.
0.012s (user 0.012s + system 0.000s), max rss 7776K
END *)
