/* Test for state machine. */
#include <stdbool.h>
#include <ccan/cast/cast.h>
#include <ccan/array_size/array_size.h>
#include <ccan/tal/tal.h>
#include <ccan/tal/str/str.h>
#include <ccan/err/err.h>
#include <ccan/structeq/structeq.h>
#include <ccan/htable/htable_type.h>
#include <ccan/hash/hash.h>
#include <ccan/opt/opt.h>
#include <ccan/asort/asort.h>
#include <ccan/list/list.h>
#include "version.h"

static bool record_input_mapping(int b);
#define MAPPING_INPUTS(b) \
	do { if (record_input_mapping(b)) return false; } while(0)

#include "state.h"
#include "names.c"

static bool quick = false;
static bool dot_simplify = false;
static bool dot_enable = false;
static bool dot_include_abnormal = false;
static bool dot_include_errors = false;
static bool include_nops = false;
static enum state_input *mapping_inputs;

enum failure {
	FAIL_NONE,
	FAIL_DECLINE_HTLC,
	FAIL_STEAL,
	FAIL_ACCEPT_OPEN,
	FAIL_ACCEPT_ANCHOR,
	FAIL_ACCEPT_OPEN_COMMIT_SIG,
	FAIL_ACCEPT_OPEN_COMPLETE,
	FAIL_ACCEPT_HTLC_ADD,
	FAIL_ACCEPT_HTLC_FAIL,
	FAIL_ACCEPT_HTLC_FULFILL,
	FAIL_ACCEPT_UPDATE_ACCEPT,
	FAIL_ACCEPT_UPDATE_COMPLETE,
	FAIL_ACCEPT_UPDATE_SIGNATURE,
	FAIL_ACCEPT_CLOSE,
	FAIL_ACCEPT_CLOSE_COMPLETE,
	FAIL_ACCEPT_CLOSE_ACK,
	FAIL_ACCEPT_SIMULTANEOUS_CLOSE
};

struct htlc {
	bool to_them;
	unsigned int id;
};

struct htlc_progress {
	struct htlc htlc; /* id == -1 if none in progress. */
	bool adding; /* otherwise, removing. */
};

struct htlc_spend_watch {
	unsigned int id;
	enum state_input done;
};

/* Beyond this we consider cases equal for traverse loop detection. */
#define CAP_HTLCS 1

/* How many HTLCs to negotiate. */
#define MAX_HTLCS 2

/* But we can have many different malleated commit txs. */
#define HTLC_ARRSIZE 20

/*
 * Worst case:
 * Low priority: PKT_UPDATE_ADD_HTLC
 * Receive update, which we decline: PKT_UPDATE_DECLINE_HTLC
 * Send new update: PKT_UPDATE_ADD_HTLC
 * Start close: PKT_CLOSE
 * Some error: PKT_ERROR
 */
#define MAX_OUTQ 5

/* No padding, for fast compare and hashing. */
struct core_state {
	/* What bitcoin/timeout notifications are we subscribed to? */
	uint64_t event_notifies;

	enum state_input current_command;

	enum state_input outputs[MAX_OUTQ];

	uint8_t num_outputs;
	/* Here down need to be generated from other fields */
	uint8_t state;
	uint8_t peercond;
	bool has_current_htlc;

	uint8_t capped_htlcs_to_them;
	uint8_t capped_htlcs_to_us;
	uint8_t capped_htlc_spends_to_them;
	uint8_t capped_htlc_spends_to_us;

	uint8_t capped_live_htlcs_to_them;
	uint8_t capped_live_htlcs_to_us;
	bool valid;
	bool pad[5];
};

struct peer {
	struct core_state core;

	enum state state;
	enum state_peercond cond;

	/* To store HTLC numbers. */
	unsigned int pkt_data[MAX_OUTQ];

	/* id == -1 if none currently. */
	struct htlc_progress current_htlc;

	/* Transitory: True if we just declined an HTLC. */
	bool htlc_declined;

	/* Have we created an anchor tx? */
	bool anchor;
	/* Have we broadcast anchor? */
	bool anchor_broadcast;
	/* Have we spent anchor (or seen them do it?) */
	bool anchor_spent;

	unsigned int num_htlcs_to_them, num_htlcs_to_us;
	struct htlc htlcs_to_them[MAX_HTLCS], htlcs_to_us[MAX_HTLCS];

	unsigned int num_live_htlcs_to_them, num_live_htlcs_to_us;
	struct htlc live_htlcs_to_them[HTLC_ARRSIZE], live_htlcs_to_us[HTLC_ARRSIZE];

	unsigned int num_htlc_spends_to_them, num_htlc_spends_to_us;
	struct htlc htlc_spends_to_us[HTLC_ARRSIZE],
		htlc_spends_to_them[HTLC_ARRSIZE];

	unsigned int num_rvals_known;
	unsigned int rvals_known[HTLC_ARRSIZE];

	/* Where we came from. */
	const struct trail *trail;

	/* Current input and idata (for fail()) */
	enum state_input current_input;
	const union input *current_idata;

	const char *error;

	/* ID. */
	const char *name;
	/* The other peer's data. */
	struct peer *other;
};

/* To recontruct errors. */
struct trail {
	const struct trail *prev;
	const char *name;
	enum state_input input;
	const struct peer *before, *after;
	int htlc_id;
	unsigned int num_peer_outputs;
	unsigned int depth;
	const char *pkt_sent;
};

struct situation {
	union {
		struct core_state s;
		uint32_t u32[sizeof(struct core_state)/sizeof(uint32_t)];
	} a, b;
};

static const struct situation *situation_keyof(const struct situation *situation)
{
	return situation;
}

/* After 2, we stop looping. */
static unsigned int cap(unsigned int val)
{
	return val > CAP_HTLCS ? CAP_HTLCS : val;
}

static size_t situation_hash(const struct situation *situation)
{
	BUILD_ASSERT(sizeof(situation->a.u32) == sizeof(situation->a.s));
	return hash(situation->a.u32, ARRAY_SIZE(situation->a.u32), 0);
}

static bool situation_eq(const struct situation *a, const struct situation *b)
{
	/* No padding */
	BUILD_ASSERT(sizeof(a->a.s)
		     == (sizeof(a->a.s.event_notifies)
			 + sizeof(a->a.s.state)
			 + sizeof(a->a.s.current_command)
			 + sizeof(a->a.s.outputs)
			 + sizeof(a->a.s.num_outputs)
			 + sizeof(a->a.s.peercond)
			 + sizeof(a->a.s.has_current_htlc)
			 + sizeof(a->a.s.capped_htlcs_to_us)
			 + sizeof(a->a.s.capped_htlcs_to_them)
			 + sizeof(a->a.s.capped_htlc_spends_to_us)
			 + sizeof(a->a.s.capped_htlc_spends_to_them)
			 + sizeof(a->a.s.capped_live_htlcs_to_us)
			 + sizeof(a->a.s.capped_live_htlcs_to_them)
			 + sizeof(a->a.s.valid)
			 + sizeof(a->a.s.pad)));
	return structeq(&a->a.s, &b->a.s) && structeq(&a->b.s, &b->b.s);
}

struct dot_edge {
	const char *oldstate, *newstate;
	enum state_input i;
	const char *pkt;
};

static const struct dot_edge *dot_edge_keyof(const struct dot_edge *dot_edge)
{
	return dot_edge;
}

static size_t dot_edge_hash(const struct dot_edge *d)
{
	uint32_t pkthash;

	if (d->pkt)
		pkthash = hash(d->pkt, strlen(d->pkt), d->i);
	else
		pkthash = d->i;
	return hash_pointer(d->oldstate, hash_pointer(d->newstate, pkthash));
}

static bool dot_edge_eq(const struct dot_edge *a, const struct dot_edge *b)
{
	return a->oldstate == b->oldstate
		&& a->newstate == b->newstate
		&& a->i == b->i
		&& ((a->pkt == NULL && b->pkt == NULL)
		    || streq(a->pkt, b->pkt));
}

HTABLE_DEFINE_TYPE(struct dot_edge,
		   dot_edge_keyof, dot_edge_hash, dot_edge_eq,
		   edge_hash);

HTABLE_DEFINE_TYPE(struct situation,
		   situation_keyof, situation_hash, situation_eq,
		   sithash);

struct hist {
	/* All the different state combinations. */
	struct sithash sithash;

	/* The different inputs. */
	enum state_input **inputs_per_state;

	/* The different outputs. */
	enum state_input *outputs;

	/* Edges for the dot graph, if any. */
	struct edge_hash edges;

	/* For dumping states. */
	struct state_dump {
		enum state_input input;
		enum state next;
		enum state_input pkt;
	} **state_dump;
};

struct fail_details {
	/* The universe state at the time. */
	struct peer us, other;
	enum state_input input;
	union input idata;
	/* Previous history. */
	const struct trail *prev_trail;
};

struct failpoint {
	/* Hash key (with which_fail) */
	struct situation sit;
	/* Which failure */
	enum failure which_fail;

	/* If we haven't tried failing yet, this is set */
	struct fail_details *details;
};

static const struct failpoint *
failpoint_keyof(const struct failpoint *f)
{
	return f;
}

static size_t failpoint_hash(const struct failpoint *f)
{
	return situation_hash(&f->sit) + f->which_fail;
}

static bool failpoint_eq(const struct failpoint *a,
			 const struct failpoint *b)
{
	return a->which_fail == b->which_fail
		&& situation_eq(&a->sit, &b->sit);
}

HTABLE_DEFINE_TYPE(struct failpoint,
		   failpoint_keyof, failpoint_hash, failpoint_eq,
		   failhash);

static struct failhash failhash;

static void update_core(struct core_state *core, const struct peer *peer)
{
	size_t i;

	for (i = core->num_outputs; i < ARRAY_SIZE(core->outputs); i++)
		assert(core->outputs[i] == 0);

	core->has_current_htlc = peer->current_htlc.htlc.id != -1;
	core->state = peer->state;
	BUILD_ASSERT(STATE_MAX < 256);
	core->peercond = peer->cond;
	core->capped_htlcs_to_us = cap(peer->num_htlcs_to_us);
	core->capped_htlcs_to_them = cap(peer->num_htlcs_to_them);
	core->capped_live_htlcs_to_us = cap(peer->num_live_htlcs_to_us);
	core->capped_live_htlcs_to_them = cap(peer->num_live_htlcs_to_them);
	core->capped_htlc_spends_to_us = cap(peer->num_htlc_spends_to_us);
	core->capped_htlc_spends_to_them = cap(peer->num_htlc_spends_to_them);
	core->valid = true;
}

