Browse Source

state: handle on-chain HTLCs.

When a unilateral close occurs, we have to watch on-chain ("live")
HTLCs.  If the other side spends their HTLC output, we need to grab
the rvalue.  If it times out, we need to spend it back to ourselves.
If we get an R value, we need to spend our own HTLC output back to
ourselves.

Because there are multiple HTLCs, this doesn't fit very neatly into a
state machine.  We divide into "have htlcs" and "don't have htlcs",
and use a INPUT_NO_MORE_HTLCS once all htlcs are resolved to transition.

Our test harness now tracks individual HTLCs, so we refined some
inputs (in particular, it won't try to complete/timeout an HTLC before
we have any).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
6821b4f31c
  1. 347
      state.c
  2. 150
      state.h
  3. 72
      state_types.h

347
state.c

@ -1,4 +1,5 @@
#include <state.h>
#include <ccan/build_assert/build_assert.h>
char cmd_requeue;
@ -24,6 +25,15 @@ static inline bool high_priority(enum state state)
#define INIT_EFFECT_stop_commands false
#define INIT_EFFECT_close_timeout INPUT_NONE
#define INIT_EFFECT_in_error NULL
#define INIT_EFFECT_r_value NULL
#define INIT_EFFECT_watch_htlcs NULL
#define INIT_EFFECT_unwatch_htlc NULL
#define INIT_EFFECT_htlc_in_progress NULL
#define INIT_EFFECT_htlc_abandon false
#define INIT_EFFECT_htlc_fulfill false
#define INIT_EFFECT_update_theirsig NULL
#define INIT_EFFECT_watch_htlc_spend NULL
#define INIT_EFFECT_unwatch_htlc_spend NULL
void state_effect_init(struct state_effect *effect)
{
@ -38,6 +48,15 @@ void state_effect_init(struct state_effect *effect)
effect->stop_commands = INIT_EFFECT_stop_commands;
effect->close_timeout = INIT_EFFECT_close_timeout;
effect->in_error = INIT_EFFECT_in_error;
effect->r_value = INIT_EFFECT_r_value;
effect->watch_htlcs = INIT_EFFECT_watch_htlcs;
effect->unwatch_htlc = INIT_EFFECT_unwatch_htlc;
effect->htlc_in_progress = INIT_EFFECT_htlc_in_progress;
effect->htlc_abandon = INIT_EFFECT_htlc_abandon;
effect->htlc_fulfill = INIT_EFFECT_htlc_fulfill;
effect->update_theirsig = INIT_EFFECT_update_theirsig;
effect->watch_htlc_spend = INIT_EFFECT_watch_htlc_spend;
effect->unwatch_htlc_spend = INIT_EFFECT_unwatch_htlc_spend;
}
#define set_effect(effect, field, val) \
@ -71,6 +90,8 @@ enum state state(const enum state state, const struct state_data *sdata,
Pkt *decline;
struct bitcoin_tx *steal;
Pkt *err;
struct htlc_watch *htlcs;
struct htlc_progress *htlcprog;
switch (state) {
/*
@ -90,8 +111,8 @@ enum state state(const enum state state, const struct state_data *sdata,
if (err)
goto err_close_nocleanup;
return STATE_OPEN_WAIT_FOR_ANCHOR;
} else if (input_is(input, CMD_SEND_UPDATE_ANY)) {
/* Can't do these until we're open. */
} else if (input_is(input, CMD_SEND_HTLC_UPDATE)) {
/* Can't do this until we're open. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, CMD_CLOSE)) {
@ -107,8 +128,8 @@ enum state state(const enum state state, const struct state_data *sdata,
goto err_close_nocleanup;
set_effect(effect, send, pkt_anchor(effect, sdata));
return STATE_OPEN_WAIT_FOR_COMMIT_SIG;
} else if (input_is(input, CMD_SEND_UPDATE_ANY)) {
/* Can't do these until we're open. */
} else if (input_is(input, CMD_SEND_HTLC_UPDATE)) {
/* Can't do this until we're open. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, CMD_CLOSE)) {
@ -133,8 +154,8 @@ enum state state(const enum state state, const struct state_data *sdata,
BITCOIN_ANCHOR_OTHERSPEND));
return STATE_OPEN_WAITING_THEIRANCHOR;
} else if (input_is(input, CMD_SEND_UPDATE_ANY)) {
/* Can't do these until we're open. */
} else if (input_is(input, CMD_SEND_HTLC_UPDATE)) {
/* Can't do this until we're open. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, CMD_CLOSE)) {
@ -159,8 +180,8 @@ enum state state(const enum state state, const struct state_data *sdata,
BITCOIN_ANCHOR_THEIRSPEND,
BITCOIN_ANCHOR_OTHERSPEND));
return STATE_OPEN_WAITING_OURANCHOR;
} else if (input_is(input, CMD_SEND_UPDATE_ANY)) {
/* Can't do these until we're open. */
} else if (input_is(input, CMD_SEND_HTLC_UPDATE)) {
/* Can't do this until we're open. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, CMD_CLOSE)) {
@ -180,8 +201,8 @@ enum state state(const enum state state, const struct state_data *sdata,
/* Ignore until we've hit depth ourselves. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, CMD_SEND_UPDATE_ANY)) {
/* Can't do these until we're open. */
} else if (input_is(input, CMD_SEND_HTLC_UPDATE)) {
/* Can't do this until we're open. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
@ -243,8 +264,8 @@ enum state state(const enum state state, const struct state_data *sdata,
/* Ignore until we've hit depth ourselves. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, CMD_SEND_UPDATE_ANY)) {
/* Can't do these until we're open. */
} else if (input_is(input, CMD_SEND_HTLC_UPDATE)) {
/* Can't do this until we're open. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, CMD_CLOSE)) {
@ -289,8 +310,8 @@ enum state state(const enum state state, const struct state_data *sdata,
} else if (input_is(input, PKT_OPEN_COMPLETE)) {
/* Ready for business! */
return STATE_NORMAL_HIGHPRIO;
} else if (input_is(input, CMD_SEND_UPDATE_ANY)) {
/* Can't do these until we're open. */
} else if (input_is(input, CMD_SEND_HTLC_UPDATE)) {
/* Can't do this until we're open. */
set_effect(effect, defer, input);
return state;
} else if (input_is(input, CMD_CLOSE)) {
@ -310,24 +331,34 @@ enum state state(const enum state state, const struct state_data *sdata,
if (input_is(input, CMD_SEND_HTLC_UPDATE)) {
/* We are to send an HTLC update. */
set_effect(effect, send,
pkt_htlc_update(effect, sdata, idata->cmd));
pkt_htlc_update(effect, sdata,
idata->htlc_prog));
set_effect(effect, htlc_in_progress, idata->htlc_prog);
return prio(state, STATE_WAIT_FOR_HTLC_ACCEPT);
} else if (input_is(input, CMD_SEND_HTLC_FULFILL)) {
/* We are to send an HTLC fulfill. */
/* This gives us the r value (FIXME: type!) */
set_effect(effect, r_value,
r_value_from_cmd(effect, sdata, idata->htlc));
set_effect(effect, send,
pkt_htlc_fulfill(effect, sdata, idata->cmd));
return prio(state, STATE_WAIT_FOR_HTLC_ACCEPT);
pkt_htlc_fulfill(effect, sdata,
idata->htlc_prog));
set_effect(effect, htlc_in_progress, idata->htlc_prog);
return prio(state, STATE_WAIT_FOR_UPDATE_ACCEPT);
} else if (input_is(input, CMD_SEND_HTLC_TIMEDOUT)) {
/* We are to send an HTLC timedout. */
set_effect(effect, send,
pkt_htlc_timedout(effect, sdata, idata->cmd));
return prio(state, STATE_WAIT_FOR_HTLC_ACCEPT);
pkt_htlc_timedout(effect, sdata,
idata->htlc_prog));
set_effect(effect, htlc_in_progress, idata->htlc_prog);
return prio(state, STATE_WAIT_FOR_UPDATE_ACCEPT);
} else if (input_is(input, CMD_SEND_HTLC_ROUTEFAIL)) {
/* We are to send an HTLC routefail. */
set_effect(effect, send,
pkt_htlc_routefail(effect, sdata,
idata->cmd));
return prio(state, STATE_WAIT_FOR_HTLC_ACCEPT);
idata->htlc_prog));
set_effect(effect, htlc_in_progress, idata->htlc_prog);
return prio(state, STATE_WAIT_FOR_UPDATE_ACCEPT);
} else if (input_is(input, CMD_CLOSE)) {
goto start_closing;
} else if (input_is(input, PKT_UPDATE_ADD_HTLC)) {
@ -355,15 +386,26 @@ enum state state(const enum state state, const struct state_data *sdata,
/* HTLCs can also evoke a refusal. */
if (input_is(input, PKT_UPDATE_DECLINE_HTLC)) {
fail_cmd(effect, CMD_SEND_HTLC_UPDATE, idata->pkt);
set_effect(effect, htlc_abandon, true);
/* Toggle between high and low priority states. */
return toggle_prio(state, STATE_NORMAL);
} else if (input_is(input, PKT_UPDATE_ADD_HTLC)) {
/* They can't close with an HTLC, so only possible here */
} else if (input_is(input, PKT_CLOSE)) {
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
set_effect(effect, htlc_abandon, true);
goto accept_closing;
}
/* Fall thru */
case STATE_WAIT_FOR_UPDATE_ACCEPT_LOWPRIO:
case STATE_WAIT_FOR_UPDATE_ACCEPT_HIGHPRIO:
if (input_is(input, PKT_UPDATE_ADD_HTLC)) {
/* If we're high priority, ignore their packet */
if (high_priority(state))
return state;
/* Otherwise, process their request first: defer ours */
requeue_cmd(effect, CMD_SEND_UPDATE_ANY);
set_effect(effect, htlc_abandon, true);
goto accept_htlc_update;
} else if (input_is(input, PKT_UPDATE_FULFILL_HTLC)) {
/* If we're high priority, ignore their packet */
@ -372,6 +414,7 @@ enum state state(const enum state state, const struct state_data *sdata,
/* Otherwise, process their request first: defer ours */
requeue_cmd(effect, CMD_SEND_UPDATE_ANY);
set_effect(effect, htlc_abandon, true);
goto accept_htlc_fulfill;
} else if (input_is(input, PKT_UPDATE_TIMEDOUT_HTLC)) {
/* If we're high priority, ignore their packet */
@ -380,6 +423,7 @@ enum state state(const enum state state, const struct state_data *sdata,
/* Otherwise, process their request first: defer ours */
requeue_cmd(effect, CMD_SEND_UPDATE_ANY);
set_effect(effect, htlc_abandon, true);
goto accept_htlc_timedout;
} else if (input_is(input, PKT_UPDATE_ROUTEFAIL_HTLC)) {
/* If we're high priority, ignore their packet */
@ -388,31 +432,37 @@ enum state state(const enum state state, const struct state_data *sdata,
/* Otherwise, process their request first: defer ours */
requeue_cmd(effect, CMD_SEND_UPDATE_ANY);
set_effect(effect, htlc_abandon, true);
goto accept_htlc_routefail;
} else if (input_is(input, PKT_UPDATE_ACCEPT)) {
struct signature *sig;
err = accept_pkt_update_accept(effect, sdata,
idata->pkt);
idata->pkt, &sig);
if (err) {
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
goto err_start_unilateral_close;
}
set_effect(effect, update_theirsig, sig);
set_effect(effect, send,
pkt_update_signature(effect, sdata));
/* HTLC is signed (though old tx not revoked yet!) */
set_effect(effect, htlc_fulfill, true);
return prio(state, STATE_WAIT_FOR_UPDATE_COMPLETE);
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
set_effect(effect, htlc_abandon, true);
goto anchor_unspent;
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
set_effect(effect, htlc_abandon, true);
goto them_unilateral;
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
set_effect(effect, htlc_abandon, true);
goto old_commit_spotted;
} else if (input_is(input, PKT_CLOSE)) {
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
goto accept_closing;
} else if (input_is_pkt(input)) {
fail_cmd(effect, CMD_SEND_UPDATE_ANY, NULL);
set_effect(effect, htlc_abandon, true);
goto unexpected_pkt;
}
break;
@ -445,26 +495,34 @@ enum state state(const enum state state, const struct state_data *sdata,
case STATE_WAIT_FOR_UPDATE_SIG_LOWPRIO:
case STATE_WAIT_FOR_UPDATE_SIG_HIGHPRIO:
if (input_is(input, PKT_UPDATE_SIGNATURE)) {
struct signature *sig;
err = accept_pkt_update_signature(effect, sdata,
idata->pkt);
idata->pkt, &sig);
if (err)
goto err_start_unilateral_close;
set_effect(effect, update_theirsig, sig);
set_effect(effect, send,
pkt_update_complete(effect, sdata));
set_effect(effect, htlc_fulfill, true);
/* Toggle between high and low priority states. */
return toggle_prio(state, STATE_NORMAL);
} else if (input_is(input, CMD_SEND_UPDATE_ANY)) {
set_effect(effect, defer, input);
return state;
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
set_effect(effect, htlc_abandon, true);
goto anchor_unspent;
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
set_effect(effect, htlc_abandon, true);
goto them_unilateral;
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
set_effect(effect, htlc_abandon, true);
goto old_commit_spotted;
} else if (input_is(input, CMD_CLOSE)) {
set_effect(effect, htlc_abandon, true);
goto start_closing;
} else if (input_is_pkt(input)) {
set_effect(effect, htlc_abandon, true);
goto unexpected_pkt;
}
break;
@ -511,7 +569,11 @@ enum state state(const enum state state, const struct state_data *sdata,
bitcoin_watch_delayed(effect,
effect->broadcast,
BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED));
/* They could still close. */
/* We agreed to close: shouldn't have any HTLCs */
if (committed_to_htlcs(sdata))
return STATE_ERR_INTERNAL;
return STATE_CLOSE_WAIT_CLOSE_OURCOMMIT;
}
fail_cmd(effect, CMD_CLOSE, NULL);
@ -545,51 +607,87 @@ enum state state(const enum state state, const struct state_data *sdata,
goto fail_during_close;
/* Close states are regular: handle as a group. */
case STATE_CLOSE_WAIT_HTLCS:
case STATE_CLOSE_WAIT_STEAL:
case STATE_CLOSE_WAIT_SPENDTHEM:
case STATE_CLOSE_WAIT_SPENDTHEM_WITH_HTLCS:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_WITH_HTLCS:
case STATE_CLOSE_WAIT_CLOSE:
case STATE_CLOSE_WAIT_STEAL_CLOSE:
case STATE_CLOSE_WAIT_SPENDTHEM_CLOSE:
case STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_WITH_HTLCS:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_WITH_HTLCS:
case STATE_CLOSE_WAIT_STEAL_OURCOMMIT:
case STATE_CLOSE_WAIT_STEAL_OURCOMMIT_WITH_HTLCS:
case STATE_CLOSE_WAIT_SPENDTHEM_OURCOMMIT:
case STATE_CLOSE_WAIT_SPENDTHEM_OURCOMMIT_WITH_HTLCS:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_OURCOMMIT:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_OURCOMMIT_WITH_HTLCS:
case STATE_CLOSE_WAIT_CLOSE_OURCOMMIT:
case STATE_CLOSE_WAIT_STEAL_CLOSE_OURCOMMIT:
case STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_OURCOMMIT:
case STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_OURCOMMIT_WITH_HTLCS:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_OURCOMMIT:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_OURCOMMIT_WITH_HTLCS:
case STATE_CLOSE_WAIT_STEAL_SPENDOURS:
case STATE_CLOSE_WAIT_STEAL_SPENDOURS_WITH_HTLCS:
case STATE_CLOSE_WAIT_SPENDTHEM_SPENDOURS:
case STATE_CLOSE_WAIT_SPENDTHEM_SPENDOURS_WITH_HTLCS:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_SPENDOURS:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_SPENDOURS_WITH_HTLCS:
case STATE_CLOSE_WAIT_CLOSE_SPENDOURS:
case STATE_CLOSE_WAIT_STEAL_CLOSE_SPENDOURS:
case STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_SPENDOURS:
case STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_SPENDOURS_WITH_HTLCS:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_SPENDOURS:
case STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_SPENDOURS_WITH_HTLCS:
case STATE_CLOSE_WAIT_OURCOMMIT:
case STATE_CLOSE_WAIT_SPENDOURS: {
case STATE_CLOSE_WAIT_OURCOMMIT_WITH_HTLCS:
case STATE_CLOSE_WAIT_SPENDOURS:
case STATE_CLOSE_WAIT_SPENDOURS_WITH_HTLCS: {
unsigned int bits, base;
enum state_input closed;
base = (unsigned)STATE_CLOSE_WAIT_STEAL - 1;
base = (unsigned)STATE_CLOSED;
bits = (unsigned)state - base;
/* Once we see a steal or spend completely buried, we
* close unless we're still waiting for htlcs*/
if (bits & STATE_CLOSE_HTLCS_BIT)
closed = STATE_CLOSE_WAIT_HTLCS;
else
closed = STATE_CLOSED;
if ((bits & STATE_CLOSE_STEAL_BIT)
&& input_is(input, BITCOIN_STEAL_DONE)) {
/* One a steal is complete, we don't care about htlcs
* (we stole them all) */
if (bits & STATE_CLOSE_HTLCS_BIT)
set_effect(effect, unwatch_htlc,
htlc_unwatch_all(effect, sdata));
return STATE_CLOSED;
}
if ((bits & STATE_CLOSE_SPENDTHEM_BIT)
&& input_is(input, BITCOIN_SPEND_THEIRS_DONE)) {
return STATE_CLOSED;
BUILD_ASSERT(!((STATE_CLOSE_WAIT_HTLCS - base)
& STATE_CLOSE_SPENDTHEM_BIT));
return closed;
}
if ((bits & STATE_CLOSE_CLOSE_BIT)
&& input_is(input, BITCOIN_CLOSE_DONE)) {
return STATE_CLOSED;
BUILD_ASSERT(!((STATE_CLOSE_WAIT_HTLCS - base)
& STATE_CLOSE_CLOSE_BIT));
return closed;
}
if ((bits & STATE_CLOSE_OURCOMMIT_BIT)
&& input_is(input, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED)) {
BUILD_ASSERT(!((STATE_CLOSE_WAIT_HTLCS - base)
& STATE_CLOSE_OURCOMMIT_BIT));
/* Now we need to wait for our commit to be done. */
set_effect(effect, broadcast,
bitcoin_spend_ours(effect, sdata));
@ -603,17 +701,122 @@ enum state state(const enum state state, const struct state_data *sdata,
if ((bits & STATE_CLOSE_SPENDOURS_BIT)
&& input_is(input, BITCOIN_SPEND_OURS_DONE)) {
return STATE_CLOSED;
BUILD_ASSERT(!((STATE_CLOSE_WAIT_HTLCS - base)
& STATE_CLOSE_SPENDOURS_BIT));
return closed;
}
/* Now, other side can always spring a commit transaction on us
* (even if they already have, due to tx malleability) */
/* If we have htlcs, we can get other inputs... */
if (bits & STATE_CLOSE_HTLCS_BIT) {
if (input_is(input, INPUT_NO_MORE_HTLCS)) {
/* Clear bit, might lead to STATE_CLOSED. */
BUILD_ASSERT(((STATE_CLOSE_WAIT_HTLCS - base)
& ~STATE_CLOSE_HTLCS_BIT)
== STATE_CLOSED);
bits &= ~STATE_CLOSE_HTLCS_BIT;
return base + bits;
} else if (input_is(input, BITCOIN_HTLC_TOTHEM_SPENT)) {
/* They revealed R value. */
set_effect(effect, r_value,
bitcoin_r_value(effect, idata->htlc));
/* We don't care any more. */
set_effect(effect, unwatch_htlc,
htlc_unwatch(effect, idata->htlc,
INPUT_NO_MORE_HTLCS));
return state;
} else if (input_is(input, BITCOIN_HTLC_TOTHEM_TIMEOUT)){
/* HTLC timed out, spend it back to us. */
set_effect(effect, broadcast,
bitcoin_htlc_timeout(effect,
sdata,
idata->htlc));
/* Don't unwatch yet; they could yet
* try to spend, revealing rvalue. */
/* We're done when that gets buried. */
set_effect(effect, watch_htlc_spend,
htlc_spend_watch(effect,
effect->broadcast,
idata->cmd,
BITCOIN_HTLC_RETURN_SPEND_DONE));
return state;
} else if (input_is(input, CMD_SEND_HTLC_FULFILL)) {
/* This gives us the r value. */
set_effect(effect, r_value,
r_value_from_cmd(effect, sdata,
idata->htlc));
/* Spend it... */
set_effect(effect, broadcast,
bitcoin_htlc_spend(effect, sdata,
idata->htlc));
/* We're done when it gets buried. */
set_effect(effect, watch_htlc_spend,
htlc_spend_watch(effect,
effect->broadcast,
idata->cmd,
BITCOIN_HTLC_FULFILL_SPEND_DONE));
/* Don't care about this one any more. */
set_effect(effect, unwatch_htlc,
htlc_unwatch(effect, idata->htlc,
INPUT_NO_MORE_HTLCS));
return state;
} else if (input_is(input, BITCOIN_HTLC_FULFILL_SPEND_DONE)) {
/* Stop watching spend, send
* INPUT_NO_MORE_HTLCS when done. */
set_effect(effect, unwatch_htlc_spend,
htlc_spend_unwatch(effect,
idata->htlc,
INPUT_NO_MORE_HTLCS));
return state;
} else if (input_is(input, BITCOIN_HTLC_RETURN_SPEND_DONE)) {
/* Stop watching spend, send
* INPUT_NO_MORE_HTLCS when done. */
set_effect(effect, unwatch_htlc_spend,
htlc_spend_unwatch(effect,
idata->htlc,
INPUT_NO_MORE_HTLCS));
/* Don't need to watch the HTLC output any more,
* either. */
set_effect(effect, unwatch_htlc,
htlc_unwatch(effect, idata->htlc,
INPUT_NO_MORE_HTLCS));
return state;
} else if (input_is(input, BITCOIN_HTLC_TOUS_TIMEOUT)) {
/* They can spend, we no longer care
* about this HTLC. */
set_effect(effect, unwatch_htlc,
htlc_unwatch(effect, idata->htlc,
INPUT_NO_MORE_HTLCS));
return state;
}
}
/* If we're just waiting for HTLCs, anything else is an error */
if (state == STATE_CLOSE_WAIT_HTLCS)
break;
/*
* Now, other side can always spring a commit transaction on us
* (even if they already have, due to tx malleability).
*/
if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
set_effect(effect, broadcast,
bitcoin_spend_theirs(effect, sdata));
bitcoin_spend_theirs(effect, sdata,
idata->btc));
set_effect(effect, watch,
bitcoin_watch(effect, effect->broadcast,
BITCOIN_SPEND_THEIRS_DONE));
/* HTLC watches. */
htlcs = htlc_outputs_their_commit(effect, sdata,
idata->btc,
BITCOIN_HTLC_TOUS_TIMEOUT,
BITCOIN_HTLC_TOTHEM_SPENT,
BITCOIN_HTLC_TOTHEM_TIMEOUT);
if (htlcs) {
set_effect(effect, watch_htlcs, htlcs);
bits |= STATE_CLOSE_HTLCS_BIT;
}
bits |= STATE_CLOSE_SPENDTHEM_BIT;
return base + bits;
/* This can happen multiple times: need to steal ALL */
@ -630,6 +833,7 @@ enum state state(const enum state state, const struct state_data *sdata,
return base + bits;
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT))
goto anchor_unspent;
break;
}
@ -640,6 +844,13 @@ enum state state(const enum state state, const struct state_data *sdata,
case STATE_ERR_ANCHOR_LOST:
case STATE_CLOSED:
case STATE_MAX:
case STATE_UNUSED_CLOSE_WAIT_STEAL_WITH_HTLCS:
case STATE_UNUSED_CLOSE_WAIT_CLOSE_WITH_HTLCS:
case STATE_UNUSED_CLOSE_WAIT_STEAL_CLOSE_WITH_HTLCS:
case STATE_UNUSED_CLOSE_WAIT_CLOSE_OURCOMMIT_WITH_HTLCS:
case STATE_UNUSED_CLOSE_WAIT_STEAL_CLOSE_OURCOMMIT_WITH_HTLCS:
case STATE_UNUSED_CLOSE_WAIT_CLOSE_SPENDOURS_WITH_HTLCS:
case STATE_UNUSED_CLOSE_WAIT_STEAL_CLOSE_SPENDOURS_WITH_HTLCS:
return STATE_ERR_INTERNAL;
}
@ -652,7 +863,7 @@ unexpected_pkt:
*/
/* Don't reply to an error with an error. */
if (input_is(input, PKT_ERROR)) {
set_effect(effect, in_error, tal_steal(effect, idata->pkt));
set_effect(effect, in_error, set_errpkt(effect, idata->pkt));
goto start_unilateral_close;
}
err = unexpected_pkt(effect, input);
@ -700,9 +911,21 @@ start_unilateral_close:
set_effect(effect, watch,
bitcoin_watch_delayed(effect, effect->broadcast,
BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED));
/* HTLC watches. */
htlcs = htlc_outputs_our_commit(effect, sdata, effect->broadcast,
BITCOIN_HTLC_TOUS_TIMEOUT,
BITCOIN_HTLC_TOTHEM_SPENT,
BITCOIN_HTLC_TOTHEM_TIMEOUT);
if (htlcs) {
set_effect(effect, watch_htlcs, htlcs);
return STATE_CLOSE_WAIT_OURCOMMIT_WITH_HTLCS;
}
return STATE_CLOSE_WAIT_OURCOMMIT;
them_unilateral:
assert(input == BITCOIN_ANCHOR_THEIRSPEND);
/*
* Bitcoind tells us they did unilateral close.
*/
@ -711,14 +934,27 @@ them_unilateral:
/* No more inputs, no more commands. */
set_effect(effect, stop_packets, true);
set_effect(effect, stop_commands, true);
set_effect(effect, broadcast, bitcoin_spend_theirs(effect, sdata));
set_effect(effect, broadcast,
bitcoin_spend_theirs(effect, sdata, idata->btc));
set_effect(effect, watch,
bitcoin_watch(effect, effect->broadcast,
BITCOIN_SPEND_THEIRS_DONE));
/* HTLC watches (based on what they broadcast, which *may* be out
* of step with our current state by +/- 1 htlc. */
htlcs = htlc_outputs_their_commit(effect, sdata, idata->btc,
BITCOIN_HTLC_TOUS_TIMEOUT,
BITCOIN_HTLC_TOTHEM_SPENT,
BITCOIN_HTLC_TOTHEM_TIMEOUT);
if (htlcs) {
set_effect(effect, watch_htlcs, htlcs);
return STATE_CLOSE_WAIT_SPENDTHEM_WITH_HTLCS;
}
return STATE_CLOSE_WAIT_SPENDTHEM;
accept_htlc_update:
err = accept_pkt_htlc_update(effect, sdata, idata->pkt, &decline);
err = accept_pkt_htlc_update(effect, sdata, idata->pkt, &decline,
&htlcprog);
if (err)
goto err_start_unilateral_close;
if (decline) {
@ -726,34 +962,45 @@ accept_htlc_update:
/* Toggle between high/low priority states. */
return toggle_prio(state, STATE_NORMAL);
}
set_effect(effect, htlc_in_progress, htlcprog);
set_effect(effect, send, pkt_update_accept(effect, sdata));
return prio(state, STATE_WAIT_FOR_UPDATE_SIG);
accept_htlc_routefail:
err = accept_pkt_htlc_routefail(effect, sdata, idata->pkt);
err = accept_pkt_htlc_routefail(effect, sdata, idata->pkt, &htlcprog);
if (err)
goto err_start_unilateral_close;
set_effect(effect, htlc_in_progress, htlcprog);
set_effect(effect, send, pkt_update_accept(effect, sdata));
return prio(state, STATE_WAIT_FOR_UPDATE_SIG);
accept_htlc_timedout:
err = accept_pkt_htlc_timedout(effect, sdata, idata->pkt);
err = accept_pkt_htlc_timedout(effect, sdata, idata->pkt, &htlcprog);
if (err)
goto err_start_unilateral_close;
set_effect(effect, htlc_in_progress, htlcprog);
set_effect(effect, send, pkt_update_accept(effect, sdata));
return prio(state, STATE_WAIT_FOR_UPDATE_SIG);
accept_htlc_fulfill:
err = accept_pkt_htlc_fulfill(effect, sdata, idata->pkt);
err = accept_pkt_htlc_fulfill(effect, sdata, idata->pkt, &htlcprog);
if (err)
goto err_start_unilateral_close;
set_effect(effect, htlc_in_progress, htlcprog);
set_effect(effect, send, pkt_update_accept(effect, sdata));
set_effect(effect, r_value, r_value_from_pkt(effect, idata->pkt));
return prio(state, STATE_WAIT_FOR_UPDATE_SIG);
start_closing:
/*
* Start a mutual close.
*/
/* Protocol doesn't (currently?) allow closing with HTLCs. */
if (committed_to_htlcs(sdata)) {
fail_cmd(effect, CMD_CLOSE, NULL);
err = pkt_err(effect, "Close forced due to HTLCs");
goto err_start_unilateral_close;
}
set_effect(effect, close_timeout, INPUT_CLOSE_COMPLETE_TIMEOUT);
set_effect(effect, watch,
@ -784,6 +1031,10 @@ instant_close:
/* FIXME: Should we tell other side we're going? */
set_effect(effect, stop_packets, true);
set_effect(effect, stop_commands, true);
/* We can't have any HTLCs, since we haven't started. */
if (committed_to_htlcs(sdata))
return STATE_ERR_INTERNAL;
return STATE_CLOSED;
fail_during_close:
@ -799,11 +1050,21 @@ fail_during_close:
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
/* A reorganization could make this happen. */
set_effect(effect, broadcast,
bitcoin_spend_theirs(effect, sdata));
bitcoin_spend_theirs(effect, sdata, idata->btc));
set_effect(effect, watch,
bitcoin_watch(effect, effect->broadcast,
BITCOIN_SPEND_THEIRS_DONE));
htlcs = htlc_outputs_their_commit(effect, sdata, idata->btc,
BITCOIN_HTLC_TOUS_TIMEOUT,
BITCOIN_HTLC_TOTHEM_SPENT,
BITCOIN_HTLC_TOTHEM_TIMEOUT);
/* Expect either close or spendthem to complete */
if (htlcs) {
/* FIXME: Make sure caller uses CMD_HTLC_FULFILL again
* if they were in the middle of one! */
set_effect(effect, watch_htlcs, htlcs);
return STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_WITH_HTLCS;
}
return STATE_CLOSE_WAIT_SPENDTHEM_CLOSE;
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
steal = bitcoin_steal(effect, sdata, idata->btc);

150
state.h

@ -43,6 +43,31 @@ struct state_effect {
/* Error received from other side. */
Pkt *in_error;
/* HTLC we're working on. */
struct htlc_progress *htlc_in_progress;
/* Their signature for the new commit tx. */
struct signature *update_theirsig;
/* Stop working on HTLC. */
bool htlc_abandon;
/* Finished working on HTLC. */
bool htlc_fulfill;
/* R value. */
const struct htlc_rval *r_value;
/* HTLC outputs to watch. */
const struct htlc_watch *watch_htlcs;
/* HTLC output to unwatch. */
const struct htlc_unwatch *unwatch_htlc;
/* HTLC spends to watch/unwatch. */
const struct htlc_spend_watch *watch_htlc_spend;
const struct htlc_spend_watch *unwatch_htlc_spend;
/* FIXME: More to come (for accept_*) */
};
@ -65,6 +90,8 @@ union input {
Pkt *pkt;
struct command *cmd;
struct bitcoin_event *btc;
struct htlc *htlc;
struct htlc_progress *htlc_prog;
};
enum state state(const enum state state, const struct state_data *sdata,
@ -92,15 +119,21 @@ static inline bool input_is(enum state_input a, enum state_input b)
return a == b;
}
struct signature;
/* Create various kinds of packets, allocated off @ctx */
Pkt *pkt_open(const tal_t *ctx, const struct state_data *sdata);
Pkt *pkt_anchor(const tal_t *ctx, const struct state_data *sdata);
Pkt *pkt_open_commit_sig(const tal_t *ctx, const struct state_data *sdata);
Pkt *pkt_open_complete(const tal_t *ctx, const struct state_data *sdata);
Pkt *pkt_htlc_update(const tal_t *ctx, const struct state_data *sdata, void *data);
Pkt *pkt_htlc_fulfill(const tal_t *ctx, const struct state_data *sdata, void *data);
Pkt *pkt_htlc_timedout(const tal_t *ctx, const struct state_data *sdata, void *data);
Pkt *pkt_htlc_routefail(const tal_t *ctx, const struct state_data *sdata, void *data);
Pkt *pkt_htlc_update(const tal_t *ctx, const struct state_data *sdata,
const struct htlc_progress *htlc_prog);
Pkt *pkt_htlc_fulfill(const tal_t *ctx, const struct state_data *sdata,
const struct htlc_progress *htlc_prog);
Pkt *pkt_htlc_timedout(const tal_t *ctx, const struct state_data *sdata,
const struct htlc_progress *htlc_prog);
Pkt *pkt_htlc_routefail(const tal_t *ctx, const struct state_data *sdata,
const struct htlc_progress *htlc_prog);
Pkt *pkt_update_accept(const tal_t *ctx, const struct state_data *sdata);
Pkt *pkt_update_signature(const tal_t *ctx, const struct state_data *sdata);
Pkt *pkt_update_complete(const tal_t *ctx, const struct state_data *sdata);
@ -124,26 +157,32 @@ Pkt *accept_pkt_open_commit_sig(struct state_effect *effect,
Pkt *accept_pkt_htlc_update(struct state_effect *effect,
const struct state_data *sdata, const Pkt *pkt,
Pkt **decline);
Pkt **decline,
struct htlc_progress **htlcprog);
Pkt *accept_pkt_htlc_routefail(struct state_effect *effect,
const struct state_data *sdata, const Pkt *pkt);
const struct state_data *sdata, const Pkt *pkt,
struct htlc_progress **htlcprog);
Pkt *accept_pkt_htlc_timedout(struct state_effect *effect,
const struct state_data *sdata, const Pkt *pkt);
const struct state_data *sdata, const Pkt *pkt,
struct htlc_progress **htlcprog);
Pkt *accept_pkt_htlc_fulfill(struct state_effect *effect,
const struct state_data *sdata, const Pkt *pkt);
const struct state_data *sdata, const Pkt *pkt,
struct htlc_progress **htlcprog);
Pkt *accept_pkt_update_accept(struct state_effect *effect,
const struct state_data *sdata, const Pkt *pkt);
const struct state_data *sdata, const Pkt *pkt,
struct signature **sig);
Pkt *accept_pkt_update_complete(struct state_effect *effect,
const struct state_data *sdata, const Pkt *pkt);
Pkt *accept_pkt_update_signature(struct state_effect *effect,
const struct state_data *sdata,
const Pkt *pkt);
const Pkt *pkt,
struct signature **sig);
Pkt *accept_pkt_close(struct state_effect *effect,
const struct state_data *sdata, const Pkt *pkt);
@ -158,6 +197,14 @@ Pkt *accept_pkt_simultaneous_close(struct state_effect *effect,
Pkt *accept_pkt_close_ack(struct state_effect *effect,
const struct state_data *sdata, const Pkt *pkt);
/**
* committed_to_htlcs: do we have any locked-in HTLCs?
* @sdata: the state data for this peer.
*
* If we were to generate a commit tx now, would it have HTLCs in it?
*/
bool committed_to_htlcs(const struct state_data *sdata);
/**
* bitcoin_watch_anchor: create a watch for the anchor.
* @ctx: context to tal the watch struct off.
@ -230,7 +277,77 @@ struct watch *bitcoin_watch_close(const tal_t *ctx,
const struct state_data *sdata,
enum state_input done);
/**
* htlc_outputs_our_commit: HTLC outputs from our commit tx to watch.
* @ctx: context to tal the watch struct off.
* @sdata: the state data for this peer.
* @tx: the commitment tx
* @tous_timeout: input to give when a HTLC output to us times out.
* @tothem_spent: input to give when a HTLC output to them is spent.
* @tothem_timeout: input to give when a HTLC output to them times out.
*/
struct htlc_watch *htlc_outputs_our_commit(const tal_t *ctx,
const struct state_data *sdata,
const struct bitcoin_tx *tx,
enum state_input tous_timeout,
enum state_input tothem_spent,
enum state_input tothem_timeout);
/**
* htlc_outputs_their_commit: HTLC outputs from their commit tx to watch.
* @ctx: context to tal the watch struct off.
* @sdata: the state data for this peer.
* @tx: the commitment tx
* @tous_timeout: input to give when a HTLC output to us times out.
* @tothem_spent: input to give when a HTLC output to them is spent.
* @tothem_timeout: input to give when a HTLC output to them times out.
*/
struct htlc_watch *htlc_outputs_their_commit(const tal_t *ctx,
const struct state_data *sdata,
const struct bitcoin_event *tx,
enum state_input tous_timeout,
enum state_input tothem_spent,
enum state_input tothem_timeout);
/**
* htlc_unwatch: stop watching an HTLC
* @ctx: context to tal the watch struct off.
* @htlc: the htlc to stop watching
* @all_done: input to give if we're not watching any anymore.
*/
struct htlc_unwatch *htlc_unwatch(const tal_t *ctx,
const struct htlc *htlc,
enum state_input all_done);
/**
* htlc_unwatch_all: stop watching all HTLCs
* @ctx: context to tal the watch struct off.
* @sdata: the state data for this peer.
*/
struct htlc_unwatch *htlc_unwatch_all(const tal_t *ctx,
const struct state_data *sdata);
/**
* htlc_spend_watch: watch our spend of an HTLC
* @ctx: context to tal the watch struct off.
* @tx: the commitment tx
* @cmd: the command data.
* @done: input to give when it's completely buried.
*/
struct htlc_spend_watch *htlc_spend_watch(const tal_t *ctx,
const struct bitcoin_tx *tx,
const struct command *cmd,
enum state_input done);
/**
* htlc_spend_unwatch: stop watching an HTLC spend
* @ctx: context to tal the watch struct off.
* @htlc: the htlc to stop watching
* @all_done: input to give if we're not watching anything anymore.
*/
struct htlc_spend_watch *htlc_spend_unwatch(const tal_t *ctx,
const struct htlc *htlc,
enum state_input all_done);
/* Create a bitcoin anchor tx. */
struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx,
const struct state_data *sdata);
@ -245,7 +362,8 @@ struct bitcoin_tx *bitcoin_spend_ours(const tal_t *ctx,
/* Create a bitcoin spend tx (to spend their commit's outputs) */
struct bitcoin_tx *bitcoin_spend_theirs(const tal_t *ctx,
const struct state_data *sdata);
const struct state_data *sdata,
const struct bitcoin_event *btc);
/* Create a bitcoin steal tx (to steal all their commit's outputs) */
struct bitcoin_tx *bitcoin_steal(const tal_t *ctx,
@ -256,4 +374,14 @@ struct bitcoin_tx *bitcoin_steal(const tal_t *ctx,
struct bitcoin_tx *bitcoin_commit(const tal_t *ctx,
const struct state_data *sdata);
/* Create a HTLC refund collection */
struct bitcoin_tx *bitcoin_htlc_timeout(const tal_t *ctx,
const struct state_data *sdata,
const struct htlc *htlc);
/* Create a HTLC collection */
struct bitcoin_tx *bitcoin_htlc_spend(const tal_t *ctx,
const struct state_data *sdata,
const struct htlc *htlc);
#endif /* LIGHTNING_STATE_H */

72
state_types.h

@ -3,11 +3,12 @@
/* FIXME: cdump is really dumb, so we put these in their own header. */
#include "lightning.pb-c.h"
#define STATE_CLOSE_STEAL_BIT 1
#define STATE_CLOSE_SPENDTHEM_BIT 2
#define STATE_CLOSE_CLOSE_BIT 4
#define STATE_CLOSE_OURCOMMIT_BIT 8
#define STATE_CLOSE_SPENDOURS_BIT 16
#define STATE_CLOSE_HTLCS_BIT 1
#define STATE_CLOSE_STEAL_BIT 2
#define STATE_CLOSE_SPENDTHEM_BIT 4
#define STATE_CLOSE_CLOSE_BIT 8
#define STATE_CLOSE_OURCOMMIT_BIT 16
#define STATE_CLOSE_SPENDOURS_BIT 32
enum state {
STATE_INIT_NOANCHOR,
@ -36,6 +37,9 @@ enum state {
STATE_WAIT_FOR_HTLC_ACCEPT_LOWPRIO,
STATE_WAIT_FOR_HTLC_ACCEPT_HIGHPRIO,
STATE_WAIT_FOR_UPDATE_ACCEPT_LOWPRIO,
STATE_WAIT_FOR_UPDATE_ACCEPT_HIGHPRIO,
STATE_WAIT_FOR_UPDATE_COMPLETE_LOWPRIO,
STATE_WAIT_FOR_UPDATE_COMPLETE_HIGHPRIO,
@ -50,6 +54,11 @@ enum state {
/* They told us to close, waiting for ack msg. */
STATE_WAIT_FOR_CLOSE_ACK,
/* All closed. */
STATE_CLOSED,
/* Just waiting for HTLCs to resolve. */
STATE_CLOSE_WAIT_HTLCS,
/*
* They can broadcast one or more revoked commit tx, or their latest
* commit tx at any time. We respond to revoked commit txs by stealing
@ -88,35 +97,67 @@ enum state {
* - steal + mutual_close + spend_ours
* - spend_them + mutual_close + spend_ours
* - steal + spend_them + mutual_close + spend_ours
*
* Each of these has with-HTLC and without-HTLC variants, except:
*
* 1) We never agree to close with HTLCs,
* 2) We don't care about htlcs if we steal (we steal all outputs).
*
* Now, it is possible for us to CLOSE and them to have an HTLC,
* because we could close partway through negotiation. So, any
* commit tx they publish could introduce HTLCs.
*
* Thus, HTLC variants are only possible with SPENDTHEM, OR
* OURCOMMIT/SPENDOURS, and only no CLOSE (since CLOSE implies no HTLCs).
*/
STATE_CLOSE_WAIT_STEAL,
STATE_UNUSED_CLOSE_WAIT_STEAL_WITH_HTLCS,
STATE_CLOSE_WAIT_SPENDTHEM,
STATE_CLOSE_WAIT_SPENDTHEM_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_WITH_HTLCS,
STATE_CLOSE_WAIT_CLOSE,
STATE_UNUSED_CLOSE_WAIT_CLOSE_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_CLOSE,
STATE_UNUSED_CLOSE_WAIT_STEAL_CLOSE_WITH_HTLCS,
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE,
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_WITH_HTLCS,
STATE_CLOSE_WAIT_OURCOMMIT,
STATE_CLOSE_WAIT_OURCOMMIT_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_OURCOMMIT,
STATE_CLOSE_WAIT_STEAL_OURCOMMIT_WITH_HTLCS,
STATE_CLOSE_WAIT_SPENDTHEM_OURCOMMIT,
STATE_CLOSE_WAIT_SPENDTHEM_OURCOMMIT_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_OURCOMMIT,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_OURCOMMIT_WITH_HTLCS,
STATE_CLOSE_WAIT_CLOSE_OURCOMMIT,
STATE_UNUSED_CLOSE_WAIT_CLOSE_OURCOMMIT_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_CLOSE_OURCOMMIT,
STATE_UNUSED_CLOSE_WAIT_STEAL_CLOSE_OURCOMMIT_WITH_HTLCS,
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_OURCOMMIT,
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_OURCOMMIT_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_OURCOMMIT,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_OURCOMMIT_WITH_HTLCS,
STATE_CLOSE_WAIT_SPENDOURS,
STATE_CLOSE_WAIT_SPENDOURS_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_SPENDOURS,
STATE_CLOSE_WAIT_STEAL_SPENDOURS_WITH_HTLCS,
STATE_CLOSE_WAIT_SPENDTHEM_SPENDOURS,
STATE_CLOSE_WAIT_SPENDTHEM_SPENDOURS_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_SPENDOURS,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_SPENDOURS_WITH_HTLCS,
STATE_CLOSE_WAIT_CLOSE_SPENDOURS,
STATE_UNUSED_CLOSE_WAIT_CLOSE_SPENDOURS_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_CLOSE_SPENDOURS,
STATE_UNUSED_CLOSE_WAIT_STEAL_CLOSE_SPENDOURS_WITH_HTLCS,
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_SPENDOURS,
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_SPENDOURS_WITH_HTLCS,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_SPENDOURS,
/* All closed. */
STATE_CLOSED,
STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_SPENDOURS_WITH_HTLCS,
/*
* Where angels fear to tread.
@ -189,7 +230,13 @@ enum state_input {
BITCOIN_ANCHOR_THEIRSPEND,
/* Anchor was spent by another commit tx (eg. expired). */
BITCOIN_ANCHOR_OTHERSPEND,
/* They spent an HTLC to them (revealing R value). */
BITCOIN_HTLC_TOTHEM_SPENT,
/* HTLC to them timed out, we can get funds now. */
BITCOIN_HTLC_TOTHEM_TIMEOUT,
/* HTLC to us timed out. */
BITCOIN_HTLC_TOUS_TIMEOUT,
/* Our spend of their commit tx is completely buried. */
BITCOIN_SPEND_THEIRS_DONE,
/* Our spend of our own tx is completely buried. */
@ -198,6 +245,13 @@ enum state_input {
BITCOIN_STEAL_DONE,
/* Bitcoin close transaction considered completely buried. */
BITCOIN_CLOSE_DONE,
/* Our HTLC spend is completely buried. */
BITCOIN_HTLC_FULFILL_SPEND_DONE,
/* Our HTLC refund spend has is completely buried. */
BITCOIN_HTLC_RETURN_SPEND_DONE,
/* We are not watching any HTLCs any more. */
INPUT_NO_MORE_HTLCS,
/*
* Timeouts.

Loading…
Cancel
Save