Track the amount spent on fees as payments are retried 2021-10-on-sent-fees
authorMatt Corallo <git@bluematt.me>
Wed, 27 Oct 2021 19:04:22 +0000 (19:04 +0000)
committerMatt Corallo <git@bluematt.me>
Wed, 27 Oct 2021 20:43:18 +0000 (20:43 +0000)
Especially once we merge the `InvoicePayer` logic soon, we'll want
to expose the total fee paid in the `PaymentSent` event.

lightning-invoice/src/payment.rs
lightning/src/ln/chanmon_update_fail_tests.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/payment_tests.rs
lightning/src/ln/shutdown_tests.rs
lightning/src/util/events.rs

index 7e931d66f153a4f530d7cbb9af1623dfb1ee4e2c..4603f2bbb21f60750ce8cf2e55f9d80dfcd20674 100644 (file)
@@ -430,7 +430,7 @@ mod tests {
                assert_eq!(*payer.attempts.borrow(), 1);
 
                invoice_payer.handle_event(&Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash
+                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
                });
                assert_eq!(*event_handled.borrow(), true);
                assert_eq!(*payer.attempts.borrow(), 1);
@@ -472,7 +472,7 @@ mod tests {
                assert_eq!(*payer.attempts.borrow(), 2);
 
                invoice_payer.handle_event(&Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash
+                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
                });
                assert_eq!(*event_handled.borrow(), true);
                assert_eq!(*payer.attempts.borrow(), 2);
@@ -514,7 +514,7 @@ mod tests {
                assert_eq!(*payer.attempts.borrow(), 2);
 
                invoice_payer.handle_event(&Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash
+                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
                });
                assert_eq!(*event_handled.borrow(), true);
                assert_eq!(*payer.attempts.borrow(), 2);
@@ -802,7 +802,7 @@ mod tests {
                assert_eq!(*payer.attempts.borrow(), 1);
 
                invoice_payer.handle_event(&Event::PaymentSent {
-                       payment_id, payment_preimage, payment_hash
+                       payment_id, payment_preimage, payment_hash, fee_paid_msat: None
                });
                assert_eq!(*event_handled.borrow(), true);
                assert_eq!(*payer.attempts.borrow(), 1);
index e9b93237e3262222c7d384670be6423ea0bd4661..feefd8c18f1ecce8e9776f348b75bcb16f010f32 100644 (file)
@@ -304,7 +304,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
                                let events_3 = nodes[0].node.get_and_clear_pending_events();
                                assert_eq!(events_3.len(), 1);
                                match events_3[0] {
-                                       Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+                                       Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                                                assert_eq!(*payment_preimage, payment_preimage_1);
                                                assert_eq!(*payment_hash, payment_hash_1);
                                        },
@@ -397,7 +397,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
                        let events_3 = nodes[0].node.get_and_clear_pending_events();
                        assert_eq!(events_3.len(), 1);
                        match events_3[0] {
-                               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+                               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                                        assert_eq!(*payment_preimage, payment_preimage_1);
                                        assert_eq!(*payment_hash, payment_hash_1);
                                },
@@ -1399,7 +1399,7 @@ fn claim_while_disconnected_monitor_update_fail() {
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 1);
        match events[0] {
-               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                        assert_eq!(*payment_preimage, payment_preimage_1);
                        assert_eq!(*payment_hash, payment_hash_1);
                },
@@ -1806,7 +1806,7 @@ fn monitor_update_claim_fail_no_response() {
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 1);
        match events[0] {
-               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                        assert_eq!(*payment_preimage, payment_preimage_1);
                        assert_eq!(*payment_hash, payment_hash_1);
                },
index 97ae7a50438e178cc67574026ef9bd39295b65af..763a293fa5bcae790e21c7e2b5206c1e0d31ad76 100644 (file)
@@ -45,7 +45,7 @@ use chain::transaction::{OutPoint, TransactionData};
 use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
 use ln::features::{InitFeatures, NodeFeatures};
-use routing::router::{Payee, Route, RouteHop, RouteParameters};
+use routing::router::{Payee, Route, RouteHop, RoutePath, RouteParameters};
 use ln::msgs;
 use ln::msgs::NetAddress;
 use ln::onion_utils;
@@ -436,6 +436,8 @@ pub(crate) enum PendingOutboundPayment {
                payment_hash: PaymentHash,
                payment_secret: Option<PaymentSecret>,
                pending_amt_msat: u64,
+               /// Used to track the fee paid. Only present if the payment was serialized on 0.0.103+.
+               pending_fee_msat: Option<u64>,
                /// The total payment amount across all paths, used to verify that a retry is not overpaying.
                total_msat: u64,
                /// Our best known block height at the time this payment was initiated.
@@ -462,6 +464,12 @@ impl PendingOutboundPayment {
                        _ => false,
                }
        }
+       fn get_pending_fee_msat(&self) -> Option<u64> {
+               match self {
+                       PendingOutboundPayment::Retryable { pending_fee_msat, .. } => pending_fee_msat.clone(),
+                       _ => None,
+               }
+       }
 
        fn mark_fulfilled(&mut self) {
                let mut session_privs = HashSet::new();
@@ -484,10 +492,13 @@ impl PendingOutboundPayment {
                        }
                };
                if remove_res {
-                       if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, .. } = self {
+                       if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
                                let path = path.expect("Fulfilling a payment should always come with a path");
                                let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
                                *pending_amt_msat -= path_last_hop.fee_msat;
+                               if let Some(fee_msat) = pending_fee_msat.as_mut() {
+                                       *fee_msat -= path.get_path_fees();
+                               }
                        }
                }
                remove_res
