Proof using.
unfold get_IR_output_keys.
intros. simpl. repeat break_match; congruence.
Qed.
(* this is cleaner than the auto-generated functional induction scheme *)
Fixpoint good_trace_ind'
(P : list IR -> Prop -> Prop)
(l : list IR) :
P [] True ->
(forall k, P [IRI k] False) ->
(forall k k' l, P (IRI k :: IRI k' :: l) False) ->
(forall k k' l, P l (good_trace l) -> P (IRI k :: IRO k' :: l) (k = k' /\ good_trace l)) ->
(forall k k' l, P l (good_trace l) -> P (IRI k :: IRU k' :: l) (k = k' /\ good_trace l)) ->
(forall k l, P (IRO k :: l) False) ->
(forall k l, P (IRU k :: l) False) ->
P l (good_trace l).
Proof using.
intros.
destruct l; simpl; repeat break_match; auto; subst.
- match goal with
| [ H : context [IRI _ :: IRO _ :: _ ] |- _ ] => apply H
end.
apply good_trace_ind'; auto.
- match goal with
| [ H : context [IRI _ :: IRU _ :: _ ] |- _ ] => apply H
end.
apply good_trace_ind'; auto.
Qed.

(* Specifications: *)
Lemma good_trace_ind :
forall P : list IR -> Prop -> Prop,
P [] True ->
(forall k, P [IRI k] False) ->
(forall k k' ir, P (IRI k :: IRI k' :: ir) False) ->
(forall k k' ir, P ir (good_trace ir) -> P (IRI k :: IRO k' :: ir) (k = k' /\ good_trace ir)) ->
(forall k k' ir, P ir (good_trace ir) -> P (IRI k :: IRU k' :: ir) (k = k' /\ good_trace ir)) ->
(forall k ir, P (IRO k :: ir) False) ->
(forall k ir, P (IRU k :: ir) False) ->
forall ir, P ir (good_trace ir).