static void situation_init(struct situation *sit,
			   const struct peer *peer)
{
	if (streq(peer->name, "A")) {
		sit->a.s = peer->core;
		update_core(&sit->a.s, peer);
		/* If we're still talking to peer, their state matters. */
		if (peer->cond != PEER_CLOSED
		    || peer->other->cond != PEER_CLOSED) {
			sit->b.s = peer->other->core;
			update_core(&sit->b.s, peer->other);
		} else
			memset(&sit->b.s, 0, sizeof(sit->b.s));
	} else {
		sit->b.s = peer->core;
		update_core(&sit->b.s, peer);
		/* If we're still talking to peer, their state matters. */
		if (peer->cond != PEER_CLOSED
		    || peer->other->cond != PEER_CLOSED) {
			sit->a.s = peer->other->core;
			update_core(&sit->a.s, peer->other);
		} else
			memset(&sit->a.s, 0, sizeof(sit->a.s));
	}
}


/* Returns false if we've been here before. */
static bool sithash_update(struct sithash *sithash,
			   const struct peer *peer)
{
	struct situation sit;

	situation_init(&sit, peer);

	if (sithash_get(sithash, &sit))
		return false;

	sithash_add(sithash, tal_dup(NULL, struct situation, &sit));
	return true;
}

static void copy_peers(struct peer *dst, struct peer *other,
		       const struct peer *src)
{
	*dst = *src;
	*other = *src->other;
	dst->other = other;
	other->other = dst;
}

static const struct trail *clone_trail(const tal_t *ctx,
				       const struct trail *trail)
{
	struct trail *t;

	if (!trail)
		return NULL;

	t = tal_dup(ctx, struct trail, trail);
	t->before = tal_dup(t, struct peer, trail->before);
	t->after = trail->after ? tal_dup(t, struct peer, trail->after)
		: NULL;
	t->pkt_sent = trail->pkt_sent ? tal_strdup(t, trail->pkt_sent) : NULL;
	t->prev = clone_trail(t, trail->prev);
	return t;
}

static const union input dup_idata(const tal_t *ctx,
				    enum state_input input,
				    const union input *idata)
{
	union input i;

	if (input_is_pkt(input))
		i.pkt = (Pkt *)tal_strdup(ctx, (const char *)idata->pkt);
	else if (input == CMD_SEND_HTLC_ADD
		 || input == CMD_SEND_HTLC_FULFILL
		 || input == CMD_SEND_HTLC_FAIL) {
		i.htlc_prog = tal_dup(ctx, struct htlc_progress,
				      idata->htlc_prog);
	} else {
		if (idata->htlc)
			i.htlc = tal_dup(ctx, struct htlc, idata->htlc);
		else
			i.htlc = NULL;
	}
	return i;
}

static bool fail(const struct peer *peer, enum failure which_fail)
{
	struct failpoint *f = tal(NULL, struct failpoint), *old;

	situation_init(&f->sit, peer);
	f->which_fail = which_fail;

	/* If we've been here before... */
	old = failhash_get(&failhash, f);
	if (old) {
		tal_free(f);
		/* If we haven't tried failing, try that now. */
		if (old->details) {
			old->details = tal_free(old->details);
			return true;
		}
		return false;
	}

	/* First time here, save details, don't fail yet. */
	f->details = tal(f, struct fail_details);
	/* Copy old peer, in case it has been changed since. */
	copy_peers(&f->details->us, &f->details->other, peer->trail->before);
	f->details->us.trail = clone_trail(f->details, peer->trail);
	f->details->input = peer->current_input;
	f->details->idata = dup_idata(f->details,
				      f->details->input, peer->current_idata);

	failhash_add(&failhash, f);
	return false;
}

static enum state_input input_by_name(const char *name)
{
	size_t i;

	for (i = 0; enum_state_input_names[i].name; i++) {
		if (!strstarts(name, enum_state_input_names[i].name))
			continue;
		if (name[strlen(enum_state_input_names[i].name)] == '\0'
		    || name[strlen(enum_state_input_names[i].name)] == ':')
			return enum_state_input_names[i].v;
	}
	abort();
}

static Pkt *new_pkt(const tal_t *ctx, enum state_input i)
{
	return (Pkt *)input_name(i);
}

static unsigned int htlc_id_from_pkt(const Pkt *pkt)
{
	const char *s = strstr((const char *)pkt, ": HTLC #");
	return s ? atoi(s + strlen(": HTLC #")) : -1U;
}

static Pkt *htlc_pkt(const tal_t *ctx, const char *prefix, unsigned int id)
{
	assert(id != -1);
	return (Pkt *)tal_fmt(ctx, "%s: HTLC #%u", prefix, id);
}

static unsigned int htlc_id_from_tx(const struct bitcoin_tx *tx)
{
	const char *s = strstr((const char *)tx, "HTLC #");
	return atoi(s + strlen("HTLC #"));
}

static struct bitcoin_tx *htlc_tx(const tal_t *ctx,
				  const char *prefix, unsigned int id)
{
	return (struct bitcoin_tx *)tal_fmt(ctx, "%s HTLC #%u", prefix, id);
}

static struct htlc *find_any_htlc(const struct htlc *htlcs, size_t num,
					unsigned id)
{
	unsigned int i;

	for (i = 0; i < num; i++)
		if (htlcs[i].id == id)
			return (struct htlc *)htlcs + i;
	return NULL;
}

static struct htlc *find_htlc(const struct peer *peer, unsigned id)
{
	const struct htlc *h;

	h = find_any_htlc(peer->htlcs_to_us, peer->num_htlcs_to_us, id);
	if (!h)
		h = find_any_htlc(peer->htlcs_to_them,
				  peer->num_htlcs_to_them, id);
	return (struct htlc *)h;
}

static struct htlc *find_live_htlc(const struct peer *peer,
				   unsigned id)
{
	const struct htlc *h;

	h = find_any_htlc(peer->live_htlcs_to_us, peer->num_live_htlcs_to_us,
			  id);
	if (!h)
		h = find_any_htlc(peer->live_htlcs_to_them,
				  peer->num_live_htlcs_to_them, id);
	return (struct htlc *)h;
}

static struct htlc *find_htlc_spend(const struct peer *peer,
					  unsigned id)
{
	const struct htlc *h;

	h = find_any_htlc(peer->htlc_spends_to_us,
			  peer->num_htlc_spends_to_us,
			  id);
	if (!h)
		h = find_any_htlc(peer->htlc_spends_to_them,
				  peer->num_htlc_spends_to_them, id);
	return (struct htlc *)h;
}

/* FIXME: order functions correctly. */
static void report_trail(const struct trail *t, const char *problem);

static void set_current_htlc(struct peer *peer,
			     unsigned int id,
			     bool to_them, bool adding)
{
	if (peer->current_htlc.htlc.id != -1)
		report_trail(peer->trail, "Already have current htlc");

	assert(id != -1);
	peer->current_htlc.htlc.id = id;
	peer->current_htlc.htlc.to_them = to_them;
	peer->current_htlc.adding = adding;
}

static void clear_current_htlc(struct peer *peer)
{
	if (peer->current_htlc.htlc.id == -1)
		report_trail(peer->trail, "No current htlc");

	peer->current_htlc.htlc.id = -1;
}

static bool rval_known(const struct peer *peer, unsigned int id)
{
	unsigned int i;

	for (i = 0; i < peer->num_rvals_known; i++)
		if (peer->rvals_known[i] == id)
			return true;
	return false;
}

static void add_rval(struct peer *peer, unsigned int id)
{
	if (!rval_known(peer, id)) {
		assert(peer->num_rvals_known < ARRAY_SIZE(peer->rvals_known));
		peer->rvals_known[peer->num_rvals_known++] = id;
	}
}

Pkt *pkt_open(const tal_t *ctx, const struct peer *peer,
	      OpenChannel__AnchorOffer anchor)
{
	return new_pkt(ctx, PKT_OPEN);
}

Pkt *pkt_anchor(const tal_t *ctx, const struct peer *peer)
{
	return new_pkt(ctx, PKT_OPEN_ANCHOR);
}

Pkt *pkt_open_commit_sig(const tal_t *ctx, const struct peer *peer)
{
	return new_pkt(ctx, PKT_OPEN_COMMIT_SIG);
}

Pkt *pkt_open_complete(const tal_t *ctx, const struct peer *peer)
{
	return new_pkt(ctx, PKT_OPEN_COMPLETE);
}

Pkt *pkt_htlc_add(const tal_t *ctx, const struct peer *peer,
		     const struct htlc_progress *htlc_prog)
{
	return htlc_pkt(ctx, "PKT_UPDATE_ADD_HTLC", htlc_prog->htlc.id);
}

Pkt *pkt_htlc_fulfill(const tal_t *ctx, const struct peer *peer,
		      const struct htlc_progress *htlc_prog)
{
	return htlc_pkt(ctx, "PKT_UPDATE_FULFILL_HTLC", htlc_prog->htlc.id);
}

Pkt *pkt_htlc_fail(const tal_t *ctx, const struct peer *peer,
			const struct htlc_progress *htlc_prog)
{
	return htlc_pkt(ctx, "PKT_UPDATE_FAIL_HTLC", htlc_prog->htlc.id);
}

Pkt *pkt_update_accept(const tal_t *ctx, const struct peer *peer)
{
	return htlc_pkt(ctx, "PKT_UPDATE_ACCEPT", peer->current_htlc.htlc.id);
}

Pkt *pkt_update_signature(const tal_t *ctx, const struct peer *peer)
{
	return htlc_pkt(ctx, "PKT_UPDATE_SIGNATURE",
			peer->current_htlc.htlc.id);
}

Pkt *pkt_update_complete(const tal_t *ctx, const struct peer *peer)
{
	return htlc_pkt(ctx, "PKT_UPDATE_COMPLETE",
			peer->current_htlc.htlc.id);
}

Pkt *pkt_err(const tal_t *ctx, const char *fmt, ...)
{
	char *str;
	va_list ap;

	str = tal_strdup(ctx, "PKT_ERROR: ");
	va_start(ap, fmt);
	tal_append_vfmt(&str, fmt, ap);
	va_end(ap);

	return (Pkt *)str;
}

