diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index f9e9f9ac0..f36f9c0ef 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -1,11 +1,15 @@ #include #include +#include +#include #include #include #include #include #include +#include #include +#include #include #include #include @@ -14,14 +18,135 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include #include +struct close_command { + /* Inside struct lightningd close_commands. */ + struct list_node list; + /* Command structure. This is the parent of the close command. */ + struct command *cmd; + /* Channel being closed. */ + struct channel *channel; +}; + +/* Resolve a single close command. */ +static void +resolve_one_close_command(struct close_command *cc, bool cooperative) +{ + struct json_stream *result = json_stream_success(cc->cmd); + struct bitcoin_txid txid; + + bitcoin_txid(cc->channel->last_tx, &txid); + + json_add_tx(result, "tx", cc->channel->last_tx); + json_add_txid(result, "txid", &txid); + if (cooperative) + json_add_string(result, "type", "mutual"); + else + json_add_string(result, "type", "unilateral"); + + was_pending(command_success(cc->cmd, result)); +} + +/* Resolve a close command for a channel that will be closed soon. */ +void resolve_close_command(struct lightningd *ld, struct channel *channel, + bool cooperative) +{ + struct close_command *cc; + struct close_command *n; + + list_for_each_safe(&ld->close_commands, cc, n, list) { + if (cc->channel != channel) + continue; + resolve_one_close_command(cc, cooperative); + } +} + +/* Destroy the close command structure in reaction to the + * channel being destroyed. */ +static void +destroy_close_command_on_channel_destroy(struct channel *_ UNUSED, + struct close_command *cc) +{ + /* The cc has the command as parent, so resolving the + * command destroys the cc and triggers destroy_close_command. + * Clear the cc->channel first so that we will not try to + * remove a destructor. */ + cc->channel = NULL; + was_pending(command_fail(cc->cmd, LIGHTNINGD, + "Channel forgotten before proper close.")); +} + +/* Destroy the close command structure. */ +static void +destroy_close_command(struct close_command *cc) +{ + list_del(&cc->list); + /* If destroy_close_command_on_channel_destroy was + * triggered beforehand, it will have cleared + * the channel field, preventing us from removing it + * from an already-destroyed channel. */ + if (!cc->channel) + return; + tal_del_destructor2(cc->channel, + &destroy_close_command_on_channel_destroy, + cc); +} + +/* Handle timeout. */ +static void +close_command_timeout(struct close_command *cc) +{ + /* This will trigger drop_to_chain, which will trigger + * resolution of the command and destruction of the + * close_command. */ + json_notify_fmt(cc->cmd, LOG_INFORM, + "Timed out, forcing close."); + channel_fail_permanent(cc->channel, REASON_USER, + "Forcibly closed by `close` command timeout"); +} + +/* Construct a close command structure and add to ld. */ +static void +register_close_command(struct lightningd *ld, + struct command *cmd, + struct channel *channel, + unsigned int timeout) +{ + struct close_command *cc; + assert(channel); + + cc = tal(cmd, struct close_command); + list_add_tail(&ld->close_commands, &cc->list); + cc->cmd = cmd; + cc->channel = channel; + tal_add_destructor(cc, &destroy_close_command); + tal_add_destructor2(channel, + &destroy_close_command_on_channel_destroy, + cc); + + if (!channel->owner) { + char *msg = tal_strdup(tmpctx, "peer is offline, will negotiate once they reconnect"); + if (timeout) + tal_append_fmt(&msg, " (%u seconds before unilateral close)", + timeout); + json_notify_fmt(cmd, LOG_INFORM, "%s.", msg); + } + log_debug(ld->log, "close_command: timeout = %u", timeout); + if (timeout) + new_reltimer(ld->timers, cc, time_from_sec(timeout), + &close_command_timeout, cc); +} + static struct amount_sat calc_tx_fee(struct amount_sat sat_in, const struct bitcoin_tx *tx) { @@ -332,3 +457,304 @@ void peer_start_closingd(struct channel *channel, take(towire_gossipd_local_channel_close( tmpctx, channel->scid))); } + +static struct command_result *param_outpoint(struct command *cmd, + const char *name, + const char *buffer, + const jsmntok_t *tok, + struct bitcoin_outpoint **outp) +{ + *outp = tal(cmd, struct bitcoin_outpoint); + if (json_to_outpoint(buffer, tok, *outp)) + return NULL; + return command_fail_badparam(cmd, name, buffer, tok, + "should be a txid:outnum"); +} + +static struct command_result *param_feerate_range(struct command *cmd, + const char *name, + const char *buffer, + const jsmntok_t *tok, + u32 **feerate_range) +{ + struct command_result *ret; + u32 *rate; + + *feerate_range = tal_arr(cmd, u32, 2); + if (tok->type != JSMN_ARRAY || tok->size != 2) + return command_fail_badparam(cmd, name, buffer, tok, + "should be an array of 2 entries"); + + ret = param_feerate(cmd, name, buffer, tok+1, &rate); + if (ret) + return ret; + (*feerate_range)[0] = *rate; + ret = param_feerate(cmd, name, buffer, tok+2, &rate); + if (ret) + return ret; + (*feerate_range)[1] = *rate; + return NULL; +} + +static struct command_result *json_close(struct command *cmd, + const char *buffer, + const jsmntok_t *obj UNNEEDED, + const jsmntok_t *params) +{ + const jsmntok_t *idtok; + struct peer *peer; + struct channel *channel; + unsigned int *timeout; + const u8 *close_to_script = NULL; + bool close_script_set, wrong_funding_changed, *force_lease_close; + const char *fee_negotiation_step_str; + struct bitcoin_outpoint *wrong_funding; + u32 *feerate_range; + char* end; + bool anysegwit; + + if (!param(cmd, buffer, params, + p_req("id", param_tok, &idtok), + p_opt_def("unilateraltimeout", param_number, &timeout, + 48 * 3600), + p_opt("destination", param_bitcoin_address, &close_to_script), + p_opt("fee_negotiation_step", param_string, + &fee_negotiation_step_str), + p_opt("wrong_funding", param_outpoint, &wrong_funding), + p_opt_def("force_lease_closed", param_bool, + &force_lease_close, false), + p_opt("feerange", param_feerate_range, &feerate_range), + NULL)) + return command_param_failed(); + + peer = peer_from_json(cmd->ld, buffer, idtok); + if (peer) + channel = peer_active_channel(peer); + else { + struct command_result *res; + res = command_find_channel(cmd, buffer, idtok, &channel); + if (res) + return res; + } + + if (!channel && peer) { + struct uncommitted_channel *uc = peer->uncommitted_channel; + if (uc) { + /* Easy case: peer can simply be forgotten. */ + kill_uncommitted_channel(uc, "close command called"); + goto discard_unopened; + } + if ((channel = peer_unsaved_channel(peer))) { + channel_unsaved_close_conn(channel, + "close command called"); + goto discard_unopened; + } + return command_fail(cmd, LIGHTNINGD, + "Peer has no active channel"); + } + + if (!*force_lease_close && channel->opener != LOCAL + && get_block_height(cmd->ld->topology) < channel->lease_expiry) + return command_fail(cmd, LIGHTNINGD, + "Peer leased this channel from us, we" + " shouldn't close until lease has expired" + " (lease expires block %u," + " current block %u)", + channel->lease_expiry, + get_block_height(cmd->ld->topology)); + + /* If we've set a local shutdown script for this peer, and it's not the + * default upfront script, try to close to a different channel. + * Error is an operator error */ + if (close_to_script && channel->shutdown_scriptpubkey[LOCAL] + && !memeq(close_to_script, + tal_count(close_to_script), + channel->shutdown_scriptpubkey[LOCAL], + tal_count(channel->shutdown_scriptpubkey[LOCAL]))) { + u8 *default_close_to = p2wpkh_for_keyidx(tmpctx, cmd->ld, + channel->final_key_idx); + if (!memeq(default_close_to, tal_count(default_close_to), + channel->shutdown_scriptpubkey[LOCAL], + tal_count(channel->shutdown_scriptpubkey[LOCAL]))) { + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Destination address %s does not match " + "previous shutdown script %s", + tal_hex(tmpctx, channel->shutdown_scriptpubkey[LOCAL]), + tal_hex(tmpctx, close_to_script)); + } else { + channel->shutdown_scriptpubkey[LOCAL] = + tal_free(channel->shutdown_scriptpubkey[LOCAL]); + channel->shutdown_scriptpubkey[LOCAL] = + tal_steal(channel, close_to_script); + close_script_set = true; + } + } else if (close_to_script && !channel->shutdown_scriptpubkey[LOCAL]) { + channel->shutdown_scriptpubkey[LOCAL] + = tal_steal(channel, cast_const(u8 *, close_to_script)); + close_script_set = true; + } else if (!channel->shutdown_scriptpubkey[LOCAL]) { + channel->shutdown_scriptpubkey[LOCAL] + = p2wpkh_for_keyidx(channel, cmd->ld, channel->final_key_idx); + /* We don't save the default to disk */ + close_script_set = false; + } else + close_script_set = false; + + /* Don't send a scriptpubkey peer won't accept */ + anysegwit = feature_negotiated(cmd->ld->our_features, + channel->peer->their_features, + OPT_SHUTDOWN_ANYSEGWIT); + if (!valid_shutdown_scriptpubkey(channel->shutdown_scriptpubkey[LOCAL], + anysegwit)) { + /* Explicit check for future segwits. */ + if (!anysegwit && + valid_shutdown_scriptpubkey(channel->shutdown_scriptpubkey + [LOCAL], true)) { + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Peer does not allow v1+ shutdown addresses"); + } + + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Invalid close destination"); + } + + if (fee_negotiation_step_str == NULL) { + channel->closing_fee_negotiation_step = 50; + channel->closing_fee_negotiation_step_unit = + CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; + } else { + channel->closing_fee_negotiation_step = + strtoull(fee_negotiation_step_str, &end, 10); + + if (channel->closing_fee_negotiation_step == 0) + return command_fail( + cmd, JSONRPC2_INVALID_PARAMS, + "Wrong value given for fee_negotiation_step: " + "\"%s\", must be positive", + fee_negotiation_step_str); + else if (*end == '%') { + if (channel->closing_fee_negotiation_step > 100) + return command_fail( + cmd, JSONRPC2_INVALID_PARAMS, + "Wrong value given for " + "fee_negotiation_step: \"%s\", the " + "percentage should be between 1 and 100", + fee_negotiation_step_str); + channel->closing_fee_negotiation_step_unit = + CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; + } else if (*end == '\0') + channel->closing_fee_negotiation_step_unit = + CLOSING_FEE_NEGOTIATION_STEP_UNIT_SATOSHI; + else + return command_fail( + cmd, JSONRPC2_INVALID_PARAMS, + "Wrong value given for fee_negotiation_step: " + "\"%s\", should be an integer or an integer " + "followed by %%", + fee_negotiation_step_str); + } + + if (wrong_funding) { + if (!feature_negotiated(cmd->ld->our_features, + channel->peer->their_features, + OPT_SHUTDOWN_WRONG_FUNDING)) { + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "wrong_funding feature not negotiated" + " (we said %s, they said %s: try experimental-shutdown-wrong-funding?)", + feature_offered(cmd->ld->our_features + ->bits[INIT_FEATURE], + OPT_SHUTDOWN_WRONG_FUNDING) + ? "yes" : "no", + feature_offered(channel->peer->their_features, + OPT_SHUTDOWN_WRONG_FUNDING) + ? "yes" : "no"); + } + + wrong_funding_changed = true; + channel->shutdown_wrong_funding + = tal_steal(channel, wrong_funding); + } else { + if (channel->shutdown_wrong_funding) { + channel->shutdown_wrong_funding + = tal_free(channel->shutdown_wrong_funding); + wrong_funding_changed = true; + } else + wrong_funding_changed = false; + } + + /* May already be set by previous close cmd. */ + tal_free(channel->closing_feerate_range); + + /* Works fine if feerate_range is NULL */ + channel->closing_feerate_range = tal_steal(channel, feerate_range); + + /* Normal case. + * We allow states shutting down and sigexchange; a previous + * close command may have timed out, and this current command + * will continue waiting for the effects of the previous + * close command. */ + + /* If normal or locking in, transition to shutting down + * state. + * (if already shutting down or sigexchange, just keep + * waiting) */ + switch (channel->state) { + case CHANNELD_NORMAL: + case CHANNELD_AWAITING_LOCKIN: + case DUALOPEND_AWAITING_LOCKIN: + channel_set_state(channel, + channel->state, CHANNELD_SHUTTING_DOWN, + REASON_USER, + "User or plugin invoked close command"); + /* fallthrough */ + case CHANNELD_SHUTTING_DOWN: + if (channel->owner) { + u8 *msg; + if (streq(channel->owner->name, "dualopend")) { + msg = towire_dualopend_send_shutdown( + NULL, + channel->shutdown_scriptpubkey[LOCAL]); + } else + msg = towire_channeld_send_shutdown( + NULL, + channel->shutdown_scriptpubkey[LOCAL], + channel->shutdown_wrong_funding); + subd_send_msg(channel->owner, take(msg)); + } + + break; + case CLOSINGD_SIGEXCHANGE: + break; + default: + return command_fail(cmd, LIGHTNINGD, "Channel is in state %s", + channel_state_name(channel)); + } + + /* Register this command for later handling. */ + register_close_command(cmd->ld, cmd, channel, *timeout); + + /* If we set `channel->shutdown_scriptpubkey[LOCAL]` or + * changed shutdown_wrong_funding, save it. */ + if (close_script_set || wrong_funding_changed) + wallet_channel_save(cmd->ld->wallet, channel); + + /* Wait until close drops down to chain. */ + return command_still_pending(cmd); + +discard_unopened: { + struct json_stream *result = json_stream_success(cmd); + json_add_string(result, "type", "unopened"); + return command_success(cmd, result); + } +} + +static const struct json_command close_command = { + "close", + "channels", + json_close, + "Close the channel with {id} " + "(either peer ID, channel ID, or short channel ID). " + "Force a unilateral close after {unilateraltimeout} seconds (default 48h). " + "If {destination} address is provided, will be used as output address." +}; +AUTODATA(json_command, &close_command); diff --git a/lightningd/closing_control.h b/lightningd/closing_control.h index 0ee6afb29..8991b4443 100644 --- a/lightningd/closing_control.h +++ b/lightningd/closing_control.h @@ -2,10 +2,15 @@ #define LIGHTNING_LIGHTNINGD_CLOSING_CONTROL_H #include "config.h" #include +#include struct channel; +struct lightningd; struct per_peer_state; +void resolve_close_command(struct lightningd *ld, struct channel *channel, + bool cooperative); + void peer_start_closingd(struct channel *channel, struct per_peer_state *pps); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 39481b031..7fd89b78d 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include @@ -65,15 +64,6 @@ #include #include -struct close_command { - /* Inside struct lightningd close_commands. */ - struct list_node list; - /* Command structure. This is the parent of the close command. */ - struct command *cmd; - /* Channel being closed. */ - struct channel *channel; -}; - static void destroy_peer(struct peer *peer) { list_del_from(&peer->ld->peers, &peer->list); @@ -218,116 +208,6 @@ static void remove_sig(struct bitcoin_tx *signed_tx) bitcoin_tx_input_set_witness(signed_tx, 0, NULL); } -/* Resolve a single close command. */ -static void -resolve_one_close_command(struct close_command *cc, bool cooperative) -{ - struct json_stream *result = json_stream_success(cc->cmd); - struct bitcoin_txid txid; - - bitcoin_txid(cc->channel->last_tx, &txid); - - json_add_tx(result, "tx", cc->channel->last_tx); - json_add_txid(result, "txid", &txid); - if (cooperative) - json_add_string(result, "type", "mutual"); - else - json_add_string(result, "type", "unilateral"); - - was_pending(command_success(cc->cmd, result)); -} - -/* Resolve a close command for a channel that will be closed soon. */ -static void -resolve_close_command(struct lightningd *ld, struct channel *channel, - bool cooperative) -{ - struct close_command *cc; - struct close_command *n; - - list_for_each_safe (&ld->close_commands, cc, n, list) { - if (cc->channel != channel) - continue; - resolve_one_close_command(cc, cooperative); - } -} - -/* Destroy the close command structure in reaction to the - * channel being destroyed. */ -static void -destroy_close_command_on_channel_destroy(struct channel *_ UNUSED, - struct close_command *cc) -{ - /* The cc has the command as parent, so resolving the - * command destroys the cc and triggers destroy_close_command. - * Clear the cc->channel first so that we will not try to - * remove a destructor. */ - cc->channel = NULL; - was_pending(command_fail(cc->cmd, LIGHTNINGD, - "Channel forgotten before proper close.")); -} - -/* Destroy the close command structure. */ -static void -destroy_close_command(struct close_command *cc) -{ - list_del(&cc->list); - /* If destroy_close_command_on_channel_destroy was - * triggered beforehand, it will have cleared - * the channel field, preventing us from removing it - * from an already-destroyed channel. */ - if (!cc->channel) - return; - tal_del_destructor2(cc->channel, - &destroy_close_command_on_channel_destroy, - cc); -} - -/* Handle timeout. */ -static void -close_command_timeout(struct close_command *cc) -{ - /* This will trigger drop_to_chain, which will trigger - * resolution of the command and destruction of the - * close_command. */ - json_notify_fmt(cc->cmd, LOG_INFORM, - "Timed out, forcing close."); - channel_fail_permanent(cc->channel, REASON_USER, - "Forcibly closed by `close` command timeout"); -} - -/* Construct a close command structure and add to ld. */ -static void -register_close_command(struct lightningd *ld, - struct command *cmd, - struct channel *channel, - unsigned int timeout) -{ - struct close_command *cc; - assert(channel); - - cc = tal(cmd, struct close_command); - list_add_tail(&ld->close_commands, &cc->list); - cc->cmd = cmd; - cc->channel = channel; - tal_add_destructor(cc, &destroy_close_command); - tal_add_destructor2(channel, - &destroy_close_command_on_channel_destroy, - cc); - - if (!channel->owner) { - char *msg = tal_strdup(tmpctx, "peer is offline, will negotiate once they reconnect"); - if (timeout) - tal_append_fmt(&msg, " (%u seconds before unilateral close)", - timeout); - json_notify_fmt(cmd, LOG_INFORM, "%s.", msg); - } - log_debug(ld->log, "close_command: timeout = %u", timeout); - if (timeout) - new_reltimer(ld->timers, cc, time_from_sec(timeout), - &close_command_timeout, cc); -} - static bool invalid_last_tx(const struct bitcoin_tx *tx) { /* This problem goes back further, but was discovered just before the @@ -1610,7 +1490,7 @@ static const struct json_command listpeers_command = { /* Comment added to satisfice AUTODATA */ AUTODATA(json_command, &listpeers_command); -static struct command_result * +struct command_result * command_find_channel(struct command *cmd, const char *buffer, const jsmntok_t *tok, struct channel **channel) @@ -1647,307 +1527,6 @@ command_find_channel(struct command *cmd, } } -static struct command_result *param_outpoint(struct command *cmd, - const char *name, - const char *buffer, - const jsmntok_t *tok, - struct bitcoin_outpoint **outp) -{ - *outp = tal(cmd, struct bitcoin_outpoint); - if (json_to_outpoint(buffer, tok, *outp)) - return NULL; - return command_fail_badparam(cmd, name, buffer, tok, - "should be a txid:outnum"); -} - -static struct command_result *param_feerate_range(struct command *cmd, - const char *name, - const char *buffer, - const jsmntok_t *tok, - u32 **feerate_range) -{ - struct command_result *ret; - u32 *rate; - - *feerate_range = tal_arr(cmd, u32, 2); - if (tok->type != JSMN_ARRAY || tok->size != 2) - return command_fail_badparam(cmd, name, buffer, tok, - "should be an array of 2 entries"); - - ret = param_feerate(cmd, name, buffer, tok+1, &rate); - if (ret) - return ret; - (*feerate_range)[0] = *rate; - ret = param_feerate(cmd, name, buffer, tok+2, &rate); - if (ret) - return ret; - (*feerate_range)[1] = *rate; - return NULL; -} - -static struct command_result *json_close(struct command *cmd, - const char *buffer, - const jsmntok_t *obj UNNEEDED, - const jsmntok_t *params) -{ - const jsmntok_t *idtok; - struct peer *peer; - struct channel *channel COMPILER_WANTS_INIT("gcc 7.3.0 fails, 8.3 OK"); - unsigned int *timeout; - const u8 *close_to_script = NULL; - bool close_script_set, wrong_funding_changed, *force_lease_close; - const char *fee_negotiation_step_str; - struct bitcoin_outpoint *wrong_funding; - u32 *feerate_range; - char* end; - bool anysegwit; - - if (!param(cmd, buffer, params, - p_req("id", param_tok, &idtok), - p_opt_def("unilateraltimeout", param_number, &timeout, - 48 * 3600), - p_opt("destination", param_bitcoin_address, &close_to_script), - p_opt("fee_negotiation_step", param_string, - &fee_negotiation_step_str), - p_opt("wrong_funding", param_outpoint, &wrong_funding), - p_opt_def("force_lease_closed", param_bool, - &force_lease_close, false), - p_opt("feerange", param_feerate_range, &feerate_range), - NULL)) - return command_param_failed(); - - peer = peer_from_json(cmd->ld, buffer, idtok); - if (peer) - channel = peer_active_channel(peer); - else { - struct command_result *res; - res = command_find_channel(cmd, buffer, idtok, &channel); - if (res) - return res; - } - - if (!channel && peer) { - struct uncommitted_channel *uc = peer->uncommitted_channel; - if (uc) { - /* Easy case: peer can simply be forgotten. */ - kill_uncommitted_channel(uc, "close command called"); - goto discard_unopened; - } - if ((channel = peer_unsaved_channel(peer))) { - channel_unsaved_close_conn(channel, - "close command called"); - goto discard_unopened; - } - return command_fail(cmd, LIGHTNINGD, - "Peer has no active channel"); - } - - if (!*force_lease_close && channel->opener != LOCAL - && get_block_height(cmd->ld->topology) < channel->lease_expiry) - return command_fail(cmd, LIGHTNINGD, - "Peer leased this channel from us, we" - " shouldn't close until lease has expired" - " (lease expires block %u," - " current block %u)", - channel->lease_expiry, - get_block_height(cmd->ld->topology)); - - /* If we've set a local shutdown script for this peer, and it's not the - * default upfront script, try to close to a different channel. - * Error is an operator error */ - if (close_to_script && channel->shutdown_scriptpubkey[LOCAL] - && !memeq(close_to_script, - tal_count(close_to_script), - channel->shutdown_scriptpubkey[LOCAL], - tal_count(channel->shutdown_scriptpubkey[LOCAL]))) { - u8 *default_close_to = p2wpkh_for_keyidx(tmpctx, cmd->ld, - channel->final_key_idx); - if (!memeq(default_close_to, tal_count(default_close_to), - channel->shutdown_scriptpubkey[LOCAL], - tal_count(channel->shutdown_scriptpubkey[LOCAL]))) { - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Destination address %s does not match " - "previous shutdown script %s", - tal_hex(tmpctx, channel->shutdown_scriptpubkey[LOCAL]), - tal_hex(tmpctx, close_to_script)); - } else { - channel->shutdown_scriptpubkey[LOCAL] = - tal_free(channel->shutdown_scriptpubkey[LOCAL]); - channel->shutdown_scriptpubkey[LOCAL] = - tal_steal(channel, close_to_script); - close_script_set = true; - } - } else if (close_to_script && !channel->shutdown_scriptpubkey[LOCAL]) { - channel->shutdown_scriptpubkey[LOCAL] - = tal_steal(channel, cast_const(u8 *, close_to_script)); - close_script_set = true; - } else if (!channel->shutdown_scriptpubkey[LOCAL]) { - channel->shutdown_scriptpubkey[LOCAL] - = p2wpkh_for_keyidx(channel, cmd->ld, channel->final_key_idx); - /* We don't save the default to disk */ - close_script_set = false; - } else - close_script_set = false; - - /* Don't send a scriptpubkey peer won't accept */ - anysegwit = feature_negotiated(cmd->ld->our_features, - channel->peer->their_features, - OPT_SHUTDOWN_ANYSEGWIT); - if (!valid_shutdown_scriptpubkey(channel->shutdown_scriptpubkey[LOCAL], - anysegwit)) { - /* Explicit check for future segwits. */ - if (!anysegwit && - valid_shutdown_scriptpubkey(channel->shutdown_scriptpubkey - [LOCAL], true)) { - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Peer does not allow v1+ shutdown addresses"); - } - - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Invalid close destination"); - } - - if (fee_negotiation_step_str == NULL) { - channel->closing_fee_negotiation_step = 50; - channel->closing_fee_negotiation_step_unit = - CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; - } else { - channel->closing_fee_negotiation_step = - strtoull(fee_negotiation_step_str, &end, 10); - - if (channel->closing_fee_negotiation_step == 0) - return command_fail( - cmd, JSONRPC2_INVALID_PARAMS, - "Wrong value given for fee_negotiation_step: " - "\"%s\", must be positive", - fee_negotiation_step_str); - else if (*end == '%') { - if (channel->closing_fee_negotiation_step > 100) - return command_fail( - cmd, JSONRPC2_INVALID_PARAMS, - "Wrong value given for " - "fee_negotiation_step: \"%s\", the " - "percentage should be between 1 and 100", - fee_negotiation_step_str); - channel->closing_fee_negotiation_step_unit = - CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; - } else if (*end == '\0') - channel->closing_fee_negotiation_step_unit = - CLOSING_FEE_NEGOTIATION_STEP_UNIT_SATOSHI; - else - return command_fail( - cmd, JSONRPC2_INVALID_PARAMS, - "Wrong value given for fee_negotiation_step: " - "\"%s\", should be an integer or an integer " - "followed by %%", - fee_negotiation_step_str); - } - - if (wrong_funding) { - if (!feature_negotiated(cmd->ld->our_features, - channel->peer->their_features, - OPT_SHUTDOWN_WRONG_FUNDING)) { - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "wrong_funding feature not negotiated" - " (we said %s, they said %s: try experimental-shutdown-wrong-funding?)", - feature_offered(cmd->ld->our_features - ->bits[INIT_FEATURE], - OPT_SHUTDOWN_WRONG_FUNDING) - ? "yes" : "no", - feature_offered(channel->peer->their_features, - OPT_SHUTDOWN_WRONG_FUNDING) - ? "yes" : "no"); - } - - wrong_funding_changed = true; - channel->shutdown_wrong_funding - = tal_steal(channel, wrong_funding); - } else { - if (channel->shutdown_wrong_funding) { - channel->shutdown_wrong_funding - = tal_free(channel->shutdown_wrong_funding); - wrong_funding_changed = true; - } else - wrong_funding_changed = false; - } - - /* May already be set by previous close cmd. */ - tal_free(channel->closing_feerate_range); - - /* Works fine if feerate_range is NULL */ - channel->closing_feerate_range = tal_steal(channel, feerate_range); - - /* Normal case. - * We allow states shutting down and sigexchange; a previous - * close command may have timed out, and this current command - * will continue waiting for the effects of the previous - * close command. */ - - /* If normal or locking in, transition to shutting down - * state. - * (if already shutting down or sigexchange, just keep - * waiting) */ - switch (channel->state) { - case CHANNELD_NORMAL: - case CHANNELD_AWAITING_LOCKIN: - case DUALOPEND_AWAITING_LOCKIN: - channel_set_state(channel, - channel->state, CHANNELD_SHUTTING_DOWN, - REASON_USER, - "User or plugin invoked close command"); - /* fallthrough */ - case CHANNELD_SHUTTING_DOWN: - if (channel->owner) { - u8 *msg; - if (streq(channel->owner->name, "dualopend")) { - msg = towire_dualopend_send_shutdown( - NULL, - channel->shutdown_scriptpubkey[LOCAL]); - } else - msg = towire_channeld_send_shutdown( - NULL, - channel->shutdown_scriptpubkey[LOCAL], - channel->shutdown_wrong_funding); - subd_send_msg(channel->owner, take(msg)); - } - - break; - case CLOSINGD_SIGEXCHANGE: - break; - default: - return command_fail(cmd, LIGHTNINGD, "Channel is in state %s", - channel_state_name(channel)); - } - - /* Register this command for later handling. */ - register_close_command(cmd->ld, cmd, channel, *timeout); - - /* If we set `channel->shutdown_scriptpubkey[LOCAL]` or - * changed shutdown_wrong_funding, save it. */ - if (close_script_set || wrong_funding_changed) - wallet_channel_save(cmd->ld->wallet, channel); - - /* Wait until close drops down to chain. */ - return command_still_pending(cmd); - -discard_unopened: { - struct json_stream *result = json_stream_success(cmd); - json_add_string(result, "type", "unopened"); - return command_success(cmd, result); - } -} - -static const struct json_command close_command = { - "close", - "channels", - json_close, - "Close the channel with {id} " - "(either peer ID, channel ID, or short channel ID). " - "Force a unilateral close after {unilateraltimeout} seconds (default 48h). " - "If {destination} address is provided, will be used as output address." -}; -AUTODATA(json_command, &close_command); - static void activate_peer(struct peer *peer, u32 delay) { u8 *msg; diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 419ddfbeb..85377efdb 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -109,4 +109,11 @@ void handle_custommsg_in(struct lightningd *ld, const struct node_id *peer_id, void waitblockheight_notify_new_block(struct lightningd *ld, u32 block_height); + +/* JSON parameter by channel_id or scid */ +struct command_result * +command_find_channel(struct command *cmd, + const char *buffer, const jsmntok_t *tok, + struct channel **channel); + #endif /* LIGHTNING_LIGHTNINGD_PEER_CONTROL_H */ diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 9e36d9e19..30b5d883c 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -102,13 +102,6 @@ void channel_set_last_tx(struct channel *channel UNNEEDED, const struct bitcoin_signature *sig UNNEEDED, enum wallet_tx_type type UNNEEDED) { fprintf(stderr, "channel_set_last_tx called!\n"); abort(); } -/* Generated stub for channel_set_state */ -void channel_set_state(struct channel *channel UNNEEDED, - enum channel_state old_state UNNEEDED, - enum channel_state state UNNEEDED, - enum state_change reason UNNEEDED, - char *why UNNEEDED) -{ fprintf(stderr, "channel_set_state called!\n"); abort(); } /* Generated stub for channel_state_name */ const char *channel_state_name(const struct channel *channel UNNEEDED) { fprintf(stderr, "channel_state_name called!\n"); abort(); } @@ -197,9 +190,6 @@ bool feature_is_set(const u8 *features UNNEEDED, size_t bit UNNEEDED) bool feature_negotiated(const struct feature_set *our_features UNNEEDED, const u8 *their_features UNNEEDED, size_t f UNNEEDED) { fprintf(stderr, "feature_negotiated called!\n"); abort(); } -/* Generated stub for feature_offered */ -bool feature_offered(const u8 *features UNNEEDED, size_t f UNNEEDED) -{ fprintf(stderr, "feature_offered called!\n"); abort(); } /* Generated stub for find_plugin_for_command */ struct plugin *find_plugin_for_command(struct lightningd *ld UNNEEDED, const char *cmd_name UNNEEDED) @@ -378,12 +368,6 @@ void json_array_start(struct json_stream *js UNNEEDED, const char *fieldname UNN char *json_member_direct(struct json_stream *js UNNEEDED, const char *fieldname UNNEEDED, size_t extra UNNEEDED) { fprintf(stderr, "json_member_direct called!\n"); abort(); } -/* Generated stub for json_notify_fmt */ -void json_notify_fmt(struct command *cmd UNNEEDED, - enum log_level level UNNEEDED, - const char *fmt UNNEEDED, ...) - -{ fprintf(stderr, "json_notify_fmt called!\n"); abort(); } /* Generated stub for json_object_end */ void json_object_end(struct json_stream *js UNNEEDED) { fprintf(stderr, "json_object_end called!\n"); abort(); } @@ -412,10 +396,6 @@ bool json_to_msat(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, struct node_id *id UNNEEDED) { fprintf(stderr, "json_to_node_id called!\n"); abort(); } -/* Generated stub for json_to_outpoint */ -bool json_to_outpoint(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, - struct bitcoin_outpoint *op UNNEEDED) -{ fprintf(stderr, "json_to_outpoint called!\n"); abort(); } /* Generated stub for json_to_short_channel_id */ bool json_to_short_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, struct short_channel_id *scid UNNEEDED) @@ -511,13 +491,6 @@ struct command_result *param_bin_from_hex(struct command *cmd UNNEEDED, const ch const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, u8 **bin UNNEEDED) { fprintf(stderr, "param_bin_from_hex called!\n"); abort(); } -/* Generated stub for param_bitcoin_address */ -struct command_result *param_bitcoin_address(struct command *cmd UNNEEDED, - const char *name UNNEEDED, - const char *buffer UNNEEDED, - const jsmntok_t *tok UNNEEDED, - const u8 **scriptpubkey UNNEEDED) -{ fprintf(stderr, "param_bitcoin_address called!\n"); abort(); } /* Generated stub for param_bool */ struct command_result *param_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, @@ -537,11 +510,6 @@ struct command_result *param_escaped_string(struct command *cmd UNNEEDED, const jsmntok_t *tok UNNEEDED, const char **str UNNEEDED) { fprintf(stderr, "param_escaped_string called!\n"); abort(); } -/* Generated stub for param_feerate */ -struct command_result *param_feerate(struct command *cmd UNNEEDED, const char *name UNNEEDED, - const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, - u32 **feerate UNNEEDED) -{ fprintf(stderr, "param_feerate called!\n"); abort(); } /* Generated stub for param_label */ struct command_result *param_label(struct command *cmd UNNEEDED, const char *name UNNEEDED, const char * buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, @@ -588,11 +556,6 @@ struct command_result *param_string(struct command *cmd UNNEEDED, const char *na const char * buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char **str UNNEEDED) { fprintf(stderr, "param_string called!\n"); abort(); } -/* Generated stub for param_tok */ -struct command_result *param_tok(struct command *cmd UNNEEDED, const char *name UNNEEDED, - const char *buffer UNNEEDED, const jsmntok_t * tok UNNEEDED, - const jsmntok_t **out UNNEEDED) -{ fprintf(stderr, "param_tok called!\n"); abort(); } /* Generated stub for param_u64 */ struct command_result *param_u64(struct command *cmd UNNEEDED, const char *name UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, @@ -644,6 +607,10 @@ bool plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook void plugin_request_send(struct plugin *plugin UNNEEDED, struct jsonrpc_request *req TAKES UNNEEDED) { fprintf(stderr, "plugin_request_send called!\n"); abort(); } +/* Generated stub for resolve_close_command */ +void resolve_close_command(struct lightningd *ld UNNEEDED, struct channel *channel UNNEEDED, + bool cooperative UNNEEDED) +{ fprintf(stderr, "resolve_close_command called!\n"); abort(); } /* Generated stub for subd_req_ */ void subd_req_(const tal_t *ctx UNNEEDED, struct subd *sd UNNEEDED, @@ -670,9 +637,6 @@ u8 *towire_channeld_dev_memleak(const tal_t *ctx UNNEEDED) /* Generated stub for towire_channeld_dev_reenable_commit */ u8 *towire_channeld_dev_reenable_commit(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channeld_dev_reenable_commit called!\n"); abort(); } -/* Generated stub for towire_channeld_send_shutdown */ -u8 *towire_channeld_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *shutdown_scriptpubkey UNNEEDED, const struct bitcoin_outpoint *wrong_funding UNNEEDED) -{ fprintf(stderr, "towire_channeld_send_shutdown called!\n"); abort(); } /* Generated stub for towire_channeld_specific_feerates */ u8 *towire_channeld_specific_feerates(const tal_t *ctx UNNEEDED, u32 feerate_base UNNEEDED, u32 feerate_ppm UNNEEDED) { fprintf(stderr, "towire_channeld_specific_feerates called!\n"); abort(); } @@ -682,9 +646,6 @@ u8 *towire_connectd_connect_to_peer(const tal_t *ctx UNNEEDED, const struct node /* Generated stub for towire_connectd_peer_final_msg */ u8 *towire_connectd_peer_final_msg(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const struct per_peer_state *pps UNNEEDED, const u8 *msg UNNEEDED) { fprintf(stderr, "towire_connectd_peer_final_msg called!\n"); abort(); } -/* Generated stub for towire_dualopend_send_shutdown */ -u8 *towire_dualopend_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *shutdown_scriptpubkey UNNEEDED) -{ fprintf(stderr, "towire_dualopend_send_shutdown called!\n"); abort(); } /* Generated stub for towire_errorfmt */ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, @@ -710,10 +671,6 @@ u8 *towire_warningfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "towire_warningfmt called!\n"); abort(); } -/* Generated stub for valid_shutdown_scriptpubkey */ -bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey UNNEEDED, - bool anysegwit UNNEEDED) -{ fprintf(stderr, "valid_shutdown_scriptpubkey called!\n"); abort(); } /* Generated stub for version */ const char *version(void) { fprintf(stderr, "version called!\n"); abort(); } diff --git a/wallet/db_postgres_sqlgen.c b/wallet/db_postgres_sqlgen.c index ce2e74609..2e3ce8481 100644 --- a/wallet/db_postgres_sqlgen.c +++ b/wallet/db_postgres_sqlgen.c @@ -2074,4 +2074,4 @@ struct db_query db_postgres_queries[] = { #endif /* LIGHTNINGD_WALLET_GEN_DB_POSTGRES */ -// SHA256STAMP:a70af01d3b2f3a7003703b7feb0b2ef12359e0d2850bde1697a53780e2f5dbae +// SHA256STAMP:e356b7327b760559f9a7c31a7ea4a09d50194c7aacc6daef6ba9fb5caf43ae83 diff --git a/wallet/db_sqlite3_sqlgen.c b/wallet/db_sqlite3_sqlgen.c index c0ff23316..d8d886dcb 100644 --- a/wallet/db_sqlite3_sqlgen.c +++ b/wallet/db_sqlite3_sqlgen.c @@ -2074,4 +2074,4 @@ struct db_query db_sqlite3_queries[] = { #endif /* LIGHTNINGD_WALLET_GEN_DB_SQLITE3 */ -// SHA256STAMP:a70af01d3b2f3a7003703b7feb0b2ef12359e0d2850bde1697a53780e2f5dbae +// SHA256STAMP:e356b7327b760559f9a7c31a7ea4a09d50194c7aacc6daef6ba9fb5caf43ae83 diff --git a/wallet/statements_gettextgen.po b/wallet/statements_gettextgen.po index 570d63d84..8933f0207 100644 --- a/wallet/statements_gettextgen.po +++ b/wallet/statements_gettextgen.po @@ -1362,11 +1362,11 @@ msgstr "" msgid "not a valid SQL statement" msgstr "" -#: wallet/test/run-wallet.c:1541 +#: wallet/test/run-wallet.c:1508 msgid "SELECT COUNT(1) FROM channel_funding_inflights WHERE channel_id = ?;" msgstr "" -#: wallet/test/run-wallet.c:1754 +#: wallet/test/run-wallet.c:1721 msgid "INSERT INTO channels (id) VALUES (1);" msgstr "" -# SHA256STAMP:651a6c15e8780351cd32a4e6dc3011b1c5fc2af6308b0e65a442dda2a3874e19 +# SHA256STAMP:0b3b17a4eb95067fdebc9d90c962c46e40fdef2002f92856cc31800ab37fbe59 diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index dc1417a5e..ae0069431 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -381,12 +381,6 @@ void json_array_start(struct json_stream *js UNNEEDED, const char *fieldname UNN const jsmntok_t *json_get_member(const char *buffer UNNEEDED, const jsmntok_t tok[] UNNEEDED, const char *label UNNEEDED) { fprintf(stderr, "json_get_member called!\n"); abort(); } -/* Generated stub for json_notify_fmt */ -void json_notify_fmt(struct command *cmd UNNEEDED, - enum log_level level UNNEEDED, - const char *fmt UNNEEDED, ...) - -{ fprintf(stderr, "json_notify_fmt called!\n"); abort(); } /* Generated stub for json_object_end */ void json_object_end(struct json_stream *js UNNEEDED) { fprintf(stderr, "json_object_end called!\n"); abort(); } @@ -407,10 +401,6 @@ bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool json_to_number(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, unsigned int *num UNNEEDED) { fprintf(stderr, "json_to_number called!\n"); abort(); } -/* Generated stub for json_to_outpoint */ -bool json_to_outpoint(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, - struct bitcoin_outpoint *op UNNEEDED) -{ fprintf(stderr, "json_to_outpoint called!\n"); abort(); } /* Generated stub for json_to_preimage */ bool json_to_preimage(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, struct preimage *preimage UNNEEDED) { fprintf(stderr, "json_to_preimage called!\n"); abort(); } @@ -549,13 +539,6 @@ struct command_result *param_bin_from_hex(struct command *cmd UNNEEDED, const ch const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, u8 **bin UNNEEDED) { fprintf(stderr, "param_bin_from_hex called!\n"); abort(); } -/* Generated stub for param_bitcoin_address */ -struct command_result *param_bitcoin_address(struct command *cmd UNNEEDED, - const char *name UNNEEDED, - const char *buffer UNNEEDED, - const jsmntok_t *tok UNNEEDED, - const u8 **scriptpubkey UNNEEDED) -{ fprintf(stderr, "param_bitcoin_address called!\n"); abort(); } /* Generated stub for param_bool */ struct command_result *param_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, @@ -568,11 +551,6 @@ struct command_result *param_channel_id(struct command *cmd UNNEEDED, const jsmntok_t *tok UNNEEDED, struct channel_id **cid UNNEEDED) { fprintf(stderr, "param_channel_id called!\n"); abort(); } -/* Generated stub for param_feerate */ -struct command_result *param_feerate(struct command *cmd UNNEEDED, const char *name UNNEEDED, - const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, - u32 **feerate UNNEEDED) -{ fprintf(stderr, "param_feerate called!\n"); abort(); } /* Generated stub for param_loglevel */ struct command_result *param_loglevel(struct command *cmd UNNEEDED, const char *name UNNEEDED, @@ -609,11 +587,6 @@ struct command_result *param_string(struct command *cmd UNNEEDED, const char *na const char * buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char **str UNNEEDED) { fprintf(stderr, "param_string called!\n"); abort(); } -/* Generated stub for param_tok */ -struct command_result *param_tok(struct command *cmd UNNEEDED, const char *name UNNEEDED, - const char *buffer UNNEEDED, const jsmntok_t * tok UNNEEDED, - const jsmntok_t **out UNNEEDED) -{ fprintf(stderr, "param_tok called!\n"); abort(); } /* Generated stub for parse_onionpacket */ struct onionpacket *parse_onionpacket(const tal_t *ctx UNNEEDED, const u8 *src UNNEEDED, @@ -680,6 +653,10 @@ struct route_step *process_onionpacket( bool has_realm ) { fprintf(stderr, "process_onionpacket called!\n"); abort(); } +/* Generated stub for resolve_close_command */ +void resolve_close_command(struct lightningd *ld UNNEEDED, struct channel *channel UNNEEDED, + bool cooperative UNNEEDED) +{ fprintf(stderr, "resolve_close_command called!\n"); abort(); } /* Generated stub for serialize_onionpacket */ u8 *serialize_onionpacket( const tal_t *ctx UNNEEDED, @@ -738,9 +715,6 @@ u8 *towire_channeld_got_revoke_reply(const tal_t *ctx UNNEEDED) /* Generated stub for towire_channeld_offer_htlc */ u8 *towire_channeld_offer_htlc(const tal_t *ctx UNNEEDED, struct amount_msat amount_msat UNNEEDED, u32 cltv_expiry UNNEEDED, const struct sha256 *payment_hash UNNEEDED, const u8 onion_routing_packet[1366] UNNEEDED, const struct pubkey *blinding UNNEEDED) { fprintf(stderr, "towire_channeld_offer_htlc called!\n"); abort(); } -/* Generated stub for towire_channeld_send_shutdown */ -u8 *towire_channeld_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *shutdown_scriptpubkey UNNEEDED, const struct bitcoin_outpoint *wrong_funding UNNEEDED) -{ fprintf(stderr, "towire_channeld_send_shutdown called!\n"); abort(); } /* Generated stub for towire_channeld_sending_commitsig_reply */ u8 *towire_channeld_sending_commitsig_reply(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channeld_sending_commitsig_reply called!\n"); abort(); } @@ -759,9 +733,6 @@ u8 *towire_connectd_peer_final_msg(const tal_t *ctx UNNEEDED, const struct node_ /* Generated stub for towire_custommsg_out */ u8 *towire_custommsg_out(const tal_t *ctx UNNEEDED, const u8 *msg UNNEEDED) { fprintf(stderr, "towire_custommsg_out called!\n"); abort(); } -/* Generated stub for towire_dualopend_send_shutdown */ -u8 *towire_dualopend_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *shutdown_scriptpubkey UNNEEDED) -{ fprintf(stderr, "towire_dualopend_send_shutdown called!\n"); abort(); } /* Generated stub for towire_errorfmt */ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, @@ -835,10 +806,6 @@ u8 *towire_warningfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "towire_warningfmt called!\n"); abort(); } -/* Generated stub for valid_shutdown_scriptpubkey */ -bool valid_shutdown_scriptpubkey(const u8 *scriptpubkey UNNEEDED, - bool anysegwit UNNEEDED) -{ fprintf(stderr, "valid_shutdown_scriptpubkey called!\n"); abort(); } /* Generated stub for watch_txid */ struct txwatch *watch_txid(const tal_t *ctx UNNEEDED, struct chain_topology *topo UNNEEDED,