Skip to content

Commit f69311c

Browse files
committed
Store holder channel reserve and max-htlc-in-flight explicitly
Previously, `holder_selected_channel_reserve_satoshis` and `holder_max_htlc_value_in_flight_msat` were constant functions of the channel value satoshis. However, in the future we may allow allow users to specify it. In order to do so, we'll need to track them explicitly, including serializing them as appropriate. We go ahead and do so here, in part as it will make testing different counterparty-selected channel reserve values easier.
1 parent ef86a3e commit f69311c

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

lightning/src/ln/channel.rs

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -524,10 +524,11 @@ pub(super) struct Channel<Signer: Sign> {
524524
pub(super) counterparty_max_htlc_value_in_flight_msat: u64,
525525
#[cfg(not(test))]
526526
counterparty_max_htlc_value_in_flight_msat: u64,
527-
//get_holder_max_htlc_value_in_flight_msat(): u64,
527+
holder_max_htlc_value_in_flight_msat: u64,
528+
528529
/// minimum channel reserve for self to maintain - set by them.
529530
counterparty_selected_channel_reserve_satoshis: Option<u64>,
530-
// get_holder_selected_channel_reserve_satoshis(channel_value_sats: u64): u64
531+
holder_selected_channel_reserve_satoshis: u64,
531532
counterparty_htlc_minimum_msat: u64,
532533
holder_htlc_minimum_msat: u64,
533534
#[cfg(test)]
@@ -679,6 +680,10 @@ impl<Signer: Sign> Channel<Signer> {
679680
/// required by us.
680681
///
681682
/// Guaranteed to return a value no larger than channel_value_satoshis
683+
///
684+
/// This is used both for new channels and to figure out what reserve value we sent to peers
685+
/// for channels serialized before we included our selected reserve value in the serialized
686+
/// data explicitly.
682687
pub(crate) fn get_holder_selected_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 {
683688
let (q, _) = channel_value_satoshis.overflowing_div(100);
684689
cmp::min(channel_value_satoshis, cmp::max(q, 1000)) //TODO
@@ -792,7 +797,9 @@ impl<Signer: Sign> Channel<Signer> {
792797
counterparty_dust_limit_satoshis: 0,
793798
holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
794799
counterparty_max_htlc_value_in_flight_msat: 0,
800+
holder_max_htlc_value_in_flight_msat: Self::get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis),
795801
counterparty_selected_channel_reserve_satoshis: None, // Filled in in accept_channel
802+
holder_selected_channel_reserve_satoshis,
796803
counterparty_htlc_minimum_msat: 0,
797804
holder_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
798805
counterparty_max_accepted_htlcs: 0,
@@ -1083,7 +1090,9 @@ impl<Signer: Sign> Channel<Signer> {
10831090
counterparty_dust_limit_satoshis: msg.dust_limit_satoshis,
10841091
holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
10851092
counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000),
1093+
holder_max_htlc_value_in_flight_msat: Self::get_holder_max_htlc_value_in_flight_msat(msg.funding_satoshis),
10861094
counterparty_selected_channel_reserve_satoshis: Some(msg.channel_reserve_satoshis),
1095+
holder_selected_channel_reserve_satoshis,
10871096
counterparty_htlc_minimum_msat: msg.htlc_minimum_msat,
10881097
holder_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
10891098
counterparty_max_accepted_htlcs: msg.max_accepted_htlcs,
@@ -1288,7 +1297,7 @@ impl<Signer: Sign> Channel<Signer> {
12881297
};
12891298
debug_assert!(broadcaster_max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.counterparty_selected_channel_reserve_satoshis.unwrap() as i64);
12901299
broadcaster_max_commitment_tx_output.0 = cmp::max(broadcaster_max_commitment_tx_output.0, value_to_self_msat as u64);
1291-
debug_assert!(broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) as i64);
1300+
debug_assert!(broadcaster_max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= self.holder_selected_channel_reserve_satoshis as i64);
12921301
broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat as u64);
12931302
}
12941303