Pkt *pkt_close(const tal_t *ctx, const struct peer *peer)
{
	return new_pkt(ctx, PKT_CLOSE);
}

Pkt *pkt_close_complete(const tal_t *ctx, const struct peer *peer)
{
	return new_pkt(ctx, PKT_CLOSE_COMPLETE);
}

Pkt *pkt_close_ack(const tal_t *ctx, const struct peer *peer)
{
	return new_pkt(ctx, PKT_CLOSE_ACK);
}

Pkt *pkt_err_unexpected(const tal_t *ctx, const Pkt *pkt)
{
	return pkt_err("Unexpected pkt %s", (const char *)pkt);
}

Pkt *accept_pkt_open(const tal_t *ctx,
		     struct peer *peer,
		     const Pkt *pkt)
{
	if (fail(peer, FAIL_ACCEPT_OPEN))
		return pkt_err(ctx, "Error inject");
	return NULL;
}

Pkt *accept_pkt_anchor(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
{
	if (fail(peer, FAIL_ACCEPT_ANCHOR))
		return pkt_err(ctx, "Error inject");
	return NULL;
}

Pkt *accept_pkt_open_commit_sig(const tal_t *ctx,
				struct peer *peer,
				const Pkt *pkt)
{
	if (fail(peer, FAIL_ACCEPT_OPEN_COMMIT_SIG))
		return pkt_err(ctx, "Error inject");
	return NULL;
}

Pkt *accept_pkt_open_complete(const tal_t *ctx,
			      struct peer *peer,
			      const Pkt *pkt)
{
	if (fail(peer, FAIL_ACCEPT_OPEN_COMPLETE))
		return pkt_err(ctx, "Error inject");
	return NULL;
}

Pkt *accept_pkt_htlc_add(const tal_t *ctx,
			    struct peer *peer, const Pkt *pkt,
			    Pkt **decline)
{
	if (fail(peer, FAIL_ACCEPT_HTLC_ADD))
		return pkt_err(ctx, "Error inject");

	/* This is the current htlc: If they propose it, it's to us. */
	set_current_htlc(peer, htlc_id_from_pkt(pkt), false, true);

	if (fail(peer, FAIL_DECLINE_HTLC))
		*decline = new_pkt(ctx, PKT_UPDATE_DECLINE_HTLC);
	else
		*decline = NULL;

	return NULL;
}

Pkt *accept_pkt_htlc_fail(const tal_t *ctx,
			       struct peer *peer, const Pkt *pkt)
{
	unsigned int id = htlc_id_from_pkt(pkt);
	const struct htlc *h = find_htlc(peer, id);

	if (fail(peer, FAIL_ACCEPT_HTLC_FAIL))
		return pkt_err(ctx, "Error inject");

	/* The shouldn't fail unless it's to them */
	assert(h->to_them);

	/* This is the current htlc */
	set_current_htlc(peer, h->id, h->to_them, false);
	return NULL;
}

Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
			     struct peer *peer, const Pkt *pkt)
{
	unsigned int id = htlc_id_from_pkt(pkt);
	const struct htlc *h = find_htlc(peer, id);

	if (fail(peer, FAIL_ACCEPT_HTLC_FULFILL))
		return pkt_err(ctx, "Error inject");

	/* The shouldn't complete unless it's to them */
	assert(h->to_them);

	/* This gives us the r value. */
	add_rval(peer, htlc_id_from_pkt(pkt));

	/* This is the current htlc */
	set_current_htlc(peer, h->id, h->to_them, false);
	return NULL;
}

Pkt *accept_pkt_update_accept(const tal_t *ctx,
			      struct peer *peer, const Pkt *pkt)
{
	unsigned int id = htlc_id_from_pkt(pkt);

	assert(id == peer->current_htlc.htlc.id);

	if (fail(peer, FAIL_ACCEPT_UPDATE_ACCEPT))
		return pkt_err(ctx, "Error inject");

	return NULL;
}

Pkt *accept_pkt_update_complete(const tal_t *ctx,
				struct peer *peer, const Pkt *pkt)
{
	unsigned int id = htlc_id_from_pkt(pkt);

	assert(id == peer->current_htlc.htlc.id);

	if (fail(peer, FAIL_ACCEPT_UPDATE_COMPLETE))
		return pkt_err(ctx, "Error inject");

	return NULL;
}

Pkt *accept_pkt_update_signature(const tal_t *ctx,
 				 struct peer *peer, const Pkt *pkt)
{
	unsigned int id = htlc_id_from_pkt(pkt);

	assert(id == peer->current_htlc.htlc.id);

	if (fail(peer, FAIL_ACCEPT_UPDATE_SIGNATURE))
		return pkt_err(ctx, "Error inject");

	return NULL;
}

Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
{
	if (fail(peer, FAIL_ACCEPT_CLOSE))
		return pkt_err(ctx, "Error inject");
	return NULL;
}

Pkt *accept_pkt_close_complete(const tal_t *ctx,
			       struct peer *peer, const Pkt *pkt)
{
	if (fail(peer, FAIL_ACCEPT_CLOSE_COMPLETE))
		return pkt_err(ctx, "Error inject");
	return NULL;
}

Pkt *accept_pkt_simultaneous_close(const tal_t *ctx,
				   struct peer *peer,
				   const Pkt *pkt)
{
	if (fail(peer, FAIL_ACCEPT_SIMULTANEOUS_CLOSE))
		return pkt_err(ctx, "Error inject");
	return NULL;
}

Pkt *accept_pkt_close_ack(const tal_t *ctx,
			  struct peer *peer, const Pkt *pkt)
{
	if (fail(peer, FAIL_ACCEPT_CLOSE_ACK))
		return pkt_err(ctx, "Error inject");
	return NULL;
}

static struct bitcoin_tx *bitcoin_tx(const char *str)
{
	return (struct bitcoin_tx *)str;
}

static bool bitcoin_tx_is(const struct bitcoin_tx *btx, const char *str)
{
	return streq((const char *)btx, str);
}

const struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx, struct peer *peer)
{
	if (!peer->anchor)
		report_trail(peer->trail, "Can't create anchor tx: no anchor!");
	peer->anchor = false;
	peer->anchor_broadcast = true;
	return bitcoin_tx("anchor");
}

const struct bitcoin_tx *bitcoin_close(const tal_t *ctx,
				       struct peer *peer)
{
	peer->anchor_spent = true;
	return bitcoin_tx("close");
}

const struct bitcoin_tx *bitcoin_spend_ours(const tal_t *ctx,
					    const struct peer *peer)
{
	return bitcoin_tx("spend our commit");
}

const struct bitcoin_tx *bitcoin_spend_theirs(const tal_t *ctx,
					      const struct peer *peer,
					      const struct bitcoin_event *btc)
{
	return bitcoin_tx("spend their commit");
}

const struct bitcoin_tx *bitcoin_steal(const tal_t *ctx,
				       const struct peer *peer,
				       struct bitcoin_event *btc)
{
	if (fail(peer, FAIL_STEAL))
		return NULL;
	return bitcoin_tx("steal");
}

const struct bitcoin_tx *bitcoin_commit(const tal_t *ctx, struct peer *peer)
{
	peer->anchor_spent = true;
	return bitcoin_tx("our commit");
}

/* Create a HTLC refund collection */
const struct bitcoin_tx *bitcoin_htlc_timeout(const tal_t *ctx,
					      const struct peer *peer,
					      const struct htlc *htlc)
{
	return htlc_tx(ctx, "htlc timeout", htlc->id);
}

/* Create a HTLC collection */
const struct bitcoin_tx *bitcoin_htlc_spend(const tal_t *ctx,
					    const struct peer *peer,
					    const struct htlc *htlc)
{
	return htlc_tx(ctx, "htlc fulfill", htlc->id);
}

bool committed_to_htlcs(const struct peer *peer)
{
	return peer->num_htlcs_to_them != 0 || peer->num_htlcs_to_us != 0;
}

#define TEST_STATE_COVERAGE 1
#include "state.c"
#include <ccan/tal/tal.h>
#include <stdio.h>

static void peer_init(struct peer *peer,
		      struct peer *other,
		      const char *name)
{
	peer->cond = PEER_CMD_OK;
	peer->state = STATE_INIT;
	peer->core.num_outputs = 0;
	peer->current_htlc.htlc.id = -1;
	peer->num_htlcs_to_us = 0;
	peer->num_htlcs_to_them = 0;
	peer->num_live_htlcs_to_us = 0;
	peer->num_live_htlcs_to_them = 0;
	peer->num_htlc_spends_to_us = 0;
	peer->num_htlc_spends_to_them = 0;
	peer->num_rvals_known = 0;
	peer->error = NULL;
	peer->htlc_declined = false;
	peer->anchor = false;
	peer->anchor_broadcast = false;
	peer->anchor_spent = false;
	memset(peer->core.outputs, 0, sizeof(peer->core.outputs));
	peer->pkt_data[0] = -1;
	peer->core.current_command = INPUT_NONE;
	peer->core.event_notifies = 0;
	peer->name = name;
	peer->other = other;
	peer->trail = NULL;
	memset(peer->core.pad, 0, sizeof(peer->core.pad));
}

/* Recursion! */
static void run_peer(const struct peer *peer,
		     bool normalpath, bool errorpath,
		     const struct trail *prev_trail,
		     struct hist *hist);

static void init_trail(struct trail *t,
		       enum state_input input,
		       const union input *idata,
		       const struct peer *before,
		       const struct trail *prev)
{
	t->name = before->name;
	t->prev = prev;
	t->depth = prev ? prev->depth + 1 : 0;
	t->input = input;
	t->before = before;
	t->after = NULL;
	t->num_peer_outputs = -1;
	t->pkt_sent = NULL;
	if (input == CMD_SEND_HTLC_FULFILL
	    || input == INPUT_RVALUE
	    || input == BITCOIN_HTLC_TOTHEM_TIMEOUT
	    || input == BITCOIN_HTLC_TOTHEM_SPENT
	    || input == BITCOIN_HTLC_TOUS_TIMEOUT
	    || input == BITCOIN_HTLC_FULFILL_SPEND_DONE
	    || input == BITCOIN_HTLC_RETURN_SPEND_DONE)
		t->htlc_id = idata->htlc->id;
	else if (input == PKT_UPDATE_ADD_HTLC)
		t->htlc_id = htlc_id_from_pkt(idata->pkt);
	else
		t->htlc_id = -1;
}

