Add PaymentClaimable::counterparty_skimmed_fee_msat
authorValentine Wallace <vwallace@protonmail.com>
Tue, 16 May 2023 20:14:40 +0000 (16:14 -0400)
committerValentine Wallace <vwallace@protonmail.com>
Tue, 20 Jun 2023 21:57:38 +0000 (17:57 -0400)
See its docs

lightning/src/events/mod.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/util/config.rs
pending_changelog/forward-underpaying-htlc.txt

index b4b5bf838ee1a7ab001506a958564861549cf8f6..3d8f890861cb69292431975025f3869c3dc8e409 100644 (file)
@@ -387,8 +387,24 @@ pub enum Event {
                ///
                /// Payments received on LDK versions prior to 0.0.115 will have this field unset.
                onion_fields: Option<RecipientOnionFields>,
-               /// The value, in thousandths of a satoshi, that this payment is for.
+               /// The value, in thousandths of a satoshi, that this payment is claimable for.
+               ///
+               /// May be less than the invoice amount if [`ChannelConfig::accept_underpaying_htlcs`] is set
+               /// and the previous hop took an extra fee.
+               ///
+               /// # Note
+               /// If [`ChannelConfig::accept_underpaying_htlcs`] is set and you claim without verifying this
+               /// field, you may lose money!
+               ///
+               /// [`ChannelConfig::accept_underpaying_htlcs`]: crate::util::config::ChannelConfig::accept_underpaying_htlcs
                amount_msat: u64,
+               /// The value, in thousands of a satoshi, that was skimmed off of this payment as an extra fee
+               /// taken by our channel counterparty.
+               ///
+               /// Will always be 0 unless [`ChannelConfig::accept_underpaying_htlcs`] is set.
+               ///
+               /// [`ChannelConfig::accept_underpaying_htlcs`]: crate::util::config::ChannelConfig::accept_underpaying_htlcs
+               counterparty_skimmed_fee_msat: u64,
                /// Information for claiming this received payment, based on whether the purpose of the
                /// payment is to pay an invoice or to send a spontaneous payment.
                purpose: PaymentPurpose,
@@ -833,8 +849,8 @@ impl Writeable for Event {
                                // We never write out FundingGenerationReady events as, upon disconnection, peers
                                // drop any channels which have not yet exchanged funding_signed.
                        },
-                       &Event::PaymentClaimable { ref payment_hash, ref amount_msat, ref purpose,
-                               ref receiver_node_id, ref via_channel_id, ref via_user_channel_id,
+                       &Event::PaymentClaimable { ref payment_hash, ref amount_msat, counterparty_skimmed_fee_msat,
+                               ref purpose, ref receiver_node_id, ref via_channel_id, ref via_user_channel_id,
                                ref claim_deadline, ref onion_fields
                        } => {
                                1u8.write(writer)?;
@@ -849,6 +865,8 @@ impl Writeable for Event {
                                                payment_preimage = Some(*preimage);
                                        }
                                }
+                               let skimmed_fee_opt = if counterparty_skimmed_fee_msat == 0 { None }
+                                       else { Some(counterparty_skimmed_fee_msat) };
                                write_tlv_fields!(writer, {
                                        (0, payment_hash, required),
                                        (1, receiver_node_id, option),
@@ -860,6 +878,7 @@ impl Writeable for Event {
                                        (7, claim_deadline, option),
                                        (8, payment_preimage, option),
                                        (9, onion_fields, option),
+                                       (10, skimmed_fee_opt, option),
                                });
                        },
                        &Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => {
@@ -1059,6 +1078,7 @@ impl MaybeReadable for Event {
                                        let mut payment_preimage = None;
                                        let mut payment_secret = None;
                                        let mut amount_msat = 0;
+                                       let mut counterparty_skimmed_fee_msat_opt = None;
                                        let mut receiver_node_id = None;
                                        let mut _user_payment_id = None::<u64>; // For compatibility with 0.0.103 and earlier
                                        let mut via_channel_id = None;
@@ -1076,6 +1096,7 @@ impl MaybeReadable for Event {
                                                (7, claim_deadline, option),
                                                (8, payment_preimage, option),
                                                (9, onion_fields, option),
+                                               (10, counterparty_skimmed_fee_msat_opt, option),
                                        });
                                        let purpose = match payment_secret {
                                                Some(secret) => PaymentPurpose::InvoicePayment {
@@ -1089,6 +1110,7 @@ impl MaybeReadable for Event {
                                                receiver_node_id,
                                                payment_hash,
                                                amount_msat,
+                                               counterparty_skimmed_fee_msat: counterparty_skimmed_fee_msat_opt.unwrap_or(0),
                                                purpose,
                                                via_channel_id,
                                                via_user_channel_id,
index 808c7ffcd3ac2196e5961f406f13d5f347fee0c5..4444e6cc50189e75b17f1afec9856177904b2347 100644 (file)
@@ -3923,11 +3923,14 @@ where
                                                                                        htlcs.push(claimable_htlc);
                                                                                        let amount_msat = htlcs.iter().map(|htlc| htlc.value).sum();
                                                                                        htlcs.iter_mut().for_each(|htlc| htlc.total_value_received = Some(amount_msat));
+                                                                                       let counterparty_skimmed_fee_msat = htlcs.iter()
+                                                                                               .map(|htlc| htlc.counterparty_skimmed_fee_msat.unwrap_or(0)).sum();
                                                                                        new_events.push_back((events::Event::PaymentClaimable {
                                                                                                receiver_node_id: Some(receiver_node_id),
                                                                                                payment_hash,
                                                                                                purpose: $purpose,
                                                                                                amount_msat,
+                                                                                               counterparty_skimmed_fee_msat,
                                                                                                via_channel_id: Some(prev_channel_id),
                                                                                                via_user_channel_id: Some(prev_user_channel_id),
                                                                                                claim_deadline: Some(earliest_expiry - HTLC_FAIL_BACK_BUFFER),
index 6107642cbf27c644bbe66691853adf3709d7fe8d..9f1ffb28b6b6a38858cc4f004967db96e7b8b598 100644 (file)
@@ -2124,7 +2124,7 @@ pub fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_p
                                match &events_2[0] {
                                        Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat,
                                                receiver_node_id, ref via_channel_id, ref via_user_channel_id,
-                                               claim_deadline, onion_fields,
+                                               claim_deadline, onion_fields, ..
                                        } => {
                                                assert_eq!(our_payment_hash, *payment_hash);
                                                assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap());
index b948a13835708db4ee3cb6328b5951f733f1b1a1..1faf595ac8fabc7440729f24c14bc6e2cc34b6e7 100644 (file)
@@ -412,9 +412,12 @@ pub struct ChannelConfig {
        /// # Note
        /// It's important for payee wallet software to verify that [`PaymentClaimable::amount_msat`] is
        /// as-expected if this feature is activated, otherwise they may lose money!
+       /// [`PaymentClaimable::counterparty_skimmed_fee_msat`] provides the fee taken by the
+       /// counterparty.
        ///
        /// # Note
        /// Switching this config flag on may break compatibility with versions of LDK prior to 0.0.116.
+       /// Unsetting this flag between restarts may lead to payment receive failures.
        ///
        /// Default value: false.
        ///
@@ -423,6 +426,7 @@ pub struct ChannelConfig {
        /// [`HTLCIntercepted`]: crate::events::Event::HTLCIntercepted
        /// [`HTLCIntercepted::expected_outbound_amount_msat`]: crate::events::Event::HTLCIntercepted::expected_outbound_amount_msat
        /// [`PaymentClaimable::amount_msat`]: crate::events::Event::PaymentClaimable::amount_msat
+       /// [`PaymentClaimable::counterparty_skimmed_fee_msat`]: crate::events::Event::PaymentClaimable::counterparty_skimmed_fee_msat
        //  TODO: link to bLIP when it's merged
        pub accept_underpaying_htlcs: bool,
 }
index 21f4a14642ad96797d5fb7642b2d16f60a7813ff..5b6c223775391a30a84f610a953ac3d30e8bad46 100644 (file)
@@ -2,3 +2,5 @@
 
 * Forwarding less than the expected amount in `ChannelManager::forward_intercepted_htlc` may break
        compatibility with versions of LDK prior to 0.0.116
+* Setting `ChannelConfig::accept_underpaying_htlcs` may break compatibility with versions of LDK
+       prior to 0.0.116, and unsetting the feature between restarts may lead to payment failures.