@@ -1706,9 +1715,8 @@ impl<Signer: Sign> Channel<Signer> {
17061715
if msg.channel_reserve_satoshis < self.holder_dust_limit_satoshis {
17071716
return Err(ChannelError::Close(format!("Peer never wants payout outputs? channel_reserve_satoshis was ({}). dust_limit is ({})", msg.channel_reserve_satoshis, self.holder_dust_limit_satoshis)));
17081717
}
1709-
let remote_reserve = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis);
1710-
if msg.dust_limit_satoshis > remote_reserve {
1711-
return Err(ChannelError::Close(format!("Dust limit ({}) is bigger than our channel reserve ({})", msg.dust_limit_satoshis, remote_reserve)));
1718+
if msg.dust_limit_satoshis > self.holder_selected_channel_reserve_satoshis {
1719+
return Err(ChannelError::Close(format!("Dust limit ({}) is bigger than our channel reserve ({})", msg.dust_limit_satoshis, self.holder_selected_channel_reserve_satoshis)));
17121720
}
17131721
let full_channel_value_msat = (self.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000;
17141722
if msg.htlc_minimum_msat >= full_channel_value_msat {
@@ -2109,7 +2117,7 @@ impl<Signer: Sign> Channel<Signer> {
21092117
cmp::max(self.channel_value_satoshis as i64 * 1000
21102118
- self.value_to_self_msat as i64
21112119
- self.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64
2112-
- Self::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) as i64 * 1000,
2120+
- self.holder_selected_channel_reserve_satoshis as i64 * 1000,
21132121
0) as u64,
21142122
cmp::max(self.value_to_self_msat as i64
21152123
- self.get_outbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64
@@ -2119,8 +2127,7 @@ impl<Signer: Sign> Channel<Signer> {
21192127
}
21202128

21212129
pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option<u64>) {
2122-
(Self::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis),
2123-
self.counterparty_selected_channel_reserve_satoshis)
2130+
(self.holder_selected_channel_reserve_satoshis, self.counterparty_selected_channel_reserve_satoshis)
21242131
}
21252132

21262133
// Get the fee cost in MSATS of a commitment tx with a given number of HTLC outputs.
@@ -2336,9 +2343,8 @@ impl<Signer: Sign> Channel<Signer> {
23362343
if inbound_stats.pending_htlcs + 1 > OUR_MAX_HTLCS as u32 {
23372344
return Err(ChannelError::Close(format!("Remote tried to push more than our max accepted HTLCs ({})", OUR_MAX_HTLCS)));
23382345
}
2339-
let holder_max_htlc_value_in_flight_msat = Channel::<Signer>::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis);
2340-
if inbound_stats.pending_htlcs_value_msat + msg.amount_msat > holder_max_htlc_value_in_flight_msat {
2341-
return Err(ChannelError::Close(format!("Remote HTLC add would put them over our max HTLC value ({})", holder_max_htlc_value_in_flight_msat)));
2346+
if inbound_stats.pending_htlcs_value_msat + msg.amount_msat > self.holder_max_htlc_value_in_flight_msat {
2347+
return Err(ChannelError::Close(format!("Remote HTLC add would put them over our max HTLC value ({})", self.holder_max_htlc_value_in_flight_msat)));
23422348
}
23432349
// Check holder_selected_channel_reserve_satoshis (we're getting paid, so they have to at least meet
23442350
// the reserve_satoshis we told them to always have as direct payment so that they lose
@@ -2399,9 +2405,7 @@ impl<Signer: Sign> Channel<Signer> {
23992405
return Err(ChannelError::Close("Remote HTLC add would not leave enough to pay for fees".to_owned()));
24002406
};
24012407

2402-
let chan_reserve_msat =
2403-
Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) * 1000;
2404-
if pending_remote_value_msat - msg.amount_msat - remote_commit_tx_fee_msat < chan_reserve_msat {
2408+
if pending_remote_value_msat - msg.amount_msat - remote_commit_tx_fee_msat < self.holder_selected_channel_reserve_satoshis * 1000 {
24052409
return Err(ChannelError::Close("Remote HTLC add would put them under remote reserve value".to_owned()));
24062410
}
24072411

@@ -2416,7 +2420,7 @@ impl<Signer: Sign> Channel<Signer> {
24162420
// sensitive to fee spikes.
24172421
let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
24182422
let remote_fee_cost_incl_stuck_buffer_msat = 2 * self.next_remote_commit_tx_fee_msat(htlc_candidate, Some(()));
2419-
if pending_remote_value_msat - msg.amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat {
2423+
if pending_remote_value_msat - msg.amount_msat - self.holder_selected_channel_reserve_satoshis * 1000 < remote_fee_cost_incl_stuck_buffer_msat {
24202424
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
24212425
// the HTLC, i.e. its status is already set to failing.
24222426
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));
@@ -2559,7 +2563,7 @@ impl<Signer: Sign> Channel<Signer> {
25592563
} else { false };
25602564
if update_fee {
25612565
debug_assert!(!self.is_outbound());
2562-
let counterparty_reserve_we_require_msat = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) * 1000;
2566+
let counterparty_reserve_we_require_msat = self.holder_selected_channel_reserve_satoshis * 1000;
25632567
if commitment_stats.remote_balance_msat < commitment_stats.total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
25642568
return Err((None, ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned())));
25652569
}
@@ -4000,7 +4004,7 @@ impl<Signer: Sign> Channel<Signer> {
40004004
// channel might have been used to route very small values (either by honest users or as DoS).
40014005
self.channel_value_satoshis * 1000 * 9 / 10,
40024006

4003-
Channel::<Signer>::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis)
4007+
self.holder_max_htlc_value_in_flight_msat
40044008
);
40054009
}
40064010

