@@ -1011,6 +1011,11 @@ var closeChannelCommand = cli.Command{
1011
1011
comparison is the end boundary of the fee negotiation, if not specified
1012
1012
it's always x3 of the starting value. Increasing this value increases
1013
1013
the chance of a successful negotiation.
1014
+ Moreover if the channel has active HTLCs on it, the coop close will
1015
+ wait until all HTLCs are resolved and will not allow any new HTLCs on
1016
+ the channel. The channel will appear as disabled in the listchannels
1017
+ output. The command will block in that case until the channel close tx
1018
+ is broadcasted.
1014
1019
1015
1020
In the case of a cooperative closure, one can manually set the address
1016
1021
to deliver funds to upon closure. This is optional, and may only be used
@@ -1042,8 +1047,10 @@ var closeChannelCommand = cli.Command{
1042
1047
Usage : "attempt an uncooperative closure" ,
1043
1048
},
1044
1049
cli.BoolFlag {
1045
- Name : "block" ,
1046
- Usage : "block until the channel is closed" ,
1050
+ Name : "block" ,
1051
+ Usage : `block will wait for the channel to be closed,
1052
+ "meaning that it will wait for the channel close tx to
1053
+ get 1 confirmation.` ,
1047
1054
},
1048
1055
cli.Int64Flag {
1049
1056
Name : "conf_target" ,
@@ -1117,6 +1124,9 @@ func closeChannel(ctx *cli.Context) error {
1117
1124
SatPerVbyte : ctx .Uint64 (feeRateFlag ),
1118
1125
DeliveryAddress : ctx .String ("delivery_addr" ),
1119
1126
MaxFeePerVbyte : ctx .Uint64 ("max_fee_rate" ),
1127
+ // This makes sure that a coop close will also be executed if
1128
+ // active HTLCs are present on the channel.
1129
+ NoWait : true ,
1120
1130
}
1121
1131
1122
1132
// After parsing the request, we'll spin up a goroutine that will
@@ -1154,7 +1164,9 @@ func closeChannel(ctx *cli.Context) error {
1154
1164
// executeChannelClose attempts to close the channel from a request. The closing
1155
1165
// transaction ID is sent through `txidChan` as soon as it is broadcasted to the
1156
1166
// network. The block boolean is used to determine if we should block until the
1157
- // closing transaction receives all of its required confirmations.
1167
+ // closing transaction receives a confirmation of 1 block. The logging outputs
1168
+ // are sent to stderr to avoid conflicts with the JSON output of the command
1169
+ // and potential work flows which depend on a proper JSON output.
1158
1170
func executeChannelClose (ctxc context.Context , client lnrpc.LightningClient ,
1159
1171
req * lnrpc.CloseChannelRequest , txidChan chan <- string , block bool ) error {
1160
1172
@@ -1173,22 +1185,40 @@ func executeChannelClose(ctxc context.Context, client lnrpc.LightningClient,
1173
1185
1174
1186
switch update := resp .Update .(type ) {
1175
1187
case * lnrpc.CloseStatusUpdate_CloseInstant :
1176
- if req .NoWait {
1177
- return nil
1188
+ fmt .Fprintln (os .Stderr , "Channel close successfully " +
1189
+ "initiated" )
1190
+
1191
+ pendingHtlcs := update .CloseInstant .NumPendingHtlcs
1192
+ if pendingHtlcs > 0 {
1193
+ fmt .Fprintf (os .Stderr , "Cooperative channel " +
1194
+ "close waiting for %d HTLCs to be " +
1195
+ "resolved before the close process " +
1196
+ "can kick off\n " , pendingHtlcs )
1178
1197
}
1198
+
1179
1199
case * lnrpc.CloseStatusUpdate_ClosePending :
1180
1200
closingHash := update .ClosePending .Txid
1181
1201
txid , err := chainhash .NewHash (closingHash )
1182
1202
if err != nil {
1183
1203
return err
1184
1204
}
1185
1205
1206
+ fmt .Fprintf (os .Stderr , "Channel close transaction " +
1207
+ "broadcasted: %v\n " , txid )
1208
+
1186
1209
txidChan <- txid .String ()
1187
1210
1188
1211
if ! block {
1189
1212
return nil
1190
1213
}
1214
+
1215
+ fmt .Fprintln (os .Stderr , "Waiting for channel close " +
1216
+ "confirmation ..." )
1217
+
1191
1218
case * lnrpc.CloseStatusUpdate_ChanClose :
1219
+ fmt .Fprintln (os .Stderr , "Channel close successfully " +
1220
+ "confirmed" )
1221
+
1192
1222
return nil
1193
1223
}
1194
1224
}
0 commit comments