Skip to content

Commit d6860ec

Browse files
f Jeff refactor
1 parent abb722b commit d6860ec

File tree

1 file changed

+80
-30
lines changed

1 file changed

+80
-30
lines changed

lightning/src/ln/channel.rs

Lines changed: 80 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,27 @@ enum UpdateStatus {
260260
DisabledStaged,
261261
}
262262

263+
/// An enum indicating whether the local or remote side offered a given HTLC.
264+
enum HTLCInitiator {
265+
LocalOffered,
266+
RemoteOffered,
267+
}
268+
269+
/// Used when calculating whether we or the remote can afford an additional HTLC.
270+
struct HTLCCandidate {
271+
amount_msat: u64,
272+
origin: HTLCInitiator,
273+
}
274+
275+
impl HTLCCandidate {
276+
fn new(amount_msat: u64, origin: HTLCInitiator) -> Self {
277+
Self {
278+
amount_msat,
279+
origin,
280+
}
281+
}
282+
}
283+
263284
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
264285
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
265286
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
@@ -1718,18 +1739,25 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17181739
// number of pending HTLCs that are on track to be in our next commitment tx, plus an additional
17191740
// HTLC if `fee_spike_buffer_htlc` is Some, plus a new HTLC given by `new_htlc_amount`. Dust HTLCs
17201741
// are excluded.
1721-
fn next_local_commit_tx_fee_msat(&self, new_htlc_amount: u64, locally_offered: bool, fee_spike_buffer_htlc: Option<()>) -> u64 {
1742+
fn next_local_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 {
17221743
assert!(self.is_outbound());
17231744

17241745
let real_dust_limit_success_sat = (self.feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000) + self.holder_dust_limit_satoshis;
17251746
let real_dust_limit_timeout_sat = (self.feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000) + self.holder_dust_limit_satoshis;
17261747

17271748
let mut addl_htlcs = 0;
17281749
if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
1729-
if locally_offered && new_htlc_amount / 1000 >= real_dust_limit_timeout_sat {
1730-
addl_htlcs += 1;
1731-
} else if !locally_offered && new_htlc_amount / 1000 >= real_dust_limit_success_sat {
1732-
addl_htlcs += 1;
1750+
match htlc.origin {
1751+
HTLCInitiator::LocalOffered => {
1752+
if htlc.amount_msat / 1000 >= real_dust_limit_timeout_sat {
1753+
addl_htlcs += 1;
1754+
}
1755+
},
1756+
HTLCInitiator::RemoteOffered => {
1757+
if htlc.amount_msat / 1000 >= real_dust_limit_success_sat {
1758+
addl_htlcs += 1;
1759+
}
1760+
}
17331761
}
17341762

17351763
let mut included_htlcs = 0;
@@ -1783,11 +1811,13 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17831811
let commitment_tx_info = CommitmentTxInfoCached {
17841812
fee,
17851813
total_pending_htlcs,
1786-
next_holder_htlc_id: if locally_offered { self.next_holder_htlc_id + 1 } else {
1787-
self.next_holder_htlc_id
1814+
next_holder_htlc_id: match htlc.origin {
1815+
HTLCInitiator::LocalOffered => self.next_holder_htlc_id + 1,
1816+
HTLCInitiator::RemoteOffered => self.next_holder_htlc_id,
17881817
},
1789-
next_counterparty_htlc_id: if locally_offered { self.next_counterparty_htlc_id } else {
1790-
self.next_counterparty_htlc_id + 1
1818+
next_counterparty_htlc_id: match htlc.origin {
1819+
HTLCInitiator::LocalOffered => self.next_counterparty_htlc_id,
1820+
HTLCInitiator::RemoteOffered => self.next_counterparty_htlc_id + 1,
17911821
},
17921822
feerate: self.feerate_per_kw,
17931823
};
@@ -1800,18 +1830,25 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
18001830
// pending HTLCs that are on track to be in their next commitment tx, plus an additional HTLC if
18011831
// `fee_spike_buffer_htlc` is Some, plus a new HTLC given by `new_htlc_amount`. Dust HTLCs are
18021832
// excluded.
1803-
fn next_remote_commit_tx_fee_msat(&self, new_htlc_amount: u64, locally_offered: bool, fee_spike_buffer_htlc: Option<()>) -> u64 {
1833+
fn next_remote_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 {
18041834
assert!(!self.is_outbound());
18051835

18061836
let real_dust_limit_success_sat = (self.feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000) + self.counterparty_dust_limit_satoshis;
18071837
let real_dust_limit_timeout_sat = (self.feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000) + self.counterparty_dust_limit_satoshis;
18081838

18091839
let mut addl_htlcs = 0;
18101840
if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
1811-
if locally_offered && new_htlc_amount / 1000 >= real_dust_limit_success_sat {
1812-
addl_htlcs += 1;
1813-
} else if !locally_offered && new_htlc_amount / 1000 >= real_dust_limit_timeout_sat {
1814-
addl_htlcs += 1;
1841+
match htlc.origin {
1842+
HTLCInitiator::LocalOffered => {
1843+
if htlc.amount_msat / 1000 >= real_dust_limit_success_sat {
1844+
addl_htlcs += 1;
1845+
}
1846+
},
1847+
HTLCInitiator::RemoteOffered => {
1848+
if htlc.amount_msat / 1000 >= real_dust_limit_timeout_sat {
1849+
addl_htlcs += 1;
1850+
}
1851+
}
18151852
}
18161853

18171854
// When calculating the set of HTLCs which will be included in their next commitment_signed, all
@@ -1851,11 +1888,13 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
18511888
let commitment_tx_info = CommitmentTxInfoCached {
18521889
fee,
18531890
total_pending_htlcs,
1854-
next_holder_htlc_id: if locally_offered { self.next_holder_htlc_id + 1 } else {
1855-
self.next_holder_htlc_id
1891+
next_holder_htlc_id: match htlc.origin {
1892+
HTLCInitiator::LocalOffered => self.next_holder_htlc_id + 1,
1893+
HTLCInitiator::RemoteOffered => self.next_holder_htlc_id,
18561894
},
1857-
next_counterparty_htlc_id: if locally_offered { self.next_counterparty_htlc_id } else {
1858-
self.next_counterparty_htlc_id + 1
1895+
next_counterparty_htlc_id: match htlc.origin {
1896+
HTLCInitiator::LocalOffered => self.next_counterparty_htlc_id,
1897+
HTLCInitiator::RemoteOffered => self.next_counterparty_htlc_id + 1,
18591898
},
18601899
feerate: self.feerate_per_kw,
18611900
};
@@ -1929,7 +1968,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
19291968
// Check that the remote can afford to pay for this HTLC on-chain at the current
19301969
// feerate_per_kw, while maintaining their channel reserve (as required by the spec).
19311970
let remote_commit_tx_fee_msat = if self.is_outbound() { 0 } else {
1932-
self.next_remote_commit_tx_fee_msat(msg.amount_msat, false, None) // Don't include the extra fee spike buffer HTLC in calculations
1971+
let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
1972+
self.next_remote_commit_tx_fee_msat(htlc_candidate, None) // Don't include the extra fee spike buffer HTLC in calculations
19331973
};
19341974
if pending_remote_value_msat - msg.amount_msat < remote_commit_tx_fee_msat {
19351975
return Err(ChannelError::Close("Remote HTLC add would not leave enough to pay for fees".to_owned()));
@@ -1950,7 +1990,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
19501990
// the extra htlc when calculating the next remote commitment transaction fee as we should
19511991
// still be able to afford adding this HTLC plus one more future HTLC, regardless of being
19521992
// sensitive to fee spikes.
1953-
let remote_fee_cost_incl_stuck_buffer_msat = 2 * self.next_remote_commit_tx_fee_msat(msg.amount_msat, false, Some(()));
1993+
let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
1994+
let remote_fee_cost_incl_stuck_buffer_msat = 2 * self.next_remote_commit_tx_fee_msat(htlc_candidate, Some(()));
19541995
if pending_remote_value_msat - msg.amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat {
19551996
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
19561997
// the HTLC, i.e. its status is already set to failing.
@@ -1959,7 +2000,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
19592000
}
19602001
} else {
19612002
// Check that they won't violate our local required channel reserve by adding this HTLC.
1962-
let local_commit_tx_fee_msat = self.next_local_commit_tx_fee_msat(msg.amount_msat, false, None);
2003+
let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
2004+
let local_commit_tx_fee_msat = self.next_local_commit_tx_fee_msat(htlc_candidate, None);
19632005
if self.value_to_self_msat < self.counterparty_selected_channel_reserve_satoshis * 1000 + local_commit_tx_fee_msat {
19642006
return Err(ChannelError::Close("Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_owned()));
19652007
}
@@ -3863,7 +3905,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
38633905
// Check that we won't violate the remote channel reserve by adding this HTLC.
38643906
let counterparty_balance_msat = self.channel_value_satoshis * 1000 - self.value_to_self_msat;
38653907
let holder_selected_chan_reserve_msat = Channel::<ChanSigner>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis);
3866-
let counterparty_commit_tx_fee_msat = self.next_remote_commit_tx_fee_msat(amount_msat, true, None);
3908+
let htlc_candidate = HTLCCandidate::new(amount_msat, HTLCInitiator::LocalOffered);
3909+
let counterparty_commit_tx_fee_msat = self.next_remote_commit_tx_fee_msat(htlc_candidate, None);
38673910
if counterparty_balance_msat < holder_selected_chan_reserve_msat + counterparty_commit_tx_fee_msat {
38683911
return Err(ChannelError::Ignore("Cannot send value that would put counterparty balance under holder-announced channel reserve value".to_owned()));
38693912
}
@@ -3876,7 +3919,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
38763919

38773920
// `2 *` and extra HTLC are for the fee spike buffer.
38783921
let commit_tx_fee_msat = if self.is_outbound() {
3879-
2 * self.next_local_commit_tx_fee_msat(amount_msat, true, Some(()))
3922+
let htlc_candidate = HTLCCandidate::new(amount_msat, HTLCInitiator::LocalOffered);
3923+
2 * self.next_local_commit_tx_fee_msat(htlc_candidate, Some(()))
38803924
} else { 0 };
38813925
if pending_value_to_self_msat - amount_msat < commit_tx_fee_msat {
38823926
return Err(ChannelError::Ignore(format!("Cannot send value that would not leave enough to pay for fees. Pending value to self: {}. local_commit_tx_fee {}", pending_value_to_self_msat, commit_tx_fee_msat)));
@@ -4648,7 +4692,7 @@ mod tests {
46484692
use bitcoin::hashes::hex::FromHex;
46494693
use hex;
46504694
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
4651-
use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys};
4695+
use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys};
46524696
use ln::channel::MAX_FUNDING_SATOSHIS;
46534697
use ln::features::InitFeatures;
46544698
use ln::msgs::{OptionalField, DataLossProtect, DecodeError};
@@ -4791,15 +4835,17 @@ mod tests {
47914835

47924836
// Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
47934837
// the dust limit check.
4794-
let local_commit_tx_fee = node_a_chan.next_local_commit_tx_fee_msat(htlc_amount_msat, true, None);
4838+
let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
4839+
let local_commit_tx_fee = node_a_chan.next_local_commit_tx_fee_msat(htlc_candidate, None);
47954840
let local_commit_fee_0_htlcs = node_a_chan.commit_tx_fee_msat(0);
47964841
assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs);
47974842

47984843
// Finally, make sure that when Node A calculates the remote's commitment transaction fees, all
47994844
// of the HTLCs are seen to be above the dust limit.
48004845
node_a_chan.channel_transaction_parameters.is_outbound_from_holder = false;
48014846
let remote_commit_fee_3_htlcs = node_a_chan.commit_tx_fee_msat(3);
4802-
let remote_commit_tx_fee = node_a_chan.next_remote_commit_tx_fee_msat(htlc_amount_msat, true, None);
4847+
let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
4848+
let remote_commit_tx_fee = node_a_chan.next_remote_commit_tx_fee_msat(htlc_candidate, None);
48034849
assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs);
48044850
}
48054851

@@ -4825,24 +4871,28 @@ mod tests {
48254871
// If HTLC_SUCCESS_TX_WEIGHT and HTLC_TIMEOUT_TX_WEIGHT were swapped: then this HTLC would be
48264872
// counted as dust when it shouldn't be.
48274873
let htlc_amt_above_timeout = ((253 * HTLC_TIMEOUT_TX_WEIGHT / 1000) + chan.holder_dust_limit_satoshis + 1) * 1000;
4828-
let commitment_tx_fee = chan.next_local_commit_tx_fee_msat(htlc_amt_above_timeout, true, None);
4874+
let htlc_candidate = HTLCCandidate::new(htlc_amt_above_timeout, HTLCInitiator::LocalOffered);
4875+
let commitment_tx_fee = chan.next_local_commit_tx_fee_msat(htlc_candidate, None);
48294876
assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
48304877

48314878
// If swapped: this HTLC would be counted as non-dust when it shouldn't be.
48324879
let dust_htlc_amt_below_success = ((253 * HTLC_SUCCESS_TX_WEIGHT / 1000) + chan.holder_dust_limit_satoshis - 1) * 1000;
4833-
let commitment_tx_fee = chan.next_local_commit_tx_fee_msat(dust_htlc_amt_below_success, false, None);
4880+
let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_below_success, HTLCInitiator::RemoteOffered);
4881+
let commitment_tx_fee = chan.next_local_commit_tx_fee_msat(htlc_candidate, None);
48344882
assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
48354883

48364884
chan.channel_transaction_parameters.is_outbound_from_holder = false;
48374885

48384886
// If swapped: this HTLC would be counted as non-dust when it shouldn't be.
48394887
let dust_htlc_amt_above_timeout = ((253 * HTLC_TIMEOUT_TX_WEIGHT / 1000) + chan.counterparty_dust_limit_satoshis + 1) * 1000;
4840-
let commitment_tx_fee = chan.next_remote_commit_tx_fee_msat(dust_htlc_amt_above_timeout, true, None);
4888+
let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_above_timeout, HTLCInitiator::LocalOffered);
4889+
let commitment_tx_fee = chan.next_remote_commit_tx_fee_msat(htlc_candidate, None);
48414890
assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
48424891

48434892
// If swapped: this HTLC would be counted as dust when it shouldn't be.
48444893
let htlc_amt_below_success = ((253 * HTLC_SUCCESS_TX_WEIGHT / 1000) + chan.counterparty_dust_limit_satoshis - 1) * 1000;
4845-
let commitment_tx_fee = chan.next_remote_commit_tx_fee_msat(htlc_amt_below_success, false, None);
4894+
let htlc_candidate = HTLCCandidate::new(htlc_amt_below_success, HTLCInitiator::RemoteOffered);
4895+
let commitment_tx_fee = chan.next_remote_commit_tx_fee_msat(htlc_candidate, None);
48464896
assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
48474897
}
48484898

0 commit comments

Comments
 (0)