Track amount_msat field in Event::PaymentSent

Previously, we would only track the fees paid, but not the actual amount
that was sent.
This commit is contained in:
Elias Rohrer 2025-02-13 11:15:31 +01:00
parent ca40276c9f
commit e5d46c5e71
No known key found for this signature in database
GPG key ID: 36153082BDF676FD
3 changed files with 38 additions and 4 deletions

View file

@ -929,9 +929,17 @@ pub enum Event {
/// ///
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
payment_hash: PaymentHash, payment_hash: PaymentHash,
/// The total amount that was paid, across all paths.
///
/// Note that, like [`Route::get_total_amount`], this does *not* include the paid fees.
///
/// This is only `None` for payments initiated on LDK versions prior to 0.2.
///
/// [`Route::get_total_amount`]: crate::routing::router::Route::get_total_amount
amount_msat: Option<u64>,
/// The total fee which was spent at intermediate hops in this payment, across all paths. /// 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 /// Note that, like [`Route::get_total_fees`], this does *not* include any potential
/// overpayment to the recipient node. /// overpayment to the recipient node.
/// ///
/// If the recipient or an intermediate node misbehaves and gives us free money, this may /// If the recipient or an intermediate node misbehaves and gives us free money, this may
@ -1548,13 +1556,14 @@ impl Writeable for Event {
(13, payment_id, option), (13, payment_id, option),
}); });
}, },
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => { &Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat } => {
2u8.write(writer)?; 2u8.write(writer)?;
write_tlv_fields!(writer, { write_tlv_fields!(writer, {
(0, payment_preimage, required), (0, payment_preimage, required),
(1, payment_hash, required), (1, payment_hash, required),
(3, payment_id, option), (3, payment_id, option),
(5, fee_paid_msat, option), (5, fee_paid_msat, option),
(7, amount_msat, option),
}); });
}, },
&Event::PaymentPathFailed { &Event::PaymentPathFailed {
@ -1887,12 +1896,14 @@ impl MaybeReadable for Event {
let mut payment_preimage = PaymentPreimage([0; 32]); let mut payment_preimage = PaymentPreimage([0; 32]);
let mut payment_hash = None; let mut payment_hash = None;
let mut payment_id = None; let mut payment_id = None;
let mut amount_msat = None;
let mut fee_paid_msat = None; let mut fee_paid_msat = None;
read_tlv_fields!(reader, { read_tlv_fields!(reader, {
(0, payment_preimage, required), (0, payment_preimage, required),
(1, payment_hash, option), (1, payment_hash, option),
(3, payment_id, option), (3, payment_id, option),
(5, fee_paid_msat, option), (5, fee_paid_msat, option),
(7, amount_msat, option),
}); });
if payment_hash.is_none() { if payment_hash.is_none() {
payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array())); payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()));
@ -1901,6 +1912,7 @@ impl MaybeReadable for Event {
payment_id, payment_id,
payment_preimage, payment_preimage,
payment_hash: payment_hash.unwrap(), payment_hash: payment_hash.unwrap(),
amount_msat,
fee_paid_msat, fee_paid_msat,
})) }))
}; };

View file

