Skip to content

Commit d986933

Browse files
committed
Clean up existing and add range-based closing_signed negotiation
This adds the new range-based closing_signed negotiation specified in lightning/bolts#847 as well as cleans up the existing closing_signed negotiation to unify the new codepaths and the old ones. Note that because the new range-based closing_signed negotiation allows the channel fundee to ultimately select the fee out of a range specified by the funder, which we, of course, always select the highest allowed amount from. Thus, we've added an extra round of closing_signed in the common case as we will not simply accept the first fee we see, always preferring to make the funder pay as much as they're willing to.
1 parent ca97a2a commit d986933

File tree

6 files changed

+260
-120
lines changed

6 files changed

+260
-120
lines changed

fuzz/src/full_stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
473473
let channel_id = get_slice!(1)[0] as usize;
474474
if channel_id >= channels.len() { return; }
475475
channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) });
476-
if channelmanager.close_channel(&channels[channel_id].channel_id).is_err() { return; }
476+
if channelmanager.close_channel(&channels[channel_id].channel_id, None).is_err() { return; }
477477
},
478478
7 => {
479479
if should_forward {

lightning/src/ln/channel.rs

Lines changed: 153 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,9 @@ pub(super) struct Channel<Signer: Sign> {
379379
/// Max to_local and to_remote outputs in a remote-generated commitment transaction
380380
counterparty_max_commitment_tx_output: ::std::sync::Mutex<(u64, u64)>,
381381

382-
last_sent_closing_fee: Option<(u32, u64, Signature)>, // (feerate, fee, holder_sig)
382+
last_sent_closing_fee: Option<(u64, Signature)>, // (fee, holder_sig)
383+
closing_fee_limits: Option<(u64, u64)>,
384+
target_closing_feerate_sats_per_1000_weight: Option<u32>,
383385

384386
/// The hash of the block in which the funding transaction was included.
385387
funding_tx_confirmed_in: Option<BlockHash>,
@@ -600,6 +602,8 @@ impl<Signer: Sign> Channel<Signer> {
600602
counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
601603

602604
last_sent_closing_fee: None,
605+
closing_fee_limits: None,
606+
target_closing_feerate_sats_per_1000_weight: None,
603607

604608
funding_tx_confirmed_in: None,
605609
funding_tx_confirmation_height: 0,
@@ -841,6 +845,8 @@ impl<Signer: Sign> Channel<Signer> {
841845
counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
842846

843847
last_sent_closing_fee: None,
848+
closing_fee_limits: None,
849+
target_closing_feerate_sats_per_1000_weight: None,
844850

845851
funding_tx_confirmed_in: None,
846852
funding_tx_confirmation_height: 0,
@@ -2780,6 +2786,7 @@ impl<Signer: Sign> Channel<Signer> {
27802786
// Upon reconnect we have to start the closing_signed dance over, but shutdown messages
27812787
// will be retransmitted.
27822788
self.last_sent_closing_fee = None;
2789+
self.closing_fee_limits = None;
27832790

27842791
let mut inbound_drop_count = 0;
27852792
self.pending_inbound_htlcs.retain(|htlc| {
@@ -3112,6 +3119,50 @@ impl<Signer: Sign> Channel<Signer> {
31123119
}
31133120
}
31143121

3122+
fn calculate_closing_feerate_limits<F: Deref>(&mut self, fee_estimator: &F)
3123+
where F::Target: FeeEstimator
3124+
{
3125+
if self.closing_fee_limits.is_some() { return; }
3126+
3127+
// Propose a range from our current Background feerate to our Normal feerate plus 10
3128+
// sat/vbyte. If we fail to come to consensus, we'll have to force-close.
3129+
let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
3130+
let mut proposed_max_feerate = if self.is_outbound() {
3131+
fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal)
3132+
} else {
3133+
u32::max_value()
3134+
};
3135+
3136+
// The spec requires that (when the channel does not have anchors) we only send absolute
3137+
// channel fees no greater than the absolute channel fee on the current commitment
3138+
// transaction. Its unclear *which* commitment transaction this refers to, and there isn't
3139+
// very good reason to apply such a limit in any case. We don't bother doing so, risking
3140+
// some force-closure by old nodes, but we wanted to close the channel anyway.
3141+
3142+
if let Some(target_feerate) = self.target_closing_feerate_sats_per_1000_weight {
3143+
let min_feerate = if self.is_outbound() { target_feerate } else { cmp::min(self.feerate_per_kw, target_feerate) };
3144+
proposed_feerate = cmp::max(proposed_feerate, min_feerate);
3145+
proposed_max_feerate = cmp::max(proposed_max_feerate, min_feerate);
3146+
}
3147+
3148+
// Note that technically we could end up with a lower minimum fee if one sides' balance is
3149+
// below our dust limit, causing the output to disappear. We don't bother handling this
3150+
// case, however, as this should only happen if a channel is closed before any (material)
3151+
// payments have been made on it. This may cause slight fee overpayment and/or failure to
3152+
// come to consensus with our counterparty on appropriate fees, however it should be a
3153+
// relatively rare case. We can revisit this later, though note that in order to determine
3154+
// if the funders' output is dust we have to know the absolute fee we're going to use.
3155+
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
3156+
let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000;
3157+
let proposed_max_total_fee_satoshis = if self.is_outbound() {
3158+
proposed_max_feerate as u64 * tx_weight / 1000 + self.config.force_close_avoidance_max_fee_satoshis
3159+
} else {
3160+
u64::max_value()
3161+
};
3162+
3163+
self.closing_fee_limits = Some((proposed_total_fee_satoshis, proposed_max_total_fee_satoshis));
3164+
}
3165+
31153166
pub fn maybe_propose_first_closing_signed<F: Deref, L: Deref>(&mut self, fee_estimator: &F, logger: &L)
31163167
-> Result<Option<msgs::ClosingSigned>, ChannelError>
31173168
where F::Target: FeeEstimator, L::Target: Logger
@@ -3125,26 +3176,26 @@ impl<Signer: Sign> Channel<Signer> {
31253176
return Ok(None);
31263177
}
31273178

3128-
let mut proposed_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
3129-
if self.feerate_per_kw > proposed_feerate {
3130-
proposed_feerate = self.feerate_per_kw;
3131-
}
3132-
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
3133-
let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000;
3134-
log_trace!(logger, "Proposing initial closing signed for our counterparty with a feerate of {} sat/kWeight (= {} sats)",
3135-
proposed_feerate, proposed_total_fee_satoshis);
3179+
self.calculate_closing_feerate_limits(fee_estimator);
3180+
let (our_min_fee, our_max_fee) = self.closing_fee_limits.unwrap();
3181+
3182+
let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(our_min_fee, false);
3183+
log_trace!(logger, "Proposing initial closing signed for our counterparty with a fee range of {}-{} sat (with initial proposal {} sats)",
3184+
our_min_fee, our_max_fee, total_fee_satoshis);
31363185

3137-
let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false);
31383186
let sig = self.holder_signer
31393187
.sign_closing_transaction(&closing_tx, &self.secp_ctx)
31403188
.map_err(|()| ChannelError::Close("Failed to get signature for closing transaction.".to_owned()))?;
31413189

3142-
self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis, sig.clone()));
3190+
self.last_sent_closing_fee = Some((total_fee_satoshis, sig.clone()));
31433191
Ok(Some(msgs::ClosingSigned {
31443192
channel_id: self.channel_id,
31453193
fee_satoshis: total_fee_satoshis,
31463194
signature: sig,
3147-
fee_range: None,
3195+
fee_range: Some(msgs::ClosingSignedFeeRange {
3196+
min_fee_satoshis: our_min_fee,
3197+
max_fee_satoshis: our_max_fee,
3198+
}),
31483199
}))
31493200
}
31503201

@@ -3253,6 +3304,10 @@ impl<Signer: Sign> Channel<Signer> {
32533304
return Err(ChannelError::Close("Remote tried to send us a closing tx with > 21 million BTC fee".to_owned()));
32543305
}
32553306

3307+
if self.is_outbound() && self.last_sent_closing_fee.is_none() {
3308+
return Err(ChannelError::Close("Remote tried to send a closing_signed when we were supposed to propose the first one".to_owned()));
3309+
}
3310+
32563311
let funding_redeemscript = self.get_funding_redeemscript();
32573312
let (mut closing_tx, used_total_fee) = self.build_closing_transaction(msg.fee_satoshis, false);
32583313
if used_total_fee != msg.fee_satoshis {
@@ -3271,77 +3326,104 @@ impl<Signer: Sign> Channel<Signer> {
32713326
},
32723327
};
32733328

3274-
let closing_tx_max_weight = self.get_closing_transaction_weight(
3275-
if let Some(oup) = closing_tx.output.get(0) { Some(&oup.script_pubkey) } else { None },
3276-
if let Some(oup) = closing_tx.output.get(1) { Some(&oup.script_pubkey) } else { None });
3277-
if let Some((_, last_fee, sig)) = self.last_sent_closing_fee {
3329+
if let Some((last_fee, sig)) = self.last_sent_closing_fee {
32783330
if last_fee == msg.fee_satoshis {
32793331
self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig);
3280-
assert!(closing_tx.get_weight() as u64 <= closing_tx_max_weight);
3281-
debug_assert!(closing_tx.get_weight() as u64 >= closing_tx_max_weight - 2);
32823332
self.channel_state = ChannelState::ShutdownComplete as u32;
32833333
self.update_time_counter += 1;
32843334
return Ok((None, Some(closing_tx)));
32853335
}
32863336
}
32873337

3288-
macro_rules! propose_new_feerate {
3289-
($new_feerate: expr) => {
3290-
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
3291-
let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate as u64 * tx_weight / 1000, false);
3338+
self.calculate_closing_feerate_limits(fee_estimator);
3339+
let (our_min_fee, our_max_fee) = self.closing_fee_limits.unwrap();
3340+
3341+
macro_rules! propose_new_fee {
3342+
($new_fee: expr) => {
3343+
let (mut tx, used_fee) = if $new_fee == msg.fee_satoshis {
3344+
(closing_tx, $new_fee)
3345+
} else {
3346+
self.build_closing_transaction($new_fee, false)
3347+
};
3348+
32923349
let sig = self.holder_signer
3293-
.sign_closing_transaction(&closing_tx, &self.secp_ctx)
3350+
.sign_closing_transaction(&tx, &self.secp_ctx)
32943351
.map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?;
3295-
assert!(closing_tx.get_weight() as u64 <= tx_weight);
3296-
self.last_sent_closing_fee = Some(($new_feerate, used_total_fee, sig.clone()));
3352+
3353+
let signed_tx = if $new_fee == msg.fee_satoshis {
3354+
self.channel_state = ChannelState::ShutdownComplete as u32;
3355+
self.update_time_counter += 1;
3356+
self.build_signed_closing_transaction(&mut tx, &msg.signature, &sig);
3357+
Some(tx)
3358+
} else { None };
3359+
3360+
self.last_sent_closing_fee = Some((used_fee, sig.clone()));
32973361
return Ok((Some(msgs::ClosingSigned {
32983362
channel_id: self.channel_id,
3299-
fee_satoshis: used_total_fee,
3363+
fee_satoshis: used_fee,
33003364
signature: sig,
3301-
fee_range: None,
3302-
}), None))
3365+
fee_range: Some(msgs::ClosingSignedFeeRange {
3366+
min_fee_satoshis: our_min_fee,
3367+
max_fee_satoshis: our_max_fee,
3368+
}),
3369+
}), signed_tx))
33033370
}
33043371
}
33053372