static void update_trail(struct trail *t,
			 const struct peer *after,
			 const Pkt *output)
{
	t->after = after;
	t->num_peer_outputs = after->other->core.num_outputs;
	t->pkt_sent = (const char *)output;
}

static void report_trail_rev(const struct trail *t)
{
	size_t i;

	if (t->prev)
		report_trail_rev(t->prev);

	fprintf(stderr, "%s: %s(%i) %s -> %s",
		t->name,
		input_name(t->input), t->htlc_id,
		state_name(t->before->state),
		t->after ? state_name(t->after->state) : "<unknown>");
	if (t->after) {
		for (i = 0; i < t->after->core.num_outputs; i++)
			fprintf(stderr, " >%s",
				input_name(t->after->core.outputs[i]));
	}
	fprintf(stderr, " +%u in\n",
		t->num_peer_outputs);
	if (!t->after)
		goto pkt_sent;

	if (t->after->state >= STATE_CLOSED) {
		if (t->after->num_live_htlcs_to_us
		    || t->after->num_live_htlcs_to_them) {
			fprintf(stderr, "  Live HTLCs:");
			for (i = 0; i < t->after->num_live_htlcs_to_us; i++)
				fprintf(stderr, " <%u",
					t->after->live_htlcs_to_us[i].id);
			for (i = 0; i < t->after->num_live_htlcs_to_them; i++)
				fprintf(stderr, " >%u",
					t->after->live_htlcs_to_them[i].id);
			fprintf(stderr, "\n");
		}
		if (t->after->num_htlc_spends_to_us
		    || t->after->num_htlc_spends_to_them) {
			fprintf(stderr, "  HTLC spends:");
			for (i = 0; i < t->after->num_htlc_spends_to_us; i++)
				fprintf(stderr, " <%u",
					t->after->htlc_spends_to_us[i].id);
			for (i = 0; i < t->after->num_htlc_spends_to_them; i++)
				fprintf(stderr, " <%u",
					t->after->htlc_spends_to_them[i].id);
			fprintf(stderr, "\n");
		}
	} else {
		if (t->after->num_htlcs_to_us
		    || t->after->num_htlcs_to_them) {
			fprintf(stderr, "  HTLCs:");
			for (i = 0; i < t->after->num_htlcs_to_us; i++)
				fprintf(stderr, " <%u",
					t->after->htlcs_to_us[i].id);
			for (i = 0; i < t->after->num_htlcs_to_them; i++)
				fprintf(stderr, " >%u",
					t->after->htlcs_to_them[i].id);
			fprintf(stderr, "\n");
		}
	}
pkt_sent:
	if (t->pkt_sent)
		fprintf(stderr, "  => %s\n", t->pkt_sent);
}

static void report_trail(const struct trail *t, const char *problem)
{
	fprintf(stderr, "Error: %s\n", problem);
	report_trail_rev(t);
	exit(1);
}

static void add_htlc(struct htlc *to_us, unsigned int *num_to_us,
		     struct htlc *to_them, unsigned int *num_to_them,
		     size_t arrsize,
		     const struct htlc *h)
{
	struct htlc *arr;
	unsigned int *n;

	if (h->to_them) {
		arr = to_them;
		n = num_to_them;
	} else {
		arr = to_us;
		n = num_to_us;
	}
	assert(*n < arrsize);
	arr[(*n)++] = *h;
}

static void remove_htlc(struct htlc *to_us, unsigned int *num_to_us,
			struct htlc *to_them, unsigned int *num_to_them,
			size_t arrsize,
			const struct htlc *h)
{
	size_t off;
	struct htlc *arr;
	unsigned int *n;

	if (h->to_them) {
		arr = to_them;
		n = num_to_them;
	} else {
		arr = to_us;
		n = num_to_us;
	}
	assert(*n <= arrsize);
	assert(h >= arr && h < arr + *n);

	off = h - arr;
	memmove(arr + off, arr + off + 1, (char *)(arr + *n) - (char *)(h + 1));
	(*n)--;
}

static void remove_htlc_id(struct peer *peer, unsigned int id)
{
	const struct htlc *h = find_htlc(peer, id);

	if (!h)
		report_trail(peer->trail, "Removing nonexistent HTLC?");
	if (h->to_them != peer->current_htlc.htlc.to_them)
		report_trail(peer->trail,
			     "Removing disagreed about to_them");
	remove_htlc(peer->htlcs_to_us, &peer->num_htlcs_to_us,
		    peer->htlcs_to_them, &peer->num_htlcs_to_them,
		    ARRAY_SIZE(peer->htlcs_to_us), h);
}


static bool outstanding_htlc_watches(const struct peer *peer)
{
	return peer->num_live_htlcs_to_us
		|| peer->num_live_htlcs_to_them
		|| peer->num_htlc_spends_to_us
		|| peer->num_htlc_spends_to_them;
}

static bool have_event(uint64_t events, enum state_input input)
{
	return events & (1ULL << input);
}

static bool add_event_(struct peer *peer, enum state_input input)
{
	/* This is how they say "no event please" */
	if (input == INPUT_NONE)
		return true;

	assert(input < 64);
	if (have_event(peer->core.event_notifies, input))
		return false;
	peer->core.event_notifies |= (1ULL << input);
	return true;
}

static bool remove_event_(uint64_t *events, enum state_input input)
{
	/* This is how they say "no event please" */
	if (input == INPUT_NONE)
		return true;

	assert(input < 64);
	if (!have_event(*events, input))
		return false;
	*events &= ~(1ULL << input);
	return true;
}

static void remove_event(struct peer *peer, enum state_input input)
{
	if (!remove_event_(&peer->core.event_notifies, input))
		report_trail(peer->trail, "Removing event we don't have?");
}

static void add_event(struct peer *peer, enum state_input input)
{
	if (!add_event_(peer, input))
		report_trail(peer->trail, "Adding event we already have?");
}

void peer_watch_anchor(struct peer *peer,
		       enum state_input depthok,
		       enum state_input timeout,
		       enum state_input unspent,
		       enum state_input theyspent,
		       enum state_input otherspent)
{
	/* We assume these values in activate_event. */
	assert(timeout == BITCOIN_ANCHOR_TIMEOUT
	       || timeout == INPUT_NONE);
	assert(depthok == BITCOIN_ANCHOR_DEPTHOK);

	add_event(peer, depthok);
	add_event(peer, timeout);
	add_event(peer, unspent);
	add_event(peer, theyspent);
	add_event(peer, otherspent);
}

void bitcoin_create_anchor(struct peer *peer, enum state_input done)
{
	/* We assume this below */
	assert(done == BITCOIN_ANCHOR_CREATED);
	if (peer->anchor)
		report_trail(peer->trail, "Anchor already created?");

	peer->anchor = true;
	add_event(peer, done);
}

void bitcoin_release_anchor(struct peer *peer, enum state_input done)
{
	if (!peer->anchor)
		report_trail(peer->trail, "Anchor not created?");

	peer->anchor = false;
	remove_event(peer, done);
}

void peer_unwatch_anchor_depth(struct peer *peer,
			       enum state_input depthok,
			       enum state_input timeout)
{
	/* We assume these values in activate_event. */
	assert(timeout == BITCOIN_ANCHOR_TIMEOUT
	       || timeout == INPUT_NONE);
	assert(depthok == BITCOIN_ANCHOR_DEPTHOK);

	remove_event(peer, depthok);
	remove_event(peer, timeout);
}

/* Wait for our commit to be spendable. */
void peer_watch_delayed(struct peer *peer,
			const struct bitcoin_tx *tx, enum state_input canspend)
{
	assert(bitcoin_tx_is(tx, "our commit"));
	add_event(peer, canspend);
}

/* Wait for commit to be very deeply buried (so we no longer need to
 * even watch) */
void peer_watch_tx(struct peer *peer,
		   const struct bitcoin_tx *tx,
		   enum state_input done)
{
	/* We can have multiple steals or spendtheirs in flight, so
	 * allow repeats for
	 * BITCOIN_STEAL_DONE/BITCOIN_SPEND_THEIRS_DONE */
	if (done == BITCOIN_STEAL_DONE) {
		assert(bitcoin_tx_is(tx, "steal"));
		add_event_(peer, done);
	} else if (done == BITCOIN_SPEND_THEIRS_DONE) {
		assert(bitcoin_tx_is(tx, "spend their commit"));
		add_event_(peer, done);
	} else if (done == BITCOIN_SPEND_OURS_DONE) {
		assert(bitcoin_tx_is(tx, "spend our commit"));
		add_event(peer, done);
	} else
		report_trail(peer->trail, "Unknown watch effect");
}

/* Other side should drop close tx; watch for it. */
void peer_watch_close(struct peer *peer,
		      enum state_input done, enum state_input timedout)
{
	add_event(peer, done);

	/* We assume this. */
	assert(timedout == INPUT_CLOSE_COMPLETE_TIMEOUT || timedout == INPUT_NONE);
	add_event(peer, timedout);
}

void peer_unwatch_close_timeout(struct peer *peer, enum state_input timedout)
{
	assert(timedout == INPUT_CLOSE_COMPLETE_TIMEOUT);
	if (!mapping_inputs)
		remove_event(peer, timedout);
}

bool peer_watch_our_htlc_outputs(struct peer *peer,
				 const struct bitcoin_tx *tx,
				 enum state_input tous_timeout,
				 enum state_input tothem_spent,
				 enum state_input tothem_timeout)
{
	/* FIXME: We assume these. */
	assert(tous_timeout == BITCOIN_HTLC_TOUS_TIMEOUT);
	assert(tothem_spent == BITCOIN_HTLC_TOTHEM_SPENT);
	assert(tothem_timeout == BITCOIN_HTLC_TOTHEM_TIMEOUT);

	if (!peer->num_htlcs_to_us && !peer->num_htlcs_to_them)
		return false;

