#include "htlc.h" #include "log.h" #include "peer.h" #include "gen_htlc_state_names.h" #include #include const char *htlc_state_name(enum htlc_state s) { size_t i; for (i = 0; enum_htlc_state_names[i].name; i++) if (enum_htlc_state_names[i].v == s) return enum_htlc_state_names[i].name; return "unknown"; } /* This is the flags for each state. */ static const int per_state_bits[] = { [SENT_ADD_HTLC] = HTLC_ADDING + HTLC_LOCAL_F_OWNER + HTLC_REMOTE_F_PENDING, [SENT_ADD_COMMIT] = HTLC_ADDING + HTLC_LOCAL_F_OWNER + HTLC_REMOTE_F_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_ADD_REVOCATION] = HTLC_ADDING + HTLC_LOCAL_F_OWNER + HTLC_REMOTE_F_COMMITTED + HTLC_REMOTE_F_REVOKED + HTLC_LOCAL_F_PENDING + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_ADD_ACK_COMMIT] = HTLC_ADDING + HTLC_LOCAL_F_OWNER + HTLC_REMOTE_F_COMMITTED + HTLC_REMOTE_F_REVOKED + HTLC_LOCAL_F_COMMITTED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [SENT_ADD_ACK_REVOCATION] = HTLC_LOCAL_F_OWNER + HTLC_REMOTE_F_COMMITTED + HTLC_REMOTE_F_REVOKED + HTLC_LOCAL_F_COMMITTED + HTLC_LOCAL_F_REVOKED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_REMOVE_HTLC] = HTLC_REMOVING + HTLC_LOCAL_F_OWNER + HTLC_LOCAL_F_PENDING + HTLC_LOCAL_F_COMMITTED + HTLC_REMOTE_F_COMMITTED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_REMOVE_COMMIT] = HTLC_REMOVING + HTLC_LOCAL_F_OWNER + HTLC_REMOTE_F_COMMITTED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [SENT_REMOVE_REVOCATION] = HTLC_REMOVING + HTLC_LOCAL_F_OWNER + HTLC_REMOTE_F_COMMITTED + HTLC_LOCAL_F_REVOKED + HTLC_REMOTE_F_PENDING + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [SENT_REMOVE_ACK_COMMIT] = HTLC_REMOVING + HTLC_LOCAL_F_OWNER + HTLC_LOCAL_F_REVOKED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_REMOVE_ACK_REVOCATION] = HTLC_LOCAL_F_OWNER + HTLC_LOCAL_F_REVOKED + HTLC_REMOTE_F_REVOKED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_ADD_HTLC] = HTLC_ADDING + HTLC_REMOTE_F_OWNER + HTLC_LOCAL_F_PENDING, [RCVD_ADD_COMMIT] = HTLC_ADDING + HTLC_REMOTE_F_OWNER + HTLC_LOCAL_F_COMMITTED + HTLC_LOCAL_F_WAS_COMMITTED, [SENT_ADD_REVOCATION] = HTLC_ADDING + HTLC_REMOTE_F_OWNER + HTLC_LOCAL_F_COMMITTED + HTLC_LOCAL_F_REVOKED + HTLC_REMOTE_F_PENDING + HTLC_LOCAL_F_WAS_COMMITTED, [SENT_ADD_ACK_COMMIT] = HTLC_ADDING + HTLC_REMOTE_F_OWNER + HTLC_LOCAL_F_COMMITTED + HTLC_LOCAL_F_REVOKED + HTLC_REMOTE_F_COMMITTED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_ADD_ACK_REVOCATION] = HTLC_REMOTE_F_OWNER + HTLC_LOCAL_F_COMMITTED + HTLC_LOCAL_F_REVOKED + HTLC_REMOTE_F_COMMITTED + HTLC_REMOTE_F_REVOKED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [SENT_REMOVE_HTLC] = HTLC_REMOVING + HTLC_REMOTE_F_OWNER + HTLC_REMOTE_F_PENDING + HTLC_LOCAL_F_COMMITTED + HTLC_REMOTE_F_COMMITTED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [SENT_REMOVE_COMMIT] = HTLC_REMOVING + HTLC_REMOTE_F_OWNER + HTLC_LOCAL_F_COMMITTED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_REMOVE_REVOCATION] = HTLC_REMOVING + HTLC_REMOTE_F_OWNER + HTLC_LOCAL_F_COMMITTED + HTLC_REMOTE_F_REVOKED + HTLC_LOCAL_F_PENDING + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [RCVD_REMOVE_ACK_COMMIT] = HTLC_REMOVING + HTLC_REMOTE_F_OWNER + HTLC_REMOTE_F_REVOKED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED, [SENT_REMOVE_ACK_REVOCATION] = HTLC_REMOTE_F_OWNER + HTLC_REMOTE_F_REVOKED + HTLC_LOCAL_F_REVOKED + HTLC_LOCAL_F_WAS_COMMITTED + HTLC_REMOTE_F_WAS_COMMITTED }; int htlc_state_flags(enum htlc_state state) { assert(state < ARRAY_SIZE(per_state_bits)); assert(per_state_bits[state]); return per_state_bits[state]; } void htlc_changestate(struct htlc *h, enum htlc_state oldstate, enum htlc_state newstate) { log_debug(h->peer->log, "htlc %"PRIu64": %s->%s", h->id, htlc_state_name(h->state), htlc_state_name(newstate)); assert(h->state == oldstate); /* You can only go to consecutive states. */ assert(newstate == h->state + 1); /* You can't change sides. */ assert((htlc_state_flags(h->state)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) == (htlc_state_flags(newstate)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); h->state = newstate; } void htlc_undostate(struct htlc *h, enum htlc_state oldstate, enum htlc_state newstate) { log_debug(h->peer->log, "htlc %"PRIu64": %s->%s", h->id, htlc_state_name(h->state), htlc_state_name(newstate)); assert(h->state == oldstate); /* You can only return to previous state. */ assert(newstate == h->state - 1); /* And must only be proposal, not commit. */ assert(h->state == SENT_REMOVE_HTLC || h->state == RCVD_REMOVE_HTLC); /* You can't change sides. */ assert((htlc_state_flags(h->state)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) == (htlc_state_flags(newstate)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); h->state = newstate; }