From f3b54a510be8d16eb6193dd47b4bca8a53ea5204 Mon Sep 17 00:00:00 2001 From: niftynei Date: Fri, 2 Jul 2021 15:38:59 -0500 Subject: [PATCH] close: param to force-close a leased channel By default, we won't close a channel that we leased to a peer. You can override this with the `force_lease_closed` flag. Changelog-Added: JSON-RPC: close now has parameter to force close a leased channel (option_will_fund) --- channeld/channeld.c | 3 +++ contrib/pyln-client/pyln/client/lightning.py | 10 ++++++++-- doc/lightning-close.7 | 9 +++++++-- doc/lightning-close.7.md | 7 ++++++- lightningd/peer_control.c | 13 ++++++++++++- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 410dc74ce..6b08faca8 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1997,6 +1997,9 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) peer_failed_warn(peer->pps, &peer->channel_id, "Bad shutdown %s", tal_hex(peer, shutdown)); + /* FIXME: We shouldn't let them initiate a shutdown while the + * channel is active (if we leased funds) */ + /* BOLT #2: * * - if both nodes advertised the `option_upfront_shutdown_script` diff --git a/contrib/pyln-client/pyln/client/lightning.py b/contrib/pyln-client/pyln/client/lightning.py index 74bf55938..4f3a4549f 100644 --- a/contrib/pyln-client/pyln/client/lightning.py +++ b/contrib/pyln-client/pyln/client/lightning.py @@ -515,17 +515,23 @@ class LightningRpc(UnixDomainSocketRpc): payload.update({k: v for k, v in kwargs.items()}) return self.call("check", payload) - def close(self, peer_id, unilateraltimeout=None, destination=None, fee_negotiation_step=None): + def close(self, peer_id, unilateraltimeout=None, destination=None, fee_negotiation_step=None, force_lease_closed=False): """ Close the channel with peer {id}, forcing a unilateral close after {unilateraltimeout} seconds if non-zero, and the to-local output will be sent to {destination}. + + If channel funds have been leased to the peer and the + lease has not yet expired, you can force a close with + {force_lease_closed}. Note that your funds will still be + locked until the lease expires. """ payload = { "id": peer_id, "unilateraltimeout": unilateraltimeout, "destination": destination, - "fee_negotiation_step": fee_negotiation_step + "fee_negotiation_step": fee_negotiation_step, + "force_lease_closed": force_lease_closed, } return self.call("close", payload) diff --git a/doc/lightning-close.7 b/doc/lightning-close.7 index 40a770203..6f8c2837a 100644 --- a/doc/lightning-close.7 +++ b/doc/lightning-close.7 @@ -3,7 +3,7 @@ lightning-close - Command for closing channels with direct peers .SH SYNOPSIS -\fBclose\fR \fIid\fR [\fIunilateraltimeout\fR] [\fIdestination\fR] [\fIfee_negotiation_step\fR] [\fIwrong_funding\\\fR] +\fBclose\fR \fIid\fR [\fIunilateraltimeout\fR] [\fIdestination\fR] [\fIfee_negotiation_step\fR] [\fIwrong_funding\fR] [\fIforce_lease_closed\fR] .SH DESCRIPTION @@ -67,6 +67,11 @@ allowed if this peer opened the channel and the channel is unused: it can rescue openings which have been manually miscreated\. +\fIforce_lease_closed\fR if the channel has funds leased to the peer +(option_will_fund), we prevent initiation of a mutual close +unless this flag is passed in\. Defaults to false\. + + The peer needs to be live and connected in order to negotiate a mutual close\. The default of unilaterally closing after 48 hours is usually a reasonable indication that you can no longer contact the peer\. @@ -123,4 +128,4 @@ ZmnSCPxj \fI is mainly responsible\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:03f1e6937a88aad4bdcd29d010da9ced148e3498ea19b388e8cbfde25276482d +\" SHA256STAMP:c36a8ba48c3d2826344e23f880c21e0183942df8523da94394e5786dec874083 diff --git a/doc/lightning-close.7.md b/doc/lightning-close.7.md index 2e4289101..4d9ab1322 100644 --- a/doc/lightning-close.7.md +++ b/doc/lightning-close.7.md @@ -4,7 +4,7 @@ lightning-close -- Command for closing channels with direct peers SYNOPSIS -------- -**close** *id* \[*unilateraltimeout*\] \[*destination*\] \[*fee_negotiation_step*\] \[*wrong_funding\*] +**close** *id* \[*unilateraltimeout*\] \[*destination*\] \[*fee_negotiation_step*\] \[*wrong_funding*\] \[*force_lease_closed*\] DESCRIPTION ----------- @@ -56,6 +56,11 @@ shutdown transaction will spend this output instead. This is only allowed if this peer opened the channel and the channel is unused: it can rescue openings which have been manually miscreated. +*force_lease_closed* if the channel has funds leased to the peer +(option_will_fund), we prevent initiation of a mutual close +unless this flag is passed in. Defaults to false. + + The peer needs to be live and connected in order to negotiate a mutual close. The default of unilaterally closing after 48 hours is usually a reasonable indication that you can no longer contact the peer. diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index b0aaf76ae..b8566946f 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1671,7 +1671,7 @@ static struct command_result *json_close(struct command *cmd, 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; + bool close_script_set, wrong_funding_changed, *force_lease_close; const char *fee_negotiation_step_str; struct bitcoin_outpoint *wrong_funding; char* end; @@ -1685,6 +1685,8 @@ static struct command_result *json_close(struct command *cmd, 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), NULL)) return command_param_failed(); @@ -1714,6 +1716,15 @@ static struct command_result *json_close(struct command *cmd, "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.