	assert(peer->num_live_htlcs_to_us + peer->num_htlcs_to_us
	       <= ARRAY_SIZE(peer->live_htlcs_to_us));
	assert(peer->num_live_htlcs_to_them + peer->num_htlcs_to_them
	       <= ARRAY_SIZE(peer->live_htlcs_to_them));
	memcpy(peer->live_htlcs_to_us + peer->num_live_htlcs_to_us,
	       peer->htlcs_to_us,
	       peer->num_htlcs_to_us * sizeof(peer->htlcs_to_us[0]));
	memcpy(peer->live_htlcs_to_them + peer->num_live_htlcs_to_them,
	       peer->htlcs_to_them,
	       peer->num_htlcs_to_them * sizeof(peer->htlcs_to_them[0]));
	peer->num_live_htlcs_to_us += peer->num_htlcs_to_us;
	peer->num_live_htlcs_to_them += peer->num_htlcs_to_them;
	/* Can happen if we were finished, then new commit tx */
	remove_event_(&peer->core.event_notifies, INPUT_NO_MORE_HTLCS);

	return true;
}

bool peer_watch_their_htlc_outputs(struct peer *peer,
				   const struct bitcoin_event *tx,
				   enum state_input tous_timeout,
				   enum state_input tothem_spent,
				   enum state_input tothem_timeout)
{
	size_t i;
	struct htlc *htlcs;

	/* We assume these. */
	assert(tous_timeout == BITCOIN_HTLC_TOUS_TIMEOUT);
	assert(tothem_spent == BITCOIN_HTLC_TOTHEM_SPENT);
	assert(tothem_timeout == BITCOIN_HTLC_TOTHEM_TIMEOUT);

	/* It's what our peer thinks is current... */
	if (!peer->other->num_htlcs_to_them && !peer->other->num_htlcs_to_us)
		return false;

	assert(peer->num_live_htlcs_to_us + peer->other->num_htlcs_to_them
	       <= ARRAY_SIZE(peer->live_htlcs_to_us));
	assert(peer->num_live_htlcs_to_them + peer->other->num_htlcs_to_us
	       <= ARRAY_SIZE(peer->live_htlcs_to_them));

	/* Copy from other peer, but reverse perspective */
	htlcs = peer->live_htlcs_to_us + peer->num_live_htlcs_to_us;
	memcpy(htlcs, peer->other->htlcs_to_them,
	       peer->other->num_htlcs_to_them * sizeof(peer->htlcs_to_us[0]));
	for (i = 0; i < peer->other->num_htlcs_to_them; i++) {
		assert(htlcs[i].to_them);
		htlcs[i].to_them = false;
	}

	htlcs = peer->live_htlcs_to_them + peer->num_live_htlcs_to_them;
	memcpy(htlcs,
	       peer->other->htlcs_to_us,
	       peer->other->num_htlcs_to_us * sizeof(peer->htlcs_to_them[0]));
	for (i = 0; i < peer->other->num_htlcs_to_us; i++) {
		assert(!htlcs[i].to_them);
		htlcs[i].to_them = true;
	}

	peer->num_live_htlcs_to_us += peer->other->num_htlcs_to_them;
	peer->num_live_htlcs_to_them += peer->other->num_htlcs_to_us;
	/* Can happen if we were finished, then new commit tx */
	remove_event_(&peer->core.event_notifies, INPUT_NO_MORE_HTLCS);

	return true;
}

void peer_unwatch_htlc_output(struct peer *peer,
			      const struct htlc *htlc,
			      enum state_input all_done)
{
	const struct htlc *h;

	/* We assume this. */
	assert(all_done == INPUT_NO_MORE_HTLCS);

	h = find_live_htlc(peer, htlc->id);

	/* That can fail, when we see them spend (and thus stop
	 * watching) after we've timed out, then our return tx wins
	 * and gets buried. */
	if (h) {
		remove_htlc(peer->live_htlcs_to_us,
			    &peer->num_live_htlcs_to_us,
			    peer->live_htlcs_to_them,
			    &peer->num_live_htlcs_to_them,
			    ARRAY_SIZE(peer->live_htlcs_to_us),
			    h);

		/* If that was last, fire INPUT_NO_MORE_HTLCS */
		if (!outstanding_htlc_watches(peer))
			add_event(peer, all_done);
	}
}

void peer_unwatch_all_htlc_outputs(struct peer *peer)
{
	/* This can happen if we get in front of INPUT_NO_MORE_HTLCS */
	if (!outstanding_htlc_watches(peer)
	    && !have_event(peer->core.event_notifies, INPUT_NO_MORE_HTLCS))
		report_trail(peer->trail, "unwatching all with no htlcs?");

	peer->num_htlc_spends_to_us = 0;
	peer->num_htlc_spends_to_them = 0;
	peer->num_live_htlcs_to_us = 0;
	peer->num_live_htlcs_to_them = 0;
}

void peer_watch_htlc_spend(struct peer *peer,
			   const struct bitcoin_tx *tx,
			   const struct htlc *htlc,
			   enum state_input done)
{
	struct htlc *h = find_live_htlc(peer, htlc_id_from_tx(tx));

	add_htlc(peer->htlc_spends_to_us, &peer->num_htlc_spends_to_us,
		 peer->htlc_spends_to_them,
		 &peer->num_htlc_spends_to_them,
		 ARRAY_SIZE(peer->htlc_spends_to_us),
		 h);

	/* We assume this */
	if (h->to_them)
		assert(done == BITCOIN_HTLC_RETURN_SPEND_DONE);
	else
		assert(done == BITCOIN_HTLC_FULFILL_SPEND_DONE);
}

void peer_unwatch_htlc_spend(struct peer *peer,
			     const struct htlc *htlc,
			     enum state_input all_done)
{
	struct htlc *h = find_htlc_spend(peer, htlc->id);

	assert(all_done == INPUT_NO_MORE_HTLCS);
	remove_htlc(peer->htlc_spends_to_us,
		    &peer->num_htlc_spends_to_us,
		    peer->htlc_spends_to_them,
		    &peer->num_htlc_spends_to_them,
		    ARRAY_SIZE(peer->htlc_spends_to_us),
		    h);

	if (!outstanding_htlc_watches(peer))
		add_event(peer, all_done);
}

void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt)
{
	const char *str = (const char *)pkt;

	/* We can get errors. */
	if (strstarts(str, "PKT_ERROR:"))
		return;

	/* Shouldn't get any other unexpected packets. */
	report_trail(peer->trail, "Unexpected packet");
}

/* Called when their update overrides our update cmd. */
void peer_htlc_ours_deferred(struct peer *peer)
{
	/* Only happens for HTLC commands of low priority. */
	if (high_priority(peer->state))
		report_trail(peer->trail, "Defer while high priority");

	if (peer->current_htlc.htlc.id == -1)
		report_trail(peer->trail, "Deferred with no current HTLC");
	if (!input_is(peer->core.current_command, CMD_SEND_UPDATE_ANY))
		report_trail(peer->trail, "Deferred their HTLC?");

	/* FIXME: Expect CMD_REQUEUE */
	clear_current_htlc(peer);
}

/* Successfully added/fulfilled/timedout/fail an HTLC. */
void peer_htlc_done(struct peer *peer)
{
	if (peer->current_htlc.htlc.id == -1)
		report_trail(peer->trail, "Adding with no current HTLC");

	if (peer->current_htlc.adding) {
		add_htlc(peer->htlcs_to_us, &peer->num_htlcs_to_us,
			 peer->htlcs_to_them, &peer->num_htlcs_to_them,
			 ARRAY_SIZE(peer->htlcs_to_us),
			 &peer->current_htlc.htlc);
	} else {
		remove_htlc_id(peer, peer->current_htlc.htlc.id);
	}
	clear_current_htlc(peer);
}

/* Someone aborted an existing HTLC update. */
void peer_htlc_aborted(struct peer *peer)
{
	if (peer->current_htlc.htlc.id == -1)
		report_trail(peer->trail, "Abort with no current HTLC");
	clear_current_htlc(peer);
}

void peer_htlc_declined(struct peer *peer, const Pkt *pkt)
{
	if (peer->current_htlc.htlc.id == -1)
		report_trail(peer->trail, "Decline with no current HTLC");
	if (!peer->current_htlc.adding)
		report_trail(peer->trail, "Decline but HTLC not marked for add");
	clear_current_htlc(peer);
	peer->htlc_declined = true;
}

const struct htlc *peer_tx_revealed_r_value(struct peer *peer,
					    const struct bitcoin_event *btc)
{
	const struct htlc *htlc = (struct htlc *)btc;
	add_rval(peer, htlc->id);
	return htlc;
}

static const char *check_changes(const struct peer *old, struct peer *new,
				 enum state_input input)
{
	if (new->cond != old->cond) {
		/* Only BUSY -> CMD_OK can go backwards. */
		if (!(old->cond == PEER_BUSY && new->cond == PEER_CMD_OK))
			if (new->cond < old->cond)
				return tal_fmt(NULL, "cond from %u to %u",
					       old->cond, new->cond);
	}
	if (new->cond == PEER_CLOSING
	    || new->cond == PEER_CLOSED) {
		if (new->core.current_command != INPUT_NONE)
			return tal_fmt(NULL,
				       "cond CLOSE with pending command %s",
				       input_name(new->core.current_command));
		if (new->current_htlc.htlc.id != -1)
			return tal_fmt(NULL,
				       "cond CLOSE with pending htlc");
		if (new->anchor)
			return tal_fmt(NULL,
				       "cond CLOSE with anchor");
	}
	if (new->cond == PEER_CLOSED) {
		/* Should not have pending close timeout. */
		if (have_event(new->core.event_notifies,
			       INPUT_CLOSE_COMPLETE_TIMEOUT))
			return tal_fmt(NULL, "CLOSED with pending close timeout");
		/* We must not leave anchor dangling, if we broadcast it. */
		if (new->anchor_broadcast && !new->anchor_spent)
			return tal_fmt(NULL, "CLOSED with unspent anchor?");
	}

	if (input == PKT_ERROR) {
		/* We should stop talking to them after error recvd. */
		if (new->cond != PEER_CLOSING
		    && new->cond != PEER_CLOSED)
			return "packets still open after error pkt";
	}

	return NULL;
}

