mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-12-08 03:41:42 +01:00
multi: coop close with active HTLCs on the channel
For the lncli cmd we now always initiate the coop close even if there are active HTLCs on the channel. In case HTLCs are on the channel and the coop close is initiated LND handles the closing flow in the background and the lncli cmd will block until the transaction is broadcasted to the mempool. In the background LND disallows any new HTLCs and waits until all HTLCs are resolved before kicking of the negotiation process. Moreover if active HTLCs are present and the no_wait param is not set the error msg is now highlightning it so the user can react accordingly.
This commit is contained in:
@@ -1011,6 +1011,11 @@ var closeChannelCommand = cli.Command{
|
||||
comparison is the end boundary of the fee negotiation, if not specified
|
||||
it's always x3 of the starting value. Increasing this value increases
|
||||
the chance of a successful negotiation.
|
||||
Moreover if the channel has active HTLCs on it, the coop close will
|
||||
wait until all HTLCs are resolved and will not allow any new HTLCs on
|
||||
the channel. The channel will appear as disabled in the listchannels
|
||||
output. The command will block in that case until the channel close tx
|
||||
is broadcasted.
|
||||
|
||||
In the case of a cooperative closure, one can manually set the address
|
||||
to deliver funds to upon closure. This is optional, and may only be used
|
||||
@@ -1042,8 +1047,10 @@ var closeChannelCommand = cli.Command{
|
||||
Usage: "attempt an uncooperative closure",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "block",
|
||||
Usage: "block until the channel is closed",
|
||||
Name: "block",
|
||||
Usage: `block will wait for the channel to be closed,
|
||||
"meaning that it will wait for the channel close tx to
|
||||
get 1 confirmation.`,
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "conf_target",
|
||||
@@ -1117,6 +1124,9 @@ func closeChannel(ctx *cli.Context) error {
|
||||
SatPerVbyte: ctx.Uint64(feeRateFlag),
|
||||
DeliveryAddress: ctx.String("delivery_addr"),
|
||||
MaxFeePerVbyte: ctx.Uint64("max_fee_rate"),
|
||||
// This makes sure that a coop close will also be executed if
|
||||
// active HTLCs are present on the channel.
|
||||
NoWait: true,
|
||||
}
|
||||
|
||||
// After parsing the request, we'll spin up a goroutine that will
|
||||
@@ -1154,7 +1164,9 @@ func closeChannel(ctx *cli.Context) error {
|
||||
// executeChannelClose attempts to close the channel from a request. The closing
|
||||
// transaction ID is sent through `txidChan` as soon as it is broadcasted to the
|
||||
// network. The block boolean is used to determine if we should block until the
|
||||
// closing transaction receives all of its required confirmations.
|
||||
// closing transaction receives a confirmation of 1 block. The logging outputs
|
||||
// are sent to stderr to avoid conflicts with the JSON output of the command
|
||||
// and potential work flows which depend on a proper JSON output.
|
||||
func executeChannelClose(ctxc context.Context, client lnrpc.LightningClient,
|
||||
req *lnrpc.CloseChannelRequest, txidChan chan<- string, block bool) error {
|
||||
|
||||
@@ -1173,9 +1185,17 @@ func executeChannelClose(ctxc context.Context, client lnrpc.LightningClient,
|
||||
|
||||
switch update := resp.Update.(type) {
|
||||
case *lnrpc.CloseStatusUpdate_CloseInstant:
|
||||
if req.NoWait {
|
||||
return nil
|
||||
fmt.Fprintln(os.Stderr, "Channel close successfully "+
|
||||
"initiated")
|
||||
|
||||
pendingHtlcs := update.CloseInstant.NumPendingHtlcs
|
||||
if pendingHtlcs > 0 {
|
||||
fmt.Fprintf(os.Stderr, "Cooperative channel "+
|
||||
"close waiting for %d HTLCs to be "+
|
||||
"resolved before the close process "+
|
||||
"can kick off\n", pendingHtlcs)
|
||||
}
|
||||
|
||||
case *lnrpc.CloseStatusUpdate_ClosePending:
|
||||
closingHash := update.ClosePending.Txid
|
||||
txid, err := chainhash.NewHash(closingHash)
|
||||
@@ -1183,12 +1203,22 @@ func executeChannelClose(ctxc context.Context, client lnrpc.LightningClient,
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Channel close transaction "+
|
||||
"broadcasted: %v\n", txid)
|
||||
|
||||
txidChan <- txid.String()
|
||||
|
||||
if !block {
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "Waiting for channel close "+
|
||||
"confirmation ...")
|
||||
|
||||
case *lnrpc.CloseStatusUpdate_ChanClose:
|
||||
fmt.Fprintln(os.Stderr, "Channel close successfully "+
|
||||
"confirmed")
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user