From 27b99acd6442f5aafe33cf20d38045f2b942244a Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Tue, 16 May 2023 16:14:40 -0400 Subject: [PATCH] Add PaymentClaimable::counterparty_skimmed_fee_msat See its docs --- lightning/src/events/mod.rs | 28 +++++++++++++++++-- lightning/src/ln/channelmanager.rs | 3 ++ lightning/src/ln/functional_test_utils.rs | 2 +- lightning/src/util/config.rs | 4 +++ .../forward-underpaying-htlc.txt | 2 ++ 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index b4b5bf83..3d8f8908 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -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, - /// 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::; // 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, diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 808c7ffc..4444e6cc 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -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), diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 6107642c..9f1ffb28 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -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()); diff --git a/lightning/src/util/config.rs b/lightning/src/util/config.rs index b948a138..1faf595a 100644 --- a/lightning/src/util/config.rs +++ b/lightning/src/util/config.rs @@ -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, } diff --git a/pending_changelog/forward-underpaying-htlc.txt b/pending_changelog/forward-underpaying-htlc.txt index 21f4a146..5b6c2237 100644 --- a/pending_changelog/forward-underpaying-htlc.txt +++ b/pending_changelog/forward-underpaying-htlc.txt @@ -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. -- 2.30.2