static const char *check_all_effects(const struct peer *old,
				     enum command_status cstatus,
				     enum state_input input,
				     struct peer *peer,
				     Pkt *output)
{
	if (cstatus != CMD_NONE) {
		assert(peer->core.current_command != INPUT_NONE);
		/* We should only requeue HTLCs if we're lowprio */
		if (cstatus == CMD_REQUEUE) {
			if (high_priority(old->state))
				return "CMD_REQUEUE despite high prio state";
			else if (!input_is(peer->core.current_command,
					   CMD_SEND_UPDATE_ANY))
				return tal_fmt(NULL, "CMD_REQUEUE on cmd %s",
					       input_name(peer->core.current_command));
			/* We expect to be replaced by their HTLC
			 * (unless we inject an error!). */
			if (peer->current_htlc.htlc.id == -1
			    && peer->cond != PEER_CLOSED
			    && !peer->htlc_declined)
				return tal_fmt(NULL, "CMD_REQUEUE but no new htlc?");
		} else {
			/* Expect no HTLCs in other cases. */
			if (peer->current_htlc.htlc.id != -1)
				return tal_fmt(NULL, "%s but still have htlc?",
					       cstatus_name(cstatus));
		}
		peer->core.current_command = INPUT_NONE;
	}

	if (output) {
		const char *pkt = (const char *)output;
		/* Check for errors. */
		if (strstarts(pkt, "PKT_ERROR: ")) {
			/* Some are expected. */
			if (!streq(pkt, "PKT_ERROR: Commit tx noticed")
			    && !streq(pkt, "PKT_ERROR: Otherspend noticed")
			    && !streq(pkt, "PKT_ERROR: Error inject")
			    && !streq(pkt, "PKT_ERROR: Anchor timed out")
			    && !streq(pkt, "PKT_ERROR: Close timed out")
			    && !streq(pkt, "PKT_ERROR: Close forced due to HTLCs")) {
				return pkt;
			}
		}
		if (peer->core.num_outputs >= ARRAY_SIZE(peer->core.outputs))
			return "Too many outputs";
		peer->core.outputs[peer->core.num_outputs]
			= input_by_name(pkt);
		peer->pkt_data[peer->core.num_outputs++]
			= htlc_id_from_pkt(output);
	}

	if (peer->state >= STATE_CLOSE_WAIT_STEAL
	    && peer->state <= STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_SPENDOURS_WITH_HTLCS) {
		if (STATE_TO_BITS(peer->state) & STATE_CLOSE_HTLCS_BIT) {
			if (!outstanding_htlc_watches(peer)
			    && !have_event(peer->core.event_notifies, INPUT_NO_MORE_HTLCS))
				return "CLOSE_HTLCS with no outstanding watches?";
		}
	}

	return check_changes(old, peer, input);
}

static void eliminate_input(enum state_input **inputs, enum state_input in)
{
	size_t i, n = tal_count(*inputs);

	for (i = 0; i < n; i++) {
		if ((*inputs)[i] != in)
			continue;

		if (i != n-1)
			(*inputs)[i] = (*inputs)[n-1];
		tal_resize(inputs, n - 1);
		break;
	}
}

static bool find_output(const enum state_input *outputs, enum state_input out)
{
	size_t n, i;

	n = tal_count(outputs);
	for (i = 0; i < n; i++)
		if (outputs[i] == out)
			return true;
	return false;
}

static void record_output(enum state_input **outputs, enum state_input out)
{
	size_t n;

	if (find_output(*outputs, out))
		return;

	n = tal_count(*outputs);
	tal_resize(outputs, n+1);
	(*outputs)[n] = out;
}

static void record_state(struct state_dump **sd,
			 enum state_input input,
			 enum state newstate,
			 const char *pktstr)
{
	size_t i, n = tal_count(*sd);
	enum state_input pkt;

	if (!pktstr)
		pkt = INPUT_NONE;
	else
		pkt = input_by_name(pktstr);

	for (i = 0; i < n; i++) {
		if ((*sd)[i].input != input)
			continue;
		if ((*sd)[i].next != newstate)
			continue;
		if ((*sd)[i].pkt != pkt)
			continue;
		/* Duplicate. */
		return;
	}
	tal_resize(sd, n+1);
	(*sd)[n].input = input;
	(*sd)[n].next = newstate;
	(*sd)[n].pkt = pkt;
}

static bool error_path(enum state_input i, enum state src, enum state dst)
{
	return state_is_error(dst) || i == PKT_ERROR;
}

static bool normal_path(enum state_input i, enum state src, enum state dst)
{
	if (error_path(i, src, dst))
		return false;

	/* Weird inputs. */
	if (i == BITCOIN_ANCHOR_TIMEOUT
	    || i == BITCOIN_ANCHOR_UNSPENT
	    || i == BITCOIN_ANCHOR_THEIRSPEND
	    || i == BITCOIN_ANCHOR_OTHERSPEND
	    || i == BITCOIN_STEAL_DONE
	    || i == PKT_UPDATE_DECLINE_HTLC
	    || i == PKT_UPDATE_FAIL_HTLC
	    || i == INPUT_CLOSE_COMPLETE_TIMEOUT)
		return false;

	return true;
}

/* These clutter the graph, so only handle from normal state. */
static bool too_cluttered(enum state_input i, enum state src)
{
	if (i == CMD_CLOSE || i == PKT_CLOSE || i == PKT_UPDATE_ADD_HTLC || i == PKT_UPDATE_FULFILL_HTLC)
		return src != STATE_NORMAL_LOWPRIO
			&& src != STATE_NORMAL_HIGHPRIO;
	return false;
}

static void add_dot(struct edge_hash *hash,
		    const char *oldstate,
		    const char *newstate,
		    enum state_input i,
		    const Pkt *pkt)
{
	struct dot_edge *d = tal(NULL, struct dot_edge);
	d->oldstate = oldstate;
	d->newstate = newstate;
	d->i = i;
	if (pkt)
		d->pkt = tal_strdup(d, (const char *)pkt);
	else
		d->pkt = NULL;

	if (edge_hash_get(hash, d))
		tal_free(d);
	else
		edge_hash_add(hash, d);
}

static const char *simplify_state(enum state s)
{
	/* Turn all high prio into low prio, and merge some open states */
	switch (s) {
	case STATE_OPEN_WAITING_OURANCHOR:
	case STATE_OPEN_WAITING_THEIRANCHOR:
		return "STATE_OPEN_WAITING";

	case STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR:
	case STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR:
		return "STATE_OPEN_WAIT_FOR_COMPLETE";

	case STATE_NORMAL_LOWPRIO:
	case STATE_NORMAL_HIGHPRIO:
		return "STATE_NORMAL";

	case STATE_WAIT_FOR_HTLC_ACCEPT_LOWPRIO:
	case STATE_WAIT_FOR_HTLC_ACCEPT_HIGHPRIO:
		return "STATE_WAIT_FOR_HTLC_ACCEPT";

	case STATE_WAIT_FOR_UPDATE_COMPLETE_LOWPRIO:
	case STATE_WAIT_FOR_UPDATE_COMPLETE_HIGHPRIO:
		return "STATE_WAIT_FOR_UPDATE_COMPLETE";

	case STATE_WAIT_FOR_UPDATE_SIG_LOWPRIO:
	case STATE_WAIT_FOR_UPDATE_SIG_HIGHPRIO:
		return "STATE_WAIT_FOR_UPDATE_SIG";

	default:
		return state_name(s);
	}
}

static bool waiting_statepair(enum state a, enum state b)
{
	/* We don't need inputs if we're waiting for anchors. */
	if (a == STATE_OPEN_WAITING_OURANCHOR
	    || a == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED
	    || a == STATE_OPEN_WAITING_THEIRANCHOR
	    || a == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED
	    || a == STATE_OPEN_WAIT_FOR_ANCHOR_CREATE)
		return true;

	if (b == STATE_OPEN_WAITING_OURANCHOR
	    || b == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED
	    || b == STATE_OPEN_WAITING_THEIRANCHOR
	    || b == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED
	    || b == STATE_OPEN_WAIT_FOR_ANCHOR_CREATE)
		return true;

	/* We don't need inputs at start of main loop. */
	if (a == STATE_NORMAL_LOWPRIO
	    && b == STATE_NORMAL_HIGHPRIO)
		return true;

	if (a == STATE_NORMAL_HIGHPRIO
	    && b == STATE_NORMAL_LOWPRIO)
		return true;

	return false;
}

static bool has_packets(const struct peer *peer)
{
	return peer->core.num_outputs != 0;
}

static void try_input(const struct peer *peer,
		      enum state_input i,
		      const union input *idata,
		      bool normalpath, bool errorpath,
		      const struct trail *prev_trail,
		      struct hist *hist)
{
	struct peer copy, other;
	struct trail t;
	const char *problem;
	Pkt *output;
	const struct bitcoin_tx *broadcast;
	const tal_t *ctx = tal_tmpctx(NULL);
	enum command_status cstatus;

	copy_peers(&copy, &other, peer);

	copy.current_input = i;
	copy.current_idata = idata;
	init_trail(&t, i, idata, peer, prev_trail);
	copy.trail = &t;

	/* The anchor is resolved in some way by these. */
	if (i == BITCOIN_ANCHOR_UNSPENT
	    || i == BITCOIN_ANCHOR_TIMEOUT
	    || i == BITCOIN_ANCHOR_THEIRSPEND
	    || i == BITCOIN_ANCHOR_OTHERSPEND
	    || i == BITCOIN_CLOSE_DONE)
		copy.anchor_spent = true;

	eliminate_input(&hist->inputs_per_state[copy.state], i);
	cstatus = state(ctx, &copy, i, idata, &output, &broadcast);

	normalpath &= normal_path(i, peer->state, copy.state);
	errorpath |= error_path(i, peer->state, copy.state);

	if (dot_enable
	    && (dot_include_abnormal || normalpath)
	    && (dot_include_errors || !errorpath)
	    && (dot_include_abnormal || !too_cluttered(i, peer->state))) {
		const char *oldstr, *newstr;

		/* Simplify folds high and low prio, skip "STATE_" */
		if (dot_simplify) {
			oldstr = simplify_state(peer->state) + 6;
			newstr = simplify_state(copy.state) + 6;
		} else {
			oldstr = state_name(peer->state) + 6;
			newstr = state_name(copy.state) + 6;
		}
		if (newstr != oldstr || include_nops)
			add_dot(&hist->edges, oldstr, newstr, i, output);
	}

	problem = check_all_effects(peer, cstatus, i, &copy, output);
	update_trail(&t, &copy, output);
	if (problem)
		report_trail(&t, problem);

	if (copy.state == STATE_ERR_INTERNAL)
		report_trail(&t, "Internal error");
	if (strstarts(state_name(copy.state), "STATE_UNUSED"))
		report_trail(&t, "Unused state");

	/* Re-set htlc_declined */
	copy.htlc_declined = false;

	/* Record any output. */
	if (output) {
		record_output(&hist->outputs,
			      input_by_name((const char *)output));
	}

