Skip to content

Commit 273106d

Browse files
authored
Merge pull request #511 from tnull/2025-03-fix-paymentdetails-panic-debug-assert
Drop `debug_assert` that would have us panic for replayed `PaymentClaimed`s
2 parents 7b41def + 4c2e5f3 commit 273106d

File tree

3 files changed

+58
-18
lines changed

3 files changed

+58
-18
lines changed

src/event.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::logger::Logger;
2020

2121
use crate::payment::store::{
2222
PaymentDetails, PaymentDetailsUpdate, PaymentDirection, PaymentKind, PaymentStatus,
23-
PaymentStore,
23+
PaymentStore, PaymentStoreUpdateResult,
2424
};
2525

2626
use crate::io::{
@@ -906,14 +906,17 @@ where
906906
};
907907

908908
match self.payment_store.update(&update) {
909-
Ok(true) => (),
910-
Ok(false) => {
909+
Ok(PaymentStoreUpdateResult::Updated)
910+
| Ok(PaymentStoreUpdateResult::Unchanged) => (
911+
// No need to do anything if the idempotent update was applied, which might
912+
// be the result of a replayed event.
913+
),
914+
Ok(PaymentStoreUpdateResult::NotFound) => {
911915
log_error!(
912916
self.logger,
913-
"Payment with ID {} couldn't be found in store",
917+
"Claimed payment with ID {} couldn't be found in store",
914918
payment_id,
915919
);
916-
debug_assert!(false);
917920
},
918921
Err(e) => {
919922
log_error!(

src/payment/bolt11.rs

+20-8
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::liquidity::LiquiditySource;
1616
use crate::logger::{log_error, log_info, LdkLogger, Logger};
1717
use crate::payment::store::{
1818
LSPFeeLimits, PaymentDetails, PaymentDetailsUpdate, PaymentDirection, PaymentKind,
19-
PaymentStatus, PaymentStore,
19+
PaymentStatus, PaymentStore, PaymentStoreUpdateResult,
2020
};
2121
use crate::payment::SendingParameters;
2222
use crate::peer_store::{PeerInfo, PeerStore};
@@ -408,13 +408,25 @@ impl Bolt11Payment {
408408
..PaymentDetailsUpdate::new(payment_id)
409409
};
410410

411-
if !self.payment_store.update(&update)? {
412-
log_error!(
413-
self.logger,
414-
"Failed to manually fail unknown payment with hash: {}",
415-
payment_hash
416-
);
417-
return Err(Error::InvalidPaymentHash);
411+
match self.payment_store.update(&update) {
412+
Ok(PaymentStoreUpdateResult::Updated) | Ok(PaymentStoreUpdateResult::Unchanged) => (),
413+
Ok(PaymentStoreUpdateResult::NotFound) => {
414+
log_error!(
415+
self.logger,
416+
"Failed to manually fail unknown payment with hash {}",
417+
payment_hash,
418+
);
419+
return Err(Error::InvalidPaymentHash);
420+
},
421+
Err(e) => {
422+
log_error!(
423+
self.logger,
424+
"Failed to manually fail payment with hash {}: {}",
425+
payment_hash,
426+
e
427+
);
428+
return Err(e);
429+
},
418430
}
419431

420432
self.channel_manager.fail_htlc_backwards(&payment_hash);

src/payment/store.rs

+30-5
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,13 @@ impl From<&PaymentDetails> for PaymentDetailsUpdate {
590590
}
591591
}
592592

593+
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
594+
pub(crate) enum PaymentStoreUpdateResult {
595+
Updated,
596+
Unchanged,
597+
NotFound,
598+
}
599+
593600
pub(crate) struct PaymentStore<L: Deref>
594601
where
595602
L::Target: LdkLogger,
@@ -670,17 +677,22 @@ where
670677
self.payments.lock().unwrap().get(id).cloned()
671678
}
672679

673-
pub(crate) fn update(&self, update: &PaymentDetailsUpdate) -> Result<bool, Error> {
674-
let mut updated = false;
680+
pub(crate) fn update(
681+
&self, update: &PaymentDetailsUpdate,
682+
) -> Result<PaymentStoreUpdateResult, Error> {
675683
let mut locked_payments = self.payments.lock().unwrap();
676684

677685
if let Some(payment) = locked_payments.get_mut(&update.id) {
678-
updated = payment.update(update);
686+
let updated = payment.update(update);
679687
if updated {
680688
self.persist_info(&update.id, payment)?;
689+
Ok(PaymentStoreUpdateResult::Updated)
690+
} else {
691+
Ok(PaymentStoreUpdateResult::Unchanged)
681692
}
693+
} else {
694+
Ok(PaymentStoreUpdateResult::NotFound)
682695
}
683-
Ok(updated)
684696
}
685697

686698
pub(crate) fn list_filter<F: FnMut(&&PaymentDetails) -> bool>(
@@ -789,9 +801,22 @@ mod tests {
789801
assert_eq!(Ok(true), payment_store.insert(payment));
790802
assert!(payment_store.get(&id).is_some());
791803

804+
// Check update returns `Updated`
792805
let mut update = PaymentDetailsUpdate::new(id);
793806
update.status = Some(PaymentStatus::Succeeded);
794-
assert_eq!(Ok(true), payment_store.update(&update));
807+
assert_eq!(Ok(PaymentStoreUpdateResult::Updated), payment_store.update(&update));
808+
809+
// Check no-op update yields `Unchanged`
810+
let mut update = PaymentDetailsUpdate::new(id);
811+
update.status = Some(PaymentStatus::Succeeded);
812+
assert_eq!(Ok(PaymentStoreUpdateResult::Unchanged), payment_store.update(&update));
813+
814+
// Check bogus update yields `NotFound`
815+
let bogus_id = PaymentId([84u8; 32]);
816+
let mut update = PaymentDetailsUpdate::new(bogus_id);
817+
update.status = Some(PaymentStatus::Succeeded);
818+
assert_eq!(Ok(PaymentStoreUpdateResult::NotFound), payment_store.update(&update));
819+
795820
assert!(payment_store.get(&id).is_some());
796821

797822
assert_eq!(PaymentStatus::Succeeded, payment_store.get(&id).unwrap().status);

0 commit comments

Comments
 (0)