@@ -502,9 +513,12 @@ impl PendingOutboundPayment {
                        PendingOutboundPayment::Fulfilled { .. } => false
                };
                if insert_res {
-                       if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, .. } = self {
+                       if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
                                let path_last_hop = path.last().expect("Outbound payments must have had a valid path");
                                *pending_amt_msat += path_last_hop.fee_msat;
+                               if let Some(fee_msat) = pending_fee_msat.as_mut() {
+                                       *fee_msat += path.get_path_fees();
+                               }
                        }
                }
                insert_res
@@ -2084,6 +2098,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        let payment = payment_entry.or_insert_with(|| PendingOutboundPayment::Retryable {
                                                session_privs: HashSet::new(),
                                                pending_amt_msat: 0,
+                                               pending_fee_msat: Some(0),
                                                payment_hash: *payment_hash,
                                                payment_secret: *payment_secret,
                                                starting_block_height: self.best_block.read().unwrap().height(),
@@ -3458,8 +3473,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                let mut session_priv_bytes = [0; 32];
                                session_priv_bytes.copy_from_slice(&session_priv[..]);
                                let mut outbounds = self.pending_outbound_payments.lock().unwrap();
-                               let found_payment = if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
+                               if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
                                        let found_payment = !payment.get().is_fulfilled();
+                                       let fee_paid_msat = payment.get().get_pending_fee_msat();
                                        payment.get_mut().mark_fulfilled();
                                        if from_onchain {
                                                // We currently immediately remove HTLCs which were fulfilled on-chain.
@@ -3473,17 +3489,17 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                        payment.remove();
                                                }
                                        }
-                                       found_payment
-                               } else { false };
-                               if found_payment {
-                                       let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
-                                       self.pending_events.lock().unwrap().push(
-                                               events::Event::PaymentSent {
-                                                       payment_id: Some(payment_id),
-                                                       payment_preimage,
-                                                       payment_hash: payment_hash
-                                               }
-                                       );
+                                       if found_payment {
+                                               let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
+                                               self.pending_events.lock().unwrap().push(
+                                                       events::Event::PaymentSent {
+                                                               payment_id: Some(payment_id),
+                                                               payment_preimage,
+                                                               payment_hash: payment_hash,
+                                                               fee_paid_msat,
+                                                       }
+                                               );
+                                       }
                                } else {
                                        log_trace!(self.logger, "Received duplicative fulfill for HTLC with payment_preimage {}", log_bytes!(payment_preimage.0));
                                }