	if (hist->state_dump) {
		record_state(&hist->state_dump[peer->state], i, copy.state,
			     (const char *)output);
	}

	/* Have we been in this overall situation before? */
	if (!sithash_update(&hist->sithash, &copy)) {
		/*
		 * We expect to loop if:
		 * 1) We deferred, OR
		 * 2) We get repeated BITCOIN_ANCHOR_OTHERSPEND/THEIRSPEND, OR
		 * 3) We pass through NORMAL state.
		 *
		 * And if we're being quick, always stop.
		 */
		if (quick
		    || cstatus == CMD_REQUEUE
		    || copy.state == STATE_NORMAL_LOWPRIO
		    || copy.state == STATE_NORMAL_HIGHPRIO
		    || i == BITCOIN_ANCHOR_OTHERSPEND
		    || i == BITCOIN_ANCHOR_THEIRSPEND
		    || quick) {
			tal_free(ctx);
			return;
		}
		if (t.depth > STATE_MAX * 10)
			report_trail(&t, "Loop");
	}

	/* Don't continue if we reached a different error state. */
	if (state_is_error(copy.state)) {
		tal_free(ctx);
		return;
	}

	/*
	 * If we're listening, someone should be talking (usually).
	 */
	if (copy.cond != PEER_CLOSED
	    && !has_packets(&copy) && !has_packets(&other)
	    && !waiting_statepair(copy.state, other.state)) {
		report_trail(&t, "Deadlock");
	}

	/* Finished? */
	if (copy.state == STATE_CLOSED) {
		if (copy.cond != PEER_CLOSED)
			report_trail(&t, "CLOSED but cond not CLOSED");

		if (copy.core.current_command != INPUT_NONE)
			report_trail(&t, input_name(copy.core.current_command));

		if (copy.current_htlc.htlc.id != -1)
			report_trail(&t, "CLOSED with htlc in progress?");

		if (outstanding_htlc_watches(&copy))
			report_trail(&t, "CLOSED but watching HTLCs?");
		tal_free(ctx);
		return;
	}

	/* Try inputs from here down. */
	run_peer(&copy, normalpath, errorpath, &t, hist);

	/* Don't bother running other peer we can't communicate. */
	if (copy.cond != PEER_CLOSED
	    || other.cond != PEER_CLOSED)
		run_peer(&other, normalpath, errorpath, &t, hist);
	tal_free(ctx);
}

static void sanity_check(const struct peer *peer)
{
	if (peer->state == STATE_NORMAL_LOWPRIO
	    || peer->state == STATE_NORMAL_HIGHPRIO) {
		/* Home state: expect commands to be finished. */
		if (peer->core.current_command != INPUT_NONE)
			errx(1, "Unexpected command %u in state %u",
			     peer->core.current_command, peer->state);
	}
}

static void activate_event(struct peer *peer, enum state_input i)
{
	/* Events are not independent. */
	switch (i) {
	case BITCOIN_ANCHOR_DEPTHOK:
		/* Can't sent TIMEOUT (may not be set) */
		remove_event_(&peer->core.event_notifies, BITCOIN_ANCHOR_TIMEOUT);
		break;
	case BITCOIN_ANCHOR_TIMEOUT:
		/* Can't sent DEPTHOK */
		remove_event(peer, BITCOIN_ANCHOR_DEPTHOK);
		break;
	/* And of the "done" cases means we won't give the others. */
	case BITCOIN_SPEND_THEIRS_DONE:
	case BITCOIN_SPEND_OURS_DONE:
	case BITCOIN_STEAL_DONE:
	case BITCOIN_CLOSE_DONE:
		remove_event_(&peer->core.event_notifies,
			      BITCOIN_SPEND_OURS_DONE);
		remove_event_(&peer->core.event_notifies,
			      BITCOIN_SPEND_THEIRS_DONE);
		remove_event_(&peer->core.event_notifies, BITCOIN_STEAL_DONE);
		remove_event_(&peer->core.event_notifies, BITCOIN_CLOSE_DONE);
		remove_event_(&peer->core.event_notifies,
			      BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED);
		remove_event_(&peer->core.event_notifies,
			      BITCOIN_ANCHOR_THEIRSPEND);
		remove_event_(&peer->core.event_notifies,
			      BITCOIN_ANCHOR_OTHERSPEND);
		remove_event_(&peer->core.event_notifies,
			      BITCOIN_ANCHOR_UNSPENT);
		break;
	default:
		;
	}
}

static bool can_refire(enum state_input i)
{
	/* They could have lots of old HTLCS */
	if (i == BITCOIN_ANCHOR_OTHERSPEND)
		return true;
 	/* Signature malleability means any number of these */
	if (i == BITCOIN_ANCHOR_THEIRSPEND)
		return true;

	/* They could have lots of htlcs. */
	if (i == BITCOIN_HTLC_TOTHEM_SPENT || i == BITCOIN_HTLC_TOTHEM_TIMEOUT
	    || i == BITCOIN_HTLC_TOUS_TIMEOUT)
		return true;

	/* We manually remove these if they're not watching any more spends */
	if (i == BITCOIN_HTLC_RETURN_SPEND_DONE
	    || i == BITCOIN_HTLC_FULFILL_SPEND_DONE)
		return true;

	return false;
}

static unsigned int next_htlc_id(void)
{
	static unsigned int num;

	return ++num;
}

static void run_peer(const struct peer *peer,
		     bool normalpath, bool errorpath,
		     const struct trail *prev_trail,
		     struct hist *hist)
{
	struct peer copy, other;
	size_t i;
	uint64_t old_notifies;
	union input *idata = talz(NULL, union input);

	sanity_check(peer);

	/* We want to frob some things... */
	copy_peers(&copy, &other, peer);

	/* If in init state, we can only send start command. */
	if (peer->state == STATE_INIT) {
		if (streq(peer->name, "A"))
			copy.core.current_command = CMD_OPEN_WITH_ANCHOR;
		else
			copy.core.current_command = CMD_OPEN_WITHOUT_ANCHOR;
		try_input(&copy, copy.core.current_command, idata,
			  normalpath, errorpath,
			  prev_trail, hist);
		return;
	}

	/* Try the event notifiers */
	old_notifies = copy.core.event_notifies;
	for (i = 0; i < 64; i++) {
		if (!have_event(copy.core.event_notifies, i))
			continue;

		/* Don't re-fire most events */
		if (!can_refire(i))
			remove_event(&copy, i);
		activate_event(&copy, i);
		try_input(&copy, i, idata, normalpath, errorpath,
			  prev_trail, hist);
		copy.core.event_notifies = old_notifies;
	}

	/* We can send a close command even if already sending a
	 * (different) command. */
	if (peer->state != STATE_INIT
	    && (peer->cond == PEER_CMD_OK
		|| peer->cond == PEER_BUSY)) {
		try_input(&copy, CMD_CLOSE, idata,
			  normalpath, errorpath, prev_trail, hist);
	}

	/* Try sending commands if allowed. */
	if (peer->cond == PEER_CMD_OK) {
		unsigned int i;

		/* Shouldn't be currently doing an HTLC. */
		assert(copy.current_htlc.htlc.id == -1);

		/* Add a new HTLC if not at max. */
		if (copy.num_htlcs_to_them < MAX_HTLCS) {
			copy.core.current_command = CMD_SEND_HTLC_ADD;
			idata->htlc_prog = tal(idata, struct htlc_progress);
			idata->htlc_prog->adding = true;
			idata->htlc_prog->htlc.to_them = true;
			idata->htlc_prog->htlc.id = next_htlc_id();

			set_current_htlc(&copy,
					 idata->htlc_prog->htlc.id,
					 idata->htlc_prog->htlc.to_them,
					 idata->htlc_prog->adding);
			try_input(&copy, copy.core.current_command, idata,
				  normalpath, errorpath,
				  prev_trail, hist);
			idata->htlc_prog = tal_free(idata->htlc_prog);
			/* If it was requeued, may already be reset. */
			copy.current_htlc.htlc.id = -1;
		}

		/* We can complete or fail an HTLC they offered */
		for (i = 0; i < peer->num_htlcs_to_us; i++) {
			idata->htlc_prog = tal(idata, struct htlc_progress);
			idata->htlc_prog->htlc = peer->htlcs_to_us[i];
			idata->htlc_prog->adding = false;

			set_current_htlc(&copy,
					 idata->htlc_prog->htlc.id,
					 idata->htlc_prog->htlc.to_them,
					 idata->htlc_prog->adding);

			/* Only send this once. */
			if (!rval_known(peer, idata->htlc_prog->htlc.id)) {
				copy.core.current_command
					= CMD_SEND_HTLC_FULFILL;
				try_input(&copy, copy.core.current_command,
					  idata, normalpath, errorpath,
					  prev_trail, hist);
			}
			copy.core.current_command = CMD_SEND_HTLC_FAIL;
			try_input(&copy, copy.core.current_command,
				  idata, normalpath, errorpath,
				  prev_trail, hist);
			/* If it was requeued, may already be reset. */
			copy.current_htlc.htlc.id = -1;
		}

		/* Restore current_command */
		copy.core.current_command = INPUT_NONE;
	}

	/* If they're watching HTLCs, we can send events. */
	for (i = 0; i < peer->num_live_htlcs_to_us; i++) {
		idata->htlc = (struct htlc *)&copy.live_htlcs_to_us[i];
		/* Only send this once. */
		if (!rval_known(peer, idata->htlc->id)) {
			try_input(&copy, INPUT_RVALUE,
				  idata, normalpath, errorpath,
				  prev_trail, hist);
		}
		try_input(&copy, BITCOIN_HTLC_TOUS_TIMEOUT,
			  idata, normalpath, errorpath,
			  prev_trail, hist);
	}

	for (i = 0; i < peer->num_live_htlcs_to_them; i++) {
		idata->btc = (struct bitcoin_event *)&copy.live_htlcs_to_them[i];
		try_input(&copy, BITCOIN_HTLC_TOTHEM_SPENT,
			  idata, normalpath, errorpath,
			  prev_trail, hist);
		idata->htlc = (struct htlc *)&copy.live_htlcs_to_them[i];
		try_input(&copy, BITCOIN_HTLC_TOTHEM_TIMEOUT,
			  idata, normalpath, errorpath,
			  prev_trail, hist);
	}

