From 819078fe18d45abff09d033926e3659cddce7e1c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sun, 16 Dec 2018 15:23:06 +1030 Subject: [PATCH] param: make command_fail/command_success WARN_UNUSED_RESULT. This causes a compiler warning if we don't do something with the result (hopefully return immediately!). We use was_pending() to ignore the result in the case where we complete a command in a callback (thus really do want to ignore the result). This actually fixes one bug: we didn't return after command_fail in json_getroute with a bad seed value. Signed-off-by: Rusty Russell --- common/json_command.h | 2 +- common/param.c | 6 ++- lightningd/chaintopology.c | 3 +- lightningd/connect_control.c | 2 +- lightningd/gossip_control.c | 40 +++++++++-------- lightningd/invoice.c | 19 ++++---- lightningd/jsonrpc.h | 12 ++++-- lightningd/memdump.c | 13 +++--- lightningd/opening_control.c | 47 ++++++++++---------- lightningd/pay.c | 14 +++--- lightningd/payalgo.c | 35 ++++++++------- lightningd/peer_control.c | 84 ++++++++++++++++++------------------ lightningd/ping.c | 7 +-- tools/mockup.sh | 2 +- wallet/walletrpc.c | 9 ++-- 15 files changed, 160 insertions(+), 135 deletions(-) diff --git a/common/json_command.h b/common/json_command.h index 1b05ee9b3..f6dfc0314 100644 --- a/common/json_command.h +++ b/common/json_command.h @@ -12,7 +12,7 @@ struct command_result; /* Caller supplied this: param assumes it can call it. */ struct command_result *command_fail(struct command *cmd, int code, const char *fmt, ...) - PRINTF_FMT(3, 4); + PRINTF_FMT(3, 4) WARN_UNUSED_RESULT; /* Also caller supplied: is this invoked simply to get usage? */ bool command_usage_only(const struct command *cmd); diff --git a/common/param.c b/common/param.c index 7b67d0c98..d576abab5 100644 --- a/common/param.c +++ b/common/param.c @@ -280,8 +280,10 @@ bool param(struct command *cmd, const char *buffer, continue; } if (!param_add(¶ms, name, required, cbx, arg)) { - command_fail(cmd, PARAM_DEV_ERROR, - "developer error: param_add %s", name); + /* We really do ignore this return! */ + if (command_fail(cmd, PARAM_DEV_ERROR, + "developer error: param_add %s", name)) + ; va_end(ap); return false; } diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 8dd782896..3e94d8498 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -139,7 +139,8 @@ static void broadcast_remainder(struct bitcoind *bitcoind, txs->cursor++; if (txs->cursor == tal_count(txs->txs)) { if (txs->cmd) - command_success(txs->cmd, null_response(txs->cmd)); + was_pending(command_success(txs->cmd, + null_response(txs->cmd))); tal_free(txs); return; } diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index fb8ab377b..0648419a9 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -245,7 +245,7 @@ static void connect_failed(struct lightningd *ld, const u8 *msg) /* We can have multiple connect commands: fail them all */ while ((c = find_connect(ld, &id)) != NULL) { /* They delete themselves from list */ - command_fail(c->cmd, LIGHTNINGD, "%s", err); + was_pending(command_fail(c->cmd, LIGHTNINGD, "%s", err)); } /* If we have an active channel, then reconnect. */ diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 4e0cfec2d..30e8c2256 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -201,7 +201,8 @@ static void json_getnodes_reply(struct subd *gossip UNUSED, const u8 *reply, size_t i, j; if (!fromwire_gossip_getnodes_reply(reply, reply, &nodes)) { - command_fail(cmd, LIGHTNINGD, "Malformed gossip_getnodes response"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Malformed gossip_getnodes response")); return; } @@ -241,7 +242,7 @@ static void json_getnodes_reply(struct subd *gossip UNUSED, const u8 *reply, } json_array_end(response); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } static struct command_result *json_listnodes(struct command *cmd, @@ -278,7 +279,8 @@ static void json_getroute_reply(struct subd *gossip UNUSED, const u8 *reply, con fromwire_gossip_getroute_reply(reply, reply, &hops); if (tal_count(hops) == 0) { - command_fail(cmd, LIGHTNINGD, "Could not find a route"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Could not find a route")); return; } @@ -286,7 +288,7 @@ static void json_getroute_reply(struct subd *gossip UNUSED, const u8 *reply, con json_object_start(response, NULL); json_add_route(response, "route", hops, tal_count(hops)); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } static struct command_result *json_getroute(struct command *cmd, @@ -325,8 +327,9 @@ static struct command_result *json_getroute(struct command *cmd, if (seedtok) { if (seedtok->end - seedtok->start > sizeof(seed)) - command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "seed must be < %zu bytes", sizeof(seed)); + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "seed must be < %zu bytes", + sizeof(seed)); memset(&seed, 0, sizeof(seed)); memcpy(&seed, buffer + seedtok->start, @@ -360,7 +363,8 @@ static void json_listchannels_reply(struct subd *gossip UNUSED, const u8 *reply, struct json_stream *response; if (!fromwire_gossip_getchannels_reply(reply, reply, &entries)) { - command_fail(cmd, LIGHTNINGD, "Invalid reply from gossipd"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Invalid reply from gossipd")); return; } @@ -396,7 +400,7 @@ static void json_listchannels_reply(struct subd *gossip UNUSED, const u8 *reply, } json_array_end(response); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } static struct command_result *json_listchannels(struct command *cmd, @@ -432,14 +436,14 @@ static void json_scids_reply(struct subd *gossip UNUSED, const u8 *reply, struct json_stream *response; if (!fromwire_gossip_scids_reply(reply, &ok, &complete)) { - command_fail(cmd, LIGHTNINGD, - "Gossip gave bad gossip_scids_reply"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Gossip gave bad gossip_scids_reply")); return; } if (!ok) { - command_fail(cmd, LIGHTNINGD, - "Gossip refused to query peer"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Gossip refused to query peer")); return; } @@ -447,7 +451,7 @@ static void json_scids_reply(struct subd *gossip UNUSED, const u8 *reply, json_object_start(response, NULL); json_add_bool(response, "complete", complete); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } static struct command_result *json_dev_query_scids(struct command *cmd, @@ -538,14 +542,14 @@ static void json_channel_range_reply(struct subd *gossip UNUSED, const u8 *reply &final_num_blocks, &final_complete, &scids)) { - command_fail(cmd, LIGHTNINGD, - "Gossip gave bad gossip_query_channel_range_reply"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Gossip gave bad gossip_query_channel_range_reply")); return; } if (final_num_blocks == 0 && final_num_blocks == 0 && !final_complete) { - command_fail(cmd, LIGHTNINGD, - "Gossip refused to query peer"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Gossip refused to query peer")); return; } @@ -561,7 +565,7 @@ static void json_channel_range_reply(struct subd *gossip UNUSED, const u8 *reply json_add_short_channel_id(response, NULL, &scids[i]); json_array_end(response); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } static struct command_result *json_dev_query_channel_range(struct command *cmd, diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 83249f375..e6771f58e 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -84,7 +84,8 @@ static struct command_result *tell_waiter(struct command *cmd, static void tell_waiter_deleted(struct command *cmd) { - command_fail(cmd, LIGHTNINGD, "Invoice deleted during wait"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Invoice deleted during wait")); } static void wait_on_invoice(const struct invoice *invoice, void *cmd) { @@ -240,8 +241,9 @@ static void gossipd_incoming_channels_reply(struct subd *gossipd, /* Check duplicate preimage (unlikely unless they specified it!) */ if (wallet_invoice_find_by_rhash(wallet, &invoice, &info->b11->payment_hash)) { - command_fail(info->cmd, INVOICE_PREIMAGE_ALREADY_EXISTS, - "preimage already used"); + was_pending(command_fail(info->cmd, + INVOICE_PREIMAGE_ALREADY_EXISTS, + "preimage already used")); return; } @@ -254,8 +256,9 @@ static void gossipd_incoming_channels_reply(struct subd *gossipd, info->b11->description, &info->payment_preimage, &info->b11->payment_hash)) { - command_fail(info->cmd, INVOICE_LABEL_ALREADY_EXISTS, - "Duplicate label '%s'", info->label->s); + was_pending(command_fail(info->cmd, INVOICE_LABEL_ALREADY_EXISTS, + "Duplicate label '%s'", + info->label->s)); return; } @@ -289,7 +292,7 @@ static void gossipd_incoming_channels_reply(struct subd *gossipd, } json_object_end(response); - command_success(info->cmd, response); + was_pending(command_success(info->cmd, response)); } static struct command_result *json_invoice(struct command *cmd, @@ -563,7 +566,7 @@ static struct command_result *json_waitanyinvoice(struct command *cmd, /* Set command as pending. We do not know if * wallet_invoice_waitany will return immediately * or not, so indicating pending is safest. */ - command_still_pending(cmd); + fixme_ignore(command_still_pending(cmd)); /* Find next paid invoice. */ wallet_invoice_waitany(cmd, wallet, *pay_index, @@ -610,7 +613,7 @@ static struct command_result *json_waitinvoice(struct command *cmd, return tell_waiter(cmd, &i); } else { /* There is an unpaid one matching, let's wait... */ - command_still_pending(cmd); + fixme_ignore(command_still_pending(cmd)); wallet_invoice_waitone(cmd, wallet, i, &wait_on_invoice, (void *) cmd); return command_its_complicated(); diff --git a/lightningd/jsonrpc.h b/lightningd/jsonrpc.h index 78a49afbb..2cf31631d 100644 --- a/lightningd/jsonrpc.h +++ b/lightningd/jsonrpc.h @@ -96,12 +96,15 @@ struct json_stream *null_response(struct command *cmd); /* These returned values are never NULL. */ struct command_result *command_success(struct command *cmd, - struct json_stream *response); + struct json_stream *response) + WARN_UNUSED_RESULT; struct command_result *command_failed(struct command *cmd, - struct json_stream *result); + struct json_stream *result) + WARN_UNUSED_RESULT; /* Mainly for documentation, that we plan to close this later. */ -struct command_result *command_still_pending(struct command *cmd); +struct command_result *command_still_pending(struct command *cmd) + WARN_UNUSED_RESULT; /* For low-level JSON stream access: */ struct json_stream *json_stream_raw_for_cmd(struct command *cmd); @@ -109,7 +112,8 @@ struct command_result *command_raw_complete(struct command *cmd, struct json_stream *result); /* To return if param() fails. */ -extern struct command_result *command_param_failed(void); +extern struct command_result *command_param_failed(void) + WARN_UNUSED_RESULT; /* Wrapper for pending commands (ignores return) */ static inline void was_pending(const struct command_result *res) diff --git a/lightningd/memdump.c b/lightningd/memdump.c index 6ad0426b5..408aed899 100644 --- a/lightningd/memdump.c +++ b/lightningd/memdump.c @@ -181,7 +181,7 @@ static void report_leak_info2(struct leak_info *leak_info) scan_mem(leak_info->cmd, response, leak_info->cmd->ld, leak_info->leaker); json_object_end(response); - command_success(leak_info->cmd, response); + was_pending(command_success(leak_info->cmd, response)); } static void report_leak_info(struct command *cmd, struct subd *leaker) @@ -205,7 +205,8 @@ static void gossip_dev_memleak_done(struct subd *gossipd, bool found_leak; if (!fromwire_gossip_dev_memleak_reply(reply, &found_leak)) { - command_fail(cmd, LIGHTNINGD, "Bad gossip_dev_memleak"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Bad gossip_dev_memleak")); return; } @@ -221,7 +222,8 @@ static void connect_dev_memleak_done(struct subd *connectd, bool found_leak; if (!fromwire_connect_dev_memleak_reply(reply, &found_leak)) { - command_fail(cmd, LIGHTNINGD, "Bad connect_dev_memleak"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Bad connect_dev_memleak")); return; } @@ -243,7 +245,8 @@ static void hsm_dev_memleak_done(struct subd *hsmd, bool found_leak; if (!fromwire_hsm_dev_memleak_reply(reply, &found_leak)) { - command_fail(cmd, LIGHTNINGD, "Bad hsm_dev_memleak"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Bad hsm_dev_memleak")); return; } @@ -299,7 +302,7 @@ static struct command_result *json_memleak(struct command *cmd, /* For simplicity, we mark pending, though an error may complete it * immediately. */ - command_still_pending(cmd); + fixme_ignore(command_still_pending(cmd)); /* This calls opening_memleak_done() async when all done. */ opening_dev_memleak(cmd); diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 5b9368ae4..662320545 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -84,7 +84,7 @@ static void uncommitted_channel_disconnect(struct uncommitted_channel *uc, log_info(uc->log, "%s", desc); subd_send_msg(uc->peer->ld->connectd, msg); if (uc->fc) - command_fail(uc->fc->cmd, LIGHTNINGD, "%s", desc); + was_pending(command_fail(uc->fc->cmd, LIGHTNINGD, "%s", desc)); } void kill_uncommitted_channel(struct uncommitted_channel *uc, @@ -264,8 +264,9 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, log_broken(fc->uc->log, "bad OPENING_FUNDER_REPLY %s", tal_hex(resp, resp)); - command_fail(fc->cmd, LIGHTNINGD, "bad OPENING_FUNDER_REPLY %s", - tal_hex(fc->cmd, resp)); + was_pending(command_fail(fc->cmd, LIGHTNINGD, + "bad OPENING_FUNDER_REPLY %s", + tal_hex(fc->cmd, resp))); goto failed; } log_debug(ld->log, @@ -311,17 +312,18 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, &fc->uc->local_funding_pubkey), type_to_string(fc, struct pubkey, &channel_info.remote_fundingkey)); - command_fail(fc->cmd, JSONRPC2_INVALID_PARAMS, - "Funding txid mismatch:" - " satoshi %"PRIu64" change %"PRIu64 - " changeidx %u" - " localkey %s remotekey %s", - fc->wtx.amount, - fc->wtx.change, fc->wtx.change_key_index, - type_to_string(fc, struct pubkey, - &fc->uc->local_funding_pubkey), - type_to_string(fc, struct pubkey, - &channel_info.remote_fundingkey)); + was_pending(command_fail(fc->cmd, JSONRPC2_INVALID_PARAMS, + "Funding txid mismatch:" + " satoshi %"PRIu64" change %"PRIu64 + " changeidx %u" + " localkey %s remotekey %s", + fc->wtx.amount, + fc->wtx.change, + fc->wtx.change_key_index, + type_to_string(fc, struct pubkey, + &fc->uc->local_funding_pubkey), + type_to_string(fc, struct pubkey, + &channel_info.remote_fundingkey))); goto failed; } @@ -337,8 +339,8 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, &channel_info, feerate); if (!channel) { - command_fail(fc->cmd, LIGHTNINGD, - "Key generation failure"); + was_pending(command_fail(fc->cmd, LIGHTNINGD, + "Key generation failure")); goto failed; } @@ -387,7 +389,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, json_add_string(response, "channel_id", type_to_string(tmpctx, struct channel_id, &cid)); json_object_end(response); - command_success(fc->cmd, response); + was_pending(command_success(fc->cmd, response)); subd_release_channel(openingd, fc->uc); fc->uc->openingd = NULL; @@ -507,14 +509,14 @@ static void opening_funder_failed(struct subd *openingd, const u8 *msg, log_broken(uc->log, "bad OPENING_FUNDER_FAILED %s", tal_hex(tmpctx, msg)); - command_fail(uc->fc->cmd, LIGHTNINGD, - "bad OPENING_FUNDER_FAILED %s", - tal_hex(uc->fc->cmd, msg)); + was_pending(command_fail(uc->fc->cmd, LIGHTNINGD, + "bad OPENING_FUNDER_FAILED %s", + tal_hex(uc->fc->cmd, msg))); tal_free(uc); return; } - command_fail(uc->fc->cmd, LIGHTNINGD, "%s", desc); + was_pending(command_fail(uc->fc->cmd, LIGHTNINGD, "%s", desc)); /* Clear uc->fc, so we can try again, and so we don't fail twice * if they close. */ @@ -890,7 +892,8 @@ static void opening_memleak_req_done(struct subd *openingd, tal_del_destructor2(openingd, opening_died_forget_memleak, cmd); if (!fromwire_opening_dev_memleak_reply(msg, &found_leak)) { - command_fail(cmd, LIGHTNINGD, "Bad opening_dev_memleak"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Bad opening_dev_memleak")); return; } diff --git a/lightningd/pay.c b/lightningd/pay.c index b3a37aecc..2a84091aa 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -856,7 +856,7 @@ json_sendpay_success(struct command *cmd, json_object_start(response, NULL); json_add_payment_fields(response, r->payment); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } static void json_waitsendpay_on_resolve(const struct sendpay_result *r, @@ -879,7 +879,8 @@ static void json_waitsendpay_on_resolve(const struct sendpay_result *r, case PAY_RHASH_ALREADY_USED: case PAY_UNSPECIFIED_ERROR: case PAY_NO_SUCH_PAYMENT: - command_fail(cmd, r->errorcode, "%s", r->details); + was_pending(command_fail(cmd, r->errorcode, "%s", + r->details)); return; case PAY_UNPARSEABLE_ONION: @@ -892,7 +893,7 @@ static void json_waitsendpay_on_resolve(const struct sendpay_result *r, json_object_start(data, NULL); json_add_hex_talarr(data, "onionreply", r->onionreply); json_object_end(data); - command_failed(cmd, data); + was_pending(command_failed(cmd, data)); return; case PAY_DESTINATION_PERM_FAIL: @@ -916,7 +917,7 @@ static void json_waitsendpay_on_resolve(const struct sendpay_result *r, json_add_hex_talarr(data, "channel_update", fail->channel_update); json_object_end(data); - command_failed(cmd, data); + was_pending(command_failed(cmd, data)); return; } abort(); @@ -936,7 +937,7 @@ static void json_sendpay_on_resolve(const struct sendpay_result* r, "Monitor status with listpayments or waitsendpay"); json_add_payment_fields(response, r->payment); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } else json_waitsendpay_on_resolve(r, cmd); } @@ -1024,7 +1025,8 @@ AUTODATA(json_command, &sendpay_command); static void waitsendpay_timeout(struct command *cmd) { - command_fail(cmd, PAY_IN_PROGRESS, "Timed out while waiting"); + was_pending(command_fail(cmd, PAY_IN_PROGRESS, + "Timed out while waiting")); } static struct command_result *json_waitsendpay(struct command *cmd, diff --git a/lightningd/payalgo.c b/lightningd/payalgo.c index 94c3a2539..4b7e3f319 100644 --- a/lightningd/payalgo.c +++ b/lightningd/payalgo.c @@ -206,7 +206,7 @@ json_pay_success(struct pay *pay, pay->route, tal_count(pay->route)); json_add_failures(response, "failures", &pay->pay_failures); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } static void json_pay_failure(struct pay *pay, @@ -226,7 +226,7 @@ static void json_pay_failure(struct pay *pay, json_add_payment_fields(data, r->payment); json_add_failures(data, "failures", &pay->pay_failures); json_object_end(data); - command_failed(pay->cmd, data); + was_pending(command_failed(pay->cmd, data)); return; case PAY_RHASH_ALREADY_USED: @@ -237,7 +237,7 @@ static void json_pay_failure(struct pay *pay, json_add_num(data, "sendpay_tries", pay->sendpay_tries); json_add_failures(data, "failures", &pay->pay_failures); json_object_end(data); - command_failed(pay->cmd, data); + was_pending(command_failed(pay->cmd, data)); return; case PAY_UNPARSEABLE_ONION: @@ -266,7 +266,7 @@ static void json_pay_failure(struct pay *pay, fail->channel_update); json_add_failures(data, "failures", &pay->pay_failures); json_object_end(data); - command_failed(pay->cmd, data); + was_pending(command_failed(pay->cmd, data)); return; case PAY_TRY_OTHER_ROUTE: @@ -305,7 +305,7 @@ static const char *should_delay_retry(const tal_t *ctx, } /* Start a payment attempt. */ -static bool json_pay_try(struct pay *pay); +static struct command_result *json_pay_try(struct pay *pay); /* Used when delaying. */ static void do_pay_try(struct pay *pay) @@ -426,7 +426,7 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED, json_add_num(data, "sendpay_tries", pay->sendpay_tries); json_add_failures(data, "failures", &pay->pay_failures); json_object_end(data); - command_failed(pay->cmd, data); + was_pending(command_failed(pay->cmd, data)); return; } @@ -474,7 +474,7 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED, json_add_failures(data, "failures", &pay->pay_failures); json_object_end(data); - command_failed(pay->cmd, data); + was_pending(command_failed(pay->cmd, data)); return; } if (fee_too_high || delay_too_high) { @@ -501,9 +501,9 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED, &json_pay_sendpay_resume, pay); } -/* Start a payment attempt. Return true if deferred, - * false if resolved now. */ -static bool json_pay_try(struct pay *pay) +/* Start a payment attempt. Return NULL if deferred, otherwise + * command_failed(). */ +static struct command_result *json_pay_try(struct pay *pay) { u8 *req; struct command *cmd = pay->cmd; @@ -524,8 +524,7 @@ static bool json_pay_try(struct pay *pay) json_add_num(data, "sendpay_tries", pay->sendpay_tries); json_add_failures(data, "failures", &pay->pay_failures); json_object_end(data); - command_failed(cmd, data); - return false; + return command_failed(cmd, data); } /* Clear previous try memory. */ @@ -566,7 +565,7 @@ static bool json_pay_try(struct pay *pay) &seed); subd_req(pay->try_parent, cmd->ld->gossip, req, -1, 0, json_pay_getroute_reply, pay); - return true; + return NULL; } static void json_pay_stop_retrying(struct pay *pay) @@ -607,6 +606,7 @@ static struct command_result *json_pay(struct command *cmd, unsigned int *retryfor; unsigned int *maxdelay; unsigned int *exemptfee; + struct command_result *res; if (!param(cmd, buffer, params, p_req("bolt11", param_string, &b11str), @@ -681,15 +681,14 @@ static struct command_result *json_pay(struct command *cmd, pay->description = b11->description; /* Initiate payment */ - if (json_pay_try(pay)) - command_still_pending(cmd); - else - return command_its_complicated(); + res = json_pay_try(pay); + if (res) + return res; /* Set up timeout. */ new_reltimer(&cmd->ld->timers, pay, time_from_sec(*retryfor), &json_pay_stop_retrying, pay); - return command_its_complicated(); + return command_still_pending(cmd); } static const struct json_command pay_command = { diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index eca830446..afb5fd089 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -241,7 +241,7 @@ resolve_one_close_command(struct close_command *cc, bool cooperative) json_add_string(result, "type", "unilateral"); json_object_end(result); - command_success(cc->cmd, result); + was_pending(command_success(cc->cmd, result)); } /* Resolve a close command for a channel that will be closed soon. */ @@ -270,8 +270,8 @@ destroy_close_command_on_channel_destroy(struct channel *_ UNUSED, * Clear the cc->channel first so that we will not try to * remove a destructor. */ cc->channel = NULL; - command_fail(cc->cmd, LIGHTNINGD, - "Channel forgotten before proper close."); + was_pending(command_fail(cc->cmd, LIGHTNINGD, + "Channel forgotten before proper close.")); } /* Destroy the close command structure. */ @@ -303,9 +303,9 @@ close_command_timeout(struct close_command *cc) else /* Fail the command directly, which will resolve the * command and destroy the close_command. */ - command_fail(cc->cmd, LIGHTNINGD, - "Channel close negotiation not finished " - "before timeout"); + was_pending(command_fail(cc->cmd, LIGHTNINGD, + "Channel close negotiation not finished " + "before timeout")); } /* Construct a close command structure and add to ld. */ @@ -842,52 +842,51 @@ static const struct json_command listpeers_command = { }; AUTODATA(json_command, &listpeers_command); -static struct channel * +static struct command_result * command_find_channel(struct command *cmd, - const char *buffer, const jsmntok_t *tok) + const char *buffer, const jsmntok_t *tok, + struct channel **channel) { struct lightningd *ld = cmd->ld; struct channel_id cid; struct channel_id channel_cid; struct short_channel_id scid; struct peer *peer; - struct channel *channel; if (json_tok_channel_id(buffer, tok, &cid)) { list_for_each(&ld->peers, peer, list) { - channel = peer_active_channel(peer); - if (!channel) + *channel = peer_active_channel(peer); + if (!*channel) continue; derive_channel_id(&channel_cid, - &channel->funding_txid, - channel->funding_outnum); + &(*channel)->funding_txid, + (*channel)->funding_outnum); if (channel_id_eq(&channel_cid, &cid)) - return channel; + return NULL; } - command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Channel ID not found: '%.*s'", - tok->end - tok->start, - buffer + tok->start); - return NULL; + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Channel ID not found: '%.*s'", + tok->end - tok->start, + buffer + tok->start); } else if (json_to_short_channel_id(buffer, tok, &scid)) { list_for_each(&ld->peers, peer, list) { - channel = peer_active_channel(peer); - if (!channel) + *channel = peer_active_channel(peer); + if (!*channel) continue; - if (channel->scid && channel->scid->u64 == scid.u64) - return channel; + if ((*channel)->scid + && (*channel)->scid->u64 == scid.u64) + return NULL; } - command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Short channel ID not found: '%.*s'", - tok->end - tok->start, - buffer + tok->start); - return NULL; + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Short channel ID not found: '%.*s'", + tok->end - tok->start, + buffer + tok->start); } else { - command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Given id is not a channel ID or " - "short channel ID: '%.*s'", - json_tok_full_len(tok), json_tok_full(buffer, tok)); - return NULL; + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Given id is not a channel ID or " + "short channel ID: '%.*s'", + json_tok_full_len(tok), + json_tok_full(buffer, tok)); } } @@ -913,9 +912,10 @@ static struct command_result *json_close(struct command *cmd, if (peer) channel = peer_active_channel(peer); else { - channel = command_find_channel(cmd, buffer, idtok); - if (!channel) - return command_its_complicated(); + struct command_result *res; + res = command_find_channel(cmd, buffer, idtok, &channel); + if (res) + return res; } if (!channel && peer) { @@ -1307,14 +1307,14 @@ static void process_dev_forget_channel(struct bitcoind *bitcoind UNUSED, struct json_stream *response; struct dev_forget_channel_cmd *forget = arg; if (txout != NULL && !forget->force) { - command_fail(forget->cmd, LIGHTNINGD, + was_pending(command_fail(forget->cmd, LIGHTNINGD, "Cowardly refusing to forget channel with an " "unspent funding output, if you know what " "you're doing you can override with " "`force=true`, otherwise consider `close` or " "`dev-fail`! If you force and the channel " "confirms we will not track the funds in the " - "channel"); + "channel")); return; } response = json_stream_success(forget->cmd); @@ -1329,7 +1329,7 @@ static void process_dev_forget_channel(struct bitcoind *bitcoind UNUSED, "dev_forget_channel"); delete_channel(forget->channel); - command_success(forget->cmd, response); + was_pending(command_success(forget->cmd, response)); } static struct command_result *json_dev_forget_channel(struct command *cmd, @@ -1428,7 +1428,8 @@ static void channeld_memleak_req_done(struct subd *channeld, tal_del_destructor2(channeld, subd_died_forget_memleak, cmd); if (!fromwire_channel_dev_memleak_reply(msg, &found_leak)) { - command_fail(cmd, LIGHTNINGD, "Bad channel_dev_memleak"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Bad channel_dev_memleak")); return; } peer_memleak_req_done(channeld, found_leak, cmd); @@ -1442,7 +1443,8 @@ static void onchaind_memleak_req_done(struct subd *onchaind, tal_del_destructor2(onchaind, subd_died_forget_memleak, cmd); if (!fromwire_onchain_dev_memleak_reply(msg, &found_leak)) { - command_fail(cmd, LIGHTNINGD, "Bad onchain_dev_memleak"); + was_pending(command_fail(cmd, LIGHTNINGD, + "Bad onchain_dev_memleak")); return; } peer_memleak_req_done(onchaind, found_leak, cmd); diff --git a/lightningd/ping.c b/lightningd/ping.c index a1671bd58..106d0b112 100644 --- a/lightningd/ping.c +++ b/lightningd/ping.c @@ -66,16 +66,17 @@ void ping_reply(struct subd *subd, const u8 *msg) assert(pc); if (!ok) - command_fail(pc->cmd, LIGHTNINGD, "Bad reply message"); + was_pending(command_fail(pc->cmd, LIGHTNINGD, + "Bad reply message")); else if (!sent) - command_fail(pc->cmd, LIGHTNINGD, "Unknown peer"); + was_pending(command_fail(pc->cmd, LIGHTNINGD, "Unknown peer")); else { struct json_stream *response = json_stream_success(pc->cmd); json_object_start(response, NULL); json_add_num(response, "totlen", totlen); json_object_end(response); - command_success(pc->cmd, response); + was_pending(command_success(pc->cmd, response)); } } diff --git a/tools/mockup.sh b/tools/mockup.sh index 9b23d0b0a..66192a598 100755 --- a/tools/mockup.sh +++ b/tools/mockup.sh @@ -33,5 +33,5 @@ for SYMBOL; do END=$(tail -n "+${LINE}" < "$FILE" | grep -n ';$'); NUM=${END%%:*} - tail -n "+${LINE}" < "$FILE" | head -n "$NUM" | sed 's/^extern *//' | sed 's/PRINTF_FMT([^)]*)//' | sed 's/NORETURN//g' | sed 's/LAST_ARG_NULL//g' | sed 's/,/ UNNEEDED,/g' | sed 's/\([a-z0-9A-Z*_]* [a-z0-9A-Z*_]*\));/\1 UNNEEDED);/' | sed "s/;\$/$STUB/" | sed 's/\s*$//' + tail -n "+${LINE}" < "$FILE" | head -n "$NUM" | sed 's/^extern *//' | sed 's/PRINTF_FMT([^)]*)//' | sed 's/NORETURN//g' | sed 's/LAST_ARG_NULL//g' | sed 's/WARN_UNUSED_RESULT//g' | sed 's/,/ UNNEEDED,/g' | sed 's/\([a-z0-9A-Z*_]* [a-z0-9A-Z*_]*\));/\1 UNNEEDED);/' | sed "s/;\$/$STUB/" | sed 's/\s*$//' done diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 565c6dbfb..500cc3ce4 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -71,10 +71,11 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED, json_add_string(response, "tx", withdraw->hextx); json_add_string(response, "txid", output); json_object_end(response); - command_success(cmd, response); + was_pending(command_success(cmd, response)); } else { - command_fail(cmd, LIGHTNINGD, - "Error broadcasting transaction: %s", output); + was_pending(command_fail(cmd, LIGHTNINGD, + "Error broadcasting transaction: %s", + output)); } } @@ -503,7 +504,7 @@ static void process_utxo_result(struct bitcoind *bitcoind, /* Complete the response */ json_array_end(rescan->response); json_object_end(rescan->response); - command_success(rescan->cmd, rescan->response); + was_pending(command_success(rescan->cmd, rescan->response)); } else { bitcoind_gettxout( bitcoind->ld->topology->bitcoind, &rescan->utxos[0]->txid,