diff --git a/daemon/peer.c b/daemon/peer.c index 97e16ecdc..8e3fe0cdd 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -78,11 +78,18 @@ static struct json_result *null_response(const tal_t *ctx) return response; } -/* FIXME: reorder to avoid predecls. */ -static bool peer_uncommitted_changes(const struct peer *peer); -static void state_event(struct peer *peer, - const enum state_input input, - const union input *idata); +static bool peer_uncommitted_changes(const struct peer *peer) +{ + /* Not initialized yet? */ + if (!peer->remote.staging_cstate + || !peer->remote.commit + || !peer->remote.commit->cstate) + return false; + + /* We could have proposed changes to their commit */ + return peer->remote.staging_cstate->changes + != peer->remote.commit->cstate->changes; +} void peer_update_complete(struct peer *peer, const char *problem) { @@ -124,87 +131,6 @@ static void set_peer_state(struct peer *peer, enum state newstate, peer->state = newstate; } -/* FIXME: Flatten into do_commit. */ -static void command_send_commit(struct peer *peer, struct command *jsoncmd) -{ - assert(state_can_commit(peer->state)); - assert(!peer->commit_jsoncmd); - - peer->commit_jsoncmd = jsoncmd; - if (peer->state == STATE_CLEARING) { - queue_pkt_commit(peer); - set_peer_state(peer, STATE_CLEARING_COMMITTING, __func__); - } else { - /* You can send commands if closing; peer->cond == CLOSING */ - assert(peer->state == STATE_NORMAL); - state_event(peer, CMD_SEND_COMMIT, NULL); - } -} - -static bool command_htlc_fail(struct peer *peer, u64 id, struct command *jsoncmd) -{ - if (!state_can_remove_htlc(peer->state)) { - if (jsoncmd) - command_fail(jsoncmd, - "htlc_fail not possible in state %s", - state_name(peer->state)); - return false; - } - - if (peer->state == STATE_CLEARING) { - queue_pkt_htlc_fail(peer, id); - } else { - union input idata; - struct htlc_progress prog; - - prog.stage.fail.fail = HTLC_FAIL; - prog.stage.fail.id = id; - /* FIXME: get rid of htlc_progress, just use htlc_staging. */ - idata.htlc_prog = &prog; - state_event(peer, CMD_SEND_HTLC_FAIL, &idata); - } - - if (jsoncmd) - command_success(jsoncmd, null_response(jsoncmd)); - return true; -} - -/* FIXME: Flatten into json_fulfillhtlc. */ -static bool command_htlc_fulfill(struct peer *peer, - u64 id, - const struct sha256 *r, - struct command *jsoncmd) -{ - if (!state_can_remove_htlc(peer->state)) { - if (jsoncmd) - command_fail(jsoncmd, - "htlc_fulfill not possible in state %s", - state_name(peer->state)); - return false; - } - - /* Commands should still be blocked during this! */ - assert(peer->state != STATE_CLEARING_COMMITTING); - - if (peer->state == STATE_CLEARING) { - queue_pkt_htlc_fulfill(peer, id, r); - } else { - union input idata; - struct htlc_progress prog; - - prog.stage.fulfill.fulfill = HTLC_FULFILL; - prog.stage.fulfill.r = *r; - prog.stage.fulfill.id = id; - /* FIXME: get rid of htlc_progress, just use htlc_staging. */ - idata.htlc_prog = &prog; - state_event(peer, CMD_SEND_HTLC_FULFILL, &idata); - } - - if (jsoncmd) - command_success(jsoncmd, null_response(jsoncmd)); - return true; -} - static void peer_breakdown(struct peer *peer) { /* If we have a closing tx, use it. */ @@ -224,19 +150,6 @@ static void peer_breakdown(struct peer *peer) } } -static bool peer_uncommitted_changes(const struct peer *peer) -{ - /* Not initialized yet? */ - if (!peer->remote.staging_cstate - || !peer->remote.commit - || !peer->remote.commit->cstate) - return false; - - /* We could have proposed changes to their commit */ - return peer->remote.staging_cstate->changes - != peer->remote.commit->cstate->changes; -} - /* All unrevoked commit txs must have no HTLCs in them. */ static bool committed_to_htlcs(const struct peer *peer) { @@ -575,6 +488,52 @@ static void state_event(struct peer *peer, } } +static bool command_htlc_fail(struct peer *peer, u64 id) +{ + if (!state_can_remove_htlc(peer->state)) + return false; + + if (peer->state == STATE_CLEARING) { + queue_pkt_htlc_fail(peer, id); + } else { + union input idata; + struct htlc_progress prog; + + prog.stage.fail.fail = HTLC_FAIL; + prog.stage.fail.id = id; + /* FIXME: get rid of htlc_progress, just use htlc_staging. */ + idata.htlc_prog = &prog; + state_event(peer, CMD_SEND_HTLC_FAIL, &idata); + } + return true; +} + +static bool command_htlc_fulfill(struct peer *peer, + u64 id, + const struct sha256 *r) +{ + if (!state_can_remove_htlc(peer->state)) + return false; + + /* Commands should still be blocked during this! */ + assert(peer->state != STATE_CLEARING_COMMITTING); + + if (peer->state == STATE_CLEARING) { + queue_pkt_htlc_fulfill(peer, id, r); + } else { + union input idata; + struct htlc_progress prog; + + prog.stage.fulfill.fulfill = HTLC_FULFILL; + prog.stage.fulfill.r = *r; + prog.stage.fulfill.id = id; + /* FIXME: get rid of htlc_progress, just use htlc_staging. */ + idata.htlc_prog = &prog; + state_event(peer, CMD_SEND_HTLC_FULFILL, &idata); + } + return true; +} + static struct io_plan *pkt_out(struct io_conn *conn, struct peer *peer) { Pkt *out; @@ -675,16 +634,24 @@ static void peer_disconnect(struct io_conn *conn, struct peer *peer) static void do_commit(struct peer *peer, struct command *jsoncmd) { /* We can have changes we suggested, or changes they suggested. */ - if (peer_uncommitted_changes(peer)) { - log_debug(peer->log, "do_commit: sending commit command"); - command_send_commit(peer, jsoncmd); - return; + if (!peer_uncommitted_changes(peer)) { + log_debug(peer->log, "do_commit: no changes to commit"); + if (jsoncmd) + command_fail(jsoncmd, "no changes to commit"); } - log_debug(peer->log, "do_commit: no changes to commit"); - if (jsoncmd) { - command_fail(jsoncmd, "no changes to commit"); - return; + log_debug(peer->log, "do_commit: sending commit command"); + + assert(state_can_commit(peer->state)); + assert(!peer->commit_jsoncmd); + + peer->commit_jsoncmd = jsoncmd; + if (peer->state == STATE_CLEARING) { + queue_pkt_commit(peer); + set_peer_state(peer, STATE_CLEARING_COMMITTING, __func__); + } else { + assert(peer->state == STATE_NORMAL); + state_event(peer, CMD_SEND_COMMIT, NULL); } } @@ -2328,7 +2295,7 @@ static void check_htlc_expiry(struct peer *peer) continue; /* This can fail only if we're in an error state. */ - command_htlc_fail(peer, htlc->id, NULL); + command_htlc_fail(peer, htlc->id); return; } } @@ -2506,32 +2473,15 @@ static size_t find_their_committed_htlc(struct peer *peer, return funding_find_htlc(peer->remote.staging_cstate, rhash, THEIRS); } -static void do_fullfill(struct peer *peer, - const struct sha256 *r, - struct command *jsoncmd) -{ - struct sha256 rhash; - size_t i; - u64 id; - - sha256(&rhash, r, sizeof(*r)); - - i = find_their_committed_htlc(peer, &rhash); - if (i == -1) { - command_fail(jsoncmd, "preimage htlc not found"); - return; - } - - id = peer->remote.staging_cstate->side[THEIRS].htlcs[i].id; - command_htlc_fulfill(peer, id, r, jsoncmd); -} - static void json_fulfillhtlc(struct command *cmd, const char *buffer, const jsmntok_t *params) { struct peer *peer; jsmntok_t *peeridtok, *rtok; struct sha256 r; + struct sha256 rhash; + size_t i; + u64 id; if (!json_get_params(buffer, params, "peerid", &peeridtok, @@ -2560,7 +2510,22 @@ static void json_fulfillhtlc(struct command *cmd, buffer + rtok->start); return; } - do_fullfill(peer, &r, cmd); + + sha256(&rhash, &r, sizeof(r)); + + i = find_their_committed_htlc(peer, &rhash); + if (i == -1) { + command_fail(cmd, "preimage htlc not found"); + return; + } + + id = peer->remote.staging_cstate->side[THEIRS].htlcs[i].id; + if (command_htlc_fulfill(peer, id, &r)) + command_success(cmd, null_response(cmd)); + else + command_fail(cmd, + "htlc_fulfill not possible in state %s", + state_name(peer->state)); } const struct json_command fulfillhtlc_command = { @@ -2570,31 +2535,14 @@ const struct json_command fulfillhtlc_command = { "Returns an empty result on success" }; -/* FIXME: Flatten into json_failhtlc. */ -static void do_failhtlc(struct peer *peer, - const struct sha256 *rhash, - struct command *jsoncmd) -{ - size_t i; - u64 id; - - /* Look in peer->remote.staging_cstate->a, as that's where we'll - * immediately remove it from: avoids double-handling. */ - i = find_their_committed_htlc(peer, rhash); - if (i == -1) { - command_fail(jsoncmd, "htlc not found"); - return; - } - id = peer->remote.staging_cstate->side[THEIRS].htlcs[i].id; - command_htlc_fail(peer, id, jsoncmd); -} - static void json_failhtlc(struct command *cmd, const char *buffer, const jsmntok_t *params) { struct peer *peer; jsmntok_t *peeridtok, *rhashtok; struct sha256 rhash; + size_t i; + u64 id; if (!json_get_params(buffer, params, "peerid", &peeridtok, @@ -2624,7 +2572,20 @@ static void json_failhtlc(struct command *cmd, return; } - do_failhtlc(peer, &rhash, cmd); + /* Look in peer->remote.staging_cstate->a, as that's where we'll + * immediately remove it from: avoids double-handling. */ + i = find_their_committed_htlc(peer, &rhash); + if (i == -1) { + command_fail(cmd, "htlc not found"); + return; + } + id = peer->remote.staging_cstate->side[THEIRS].htlcs[i].id; + if (command_htlc_fail(peer, id)) + command_success(cmd, null_response(cmd)); + else + command_fail(cmd, + "htlc_fail not possible in state %s", + state_name(peer->state)); } const struct json_command failhtlc_command = {