	/* If they're watching HTLC spends, we can send events. */
	for (i = 0; i < peer->num_htlc_spends_to_us; i++) {
		idata->htlc = (struct htlc *)&copy.htlc_spends_to_us[i];
		try_input(&copy, BITCOIN_HTLC_FULFILL_SPEND_DONE,
			  idata, normalpath, errorpath,
			  prev_trail, hist);
	}
	for (i = 0; i < peer->num_htlc_spends_to_them; i++) {
		idata->htlc = (struct htlc *)&copy.htlc_spends_to_them[i];
		try_input(&copy, BITCOIN_HTLC_RETURN_SPEND_DONE,
			  idata, normalpath, errorpath,
			  prev_trail, hist);
	}

	/* Allowed to send packets? */
	if (copy.cond != PEER_CLOSED) {
		enum state_input i;

		if (other.core.num_outputs) {
			i = other.core.outputs[0];
			if (i == PKT_ERROR)
				idata->pkt = pkt_err(idata, "");
			else if (other.pkt_data[0] == -1U)
				idata->pkt = (Pkt *)talz(idata, char);
			else
				idata->pkt = htlc_pkt(idata, input_name(i),
						      other.pkt_data[0]);

			/* Do the first, recursion does the rest. */
			memmove(other.core.outputs, other.core.outputs + 1,
				sizeof(other.core.outputs)
				- sizeof(other.core.outputs[0]));
			memmove(other.pkt_data, other.pkt_data + 1,
				sizeof(other.pkt_data)-sizeof(other.pkt_data[0]));
			other.core.num_outputs--;
			/* Reset so that hashing doesn't get confused. */
			other.core.outputs[other.core.num_outputs] = 0;
			try_input(&copy, i, idata, normalpath, errorpath,
				  prev_trail, hist);
		}
	}
	tal_free(idata);
}

static bool record_input_mapping(int b)
{
	size_t n;

	if (!mapping_inputs)
		return false;

	/* Accumulating tested inputs? */
	n = tal_count(mapping_inputs);
	tal_resize(&mapping_inputs, n+1);
	mapping_inputs[n] = b;
	return true;
}

static enum state_input **map_inputs(void)
{
	enum state_input **inps = tal_arr(NULL, enum state_input *, STATE_MAX);
	unsigned int i;
	const tal_t *ctx = tal_tmpctx(NULL);

	for (i = 0; i < STATE_MAX; i++) {
		/* This is a global */
		mapping_inputs = tal_arr(inps, enum state_input, 0);

		/* This adds to mapping_inputs every input_is() call */
		if (!state_is_error(i)) {
			struct peer dummy;
			const struct bitcoin_tx *dummy_tx;
			Pkt *dummy_pkt;
			memset(&dummy, 0, sizeof(dummy));
			dummy.state = i;
			state(ctx, &dummy, INPUT_NONE, NULL, &dummy_pkt,
			      &dummy_tx);
		}
		inps[i] = mapping_inputs;
	}

	/* Reset global */
	mapping_inputs = NULL;
	tal_free(ctx);
	return inps;
}

static bool visited_state(const struct sithash *sithash,
			  enum state state, bool b)
{
	struct situation *h;
	struct sithash_iter i;
	unsigned int num = 0;

	for (h = sithash_first(sithash, &i); h; h = sithash_next(sithash, &i)) {
		num++;
		if (b) {
			if (h->a.s.valid && h->b.s.state == state)
				return true;
		} else {
			if (h->a.s.valid && h->a.s.state == state)
				return true;
		}
	}
	return false;
}

static int state_dump_cmp(const struct state_dump *a,
			  const struct state_dump *b,
			  void *unused)
{
	if (a->input != b->input)
		return a->input - b->input;
	if (a->next != b->next)
		return a->next - b->next;
	return 0;
}

int main(int argc, char *argv[])
{
	struct peer a, b;
	unsigned int i;
	struct hist hist;
	bool dump_states = false;
	bool more_failpoints;

	err_set_progname(argv[0]);

	opt_register_noarg("--help|-h", opt_usage_and_exit,
			   ""
			   "Test lightning state machine",
			   "Print this message.");
	opt_register_noarg("--dot",
			   opt_set_bool, &dot_enable,
			   "Output dot format for normal paths");
	opt_register_noarg("--dot-all",
			   opt_set_bool, &dot_include_abnormal,
			   "Output dot format for all non-error paths");
	opt_register_noarg("--dot-include-errors",
			   opt_set_bool, &dot_include_errors,
			   "Output dot format for error paths");
	opt_register_noarg("--include-nops",
			   opt_set_bool, &include_nops,
			   "Output even for inputs which don't change state");
	opt_register_noarg("--dot-simplify",
			   opt_set_bool, &dot_simplify,
			   "Merge high and low priority states");
	opt_register_noarg("--dump-states",
			   opt_set_bool, &dump_states,
			   "Summarize all state transitions");
	opt_register_version();

 	opt_parse(&argc, argv, opt_log_stderr_exit);
	if (dot_include_abnormal)
		dot_enable = true;
	if (dot_simplify && !dot_enable)
		opt_usage_exit_fail("--dot-simplify needs --dot/--dot-all");
	if (dot_include_errors && !dot_enable)
		opt_usage_exit_fail("--dot-include-errors needs --dot/--dot-all");
	if (include_nops && !dot_enable && !dump_states)
		opt_usage_exit_fail("--include-nops needs --dot/--dot-all/--dump-states");

	/* Map the inputs tested in each state. */
	hist.inputs_per_state = map_inputs();
	sithash_init(&hist.sithash);
	hist.outputs = tal_arr(NULL, enum state_input, 0);
	edge_hash_init(&hist.edges);
	if (dump_states) {
		hist.state_dump = tal_arr(NULL, struct state_dump *, STATE_MAX);
		for (i = 0; i < STATE_MAX; i++)
			hist.state_dump[i] = tal_arr(hist.state_dump,
						     struct state_dump, 0);
	} else
		hist.state_dump = NULL;

#if 0
	quick = dot_enable || dump_states;
#else
	quick = true;
#endif

	/* Initialize universe. */
	peer_init(&a, &b, "A");
	peer_init(&b, &a, "B");
	if (!sithash_update(&hist.sithash, &a))
		abort();
	failhash_init(&failhash);

	/* Now, try each input in each state. */
	run_peer(&a, true, false, NULL, &hist);

	/* Now probe all the failure points */
	do {
		struct failpoint *f;
		struct failhash_iter i;
		more_failpoints = false;

		for (f = failhash_first(&failhash, &i);
		     f;
		     f = failhash_next(&failhash, &i)) {
			if (f->details) {
				const struct trail *t;

				/* Trail will vanish when f->details freed */
				t = tal_steal(f, f->details->us.trail);
				try_input(&f->details->us,
					  f->details->input,
					  &f->details->idata,
					  false, true,
					  t,
					  &hist);
				/* Note: it can go down an earlier path and
				 * fail differently, so f->details may
				 * still be set. */
				if (!f->details)
					tal_free(t);
				more_failpoints = true;
			}
		}
	} while (!more_failpoints);

	for (i = 0; i < STATE_MAX; i++) {
		bool a_expect = true, b_expect = true;

		/* Ignore unused states. */
		if (strstarts(state_name(i), "STATE_UNUSED"))
			continue;

		/* A supplied anchor, so doesn't enter NOANCHOR states. */
		if (i == STATE_OPEN_WAIT_FOR_OPEN_NOANCHOR
		    || i == STATE_OPEN_WAIT_FOR_ANCHOR
		    || i == STATE_OPEN_WAITING_THEIRANCHOR
		    || i == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED
		    || i == STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR
		    || i == STATE_ERR_ANCHOR_TIMEOUT)
			a_expect = false;
		if (i == STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR
		    || i == STATE_OPEN_WAIT_FOR_ANCHOR_CREATE
		    || i == STATE_OPEN_WAIT_FOR_COMMIT_SIG
		    || i == STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR
		    || i == STATE_OPEN_WAITING_OURANCHOR
		    || i == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED)
			b_expect = false;
		if (i == STATE_ERR_INTERNAL)
			a_expect = b_expect = false;
		if (visited_state(&hist.sithash, i, 0) != a_expect)
			warnx("Peer A %s state %s",
			      a_expect ? "didn't visit" : "visited",
			      state_name(i));
		if (visited_state(&hist.sithash, i, 1) != b_expect)
			warnx("Peer B %s state %s",
			     b_expect ? "didn't visit" : "visited",
			      state_name(i));
		if (!state_is_error(i) && tal_count(hist.inputs_per_state[i]))
			warnx("Never sent %s input %s", state_name(i),
			      input_name(*hist.inputs_per_state[i]));
	}

	for (i = 0; i < INPUT_MAX; i++) {
		/* Not all input values are valid. */
		if (streq(input_name(i), "unknown"))
			continue;
		/* We only expect packets to be output. */
		if (!input_is_pkt(i))
			continue;
		if (!find_output(hist.outputs, i))
			warnx("Never sent output %s", input_name(i));
	}

	if (dot_enable) {
		struct dot_edge *d;
		struct edge_hash_iter i;

		printf("digraph lightning {\n");
		for (d = edge_hash_first(&hist.edges, &i);
		     d;
		     d = edge_hash_next(&hist.edges, &i)) {
			printf("%s -> %s ", d->oldstate, d->newstate);
			if (!d->pkt)
				printf("[label=\"<%s\"];\n", input_name(d->i));
			else {
				printf("[label=\"<%s\\n>%s\"];\n",
				       input_name(d->i), d->pkt);
			}
		}
		printf("}\n");
	}

	if (dump_states) {
		for (i = 0; i < STATE_MAX; i++) {
			size_t j;
			size_t n = tal_count(hist.state_dump[i]);
			if (!n)
				continue;
			printf("%s:\n", state_name(i) + 6);
			asort(hist.state_dump[i], n, state_dump_cmp, NULL);
			for (j = 0; j < n; j++) {
				if (!include_nops
				    && hist.state_dump[i][j].next == i)
					continue;
				printf("\t%s -> %s",
				       input_name(hist.state_dump[i][j].input),
				       state_name(hist.state_dump[i][j].next)+6);
				if (hist.state_dump[i][j].pkt != INPUT_NONE)
					printf(" (%s)",
					       input_name(hist.state_dump[i][j].pkt));
				printf("\n");
			}
		}
	}

	return 0;
}