Skip to content

Commit 5224abd

Browse files
committed
Detect duplicate BOLT11 invoices
Outbound BOLT11 payments now use random payment IDs. A payment ID lookup no longer catches same-invoice retries. Scan outbound BOLT11 records by payment hash instead. Reject pending or succeeded matches while allowing failed retries. Co-Authored-By: HAL 9000
1 parent 627a545 commit 5224abd

1 file changed

Lines changed: 16 additions & 9 deletions

File tree

src/payment/bolt11.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,17 @@ mod tests {
203203
}
204204

205205
impl Bolt11Payment {
206+
fn has_pending_or_succeeded_outbound_payment(&self, payment_hash: &PaymentHash) -> bool {
207+
!self
208+
.payment_store
209+
.list_filter(|payment| {
210+
payment.direction == PaymentDirection::Outbound
211+
&& matches!(&payment.kind, PaymentKind::Bolt11 { hash, .. } if hash == payment_hash)
212+
&& matches!(payment.status, PaymentStatus::Pending | PaymentStatus::Succeeded)
213+
})
214+
.is_empty()
215+
}
216+
206217
fn send_internal(
207218
&self, invoice: &LdkBolt11Invoice, amount_msat: Option<u64>,
208219
route_parameters: Option<RouteParametersConfig>,
@@ -213,16 +224,12 @@ impl Bolt11Payment {
213224
}
214225

215226
let payment_hash = invoice.payment_hash();
227+
if self.has_pending_or_succeeded_outbound_payment(&payment_hash) {
228+
log_error!(self.logger, "Payment error: an invoice must not be paid twice.");
229+
return Err(Error::DuplicatePayment);
230+
}
231+
216232
let payment_id = PaymentId(self.keys_manager.get_secure_random_bytes());
217-
// TODO: re-add checking for duplicate payments?
218-
//if let Some(payment) = self.payment_store.get(&payment_id) {
219-
// if payment.status == PaymentStatus::Pending
220-
// || payment.status == PaymentStatus::Succeeded
221-
// {
222-
// log_error!(self.logger, "Payment error: an invoice must not be paid twice.");
223-
// return Err(Error::DuplicatePayment);
224-
// }
225-
//}
226233

227234
let route_params_config =
228235
route_parameters.or(self.config.route_parameters).unwrap_or_default();

0 commit comments

Comments
 (0)