@@ -1064,13 +1064,6 @@ pub enum AnnouncementSigsState {
10641064 PeerReceived,
10651065}
10661066
1067- /// An enum indicating whether the local or remote side offered a given HTLC.
1068- enum HTLCInitiator {
1069- LocalOffered,
1070- #[allow(dead_code)]
1071- RemoteOffered,
1072- }
1073-
10741067/// A struct gathering data on a commitment, either local or remote.
10751068struct CommitmentData<'a> {
10761069 tx: CommitmentTransaction,
@@ -1090,18 +1083,6 @@ pub(crate) struct CommitmentStats {
10901083 pub remote_balance_before_fee_msat: u64,
10911084}
10921085
1093- /// Used when calculating whether we or the remote can afford an additional HTLC.
1094- struct HTLCCandidate {
1095- amount_msat: u64,
1096- origin: HTLCInitiator,
1097- }
1098-
1099- impl HTLCCandidate {
1100- fn new(amount_msat: u64, origin: HTLCInitiator) -> Self {
1101- Self { amount_msat, origin }
1102- }
1103- }
1104-
11051086/// A return value enum for get_update_fulfill_htlc. See UpdateFulfillCommitFetch variants for
11061087/// description
11071088enum UpdateFulfillFetch {
@@ -5603,169 +5584,6 @@ where
56035584 )
56045585 }
56055586
5606- /// Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
5607- /// number of pending HTLCs that are on track to be in our next commitment tx.
5608- ///
5609- /// Includes the `HTLCCandidate` given by `htlc` and an additional non-dust HTLC if
5610- /// `fee_spike_buffer_htlc` is `Some`.
5611- ///
5612- /// The first extra HTLC is useful for determining whether we can accept a further HTLC, the
5613- /// second allows for creating a buffer to ensure a further HTLC can always be accepted/added.
5614- ///
5615- /// Dust HTLCs are excluded.
5616- #[rustfmt::skip]
5617- fn next_local_commit_tx_fee_msat(
5618- &self, funding: &FundingScope, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>,
5619- ) -> u64 {
5620- let context = self;
5621- assert!(funding.is_outbound());
5622-
5623- if funding.get_channel_type().supports_anchor_zero_fee_commitments() {
5624- debug_assert_eq!(context.feerate_per_kw, 0);
5625- debug_assert!(fee_spike_buffer_htlc.is_none());
5626- return 0;
5627- }
5628-
5629- let (htlc_success_tx_fee_sat, htlc_timeout_tx_fee_sat) = second_stage_tx_fees_sat(
5630- funding.get_channel_type(), context.feerate_per_kw,
5631- );
5632- let real_dust_limit_success_sat = htlc_success_tx_fee_sat + context.holder_dust_limit_satoshis;
5633- let real_dust_limit_timeout_sat = htlc_timeout_tx_fee_sat + context.holder_dust_limit_satoshis;
5634-
5635- let mut addl_htlcs = 0;
5636- if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
5637- match htlc.origin {
5638- HTLCInitiator::LocalOffered => {
5639- if htlc.amount_msat / 1000 >= real_dust_limit_timeout_sat {
5640- addl_htlcs += 1;
5641- }
5642- },
5643- HTLCInitiator::RemoteOffered => {
5644- if htlc.amount_msat / 1000 >= real_dust_limit_success_sat {
5645- addl_htlcs += 1;
5646- }
5647- }
5648- }
5649-
5650- let mut included_htlcs = 0;
5651- for ref htlc in context.pending_inbound_htlcs.iter() {
5652- if htlc.amount_msat / 1000 < real_dust_limit_success_sat {
5653- continue
5654- }
5655- // We include LocalRemoved HTLCs here because we may still need to broadcast a commitment
5656- // transaction including this HTLC if it times out before they RAA.
5657- included_htlcs += 1;
5658- }
5659-
5660- for ref htlc in context.pending_outbound_htlcs.iter() {
5661- if htlc.amount_msat / 1000 < real_dust_limit_timeout_sat {
5662- continue
5663- }
5664- match htlc.state {
5665- OutboundHTLCState::LocalAnnounced {..} => included_htlcs += 1,
5666- OutboundHTLCState::Committed => included_htlcs += 1,
5667- OutboundHTLCState::RemoteRemoved {..} => included_htlcs += 1,
5668- // We don't include AwaitingRemoteRevokeToRemove HTLCs because our next commitment
5669- // transaction won't be generated until they send us their next RAA, which will mean
5670- // dropping any HTLCs in this state.
5671- _ => {},
5672- }
5673- }
5674-
5675- for htlc in context.holding_cell_htlc_updates.iter() {
5676- match htlc {
5677- &HTLCUpdateAwaitingACK::AddHTLC { amount_msat, .. } => {
5678- if amount_msat / 1000 < real_dust_limit_timeout_sat {
5679- continue
5680- }
5681- included_htlcs += 1
5682- },
5683- _ => {}, // Don't include claims/fails that are awaiting ack, because once we get the
5684- // ack we're guaranteed to never include them in commitment txs anymore.
5685- }
5686- }
5687-
5688- let num_htlcs = included_htlcs + addl_htlcs;
5689- SpecTxBuilder {}.commit_tx_fee_sat(context.feerate_per_kw, num_htlcs, funding.get_channel_type()) * 1000
5690- }
5691-
5692- /// Get the commitment tx fee for the remote's next commitment transaction based on the number of
5693- /// pending HTLCs that are on track to be in their next commitment tx
5694- ///
5695- /// Optionally includes the `HTLCCandidate` given by `htlc` and an additional non-dust HTLC if
5696- /// `fee_spike_buffer_htlc` is `Some`.
5697- ///
5698- /// The first extra HTLC is useful for determining whether we can accept a further HTLC, the
5699- /// second allows for creating a buffer to ensure a further HTLC can always be accepted/added.
5700- ///
5701- /// Dust HTLCs are excluded.
5702- #[rustfmt::skip]
5703- fn next_remote_commit_tx_fee_msat(
5704- &self, funding: &FundingScope, htlc: Option<HTLCCandidate>, fee_spike_buffer_htlc: Option<()>,
5705- ) -> u64 {
5706- let context = self;
5707- assert!(!funding.is_outbound());
5708-
5709- if funding.get_channel_type().supports_anchor_zero_fee_commitments() {
5710- debug_assert_eq!(context.feerate_per_kw, 0);
5711- debug_assert!(fee_spike_buffer_htlc.is_none());
5712- return 0
5713- }
5714-
5715- debug_assert!(htlc.is_some() || fee_spike_buffer_htlc.is_some(), "At least one of the options must be set");
5716-
5717- let (htlc_success_tx_fee_sat, htlc_timeout_tx_fee_sat) = second_stage_tx_fees_sat(
5718- funding.get_channel_type(), context.feerate_per_kw,
5719- );
5720- let real_dust_limit_success_sat = htlc_success_tx_fee_sat + context.counterparty_dust_limit_satoshis;
5721- let real_dust_limit_timeout_sat = htlc_timeout_tx_fee_sat + context.counterparty_dust_limit_satoshis;
5722-
5723- let mut addl_htlcs = 0;
5724- if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
5725- if let Some(htlc) = &htlc {
5726- match htlc.origin {
5727- HTLCInitiator::LocalOffered => {
5728- if htlc.amount_msat / 1000 >= real_dust_limit_success_sat {
5729- addl_htlcs += 1;
5730- }
5731- },
5732- HTLCInitiator::RemoteOffered => {
5733- if htlc.amount_msat / 1000 >= real_dust_limit_timeout_sat {
5734- addl_htlcs += 1;
5735- }
5736- }
5737- }
5738- }
5739-
5740- // When calculating the set of HTLCs which will be included in their next commitment_signed, all
5741- // non-dust inbound HTLCs are included (as all states imply it will be included) and only
5742- // committed outbound HTLCs, see below.
5743- let mut included_htlcs = 0;
5744- for ref htlc in context.pending_inbound_htlcs.iter() {
5745- if htlc.amount_msat / 1000 < real_dust_limit_timeout_sat {
5746- continue
5747- }
5748- included_htlcs += 1;
5749- }
5750-
5751- for ref htlc in context.pending_outbound_htlcs.iter() {
5752- if htlc.amount_msat / 1000 < real_dust_limit_success_sat {
5753- continue
5754- }
5755- // We only include outbound HTLCs if it will not be included in their next commitment_signed,
5756- // i.e. if they've responded to us with an RAA after announcement.
5757- match htlc.state {
5758- OutboundHTLCState::Committed => included_htlcs += 1,
5759- OutboundHTLCState::RemoteRemoved {..} => included_htlcs += 1,
5760- OutboundHTLCState::LocalAnnounced { .. } => included_htlcs += 1,
5761- _ => {},
5762- }
5763- }
5764-
5765- let num_htlcs = included_htlcs + addl_htlcs;
5766- SpecTxBuilder {}.commit_tx_fee_sat(context.feerate_per_kw, num_htlcs, funding.get_channel_type()) * 1000
5767- }
5768-
57695587 #[rustfmt::skip]
57705588 fn if_unbroadcasted_funding<F, O>(&self, f: F) -> Option<O> where F: Fn() -> Option<O> {
57715589 match self.channel_state {
@@ -15619,9 +15437,9 @@ mod tests {
1561915437 use crate::chain::BestBlock;
1562015438 use crate::ln::chan_utils::{self, commit_tx_fee_sat, ChannelTransactionParameters};
1562115439 use crate::ln::channel::{
15622- AwaitingChannelReadyFlags, ChannelState, FundedChannel, HTLCCandidate, HTLCInitiator ,
15623- HTLCUpdateAwaitingACK, InboundHTLCOutput, InboundHTLCState, InboundV1Channel,
15624- OutboundHTLCOutput, OutboundHTLCState, OutboundV1Channel,
15440+ AwaitingChannelReadyFlags, ChannelState, FundedChannel, HTLCUpdateAwaitingACK ,
15441+ InboundHTLCOutput, InboundHTLCState, InboundV1Channel, OutboundHTLCOutput ,
15442+ OutboundHTLCState, OutboundV1Channel,
1562515443 };
1562615444 use crate::ln::channel::{
1562715445 MAX_FUNDING_SATOSHIS_NO_WUMBO, MIN_THEIR_CHAN_RESERVE_SATOSHIS,
@@ -15636,6 +15454,7 @@ mod tests {
1563615454 use crate::ln::script::ShutdownScript;
1563715455 use crate::prelude::*;
1563815456 use crate::routing::router::{Path, RouteHop};
15457+ use crate::sign::tx_builder::HTLCAmountDirection;
1563915458 #[cfg(ldk_test_vectors)]
1564015459 use crate::sign::{ChannelSigner, EntropySource, InMemorySigner, SignerProvider};
1564115460 use crate::sync::Mutex;
@@ -15832,7 +15651,7 @@ mod tests {
1583215651 // Create Node A's channel pointing to Node B's pubkey
1583315652 let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
1583415653 let config = UserConfig::default();
15835- let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10000000, 100000 , 42, &config, 0, 42, None, &logger).unwrap();
15654+ let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_init_features(&config), 10_000_000, 100_000_000 , 42, &config, 0, 42, None, &logger).unwrap();
1583615655
1583715656 // Create Node B's channel by receiving Node A's open_channel message
1583815657 // Make sure A's dust limit is as we expect.
@@ -15890,24 +15709,24 @@ mod tests {
1589015709
1589115710 // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
1589215711 // the dust limit check.
15893- let htlc_candidate = HTLCCandidate::new( htlc_amount_msat, HTLCInitiator::LocalOffered) ;
15894- let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat (&node_a_chan.funding, htlc_candidate, None);
15712+ let htlc_candidate = HTLCAmountDirection { amount_msat: htlc_amount_msat, outbound: true } ;
15713+ let local_commit_tx_fee = node_a_chan.context.get_next_local_commitment_stats (&node_a_chan.funding, Some( htlc_candidate), true, 0, node_a_chan.context.feerate_per_kw, None).unwrap().commit_tx_fee_sat * 1000 ;
1589515714 let local_commit_fee_0_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.funding.get_channel_type()) * 1000;
1589615715 assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs);
1589715716
1589815717 // Finally, make sure that when Node A calculates the remote's commitment transaction fees, all
1589915718 // of the HTLCs are seen to be above the dust limit.
1590015719 node_a_chan.funding.channel_transaction_parameters.is_outbound_from_holder = false;
1590115720 let remote_commit_fee_3_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.funding.get_channel_type()) * 1000;
15902- let htlc_candidate = HTLCCandidate::new( htlc_amount_msat, HTLCInitiator::LocalOffered) ;
15903- let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat (&node_a_chan.funding, Some(htlc_candidate), None);
15721+ let htlc_candidate = HTLCAmountDirection { amount_msat: htlc_amount_msat, outbound: true } ;
15722+ let remote_commit_tx_fee = node_a_chan.context.get_next_remote_commitment_stats (&node_a_chan.funding, Some(htlc_candidate), true, 0, node_a_chan.context.feerate_per_kw, None).unwrap().commit_tx_fee_sat * 1000 ;
1590415723 assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs);
1590515724 }
1590615725
1590715726 #[test]
1590815727 #[rustfmt::skip]
1590915728 fn test_timeout_vs_success_htlc_dust_limit() {
15910- // Make sure that when `next_remote_commit_tx_fee_msat` and `next_local_commit_tx_fee_msat `
15729+ // Make sure that when `get_next_local/remote_commitment_stats `
1591115730 // calculate the real dust limits for HTLCs (i.e. the dust limit given by the counterparty
1591215731 // *plus* the fees paid for the HTLC) they don't swap `HTLC_SUCCESS_TX_WEIGHT` for
1591315732 // `HTLC_TIMEOUT_TX_WEIGHT`, and vice versa.
@@ -15921,7 +15740,7 @@ mod tests {
1592115740
1592215741 let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
1592315742 let config = UserConfig::default();
15924- let mut chan = OutboundV1Channel::<&TestKeysInterface>::new(&fee_est, &&keys_provider, &&keys_provider, node_id, &channelmanager::provided_init_features(&config), 10000000, 100000 , 42, &config, 0, 42, None, &logger).unwrap();
15743+ let mut chan = OutboundV1Channel::<&TestKeysInterface>::new(&fee_est, &&keys_provider, &&keys_provider, node_id, &channelmanager::provided_init_features(&config), 10_000_000, 100_000_000 , 42, &config, 0, 42, None, &logger).unwrap();
1592515744
1592615745 let commitment_tx_fee_0_htlcs = commit_tx_fee_sat(chan.context.feerate_per_kw, 0, chan.funding.get_channel_type()) * 1000;
1592715746 let commitment_tx_fee_1_htlc = commit_tx_fee_sat(chan.context.feerate_per_kw, 1, chan.funding.get_channel_type()) * 1000;
@@ -15932,28 +15751,28 @@ mod tests {
1593215751 // If HTLC_SUCCESS_TX_WEIGHT and HTLC_TIMEOUT_TX_WEIGHT were swapped: then this HTLC would be
1593315752 // counted as dust when it shouldn't be.
1593415753 let htlc_amt_above_timeout = (htlc_timeout_tx_fee_sat + chan.context.holder_dust_limit_satoshis + 1) * 1000;
15935- let htlc_candidate = HTLCCandidate::new( htlc_amt_above_timeout, HTLCInitiator::LocalOffered) ;
15936- let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat (&chan.funding, htlc_candidate, None);
15754+ let htlc_candidate = HTLCAmountDirection { amount_msat: htlc_amt_above_timeout, outbound: true } ;
15755+ let commitment_tx_fee = chan.context.get_next_local_commitment_stats (&chan.funding, Some( htlc_candidate), true, 0, chan.context.feerate_per_kw, None).unwrap().commit_tx_fee_sat * 1000 ;
1593715756 assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
1593815757
1593915758 // If swapped: this HTLC would be counted as non-dust when it shouldn't be.
1594015759 let dust_htlc_amt_below_success = (htlc_success_tx_fee_sat + chan.context.holder_dust_limit_satoshis - 1) * 1000;
15941- let htlc_candidate = HTLCCandidate::new( dust_htlc_amt_below_success, HTLCInitiator::RemoteOffered) ;
15942- let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat (&chan.funding, htlc_candidate, None);
15760+ let htlc_candidate = HTLCAmountDirection { amount_msat: dust_htlc_amt_below_success, outbound: false } ;
15761+ let commitment_tx_fee = chan.context.get_next_local_commitment_stats (&chan.funding, Some( htlc_candidate), true, 0, chan.context.feerate_per_kw, None).unwrap().commit_tx_fee_sat * 1000 ;
1594315762 assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
1594415763
1594515764 chan.funding.channel_transaction_parameters.is_outbound_from_holder = false;
1594615765
1594715766 // If swapped: this HTLC would be counted as non-dust when it shouldn't be.
1594815767 let dust_htlc_amt_above_timeout = (htlc_timeout_tx_fee_sat + chan.context.counterparty_dust_limit_satoshis + 1) * 1000;
15949- let htlc_candidate = HTLCCandidate::new( dust_htlc_amt_above_timeout, HTLCInitiator::LocalOffered) ;
15950- let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat (&chan.funding, Some(htlc_candidate), None);
15768+ let htlc_candidate = HTLCAmountDirection { amount_msat: dust_htlc_amt_above_timeout, outbound: true } ;
15769+ let commitment_tx_fee = chan.context.get_next_remote_commitment_stats (&chan.funding, Some(htlc_candidate), false, 0, chan.context.feerate_per_kw, None).unwrap().commit_tx_fee_sat * 1000 ;
1595115770 assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
1595215771
1595315772 // If swapped: this HTLC would be counted as dust when it shouldn't be.
1595415773 let htlc_amt_below_success = (htlc_success_tx_fee_sat + chan.context.counterparty_dust_limit_satoshis - 1) * 1000;
15955- let htlc_candidate = HTLCCandidate::new( htlc_amt_below_success, HTLCInitiator::RemoteOffered) ;
15956- let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat (&chan.funding, Some(htlc_candidate), None);
15774+ let htlc_candidate = HTLCAmountDirection { amount_msat: htlc_amt_below_success, outbound: false } ;
15775+ let commitment_tx_fee = chan.context.get_next_remote_commitment_stats (&chan.funding, Some(htlc_candidate), false, 0, chan.context.feerate_per_kw, None).unwrap().commit_tx_fee_sat * 1000 ;
1595715776 assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
1595815777 }
1595915778
0 commit comments