@@ -4400,8 +4404,8 @@ impl<Signer: Sign> Channel<Signer> {
44004404
funding_satoshis: self.channel_value_satoshis,
44014405
push_msat: self.channel_value_satoshis * 1000 - self.value_to_self_msat,
44024406
dust_limit_satoshis: self.holder_dust_limit_satoshis,
4403-
max_htlc_value_in_flight_msat: Channel::<Signer>::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis),
4404-
channel_reserve_satoshis: Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis),
4407+
max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat,
4408+
channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis,
44054409
htlc_minimum_msat: self.holder_htlc_minimum_msat,
44064410
feerate_per_kw: self.feerate_per_kw as u32,
44074411
to_self_delay: self.get_holder_selected_contest_delay(),
@@ -4438,8 +4442,8 @@ impl<Signer: Sign> Channel<Signer> {
44384442
msgs::AcceptChannel {
44394443
temporary_channel_id: self.channel_id,
44404444
dust_limit_satoshis: self.holder_dust_limit_satoshis,
4441-
max_htlc_value_in_flight_msat: Channel::<Signer>::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis),
4442-
channel_reserve_satoshis: Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis),
4445+
max_htlc_value_in_flight_msat: self.holder_max_htlc_value_in_flight_msat,
4446+
channel_reserve_satoshis: self.holder_selected_channel_reserve_satoshis,
44434447
htlc_minimum_msat: self.holder_htlc_minimum_msat,
44444448
minimum_depth: self.minimum_depth.unwrap(),
44454449
to_self_delay: self.get_holder_selected_contest_delay(),
@@ -4722,7 +4726,7 @@ impl<Signer: Sign> Channel<Signer> {
47224726
// Check that we won't violate the remote channel reserve by adding this HTLC.
47234727
let htlc_candidate = HTLCCandidate::new(amount_msat, HTLCInitiator::LocalOffered);
47244728
let counterparty_commit_tx_fee_msat = self.next_remote_commit_tx_fee_msat(htlc_candidate, None);
4725-
let holder_selected_chan_reserve_msat = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) * 1000;
4729+
let holder_selected_chan_reserve_msat = self.holder_selected_channel_reserve_satoshis * 1000;
47264730
if commitment_stats.remote_balance_msat < counterparty_commit_tx_fee_msat + holder_selected_chan_reserve_msat {
47274731
return Err(ChannelError::Ignore("Cannot send value that would put counterparty balance under holder-announced channel reserve value".to_owned()));
47284732
}
@@ -5368,6 +5372,15 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
53685372
let chan_type = if self.channel_type != ChannelTypeFeatures::only_static_remote_key() {
53695373
Some(&self.channel_type) } else { None };
53705374

