set preciseActions = true.

(* The type keyseed was replaced by bitstring since types are ignored. *)
(* The type pkey was replaced by bitstring since types are ignored. *)
(* The type skey was replaced by bitstring since types are ignored. *)
(* The type signature was replaced by bitstring since types are ignored. *)

fun sk(bitstring):bitstring.
fun pk(bitstring):bitstring.
fun sign(bitstring,bitstring):bitstring.

fun checksignature(bitstring,bitstring,bitstring):bool
reduc forall x:bitstring,m:bitstring; checksignature(pk(x),sign(m,sk(x)),m) = true.

event accepted(nat,bitstring).
event signed(nat,bitstring).

free c:channel.

set ignoreTypes = false.

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 counter:nat,x:bitstring;
  inj-event(accepted(counter,x)) ==>
        inj-event(signed(counter,x)).

process
  !(
  new kseed:bitstring;
  let pk1:bitstring = pk(kseed) in
  let sk1:bitstring = sk(kseed) in
  out(c,pk1);
  (
    !(  (* Application of the process signer *)
    in(c,(counter:nat,x:bitstring));
    event signed(counter,x);
    let sig:bitstring = sign((counter,x),sk1) in
    out(c,sig);
    0
    )  ) | (
    new c_state:channel; (* Application of the process verifier *)
    (
      out(c_state,0);
      0
    ) | (
      !(
      in(c,(sig:bitstring,x:bitstring));
      in(c_state,counter:nat);
      new st[]:stamp;
      event Counter(c_state,id,st,counter);
      if checksignature(pk1,sig,(counter,x)) then
      event accepted(counter,x);
      out(c_state,counter + 1);
      0
      )    )
  )
  )

(* EXPECTPV
RESULT inj-event(accepted(counter_2,x_2)) ==> inj-event(signed(counter_2,x_2)) is true.
0.012s (user 0.012s + system 0.000s), max rss 8652K
END *)