@@ -5496,6 +5512,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
        },
        (2, Retryable) => {
                (0, session_privs, required),
+               (1, pending_fee_msat, option),
                (2, payment_hash, required),
                (4, payment_secret, option),
                (6, total_msat, required),
@@ -5957,11 +5974,13 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                                                                                if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), log_bytes!(htlc.payment_hash.0));
                                                                },
                                                                hash_map::Entry::Vacant(entry) => {
+                                                                       let path_fee = path.get_path_fees();
                                                                        entry.insert(PendingOutboundPayment::Retryable {
                                                                                session_privs: [session_priv_bytes].iter().map(|a| *a).collect(),
                                                                                payment_hash: htlc.payment_hash,
                                                                                payment_secret,
                                                                                pending_amt_msat: path_amt,
+                                                                               pending_fee_msat: Some(path_fee),
                                                                                total_msat: path_amt,
                                                                                starting_block_height: best_block_height,
                                                                        });
@@ -6260,7 +6279,7 @@ mod tests {
                // further events will be generated for subsequence path successes.
                let events = nodes[0].node.get_and_clear_pending_events();
                match events[0] {
-                       Event::PaymentSent { payment_id: ref id, payment_preimage: ref preimage, payment_hash: ref hash } => {
+                       Event::PaymentSent { payment_id: ref id, payment_preimage: ref preimage, payment_hash: ref hash, .. } => {
                                assert_eq!(Some(payment_id), *id);
                                assert_eq!(payment_preimage, *preimage);
                                assert_eq!(our_payment_hash, *hash);
index 014cf3b7ddb777c22ce125039252ceea890f4ee8..92377236401de78e64ec08aa1f9af84c09801536 100644 (file)
@@ -1081,13 +1081,20 @@ macro_rules! expect_payment_received {
 
 macro_rules! expect_payment_sent {
        ($node: expr, $expected_payment_preimage: expr) => {
+               expect_payment_sent!($node, $expected_payment_preimage, None::<u64>);
+       };
+       ($node: expr, $expected_payment_preimage: expr, $expected_fee_msat_opt: expr) => {
                let events = $node.node.get_and_clear_pending_events();
                let expected_payment_hash = PaymentHash(Sha256::hash(&$expected_payment_preimage.0).into_inner());
                assert_eq!(events.len(), 1);
                match events[0] {
-                       Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+                       Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => {
                                assert_eq!($expected_payment_preimage, *payment_preimage);
                                assert_eq!(expected_payment_hash, *payment_hash);
+                               assert!(fee_paid_msat.is_some());
+                               if $expected_fee_msat_opt.is_some() {
+                                       assert_eq!(*fee_paid_msat, $expected_fee_msat_opt);
+                               }
                        },
                        _ => panic!("Unexpected event"),
                }
@@ -1237,13 +1244,15 @@ pub fn send_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route
        (our_payment_preimage, our_payment_hash, our_payment_secret, payment_id)
 }
 
-pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage) {
+pub fn do_claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage) -> u64 {
        for path in expected_paths.iter() {
                assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id());
        }
        assert!(expected_paths[0].last().unwrap().node.claim_funds(our_payment_preimage));
        check_added_monitors!(expected_paths[0].last().unwrap(), expected_paths.len());
 
+       let mut expected_total_fee_msat = 0;
+
        macro_rules! msgs_from_ev {
                ($ev: expr) => {
                        match $ev {
@@ -1286,6 +1295,7 @@ pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, exp
                                        $node.node.handle_update_fulfill_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0);
                                        let fee = $node.node.channel_state.lock().unwrap().by_id.get(&next_msgs.as_ref().unwrap().0.channel_id).unwrap().config.forwarding_fee_base_msat;
                                        expect_payment_forwarded!($node, Some(fee as u64), false);
+                                       expected_total_fee_msat += fee as u64;
                                        check_added_monitors!($node, 1);
                                        let new_next_msgs = if $new_msgs {
                                                let events = $node.node.get_and_clear_pending_msg_events();
@@ -1324,8 +1334,12 @@ pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, exp
                        last_update_fulfill_dance!(origin_node, expected_route.first().unwrap());
                }
        }
+       expected_total_fee_msat
+}
+pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage) {
+       let expected_total_fee_msat = do_claim_payment_along_route(origin_node, expected_paths, skip_last, our_payment_preimage);
        if !skip_last {
-               expect_payment_sent!(origin_node, our_payment_preimage);
+               expect_payment_sent!(origin_node, our_payment_preimage, Some(expected_total_fee_msat));
        }
 }
 
index 564a9e5a09035f0bc9554e2d2f91d93f05650436..e8367cd55ca1a6b7dd4ccb787d1ebe150de28676 100644 (file)
@@ -2659,7 +2659,7 @@ fn test_htlc_on_chain_success() {
        let mut first_claimed = false;
        for event in events {
                match event {
-                       Event::PaymentSent { payment_id: _, payment_preimage, payment_hash } => {
+                       Event::PaymentSent { payment_preimage, payment_hash, .. } => {
                                if payment_preimage == our_payment_preimage && payment_hash == payment_hash_1 {
                                        assert!(!first_claimed);
                                        first_claimed = true;
@@ -3350,7 +3350,7 @@ fn test_simple_peer_disconnect() {
                let events = nodes[0].node.get_and_clear_pending_events();
                assert_eq!(events.len(), 2);
                match events[0] {
-                       Event::PaymentSent { payment_id: _, payment_preimage, payment_hash } => {
+                       Event::PaymentSent { payment_preimage, payment_hash, .. } => {
                                assert_eq!(payment_preimage, payment_preimage_3);
                                assert_eq!(payment_hash, payment_hash_3);
                        },
@@ -3514,7 +3514,7 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
                let events_4 = nodes[0].node.get_and_clear_pending_events();
                assert_eq!(events_4.len(), 1);
                match events_4[0] {
-                       Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+                       Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                                assert_eq!(payment_preimage_1, *payment_preimage);
                                assert_eq!(payment_hash_1, *payment_hash);
                        },
@@ -3555,7 +3555,7 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
                        let events_4 = nodes[0].node.get_and_clear_pending_events();
                        assert_eq!(events_4.len(), 1);
                        match events_4[0] {
-                               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+                               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                                        assert_eq!(payment_preimage_1, *payment_preimage);
                                        assert_eq!(payment_hash_1, *payment_hash);
                                },
@@ -3790,7 +3790,7 @@ fn test_drop_messages_peer_disconnect_dual_htlc() {
                        let events_3 = nodes[0].node.get_and_clear_pending_events();
                        assert_eq!(events_3.len(), 1);
                        match events_3[0] {
-                               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+                               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                                        assert_eq!(*payment_preimage, payment_preimage_1);
                                        assert_eq!(*payment_hash, payment_hash_1);
                                },
@@ -5059,7 +5059,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
 
        let events = nodes[0].node.get_and_clear_pending_events();
        match events[0] {
-               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                        assert_eq!(*payment_preimage, our_payment_preimage);
                        assert_eq!(*payment_hash, duplicate_payment_hash);
                }
@@ -5572,7 +5572,7 @@ fn do_htlc_claim_local_commitment_only(use_dust: bool) {
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 1);
        match events[0] {
-               Event::PaymentSent { payment_id: _, payment_preimage, payment_hash } => {
+               Event::PaymentSent { payment_preimage, payment_hash, .. } => {
                        assert_eq!(payment_preimage, our_payment_preimage);
                        assert_eq!(payment_hash, our_payment_hash);
                },
@@ -6002,7 +6002,7 @@ fn test_free_and_fail_holding_cell_htlcs() {
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 1);
        match events[0] {
-               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                        assert_eq!(*payment_preimage, payment_preimage_1);
                        assert_eq!(*payment_hash, payment_hash_1);
                }
index 1b9836621e7761a3a0316c4f441ac4d2e826abbc..f685c375f38913c6fbedc9ce40a064d7e7373598 100644 (file)
@@ -296,7 +296,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
        let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
 
        let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
-       create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+       let (_, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
 
        // Serialize the ChannelManager prior to sending payments
        let nodes_0_serialized = nodes[0].node.encode();
@@ -445,7 +445,13 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
        // Finally, retry the payment (which was reloaded from the ChannelMonitor when nodes[0] was
        // reloaded) via a route over the new channel, which work without issue and eventually be
        // received and claimed at the recipient just like any other payment.
-       let (new_route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000);
+       let (mut new_route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000);
+
+       // Update the fee on the middle hop to ensure PaymentSent events have the correct (retried) fee
+       // and not the original fee. We also update node[1]'s relevant config as
+       // do_claim_payment_along_route expects us to never overpay.
+       nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan_id_2).unwrap().config.forwarding_fee_base_msat += 100_000;
+       new_route.paths[0][0].fee_msat += 100_000;
 
        assert!(nodes[0].node.retry_payment(&new_route, payment_id_1).is_err()); // Shouldn't be allowed to retry a fulfilled payment
        nodes[0].node.retry_payment(&new_route, payment_id).unwrap();
@@ -453,7 +459,8 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 1);
        pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None);
-       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+       do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+       expect_payment_sent!(nodes[0], payment_preimage, Some(new_route.paths[0][0].fee_msat));
 }
 
 #[test]
index 388104bf0239a4252f7338bab4b900107ba59587..7a089112454779572d8052410b8818ca68dadbb5 100644 (file)
@@ -131,7 +131,7 @@ fn updates_shutdown_wait() {
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 1);
        match events[0] {
-               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                        assert_eq!(our_payment_preimage, *payment_preimage);
                        assert_eq!(our_payment_hash, *payment_hash);
                },
@@ -309,7 +309,7 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) {
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 1);
        match events[0] {
-               Event::PaymentSent { payment_id: _, ref payment_preimage, ref payment_hash } => {
+               Event::PaymentSent { ref payment_preimage, ref payment_hash, .. } => {
                        assert_eq!(our_payment_preimage, *payment_preimage);
                        assert_eq!(our_payment_hash, *payment_hash);
                },
index bcd84ba42a6a069989523123290c384e594740b8..e0f0a63dbb341d8507a80ecd07b4a94f3cb91699 100644 (file)
@@ -194,6 +194,16 @@ pub enum Event {
                ///
                /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
                payment_hash: PaymentHash,
+               /// The total fee which was spent at intermediate hops in this payment, across all paths.
+               ///
+               /// Note that, like [`Route::get_total_fees`] this does *not* include any potential
+               /// overpayment to the recipient node.
+               ///
+               /// If the recipient or an intermediate node misbehaves and gives us free money, this may
+               /// overstate the amount paid, though this is unlikely.
+               ///
+               /// [`Route::get_total_fees`]: crate::routing::router::Route::get_total_fees
+               fee_paid_msat: Option<u64>,
        },
        /// Indicates an outbound payment we made failed. Probably some intermediary node dropped
        /// something. You may wish to retry with a different route.
@@ -336,12 +346,13 @@ impl Writeable for Event {
                                        (8, payment_preimage, option),
                                });
                        },
-                       &Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash} => {
+                       &Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => {
                                2u8.write(writer)?;
                                write_tlv_fields!(writer, {
                                        (0, payment_preimage, required),
                                        (1, payment_hash, required),
                                        (3, payment_id, option),
+                                       (5, fee_paid_msat, option),
                                });
                        },
                        &Event::PaymentPathFailed {
@@ -452,10 +463,12 @@ impl MaybeReadable for Event {
                                        let mut payment_preimage = PaymentPreimage([0; 32]);
                                        let mut payment_hash = None;
                                        let mut payment_id = None;
+                                       let mut fee_paid_msat = None;
                                        read_tlv_fields!(reader, {
                                                (0, payment_preimage, required),
                                                (1, payment_hash, option),
                                                (3, payment_id, option),
+                                               (5, fee_paid_msat, option),
                                        });
                                        if payment_hash.is_none() {
                                                payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()));
@@ -464,6 +477,7 @@ impl MaybeReadable for Event {
                                                payment_id,
                                                payment_preimage,
                                                payment_hash: payment_hash.unwrap(),
+                                               fee_paid_msat,
                                        }))
                                };
                                f()