3306-
let mut min_feerate = 253;
3307-
if self.is_outbound() {
3308-
let max_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
3309-
if (msg.fee_satoshis as u64) > max_feerate as u64 * closing_tx_max_weight / 1000 {
3310-
if let Some((last_feerate, _, _)) = self.last_sent_closing_fee {
3311-
if max_feerate <= last_feerate {
3312-
return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote wanted something higher ({}) than our Normal feerate ({})", last_feerate, max_feerate)));
3313-
}
3373+
if let Some(msgs::ClosingSignedFeeRange { min_fee_satoshis, max_fee_satoshis }) = msg.fee_range {
3374+
if msg.fee_satoshis < min_fee_satoshis || msg.fee_satoshis > max_fee_satoshis {
3375+
return Err(ChannelError::Close(format!("Peer sent a bogus closing_signed - suggested fee of {} sat was not in their desired range of {} sat - {} sat", msg.fee_satoshis, min_fee_satoshis, max_fee_satoshis)));
3376+
}
3377+
if max_fee_satoshis < our_min_fee {
3378+
return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote's max fee ({} sat) was smaller than our min fee ({} sat)", max_fee_satoshis, our_min_fee)));
3379+
}
3380+
if min_fee_satoshis > our_max_fee {
3381+
return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote's min fee ({} sat) was greater than our max fee ({} sat)", min_fee_satoshis, our_max_fee)));
3382+
}
3383+
3384+
if !self.is_outbound() {
3385+
// They have to pay, so pick the highest fee in the overlapping range.
3386+
debug_assert_eq!(our_max_fee, u64::max_value()); // Note that we always allow any fee
3387+
propose_new_fee!(cmp::min(max_fee_satoshis, our_max_fee));
3388+
} else {
3389+
if msg.fee_satoshis < our_min_fee || msg.fee_satoshis > our_max_fee {
3390+
return Err(ChannelError::Close(format!("Peer sent a bogus closing_signed - suggested fee of {} sat was not in our desired range of {} sat - {} sat after we informed them of our range.",
3391+
msg.fee_satoshis, our_min_fee, our_max_fee)));
33143392
}
3315-
propose_new_feerate!(max_feerate);
3393+
// The proposed fee is in our acceptable range, accept it and broadcast!
3394+
propose_new_fee!(msg.fee_satoshis);
33163395
}
33173396
} else {
3318-
min_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
3319-
}
3320-
if (msg.fee_satoshis as u64) < min_feerate as u64 * closing_tx_max_weight / 1000 {
3321-
if let Some((last_feerate, _, _)) = self.last_sent_closing_fee {
3322-
if min_feerate >= last_feerate {
3323-
return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote wanted something lower ({}) than our Background feerate ({}).", last_feerate, min_feerate)));
3397+
// Old fee style negotiation. We don't bother to enforce whether they are complying
3398+
// with the "making progress" requirements, we just comply and hope for the best.
3399+
if let Some((last_fee, _)) = self.last_sent_closing_fee {
3400+
if msg.fee_satoshis > last_fee {
3401+
if msg.fee_satoshis < our_max_fee {
3402+
propose_new_fee!(msg.fee_satoshis);
3403+
} else if last_fee < our_max_fee {
3404+
propose_new_fee!(our_max_fee);
3405+
} else {
3406+
return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote wants something ({} sat) higher than our max fee ({} sat)", msg.fee_satoshis, our_max_fee)));
3407+
}
3408+
} else {
3409+
if msg.fee_satoshis > our_min_fee {
3410+
propose_new_fee!(msg.fee_satoshis);
3411+
} else if last_fee > our_min_fee {
3412+
propose_new_fee!(our_min_fee);
3413+
} else {
3414+
return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote wants something ({} sat) lower than our min fee ({} sat)", msg.fee_satoshis, our_min_fee)));
3415+
}
3416+
}
3417+
} else {
3418+
if msg.fee_satoshis < our_min_fee {
3419+
propose_new_fee!(our_min_fee);
3420+
} else if msg.fee_satoshis > our_max_fee {
3421+
propose_new_fee!(our_max_fee);
3422+
} else {
3423+
propose_new_fee!(msg.fee_satoshis);
33243424
}
33253425
}
3326-
propose_new_feerate!(min_feerate);
33273426
}
3328-
3329-
let sig = self.holder_signer
3330-
.sign_closing_transaction(&closing_tx, &self.secp_ctx)
3331-
.map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?;
3332-
self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig);
3333-
assert!(closing_tx.get_weight() as u64 <= closing_tx_max_weight);
3334-
debug_assert!(closing_tx.get_weight() as u64 >= closing_tx_max_weight - 2);
3335-
3336-
self.channel_state = ChannelState::ShutdownComplete as u32;
3337-
self.update_time_counter += 1;
3338-
3339-
Ok((Some(msgs::ClosingSigned {
3340-
channel_id: self.channel_id,
3341-
fee_satoshis: msg.fee_satoshis,
3342-
signature: sig,
3343-
fee_range: None,
3344-
}), Some(closing_tx)))
33453427
}
33463428

33473429
// Public utilities:
@@ -4338,7 +4420,7 @@ impl<Signer: Sign> Channel<Signer> {
43384420

43394421
/// Begins the shutdown process, getting a message for the remote peer and returning all
43404422
/// holding cell HTLCs for payment failure.
4341-
pub fn get_shutdown(&mut self) -> Result<(msgs::Shutdown, Vec<(HTLCSource, PaymentHash)>), APIError> {
4423+
pub fn get_shutdown(&mut self, target_feerate_sats_per_1000_weight: Option<u32>) -> Result<(msgs::Shutdown, Vec<(HTLCSource, PaymentHash)>), APIError> {
43424424
for htlc in self.pending_outbound_htlcs.iter() {
43434425
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
43444426
return Err(APIError::APIMisuseError{err: "Cannot begin shutdown with pending HTLCs. Process pending events first".to_owned()});
@@ -4360,6 +4442,7 @@ impl<Signer: Sign> Channel<Signer> {
43604442
let closing_script = self.get_closing_scriptpubkey();
43614443

43624444
// From here on out, we may not fail!
4445+
self.target_closing_feerate_sats_per_1000_weight = target_feerate_sats_per_1000_weight;
43634446
if self.channel_state < ChannelState::FundingSent as u32 {
43644447
self.channel_state = ChannelState::ShutdownComplete as u32;
43654448
} else {
@@ -4699,6 +4782,8 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
46994782
(1, self.minimum_depth, option),
47004783
(3, self.counterparty_selected_channel_reserve_satoshis, option),
47014784
(5, self.config, required),
4785+
(7, self.closing_fee_limits, option),
4786+
(9, self.target_closing_feerate_sats_per_1000_weight, option),
47024787
});
47034788

47044789
Ok(())
@@ -4906,11 +4991,15 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
49064991
let channel_update_status = Readable::read(reader)?;
49074992

49084993
let mut announcement_sigs = None;
4994+
let mut closing_fee_limits = None;
4995+
let mut target_closing_feerate_sats_per_1000_weight = None;
49094996
read_tlv_fields!(reader, {
49104997
(0, announcement_sigs, option),
49114998
(1, minimum_depth, option),
49124999
(3, counterparty_selected_channel_reserve_satoshis, option),
49135000
(5, config, option), // Note that if none is provided we will *not* overwrite the existing one.
5001+
(7, closing_fee_limits, option),
5002+
(9, target_closing_feerate_sats_per_1000_weight, option),
49145003
});
49155004

49165005
let mut secp_ctx = Secp256k1::new();
@@ -4960,6 +5049,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
49605049
counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((0, 0)),
49615050

49625051
last_sent_closing_fee: None,
5052+
closing_fee_limits,
5053+
target_closing_feerate_sats_per_1000_weight,
49635054

49645055
funding_tx_confirmed_in,
49655056
funding_tx_confirmation_height,

lightning/src/ln/channelmanager.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,16 +1237,30 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
12371237
/// will be accepted on the given channel, and after additional timeout/the closing of all
12381238
/// pending HTLCs, the channel will be closed on chain.
12391239
///
1240+
/// `target_feerate_sat_per_1000_weight`, if provided, has different meanings depending on if
1241+
/// we initiated the channel being closed or not:
1242+
/// * If we are the channel initiator, we will pay at least this feerate on the closing
1243+
/// transaction. The upper-bound is set by
1244+
/// [`ChannelConfig::force_close_avoidance_max_fee_satoshis`] plus our [`Normal`] fee
1245+
/// estimate.
1246+
/// estimates (or `target_feerate_sat_per_1000_weight`, if it is greater).
1247+
/// * If our counterparty is the channel initiator, we will refuse to accept a channel closure
1248+
/// transaction feerate below `target_feerate_sat_per_1000_weight` (or the feerate which
1249+
/// will appear on a force-closure transaction, whichever is lower).
1250+
///
12401251
/// May generate a SendShutdown message event on success, which should be relayed.
1241-
pub fn close_channel(&self, channel_id: &[u8; 32]) -> Result<(), APIError> {
1252+
///
1253+
/// [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis
1254+
/// [`Normal`]: crate::chain::chaininterface::ConfirmationTarget::Normal
1255+
pub fn close_channel(&self, channel_id: &[u8; 32], target_feerate_sats_per_1000_weight: Option<u32>) -> Result<(), APIError> {
12421256
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
12431257

12441258
let (mut failed_htlcs, chan_option) = {
12451259
let mut channel_state_lock = self.channel_state.lock().unwrap();
12461260
let channel_state = &mut *channel_state_lock;
12471261
match channel_state.by_id.entry(channel_id.clone()) {
12481262
hash_map::Entry::Occupied(mut chan_entry) => {
1249-
let (shutdown_msg, failed_htlcs) = chan_entry.get_mut().get_shutdown()?;
1263+
let (shutdown_msg, failed_htlcs) = chan_entry.get_mut().get_shutdown(target_feerate_sats_per_1000_weight)?;
12501264
channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
12511265
node_id: chan_entry.get().get_counterparty_node_id(),
12521266
msg: shutdown_msg

0 commit comments

Comments
 (0)