@ -2299,9 +2299,10 @@ pub fn expect_payment_sent<CM: AChannelManager, H: NodeHolder<CM=CM>>(node: &H,
check_added_monitors(node, 1); check_added_monitors(node, 1);
} }
let expected_payment_id = match events[0] { let expected_payment_id = match events[0] {
Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => { Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat } => {
assert_eq!(expected_payment_preimage, *payment_preimage); assert_eq!(expected_payment_preimage, *payment_preimage);
assert_eq!(expected_payment_hash, *payment_hash); assert_eq!(expected_payment_hash, *payment_hash);
assert!(amount_msat.is_some());
if let Some(expected_fee_msat) = expected_fee_msat_opt { if let Some(expected_fee_msat) = expected_fee_msat_opt {
assert_eq!(*fee_paid_msat, expected_fee_msat); assert_eq!(*fee_paid_msat, expected_fee_msat);
} else { } else {

View file

@ -122,6 +122,8 @@ pub(crate) enum PendingOutboundPayment {
/// Filled in for any payment which moved to `Fulfilled` on LDK 0.0.104 or later. /// Filled in for any payment which moved to `Fulfilled` on LDK 0.0.104 or later.
payment_hash: Option<PaymentHash>, payment_hash: Option<PaymentHash>,
timer_ticks_without_htlcs: u8, timer_ticks_without_htlcs: u8,
/// The total payment amount across all paths, used to be able to issue `PaymentSent`.
total_msat: Option<u64>,
}, },
/// When we've decided to give up retrying a payment, we mark it as abandoned so we can eventually /// When we've decided to give up retrying a payment, we mark it as abandoned so we can eventually
/// generate a `PaymentFailed` event when all HTLCs have irrevocably failed. /// generate a `PaymentFailed` event when all HTLCs have irrevocably failed.
@ -131,6 +133,9 @@ pub(crate) enum PendingOutboundPayment {
/// Will be `None` if the payment was serialized before 0.0.115 or if downgrading to 0.0.124 /// Will be `None` if the payment was serialized before 0.0.115 or if downgrading to 0.0.124
/// or later with a reason that was added after. /// or later with a reason that was added after.
reason: Option<PaymentFailureReason>, reason: Option<PaymentFailureReason>,
/// The total payment amount across all paths, used to be able to issue `PaymentSent` if
/// an HTLC still happens to succeed after we marked the payment as abandoned.
total_msat: Option<u64>,
}, },
} }
@ -210,6 +215,15 @@ impl PendingOutboundPayment {
} }
} }
fn total_msat(&self) -> Option<u64> {
match self {
PendingOutboundPayment::Retryable { total_msat, .. } => Some(*total_msat),
PendingOutboundPayment::Fulfilled { total_msat, .. } => *total_msat,
PendingOutboundPayment::Abandoned { total_msat, .. } => *total_msat,
_ => None,
}
}
fn payment_hash(&self) -> Option<PaymentHash> { fn payment_hash(&self) -> Option<PaymentHash> {
match self { match self {
PendingOutboundPayment::Legacy { .. } => None, PendingOutboundPayment::Legacy { .. } => None,
@ -236,7 +250,8 @@ impl PendingOutboundPayment {
PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); return; }, PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); return; },
}); });
let payment_hash = self.payment_hash(); let payment_hash = self.payment_hash();
*self = PendingOutboundPayment::Fulfilled { session_privs, payment_hash, timer_ticks_without_htlcs: 0 }; let total_msat = self.total_msat();
*self = PendingOutboundPayment::Fulfilled { session_privs, payment_hash, timer_ticks_without_htlcs: 0, total_msat };
} }
fn mark_abandoned(&mut self, reason: PaymentFailureReason) { fn mark_abandoned(&mut self, reason: PaymentFailureReason) {
@ -248,6 +263,7 @@ impl PendingOutboundPayment {
}, },
_ => new_hash_set(), _ => new_hash_set(),
}; };
let total_msat = self.total_msat();
match self { match self {
Self::Retryable { payment_hash, .. } | Self::Retryable { payment_hash, .. } |
Self::InvoiceReceived { payment_hash, .. } | Self::InvoiceReceived { payment_hash, .. } |
@ -257,6 +273,7 @@ impl PendingOutboundPayment {
session_privs, session_privs,
payment_hash: *payment_hash, payment_hash: *payment_hash,
reason: Some(reason), reason: Some(reason),
total_msat,
}; };
}, },
_ => {} _ => {}
@ -1928,10 +1945,12 @@ impl OutboundPayments {
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array()); let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array());
log_info!(logger, "Payment with id {} and hash {} sent!", payment_id, payment_hash); log_info!(logger, "Payment with id {} and hash {} sent!", payment_id, payment_hash);
let fee_paid_msat = payment.get().get_pending_fee_msat(); let fee_paid_msat = payment.get().get_pending_fee_msat();
let amount_msat = payment.get().total_msat();
pending_events.push_back((events::Event::PaymentSent { pending_events.push_back((events::Event::PaymentSent {
payment_id: Some(payment_id), payment_id: Some(payment_id),
payment_preimage, payment_preimage,
payment_hash, payment_hash,
amount_msat,
fee_paid_msat, fee_paid_msat,
}, Some(ev_completion_action.clone()))); }, Some(ev_completion_action.clone())));
payment.get_mut().mark_fulfilled(); payment.get_mut().mark_fulfilled();
@ -2362,6 +2381,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
(0, session_privs, required), (0, session_privs, required),
(1, payment_hash, option), (1, payment_hash, option),
(3, timer_ticks_without_htlcs, (default_value, 0)), (3, timer_ticks_without_htlcs, (default_value, 0)),
(5, total_msat, option),
}, },
(2, Retryable) => { (2, Retryable) => {
(0, session_privs, required), (0, session_privs, required),
@ -2386,6 +2406,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
(0, session_privs, required), (0, session_privs, required),
(1, reason, upgradable_option), (1, reason, upgradable_option),
(2, payment_hash, required), (2, payment_hash, required),
(3, total_msat, option),
}, },
(5, AwaitingInvoice) => { (5, AwaitingInvoice) => {
(0, expiration, required), (0, expiration, required),