5375+
// The same logic applies for `holder_selected_channel_reserve_satoshis` and
5376+
// `holder_max_htlc_value_in_flight_msat` values other than the defaults.
5377+
let serialized_holder_selected_reserve =
5378+
if self.holder_selected_channel_reserve_satoshis != Self::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis)
5379+
{ Some(self.holder_selected_channel_reserve_satoshis) } else { None };
5380+
let serialized_holder_htlc_max_in_flight =
5381+
if self.holder_max_htlc_value_in_flight_msat != Self::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis)
5382+
{ Some(self.holder_max_htlc_value_in_flight_msat) } else { None };
5383+
53715384
write_tlv_fields!(writer, {
53725385
(0, self.announcement_sigs, option),
53735386
// minimum_depth and counterparty_selected_channel_reserve_satoshis used to have a
@@ -5379,7 +5392,9 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
53795392
(1, self.minimum_depth, option),
53805393
(2, chan_type, option),
53815394
(3, self.counterparty_selected_channel_reserve_satoshis, option),
5395+
(4, serialized_holder_selected_reserve, option),
53825396
(5, self.config, required),
5397+
(6, serialized_holder_htlc_max_in_flight, option),
53835398
(7, self.shutdown_scriptpubkey, option),
53845399
(9, self.target_closing_feerate_sats_per_kw, option),
53855400
(11, self.monitor_pending_finalized_fulfills, vec_type),
@@ -5619,6 +5634,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
56195634
let mut announcement_sigs = None;
56205635
let mut target_closing_feerate_sats_per_kw = None;
56215636
let mut monitor_pending_finalized_fulfills = Some(Vec::new());
5637+
let mut holder_selected_channel_reserve_satoshis = Some(Self::get_holder_selected_channel_reserve_satoshis(channel_value_satoshis));
5638+
let mut holder_max_htlc_value_in_flight_msat = Some(Self::get_holder_max_htlc_value_in_flight_msat(channel_value_satoshis));
56225639
// Prior to supporting channel type negotiation, all of our channels were static_remotekey
56235640
// only, so we default to that if none was written.
56245641
let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key());
@@ -5628,7 +5645,9 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
56285645
(1, minimum_depth, option),
56295646
(2, channel_type, option),
56305647
(3, counterparty_selected_channel_reserve_satoshis, option),
5648+
(4, holder_selected_channel_reserve_satoshis, option),
56315649
(5, config, option), // Note that if none is provided we will *not* overwrite the existing one.
5650+
(6, holder_max_htlc_value_in_flight_msat, option),
56325651
(7, shutdown_scriptpubkey, option),
56335652
(9, target_closing_feerate_sats_per_kw, option),
56345653
(11, monitor_pending_finalized_fulfills, vec_type),
@@ -5707,7 +5726,9 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
57075726
counterparty_dust_limit_satoshis,
57085727
holder_dust_limit_satoshis,
57095728
counterparty_max_htlc_value_in_flight_msat,
5729+
holder_max_htlc_value_in_flight_msat: holder_max_htlc_value_in_flight_msat.unwrap(),
57105730
counterparty_selected_channel_reserve_satoshis,
5731+
holder_selected_channel_reserve_satoshis: holder_selected_channel_reserve_satoshis.unwrap(),
57115732
counterparty_htlc_minimum_msat,
57125733
holder_htlc_minimum_msat,
57135734
counterparty_max_accepted_htlcs,

0 commit comments

Comments
 (0)