From 0f9889f2c68624d027c259741b1bacf112987959 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 4 May 2016 16:14:22 +0930 Subject: [PATCH] state: trim unused states. Now we never enter the state machine if we're dealing with on-chain transactions. Signed-off-by: Rusty Russell --- daemon/peer.c | 233 +++------------------- state.c | 521 ++++---------------------------------------------- state.h | 146 +------------- state_types.h | 161 +--------------- 4 files changed, 76 insertions(+), 985 deletions(-) diff --git a/daemon/peer.c b/daemon/peer.c index cc09330a6..6b6fc8ecb 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -119,6 +119,21 @@ static void set_current_command(struct peer *peer, peer->curr_cmd.jsoncmd = jsoncmd; } +static void peer_breakdown(struct peer *peer) +{ + /* If we have a closing tx, use it. */ + if (peer->closing.their_sig) { + log_unusual(peer->log, "Peer breakdown: sending close tx"); + broadcast_tx(peer, bitcoin_close(peer)); + /* If we have a signed commit tx (maybe not if we just offered + * anchor), use it. */ + } else if (peer->us.commit->sig) { + log_unusual(peer->log, "Peer breakdown: sending commit tx"); + broadcast_tx(peer, bitcoin_commit(peer)); + } else + log_info(peer->log, "Peer breakdown: nothing to do"); +} + static void state_single(struct peer *peer, const enum state_input input, const union input *idata) @@ -157,8 +172,11 @@ static void state_single(struct peer *peer, if (peer->cond == PEER_CLOSED) io_wake(peer); + if (peer->state == STATE_ERR_BREAKDOWN) + peer_breakdown(peer); + /* FIXME: Some of these should just result in this peer being killed? */ - if (state_is_error(peer->state)) { + else if (state_is_error(peer->state)) { log_broken(peer->log, "Entered error state %s", state_name(peer->state)); fatal("Peer entered error state"); @@ -223,7 +241,7 @@ static void queue_input(struct peer *peer, } /* All unrevoked commit txs must have no HTLCs in them. */ -bool committed_to_htlcs(const struct peer *peer) +static bool committed_to_htlcs(const struct peer *peer) { const struct commit_info *i; @@ -358,21 +376,6 @@ static void destroy_peer(struct peer *peer) list_del_from(&peer->dstate->peers, &peer->list); } -static void peer_breakdown(struct peer *peer) -{ - /* If we have a closing tx, use it. */ - if (peer->closing.their_sig) { - log_unusual(peer->log, "Peer breakdown: sending close tx"); - broadcast_tx(peer, bitcoin_close(peer)); - /* If we have a signed commit tx (maybe not if we just offered - * anchor), use it. */ - } else if (peer->us.commit->sig) { - log_unusual(peer->log, "Peer breakdown: sending commit tx"); - broadcast_tx(peer, bitcoin_commit(peer)); - } else - log_info(peer->log, "Peer breakdown: nothing to do"); -} - static void peer_disconnect(struct io_conn *conn, struct peer *peer) { log_info(peer->log, "Disconnected"); @@ -397,7 +400,8 @@ static void peer_disconnect(struct io_conn *conn, struct peer *peer) if (peer->cond == PEER_CLOSED) return; - peer_breakdown(peer); + if (peer->state != STATE_ERR_BREAKDOWN) + peer_breakdown(peer); } static struct peer *new_peer(struct lightningd_state *dstate, @@ -674,9 +678,6 @@ struct anchor_watch { struct peer *peer; enum state_input depthok; enum state_input timeout; - enum state_input unspent; - enum state_input theyspent; - enum state_input otherspent; /* If timeout != INPUT_NONE, this is the timer. */ struct oneshot *timer; @@ -687,6 +688,7 @@ static void anchor_depthchange(struct peer *peer, unsigned int depth, void *unused) { struct anchor_watch *w = peer->anchor.watches; + /* Still waiting for it to reach depth? */ if (w->depthok != INPUT_NONE) { if (depth >= peer->us.mindepth) { @@ -696,13 +698,9 @@ static void anchor_depthchange(struct peer *peer, unsigned int depth, w->timer = tal_free(w->timer); state_event(peer, in, NULL); } - } else { - if (depth == 0 && w->unspent != INPUT_NONE) { - enum state_input in = w->unspent; - w->unspent = INPUT_NONE; - state_event(peer, in, NULL); - } - } + } else if (depth == 0) + /* FIXME: Report losses! */ + fatal("Funding transaction was unspent!"); } /* Yay, segwit! We can just compare txids, even though we don't have both @@ -1347,8 +1345,6 @@ static void anchor_spent(struct peer *peer, /* No longer call into the state machine. */ peer->anchor.watches->depthok = INPUT_NONE; - /* FIXME: Catch unspending of anchor, report issue. */ - peer->anchor.watches->unspent = INPUT_NONE; } static void anchor_timeout(struct anchor_watch *w) @@ -1362,10 +1358,7 @@ static void anchor_timeout(struct anchor_watch *w) 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) + enum state_input timeout) { struct anchor_watch *w; @@ -1374,9 +1367,6 @@ void peer_watch_anchor(struct peer *peer, w->peer = peer; w->depthok = depthok; w->timeout = timeout; - w->unspent = unspent; - w->theyspent = theyspent; - w->otherspent = otherspent; watch_txid(w, peer, &peer->anchor.txid, anchor_depthchange, NULL); watch_txo(w, peer, &peer->anchor.txid, 0, anchor_spent, NULL); @@ -1418,78 +1408,6 @@ void peer_unwatch_anchor_depth(struct peer *peer, peer->anchor.watches = tal_free(peer->anchor.watches); } -static void commit_tx_depth(struct peer *peer, unsigned int depth, - const struct sha256_double *txid, - ptrint_t *canspend) -{ - u32 mediantime; - - log_debug(peer->log, "Commit tx reached depth %i", depth); - /* FIXME: Handle locktime in blocks, as well as seconds! */ - - /* Fell out of a block? */ - if (depth == 0) - return; - - mediantime = get_tx_mediantime(peer->dstate, txid); - assert(mediantime); - - if (get_tip_mediantime(peer->dstate) > mediantime - + rel_locktime_to_seconds(&peer->them.locktime)) { - /* Free this watch; we're done */ - peer->cur_commit.watch = tal_free(peer->cur_commit.watch); - state_event(peer, ptr2int(canspend), NULL); - } else - log_debug(peer->log, "... still CSV locked (mediantime %u, need %u + %u)", - get_tip_mediantime(peer->dstate), - mediantime, - rel_locktime_to_seconds(&peer->them.locktime)); -} - -/* We should map back from commit_tx permutation to figure out what happened. */ -static void our_commit_spent(struct peer *peer, - const struct bitcoin_tx *commit_tx, - size_t input_num, - struct commit_info *info) -{ - /* FIXME: do something useful here, if HTLCs spent */ -} - -/* FIXME: We tell bitcoind to watch all the outputs, which is overkill */ -static void watch_commit_outputs(struct peer *peer, const struct bitcoin_tx *tx) -{ - varint_t i; - struct sha256_double txid; - - bitcoin_txid(tx, &txid); - for (i = 0; i < tx->output_count; i++) { - watch_txo(peer, peer, &txid, i, our_commit_spent, - peer->us.commit); - } -} - -/* Watch the commit tx until our side is spendable. */ -void peer_watch_delayed(struct peer *peer, - const struct bitcoin_tx *tx, - enum state_input canspend) -{ - /* We only ever spend the last one. */ - assert(tx == peer->us.commit->tx); - peer->cur_commit.watch = watch_tx(tx, peer, tx, commit_tx_depth, - int2ptr(canspend)); - - watch_commit_outputs(peer, tx); -} - -static void spend_tx_done(struct peer *peer, unsigned int depth, - const struct sha256_double *txid, - ptrint_t *done) -{ - log_debug(peer->log, "tx reached depth %u", depth); - if (depth >= peer->dstate->config.forever_confirms) - state_event(peer, ptr2int(done), NULL); -} - uint64_t commit_tx_fee(const struct bitcoin_tx *commit, uint64_t anchor_satoshis) { uint64_t i, total = 0; @@ -1501,14 +1419,6 @@ uint64_t commit_tx_fee(const struct bitcoin_tx *commit, uint64_t anchor_satoshis return anchor_satoshis - total; } -/* Watch this tx until it's buried enough to be forgotten. */ -void peer_watch_tx(struct peer *peer, - const struct bitcoin_tx *tx, - enum state_input done) -{ - watch_tx(tx, peer, tx, spend_tx_done, int2ptr(done)); -} - struct bitcoin_tx *peer_create_close_tx(struct peer *peer, u64 fee) { struct channel_state cstate; @@ -1576,99 +1486,11 @@ void peer_calculate_close_fee(struct peer *peer) assert(!(peer->closing.our_fee & 1)); } -bool peer_has_close_sig(const struct peer *peer) -{ - return peer->closing.their_sig; -} - -static void send_close_timeout(struct peer *peer) -{ - /* FIXME: Remove any close_tx watches! */ - state_event(peer, INPUT_CLOSE_COMPLETE_TIMEOUT, NULL); -} - -void peer_watch_close(struct peer *peer, - enum state_input done, enum state_input timedout) -{ - /* We save some work by assuming these. */ - assert(done == BITCOIN_CLOSE_DONE); - - /* FIXME: We can't send CLOSE, so timeout immediately */ - if (!peer->conn) { - assert(timedout == INPUT_CLOSE_COMPLETE_TIMEOUT); - oneshot_timeout(peer->dstate, peer, 0, - send_close_timeout, peer); - return; - } - - /* Give them a reasonable time to respond. */ - /* FIXME: config? */ - if (timedout != INPUT_NONE) { - assert(timedout == INPUT_CLOSE_COMPLETE_TIMEOUT); - peer->close_watch_timeout - = oneshot_timeout(peer->dstate, peer, 120, - send_close_timeout, peer); - } - - /* anchor_spent will get called, we match against close_tx there. */ -} -void peer_unwatch_close_timeout(struct peer *peer, enum state_input timedout) -{ - assert(peer->close_watch_timeout); - peer->close_watch_timeout = tal_free(peer->close_watch_timeout); -} -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) -{ - if (committed_to_htlcs(peer)) - FIXME_STUB(peer); - return false; -} -bool peer_watch_their_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_STUB(peer); -} -void peer_unwatch_htlc_output(struct peer *peer, - const struct htlc_onchain *htlc_onchain, - enum state_input all_done) -{ - FIXME_STUB(peer); -} -void peer_unwatch_all_htlc_outputs(struct peer *peer) -{ - FIXME_STUB(peer); -} -void peer_watch_htlc_spend(struct peer *peer, - const struct bitcoin_tx *tx, - const struct htlc_onchain *htlc_onchain, - enum state_input done) -{ - /* FIXME! */ -} -void peer_unwatch_htlc_spend(struct peer *peer, - const struct htlc_onchain *htlc_onchain, - enum state_input all_done) -{ - FIXME_STUB(peer); -} void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt) { FIXME_STUB(peer); } -/* An on-chain transaction revealed an R value. */ -void peer_tx_revealed_r_value(struct peer *peer, const struct htlc_onchain *htlc_onchain) -{ - FIXME_STUB(peer); -} - void peer_watch_htlcs_cleared(struct peer *peer, enum state_input all_done) { @@ -2477,6 +2299,7 @@ static void json_disconnect(struct command *cmd, * one side to freak out. We just ensure we ignore it. */ log_debug(peer->log, "Pretending connection is closed"); peer->fake_close = true; + peer->state = STATE_ERR_BREAKDOWN; peer_breakdown(peer); command_success(cmd, null_response(cmd)); diff --git a/state.c b/state.c index b82ddef4c..c0d710788 100644 --- a/state.c +++ b/state.c @@ -39,14 +39,6 @@ static enum command_status unchanged_state(enum command_status cstatus) return cstatus; } -/* This may not actually change the state. */ -static enum command_status next_state_bits(struct peer *peer, - enum command_status cstatus, - unsigned int bits) -{ - return next_state_nocheck(peer, cstatus, BITS_TO_STATE(bits)); -} - static void set_peer_cond(struct peer *peer, enum state_peercond cond) { assert(peer->cond != cond); @@ -91,7 +83,6 @@ enum command_status state(struct peer *peer, const union input *idata, const struct bitcoin_tx **broadcast) { - const struct bitcoin_tx *tx; Pkt *err; enum command_status cstatus = CMD_NONE; @@ -121,16 +112,15 @@ enum command_status state(struct peer *peer, err = accept_pkt_open(peer, idata->pkt); if (err) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto err_close_nocleanup; + goto err_breakdown; } return next_state(peer, cstatus, STATE_OPEN_WAIT_FOR_ANCHOR); - } else if (input_is(input, CMD_CLOSE) - || input_is(input, INPUT_CONNECTION_LOST)) { + } else if (input_is(input, CMD_CLOSE)) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto instant_close; + goto breakdown; } else if (input_is_pkt(input)) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto unexpected_pkt_nocleanup; + goto unexpected_pkt; } break; case STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR: @@ -138,18 +128,17 @@ enum command_status state(struct peer *peer, err = accept_pkt_open(peer, idata->pkt); if (err) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto err_close_nocleanup; + goto err_breakdown; } bitcoin_create_anchor(peer, BITCOIN_ANCHOR_CREATED); return next_state(peer, cstatus, STATE_OPEN_WAIT_FOR_ANCHOR_CREATE); - } else if (input_is(input, CMD_CLOSE) - || input_is(input, INPUT_CONNECTION_LOST)) { + } else if (input_is(input, CMD_CLOSE)) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto instant_close; + goto breakdown; } else if (input_is_pkt(input)) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto unexpected_pkt_nocleanup; + goto unexpected_pkt; } break; case STATE_OPEN_WAIT_FOR_ANCHOR_CREATE: @@ -157,15 +146,14 @@ enum command_status state(struct peer *peer, queue_pkt_anchor(peer); return next_state(peer, cstatus, STATE_OPEN_WAIT_FOR_COMMIT_SIG); - } else if (input_is(input, CMD_CLOSE) - || input_is(input, INPUT_CONNECTION_LOST)) { + } else if (input_is(input, CMD_CLOSE)) { bitcoin_release_anchor(peer, BITCOIN_ANCHOR_CREATED); complete_cmd(peer, &cstatus, CMD_FAIL); - goto instant_close; + goto breakdown; } else if (input_is_pkt(input)) { bitcoin_release_anchor(peer, BITCOIN_ANCHOR_CREATED); complete_cmd(peer, &cstatus, CMD_FAIL); - goto unexpected_pkt_nocleanup; + goto unexpected_pkt; } break; case STATE_OPEN_WAIT_FOR_ANCHOR: @@ -173,25 +161,21 @@ enum command_status state(struct peer *peer, err = accept_pkt_anchor(peer, idata->pkt); if (err) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto err_close_nocleanup; + goto err_breakdown; } queue_pkt_open_commit_sig(peer); peer_watch_anchor(peer, BITCOIN_ANCHOR_DEPTHOK, - BITCOIN_ANCHOR_TIMEOUT, - BITCOIN_ANCHOR_UNSPENT, - BITCOIN_ANCHOR_THEIRSPEND, - BITCOIN_ANCHOR_OTHERSPEND); + BITCOIN_ANCHOR_TIMEOUT); return next_state(peer, cstatus, STATE_OPEN_WAITING_THEIRANCHOR); - } else if (input_is(input, CMD_CLOSE) - || input_is(input, INPUT_CONNECTION_LOST)) { + } else if (input_is(input, CMD_CLOSE)) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto instant_close; + goto breakdown; } else if (input_is_pkt(input)) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto unexpected_pkt_nocleanup; + goto unexpected_pkt; } break; case STATE_OPEN_WAIT_FOR_COMMIT_SIG: @@ -200,26 +184,22 @@ enum command_status state(struct peer *peer, if (err) { bitcoin_release_anchor(peer, INPUT_NONE); complete_cmd(peer, &cstatus, CMD_FAIL); - goto err_start_unilateral_close; + goto err_breakdown; } queue_tx_broadcast(broadcast, bitcoin_anchor(peer)); peer_watch_anchor(peer, BITCOIN_ANCHOR_DEPTHOK, - INPUT_NONE, - BITCOIN_ANCHOR_UNSPENT, - BITCOIN_ANCHOR_THEIRSPEND, - BITCOIN_ANCHOR_OTHERSPEND); + INPUT_NONE); return next_state(peer, cstatus, STATE_OPEN_WAITING_OURANCHOR); - } else if (input_is(input, CMD_CLOSE) - || input_is(input, INPUT_CONNECTION_LOST)) { + } else if (input_is(input, CMD_CLOSE)) { bitcoin_release_anchor(peer, INPUT_NONE); complete_cmd(peer, &cstatus, CMD_FAIL); - goto instant_close; + goto breakdown; } else if (input_is_pkt(input)) { bitcoin_release_anchor(peer, INPUT_NONE); complete_cmd(peer, &cstatus, CMD_FAIL); - goto unexpected_pkt_nocleanup; + goto unexpected_pkt; } break; case STATE_OPEN_WAITING_OURANCHOR: @@ -231,7 +211,7 @@ enum command_status state(struct peer *peer, peer_unwatch_anchor_depth(peer, BITCOIN_ANCHOR_DEPTHOK, INPUT_NONE); - goto err_start_unilateral_close; + goto err_breakdown; } return next_state(peer, cstatus, STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED); @@ -246,19 +226,6 @@ enum command_status state(struct peer *peer, } return next_state(peer, cstatus, STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR); - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - complete_cmd(peer, &cstatus, CMD_FAIL); - goto anchor_unspent; - } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - /* We no longer care about anchor depth. */ - peer_unwatch_anchor_depth(peer, - BITCOIN_ANCHOR_DEPTHOK, - INPUT_NONE); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto them_unilateral; - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - /* This should be impossible. */ - return next_state(peer, cstatus, STATE_ERR_INFORMATION_LEAK); } else if (input_is(input, CMD_CLOSE)) { /* We no longer care about anchor depth. */ peer_unwatch_anchor_depth(peer, @@ -266,13 +233,6 @@ enum command_status state(struct peer *peer, INPUT_NONE); complete_cmd(peer, &cstatus, CMD_FAIL); goto start_clearing; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - /* We no longer care about anchor depth. */ - peer_unwatch_anchor_depth(peer, - BITCOIN_ANCHOR_DEPTHOK, - INPUT_NONE); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_unilateral_close; } else if (input_is(input, PKT_CLOSE_CLEARING)) { /* We no longer care about anchor depth. */ peer_unwatch_anchor_depth(peer, @@ -298,7 +258,7 @@ enum command_status state(struct peer *peer, peer_unwatch_anchor_depth(peer, BITCOIN_ANCHOR_DEPTHOK, BITCOIN_ANCHOR_TIMEOUT); - goto err_start_unilateral_close; + goto err_breakdown; } return next_state(peer, cstatus, STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED); @@ -317,20 +277,6 @@ enum command_status state(struct peer *peer, } return next_state(peer, cstatus, STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR); - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - complete_cmd(peer, &cstatus, CMD_FAIL); - goto anchor_unspent; - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - /* This should be impossible. */ - return next_state(peer, cstatus, - STATE_ERR_INFORMATION_LEAK); - } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - /* We no longer care about anchor depth. */ - peer_unwatch_anchor_depth(peer, - BITCOIN_ANCHOR_DEPTHOK, - BITCOIN_ANCHOR_TIMEOUT); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto them_unilateral; } else if (input_is(input, CMD_CLOSE)) { /* We no longer care about anchor depth. */ peer_unwatch_anchor_depth(peer, @@ -338,13 +284,6 @@ enum command_status state(struct peer *peer, BITCOIN_ANCHOR_TIMEOUT); complete_cmd(peer, &cstatus, CMD_FAIL); goto start_clearing; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - /* We no longer care about anchor depth. */ - peer_unwatch_anchor_depth(peer, - BITCOIN_ANCHOR_DEPTHOK, - BITCOIN_ANCHOR_TIMEOUT); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_unilateral_close; } else if (input_is(input, PKT_CLOSE_CLEARING)) { /* We no longer care about anchor depth. */ peer_unwatch_anchor_depth(peer, @@ -372,23 +311,9 @@ enum command_status state(struct peer *peer, complete_cmd(peer, &cstatus, CMD_SUCCESS); return next_state(peer, cstatus, STATE_NORMAL); } - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - complete_cmd(peer, &cstatus, CMD_FAIL); - goto anchor_unspent; - /* Nobody should be able to spend anchor, except via the - * commit txs. */ - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - return next_state(peer, cstatus, - STATE_ERR_INFORMATION_LEAK); - } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - complete_cmd(peer, &cstatus, CMD_FAIL); - goto them_unilateral; } else if (input_is(input, CMD_CLOSE)) { complete_cmd(peer, &cstatus, CMD_FAIL); goto start_clearing; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_unilateral_close; } else if (input_is(input, PKT_CLOSE_CLEARING)) { complete_cmd(peer, &cstatus, CMD_FAIL); goto accept_clearing; @@ -433,7 +358,7 @@ enum command_status state(struct peer *peer, err = accept_pkt_revocation(peer, idata->pkt); if (err) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto err_start_unilateral_close; + goto err_breakdown; } complete_cmd(peer, &cstatus, CMD_SUCCESS); return next_state(peer, cstatus, STATE_NORMAL); @@ -444,32 +369,24 @@ enum command_status state(struct peer *peer, } else if (input_is(input, PKT_UPDATE_ADD_HTLC)) { err = accept_pkt_htlc_add(peer, idata->pkt); if (err) - goto err_start_unilateral_close; + goto err_breakdown; return unchanged_state(cstatus); } else if (input_is(input, PKT_UPDATE_FULFILL_HTLC)) { err = accept_pkt_htlc_fulfill(peer, idata->pkt); if (err) - goto err_start_unilateral_close; + goto err_breakdown; return unchanged_state(cstatus); } else if (input_is(input, PKT_UPDATE_FAIL_HTLC)) { err = accept_pkt_htlc_fail(peer, idata->pkt); if (err) - goto err_start_unilateral_close; + goto err_breakdown; return unchanged_state(cstatus); } else if (input_is(input, PKT_UPDATE_COMMIT)) { err = accept_pkt_commit(peer, idata->pkt); if (err) - goto err_start_unilateral_close; + goto err_breakdown; queue_pkt_revocation(peer); return unchanged_state(cstatus); - } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - goto them_unilateral; - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - goto old_commit_spotted; - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - goto anchor_unspent; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - goto start_unilateral_close; } else if (input_is(input, PKT_CLOSE_CLEARING)) { goto accept_clearing; } else if (input_is_pkt(input)) { @@ -481,7 +398,7 @@ enum command_status state(struct peer *peer, if (input_is(input, PKT_CLOSE_CLEARING)) { err = accept_pkt_close_clearing(peer, idata->pkt); if (err) - goto err_start_unilateral_close; + goto err_breakdown; /* Notify us when there are no more htlcs in * either commit tx */ @@ -492,9 +409,7 @@ enum command_status state(struct peer *peer, } else if (input_is(input, CMD_SEND_HTLC_FAIL) || input_is(input, CMD_SEND_HTLC_FULFILL)) { err = pkt_err(peer, "FIXME: cmd during clearing."); - goto err_start_unilateral_close; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - goto start_unilateral_close; + goto err_breakdown; } else if (input_is_pkt(input)) { /* FIXME: We must continue to allow add, fulfill & fail packets */ goto unexpected_pkt; @@ -506,9 +421,7 @@ enum command_status state(struct peer *peer, } else if (input_is(input, CMD_SEND_HTLC_FAIL) || input_is(input, CMD_SEND_HTLC_FULFILL)) { err = pkt_err(peer, "FIXME: cmd during clearing."); - goto err_start_unilateral_close; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - goto start_unilateral_close; + goto err_breakdown; } else if (input_is_pkt(input)) { /* FIXME: We must continue to allow fulfill & fail packets */ goto unexpected_pkt; @@ -520,7 +433,7 @@ enum command_status state(struct peer *peer, err = accept_pkt_close_sig(peer, idata->pkt, &acked, &we_agree); if (err) - goto err_start_unilateral_close; + goto err_breakdown; /* Are we about to offer the same fee they did? */ if (we_agree) { @@ -531,9 +444,6 @@ enum command_status state(struct peer *peer, /* Do fees now match? */ if (acked) { - peer_unwatch_close_timeout(peer, - INPUT_CLOSE_COMPLETE_TIMEOUT); - /* Send close TX. */ queue_tx_broadcast(broadcast, bitcoin_close(peer)); @@ -546,245 +456,21 @@ enum command_status state(struct peer *peer, /* Offer the new fee. */ queue_pkt_close_signature(peer); return unchanged_state(cstatus); - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - goto start_unilateral_close; } else if (input_is(input, INPUT_CLOSE_COMPLETE_TIMEOUT)) { err = pkt_err(peer, "Close timed out"); - goto err_start_unilateral_close; + goto err_breakdown; } else if (input_is_pkt(input)) { goto unexpected_pkt; } break; - /* Close states are regular: handle as a group. */ - case STATE_CLOSE_WAIT_HTLCS: - case STATE_CLOSE_WAIT_STEAL: - case STATE_CLOSE_WAIT_THEIRCOMMIT: - case STATE_CLOSE_WAIT_THEIRCOMMIT_WITH_HTLCS: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_WITH_HTLCS: - case STATE_CLOSE_WAIT_CLOSE: - case STATE_CLOSE_WAIT_STEAL_CLOSE: - case STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE: - case STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE_WITH_HTLCS: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE_WITH_HTLCS: - case STATE_CLOSE_WAIT_STEAL_OURCOMMIT: - case STATE_CLOSE_WAIT_STEAL_OURCOMMIT_WITH_HTLCS: - case STATE_CLOSE_WAIT_THEIRCOMMIT_OURCOMMIT: - case STATE_CLOSE_WAIT_THEIRCOMMIT_OURCOMMIT_WITH_HTLCS: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_OURCOMMIT: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_OURCOMMIT_WITH_HTLCS: - case STATE_CLOSE_WAIT_CLOSE_OURCOMMIT: - case STATE_CLOSE_WAIT_STEAL_CLOSE_OURCOMMIT: - case STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE_OURCOMMIT: - case STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE_OURCOMMIT_WITH_HTLCS: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE_OURCOMMIT: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE_OURCOMMIT_WITH_HTLCS: - case STATE_CLOSE_WAIT_STEAL_SPENDOURS: - case STATE_CLOSE_WAIT_STEAL_SPENDOURS_WITH_HTLCS: - case STATE_CLOSE_WAIT_THEIRCOMMIT_SPENDOURS: - case STATE_CLOSE_WAIT_THEIRCOMMIT_SPENDOURS_WITH_HTLCS: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_SPENDOURS: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_SPENDOURS_WITH_HTLCS: - case STATE_CLOSE_WAIT_CLOSE_SPENDOURS: - case STATE_CLOSE_WAIT_STEAL_CLOSE_SPENDOURS: - case STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE_SPENDOURS: - case STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE_SPENDOURS_WITH_HTLCS: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE_SPENDOURS: - case STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE_SPENDOURS_WITH_HTLCS: - case STATE_CLOSE_WAIT_OURCOMMIT: - case STATE_CLOSE_WAIT_OURCOMMIT_WITH_HTLCS: - case STATE_CLOSE_WAIT_SPENDOURS: - case STATE_CLOSE_WAIT_SPENDOURS_WITH_HTLCS: { - unsigned int bits; - enum state_input closed; - - bits = STATE_TO_BITS(peer->state); - - /* 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; - - /* Our steal is deep enough to forget? */ - 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) - peer_unwatch_all_htlc_outputs(peer); - return next_state(peer, cstatus, STATE_CLOSED); - } - - /* Their commit is buried deep enough to forget? */ - if ((bits & STATE_CLOSE_THEIRCOMMIT_BIT) - && input_is(input, BITCOIN_THEIRCOMMIT_DONE)) { - BUILD_ASSERT(!(STATE_TO_BITS(STATE_CLOSE_WAIT_HTLCS) - & STATE_CLOSE_THEIRCOMMIT_BIT)); - return next_state(peer, cstatus, closed); - } - - /* Mutual close deep enough to forget? */ - if ((bits & STATE_CLOSE_CLOSE_BIT) - && input_is(input, BITCOIN_CLOSE_DONE)) { - BUILD_ASSERT(!(STATE_TO_BITS(STATE_CLOSE_WAIT_HTLCS) - & STATE_CLOSE_CLOSE_BIT)); - return next_state(peer, cstatus, closed); - } - - /* Our commit deep enough to spend our output? */ - if ((bits & STATE_CLOSE_OURCOMMIT_BIT) - && input_is(input, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED)) { - BUILD_ASSERT(!(STATE_TO_BITS(STATE_CLOSE_WAIT_HTLCS) - & STATE_CLOSE_OURCOMMIT_BIT)); - /* FIXME: If our output was dust, just fire when - * ourcommit deep enough to forget. */ - tx = bitcoin_spend_ours(peer); - /* Now we need to wait for our commit to be done. */ - queue_tx_broadcast(broadcast, tx); - peer_watch_tx(peer, tx, BITCOIN_SPEND_OURS_DONE); - bits &= ~STATE_CLOSE_OURCOMMIT_BIT; - bits |= STATE_CLOSE_SPENDOURS_BIT; - return next_state(peer, cstatus, BITS_TO_STATE(bits)); - } - - /* Our spend of ourcommit is deep enough to forget? */ - if ((bits & STATE_CLOSE_SPENDOURS_BIT) - && input_is(input, BITCOIN_SPEND_OURS_DONE)) { - BUILD_ASSERT(!(STATE_TO_BITS(STATE_CLOSE_WAIT_HTLCS) - & STATE_CLOSE_SPENDOURS_BIT)); - return next_state(peer, cstatus, closed); - } - - /* 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((BITS_TO_STATE(STATE_TO_BITS(STATE_CLOSE_WAIT_HTLCS) & ~STATE_CLOSE_HTLCS_BIT)) == STATE_CLOSED); - bits &= ~STATE_CLOSE_HTLCS_BIT; - return next_state(peer, cstatus, - BITS_TO_STATE(bits)); - } else if (input_is(input, BITCOIN_HTLC_TOTHEM_SPENT)) { - /* They revealed R value. */ - peer_tx_revealed_r_value(peer, - idata->htlc_onchain); - /* We don't care any more. */ - peer_unwatch_htlc_output(peer, - idata->htlc_onchain, - INPUT_NO_MORE_HTLCS); - return unchanged_state(cstatus); - } else if (input_is(input, BITCOIN_HTLC_TOTHEM_TIMEOUT)){ - tx = bitcoin_htlc_timeout(peer, - idata->htlc_onchain); - /* HTLC timed out, spend it back to us. */ - queue_tx_broadcast(broadcast, tx); - /* Don't unwatch yet; they could yet - * try to spend, revealing rvalue. */ - - /* We're done when that gets buried. */ - peer_watch_htlc_spend(peer, tx, - idata->htlc_onchain, - BITCOIN_HTLC_RETURN_SPEND_DONE); - return unchanged_state(cstatus); - } else if (input_is(input, INPUT_RVALUE)) { - tx = bitcoin_htlc_spend(peer, - idata->htlc_onchain); - - /* Spend it... */ - queue_tx_broadcast(broadcast, tx); - /* We're done when it gets buried. */ - peer_watch_htlc_spend(peer, tx, - idata->htlc_onchain, - BITCOIN_HTLC_FULFILL_SPEND_DONE); - /* Don't care about this one any more. */ - peer_unwatch_htlc_output(peer, - idata->htlc_onchain, - INPUT_NO_MORE_HTLCS); - return unchanged_state(cstatus); - } else if (input_is(input, BITCOIN_HTLC_FULFILL_SPEND_DONE)) { - /* Stop watching spend, send - * INPUT_NO_MORE_HTLCS when done. */ - peer_unwatch_htlc_spend(peer, - idata->htlc_onchain, - INPUT_NO_MORE_HTLCS); - return unchanged_state(cstatus); - } else if (input_is(input, BITCOIN_HTLC_RETURN_SPEND_DONE)) { - /* Stop watching spend, send - * INPUT_NO_MORE_HTLCS when done. */ - peer_unwatch_htlc_spend(peer, - idata->htlc_onchain, - INPUT_NO_MORE_HTLCS); - - /* Don't need to watch the HTLC output any more, - * either. */ - peer_unwatch_htlc_output(peer, - idata->htlc_onchain, - INPUT_NO_MORE_HTLCS); - return unchanged_state(cstatus); - } else if (input_is(input, BITCOIN_HTLC_TOUS_TIMEOUT)) { - /* They can spend, we no longer care - * about this HTLC. */ - peer_unwatch_htlc_output(peer, - idata->htlc_onchain, - INPUT_NO_MORE_HTLCS); - return unchanged_state(cstatus); - } - } - - /* If we're just waiting for HTLCs, anything else is an error */ - if (peer->state == STATE_CLOSE_WAIT_HTLCS) - break; - - /* - * Now, other side can always spring a commit transaction on - * us (they might have two valid ones, if they didn't send - * revocation preimage yet, so always allow it). - */ - if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - peer_watch_tx(peer, idata->tx, BITCOIN_THEIRCOMMIT_DONE); - - /* HTLC watches: if any, set HTLCs bit. */ - if (peer_watch_their_htlc_outputs(peer, idata->tx, - BITCOIN_HTLC_TOUS_TIMEOUT, - BITCOIN_HTLC_TOTHEM_SPENT, - BITCOIN_HTLC_TOTHEM_TIMEOUT)) - bits |= STATE_CLOSE_HTLCS_BIT; - - bits |= STATE_CLOSE_THEIRCOMMIT_BIT; - return next_state_bits(peer, cstatus, bits); - /* This can happen multiple times: need to steal ALL */ - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - tx = bitcoin_steal(peer, idata->ci); - if (!tx) - return next_state(peer, cstatus, - STATE_ERR_INFORMATION_LEAK); - queue_tx_broadcast(broadcast, tx); - peer_watch_tx(peer, tx, BITCOIN_STEAL_DONE); - bits |= STATE_CLOSE_STEAL_BIT; - return next_state_bits(peer, cstatus, bits); - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) - goto anchor_unspent; - - break; - } - /* Should never happen. */ case STATE_ERR_INTERNAL: - case STATE_ERR_INFORMATION_LEAK: case STATE_ERR_ANCHOR_TIMEOUT: - case STATE_ERR_ANCHOR_LOST: + case STATE_ERR_BREAKDOWN: + case STATE_CLOSE_WAIT_CLOSE: 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: case STATE_CLOSE_ONCHAIN_CHEATED: case STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL: case STATE_CLOSE_ONCHAIN_OUR_UNILATERAL: @@ -796,108 +482,18 @@ enum command_status state(struct peer *peer, return next_state(peer, cstatus, STATE_ERR_INTERNAL); unexpected_pkt: - /* - * We got a weird packet, so we need to close unilaterally. - */ peer_unexpected_pkt(peer, idata->pkt); /* Don't reply to an error with an error. */ - if (input_is(input, PKT_ERROR)) { - goto start_unilateral_close; - } - err = pkt_err_unexpected(peer, idata->pkt); - goto err_start_unilateral_close; - -unexpected_pkt_nocleanup: - /* - * Unexpected packet, but nothing sent to chain yet, so no cleanup. - */ - /* Don't reply to an error with an error. */ - if (input_is(input, PKT_ERROR)) { - goto close_nocleanup; + if (!input_is(input, PKT_ERROR)) { + goto breakdown; } err = pkt_err_unexpected(peer, idata->pkt); - goto err_close_nocleanup; - -anchor_unspent: - /* - * Bitcoind tells us anchor got double-spent. If we double-spent it - * then we're malfunctioning. If they double-spent it, then they - * managed to cheat us: post_to_reddit(); - */ - return next_state(peer, cstatus, STATE_ERR_ANCHOR_LOST); - -err_close_nocleanup: - /* - * Something went wrong, but we haven't sent anything to the blockchain - * so there's nothing to clean up. - */ - queue_pkt_err(peer, err); - -close_nocleanup: - change_peer_cond(peer, PEER_CMD_OK, PEER_CLOSED); - return next_state(peer, cstatus, STATE_CLOSED); - -err_start_unilateral_close: - /* - * They timed out, or were broken; we are going to close unilaterally. - */ + +err_breakdown: queue_pkt_err(peer, err); - -start_unilateral_close: - /* - * Close unilaterally. - */ - - /* No more inputs, no more commands. */ - set_peer_cond(peer, PEER_CLOSED); - - /* - * If they sent us a close tx, that's always cheaper than - * broadcasting our last commit tx, and our funds are not - * timelocked. - */ - if (peer_has_close_sig(peer)) { - queue_tx_broadcast(broadcast, bitcoin_close(peer)); - return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE); - } - - tx = bitcoin_commit(peer); - queue_tx_broadcast(broadcast, tx); - peer_watch_delayed(peer, tx, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED); - - /* HTLC watches. */ - if (peer_watch_our_htlc_outputs(peer, tx, - BITCOIN_HTLC_TOUS_TIMEOUT, - BITCOIN_HTLC_TOTHEM_SPENT, - BITCOIN_HTLC_TOTHEM_TIMEOUT)) - return next_state(peer, cstatus, - STATE_CLOSE_WAIT_OURCOMMIT_WITH_HTLCS); - - return next_state(peer, cstatus, STATE_CLOSE_WAIT_OURCOMMIT); - -them_unilateral: - assert(input == BITCOIN_ANCHOR_THEIRSPEND); - - /* - * Bitcoind tells us they did unilateral close. - */ - queue_pkt_err(peer, pkt_err(peer, "Commit tx noticed")); - - /* No more inputs, no more commands. */ - set_peer_cond(peer, PEER_CLOSED); - peer_watch_tx(peer, idata->tx, BITCOIN_THEIRCOMMIT_DONE); - - /* HTLC watches (based on what they broadcast, which *may* be out - * of step with our current state by +/- 1 htlc. */ - if (peer_watch_their_htlc_outputs(peer, idata->tx, - BITCOIN_HTLC_TOUS_TIMEOUT, - BITCOIN_HTLC_TOTHEM_SPENT, - BITCOIN_HTLC_TOTHEM_TIMEOUT)) - return next_state(peer, cstatus, - STATE_CLOSE_WAIT_THEIRCOMMIT_WITH_HTLCS); - - return next_state(peer, cstatus, STATE_CLOSE_WAIT_THEIRCOMMIT); +breakdown: + return next_state(peer, cstatus, STATE_ERR_BREAKDOWN); start_clearing: /* @@ -913,14 +509,13 @@ start_clearing: start_closing_cleared: /* As soon as we send packet, they could close. */ peer_calculate_close_fee(peer); - peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_CLOSE_COMPLETE_TIMEOUT); queue_pkt_close_signature(peer); return next_state(peer, cstatus, STATE_WAIT_FOR_CLOSE_SIG); accept_clearing: err = accept_pkt_close_clearing(peer, idata->pkt); if (err) - goto err_start_unilateral_close; + goto err_breakdown; /* Notify us when there are no more htlcs in either commit tx */ peer_watch_htlcs_cleared(peer, INPUT_HTLCS_CLEARED); @@ -932,36 +527,4 @@ accept_clearing: queue_pkt_close_clearing(peer); return next_state(peer, cstatus, STATE_BOTH_CLEARING); - -instant_close: - /* - * Closing, but we haven't sent anything to the blockchain so - * there's nothing to clean up. - */ - /* FIXME: Should we tell other side we're going? */ - set_peer_cond(peer, PEER_CLOSED); - - /* We can't have any HTLCs, since we haven't started. */ - if (committed_to_htlcs(peer)) - return next_state(peer, cstatus, STATE_ERR_INTERNAL); - - return next_state(peer, cstatus, STATE_CLOSED); - -old_commit_spotted: - /* - * bitcoind reported a broadcast of the not-latest commit tx. - */ - queue_pkt_err(peer, pkt_err(peer, "Otherspend noticed")); - - /* No more packets, no more commands. */ - set_peer_cond(peer, PEER_CLOSED); - - /* If we can't find it, we're lost. */ - tx = bitcoin_steal(peer, idata->ci); - if (!tx) - return next_state(peer, cstatus, - STATE_ERR_INFORMATION_LEAK); - queue_tx_broadcast(broadcast, tx); - peer_watch_tx(peer, tx, BITCOIN_STEAL_DONE); - return next_state(peer, cstatus, STATE_CLOSE_WAIT_STEAL); } diff --git a/state.h b/state.h index bcdeb0269..d6e899f07 100644 --- a/state.h +++ b/state.h @@ -121,41 +121,18 @@ Pkt *accept_pkt_close_clearing(struct peer *peer, const Pkt *pkt); Pkt *accept_pkt_close_sig(struct peer *peer, const Pkt *pkt, bool *acked, bool *we_agree); -/** - * committed_to_htlcs: do we have any locked-in HTLCs? - * @peer: 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 peer *peer); - -/** - * peer_has_close_sig: do we have a valid close_sig from them? - * @peer: the state data for this peer. - * - * We use any acceptable close tx, if we have one, in preference to a commit tx. - */ -bool peer_has_close_sig(const struct peer *peer); - /** * peer_watch_anchor: create a watch for the anchor transaction. * @peer: the state data for this peer. * @depthok: the input to give when anchor reaches expected depth. * @timeout: the input to give if anchor doesn't reach depth in time. - * @unspent: the input to give if anchor is unspent after @depthok. - * @theyspent: the input to give if they spend anchor with their commit tx. - * @otherspent: the input to give if they spend anchor otherwise. * * @depthok can be INPUT_NONE if it's our anchor (we don't time * ourselves out). */ 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); - + enum state_input timeout); /** * peer_unwatch_anchor_depth: remove depth watch for the anchor. * @peer: the state data for this peer. @@ -168,127 +145,6 @@ void peer_unwatch_anchor_depth(struct peer *peer, enum state_input depthok, enum state_input timeout); -/** - * peer_watch_delayed: watch this (commit) tx, tell me when I can spend it - * @peer: the state data for this peer. - * @tx: the tx we're watching. - * @canspend: the input to give when commit reaches spendable depth. - * - * Note that this tx may be malleated, as it's dual-signed. - */ -void peer_watch_delayed(struct peer *peer, - const struct bitcoin_tx *tx, - enum state_input canspend); - -/** - * peer_watch_tx: watch this tx until it's "irreversible" - * @peer: the state data for this peer. - * @tx: the tx we're watching. - * @done: the input to give when tx is completely buried. - * - * Once this fires we consider the channel completely closed and stop - * watching (eg 100 txs down). - * - * This is used for watching a transaction we sent (such as a steal, - * or spend of their close, etc). - */ -void peer_watch_tx(struct peer *peer, - const struct bitcoin_tx *tx, - enum state_input done); - -/** - * peer_watch_close: watch for close tx until it's "irreversible" (or timedout) - * @peer: the state data for this peer. - * @done: the input to give when tx is completely buried. - * @timedout: the input to give if we time out (they don't provide sig). - * - * Once this fires we consider the channel completely closed and stop - * watching (eg 100 txs down). - * - * This is used for watching a mutual close. - */ -void peer_watch_close(struct peer *peer, - enum state_input done, enum state_input timedout); - -/** - * peer_unwatch_close_timeout: remove timeout for the close transaction - * @peer: the state data for this peer. - * @timeout: the input to give if anchor doesn't reach depth in time. - * - * This is called once we have successfully received their signature. - */ -void peer_unwatch_close_timeout(struct peer *peer, enum state_input timedout); - -/** - * peer_watch_our_htlc_outputs: HTLC outputs from our commit tx to watch. - * @peer: 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. - * - * Returns true if there were any htlc outputs to watch. - */ -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); - -/** - * peer_watch_their_htlc_outputs: HTLC outputs from their commit tx to watch. - * @peer: 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. - * - * Returns true if there were any htlc outputs to watch. - */ -bool peer_watch_their_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); - -/** - * peer_unwatch_htlc_output: stop watching an HTLC - * @peer: the state data for this peer. - * @htlc_onchain: the htlc to stop watching - * @all_done: input to give if we're not watching any outputs anymore. - */ -void peer_unwatch_htlc_output(struct peer *peer, - const struct htlc_onchain *htlc_onchain, - enum state_input all_done); - -/** - * peer_unwatch_all_htlc_outputs: stop watching all HTLCs - * @peer: the state data for this peer. - */ -void peer_unwatch_all_htlc_outputs(struct peer *peer); - -/** - * peer_watch_htlc_spend: watch our spend of an HTLC output - * @peer: the state data for this peer. - * @tx: the commitment tx - * @htlc_onchain: the htlc the tx is spending an output of - * @done: input to give when it's completely buried. - */ -void peer_watch_htlc_spend(struct peer *peer, - const struct bitcoin_tx *tx, - const struct htlc_onchain *htlc_onchain, - enum state_input done); - -/** - * peer_unwatch_htlc_spend: stop watching our HTLC spend - * @peer: the state data for this peer. - * @htlc_onchain: the htlc to stop watching the spend for. - * @all_done: input to give if we're not watching anything anymore. - */ -void peer_unwatch_htlc_spend(struct peer *peer, - const struct htlc_onchain *htlc_onchain, - enum state_input all_done); - /** * peer_watch_htlcs_cleared: tell us when no HTLCs are in commit txs. * @peer: the state data for this peer. diff --git a/state_types.h b/state_types.h index 6a3f04c9c..f8a76bc7e 100644 --- a/state_types.h +++ b/state_types.h @@ -4,13 +4,6 @@ /* FIXME: cdump is really dumb, so we put these in their own header. */ #include "lightning.pb-c.h" -#define STATE_CLOSE_HTLCS_BIT 1 -#define STATE_CLOSE_STEAL_BIT 2 -#define STATE_CLOSE_THEIRCOMMIT_BIT 4 -#define STATE_CLOSE_CLOSE_BIT 8 -#define STATE_CLOSE_OURCOMMIT_BIT 16 -#define STATE_CLOSE_SPENDOURS_BIT 32 - enum state { STATE_INIT, @@ -44,112 +37,11 @@ enum state { STATE_BOTH_CLEARING, /* We're cleared, waiting for close signature / negotiation */ STATE_WAIT_FOR_CLOSE_SIG, - + /* We've broadcast the mutual close, waiting for onchain. */ + STATE_CLOSE_WAIT_CLOSE, + /* 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 - * their funds (steal). We also track their latest commit tx (no need - * to spend our output, it's just a P2WPKH for us) (their_commit). - * They can also (with our help) broadcast a mutual close tx - * (mutual_close). - * - * We can also broadcast one of the following: - * 1) Our latest commit tx (our_commit). - * 2) After delay has passed, spend of our tx (spend_ours). - * 3) Mutual close tx (mutual_close), already covered above. - * - * Thus, we could be waiting for the following combinations: - * - steal - * - their_commit - * - steal + their_commit - * - mutual_close - * - steal + mutual_close - * - their_commit + mutual_close - * - steal + their_commit + mutual_close - * - * - our_commit - * - steal + our_commit - * - their_commit + our_commit - * - steal + their_commit + our_commit - * - mutual_close + our_commit - * - steal + mutual_close + our_commit - * - their_commit + mutual_close + our_commit - * - steal + their_commit + mutual_close + our_commit - * - * - spend_ours - * - steal + spend_ours - * - their_commit + spend_ours - * - steal + their_commit + spend_ours - * - mutual_close + spend_ours - * - steal + mutual_close + spend_ours - * - their_commit + mutual_close + spend_ours - * - steal + their_commit + 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 THEIRCOMMIT, 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_THEIRCOMMIT, - STATE_CLOSE_WAIT_THEIRCOMMIT_WITH_HTLCS, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_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_THEIRCOMMIT_CLOSE, - STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE_WITH_HTLCS, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_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_THEIRCOMMIT_OURCOMMIT, - STATE_CLOSE_WAIT_THEIRCOMMIT_OURCOMMIT_WITH_HTLCS, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_OURCOMMIT, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_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_THEIRCOMMIT_CLOSE_OURCOMMIT, - STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE_OURCOMMIT_WITH_HTLCS, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE_OURCOMMIT, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_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_THEIRCOMMIT_SPENDOURS, - STATE_CLOSE_WAIT_THEIRCOMMIT_SPENDOURS_WITH_HTLCS, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_SPENDOURS, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_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_THEIRCOMMIT_CLOSE_SPENDOURS, - STATE_CLOSE_WAIT_THEIRCOMMIT_CLOSE_SPENDOURS_WITH_HTLCS, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE_SPENDOURS, - STATE_CLOSE_WAIT_STEAL_THEIRCOMMIT_CLOSE_SPENDOURS_WITH_HTLCS, /* Four states to represent closing onchain (for getpeers) */ STATE_CLOSE_ONCHAIN_CHEATED, @@ -160,12 +52,11 @@ enum state { /* * Where angels fear to tread. */ + /* Bad packet from them / protocol breakdown. */ + STATE_ERR_BREAKDOWN, /* Their anchor didn't reach blockchain in reasonable time. */ STATE_ERR_ANCHOR_TIMEOUT, /* Anchor was double-spent, after both considered it sufficient depth. */ - STATE_ERR_ANCHOR_LOST, - /* A commitment tx we didn't recognise spent the anchor (impossible) */ - STATE_ERR_INFORMATION_LEAK, /* We ended up in an unexpected state. */ STATE_ERR_INTERNAL, @@ -213,37 +104,6 @@ enum state_input { BITCOIN_ANCHOR_DEPTHOK, /* It didn't reach the required depth in time. */ BITCOIN_ANCHOR_TIMEOUT, - /* It reached the required depth, then was forked off. */ - BITCOIN_ANCHOR_UNSPENT, - /* Anchor was spent by our commit, and we can now spend it. */ - BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED, - /* Anchor was spent by their commit tx. */ - 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, - - /* Their commit tx is completely buried. */ - BITCOIN_THEIRCOMMIT_DONE, - /* Our spend of our own tx is completely buried. */ - BITCOIN_SPEND_OURS_DONE, - /* Our spend of their revoked tx is completely buried. */ - 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, - /* No more HTLCs in either commitment tx. */ INPUT_HTLCS_CLEARED, @@ -252,14 +112,6 @@ enum state_input { */ INPUT_CLOSE_COMPLETE_TIMEOUT, - /* - * Inject a known R value. - * - * In normal operation, use CMD_SEND_HTLC_FULFILL; this is for - * after a unilateral close. - */ - INPUT_RVALUE, - /* Commands */ CMD_OPEN_WITH_ANCHOR, CMD_OPEN_WITHOUT_ANCHOR, @@ -269,9 +121,6 @@ enum state_input { CMD_SEND_COMMIT, CMD_CLOSE, - /* Connection lost/timedout with other node. */ - INPUT_CONNECTION_LOST, - INPUT_MAX };