Skip to content

Commit 2f83a94

Browse files
committed
f - Combine hash maps so only a single look-up is necessary
1 parent 4f51848 commit 2f83a94

File tree

1 file changed

+26
-38
lines changed

1 file changed

+26
-38
lines changed

lightning-invoice/src/payment.rs

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ where
6060
router: R,
6161
logger: L,
6262
event_handler: E,
63-
// Lock order: payment_attempts -> invoice_cache
64-
invoice_cache: Mutex<HashMap<PaymentHash, Invoice>>,
65-
payment_attempts: Mutex<HashMap<PaymentHash, usize>>,
63+
invoice_cache: Mutex<HashMap<PaymentHash, (Invoice, usize)>>,
6664
retry_attempts: usize,
6765
}
6866

@@ -122,7 +120,6 @@ where
122120
logger,
123121
event_handler,
124122
invoice_cache: Mutex::new(HashMap::new()),
125-
payment_attempts: Mutex::new(HashMap::new()),
126123
retry_attempts: 0,
127124
}
128125
}
@@ -139,23 +136,15 @@ where
139136
let mut invoice_cache = self.invoice_cache.lock().unwrap();
140137
match invoice_cache.entry(payment_hash) {
141138
hash_map::Entry::Vacant(entry) => {
142-
self.pay_invoice_internal(invoice)?;
143-
entry.insert(invoice.clone());
139+
self.pay_cached_invoice(invoice)?;
140+
entry.insert((invoice.clone(), 0));
144141
Ok(())
145142
},
146143
hash_map::Entry::Occupied(_) => Err(PaymentError::Invoice("payment pending")),
147144
}
148145
}
149146

150-
fn pay_cached_invoice(&self, payment_hash: &PaymentHash) -> Result<(), PaymentError> {
151-
let invoice_cache = self.invoice_cache.lock().unwrap();
152-
match invoice_cache.get(payment_hash) {
153-
Some(invoice) => self.pay_invoice_internal(invoice),
154-
None => Err(PaymentError::Invoice("unknown payment hash")),
155-
}
156-
}
157-
158-
fn pay_invoice_internal(&self, invoice: &Invoice) -> Result<(), PaymentError> {
147+
fn pay_cached_invoice(&self, invoice: &Invoice) -> Result<(), PaymentError> {
159148
let payer = self.payer.node_id();
160149
let payee = invoice.recover_payee_pub_key();
161150
let payee_features = invoice.features().cloned();
@@ -199,40 +188,39 @@ where
199188
fn handle_event(&self, event: &Event) {
200189
match event {
201190
Event::PaymentFailed { payment_hash, rejected_by_dest, .. } => {
202-
let mut attempts_by_payment_hash = self.payment_attempts.lock().unwrap();
203-
let attempts = attempts_by_payment_hash
204-
.entry(*payment_hash)
205-
.and_modify(|attempts| *attempts += 1)
206-
.or_insert(1);
207-
if !rejected_by_dest {
208-
let max_payment_attempts = self.retry_attempts + 1;
209-
if *attempts < max_payment_attempts {
210-
if self.pay_cached_invoice(payment_hash).is_ok() {
211-
log_trace!(self.logger, "Payment {} failed; retrying (attempts: {})", log_bytes!(payment_hash.0), attempts);
212-
return;
191+
let mut invoice_cache = self.invoice_cache.lock().unwrap();
192+
if let hash_map::Entry::Occupied(mut entry) = invoice_cache.entry(*payment_hash) {
193+
let (invoice, attempts) = entry.get_mut();
194+
*attempts += 1;
195+
if !rejected_by_dest {
196+
let max_payment_attempts = self.retry_attempts + 1;
197+
if *attempts < max_payment_attempts {
198+
if self.pay_cached_invoice(invoice).is_ok() {
199+
log_trace!(self.logger, "Payment {} failed; retrying (attempts: {})", log_bytes!(payment_hash.0), attempts);
200+
return;
201+
} else {
202+
log_trace!(self.logger, "Error retrying payment {}; not retrying (attempts: {})", log_bytes!(payment_hash.0), attempts);
203+
}
213204
} else {
214-
log_trace!(self.logger, "Error retrying payment {}; not retrying (attempts: {})", log_bytes!(payment_hash.0), attempts);
205+
log_trace!(self.logger, "Payment {} failed; not retrying (attempts: {})", log_bytes!(payment_hash.0), attempts);
215206
}
216207
} else {
217-
log_trace!(self.logger, "Payment {} failed; not retrying (attempts: {})", log_bytes!(payment_hash.0), attempts);
208+
log_trace!(self.logger, "Payment {} rejected by destination; not retrying (attempts: {})", log_bytes!(payment_hash.0), attempts);
218209
}
210+
211+
// Either the payment was rejected, exceeded the maximum attempts, or failed.
212+
entry.remove();
219213
} else {
220-
log_trace!(self.logger, "Payment {} rejected by destination; not retrying (attempts: {})", log_bytes!(payment_hash.0), attempts);
214+
log_trace!(self.logger, "Unknown payment {}; cannot retry)", log_bytes!(payment_hash.0));
221215
}
222-
223-
// Either the payment was rejected, exceeded the maximum attempts, or failed retry.
224-
self.remove_cached_invoice(payment_hash);
225-
attempts_by_payment_hash.remove(payment_hash);
226216
},
227217
Event::PaymentSent { payment_preimage } => {
228218
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
229-
let mut attempts_by_payment_hash = self.payment_attempts.lock().unwrap();
230-
let attempts = attempts_by_payment_hash
219+
let mut invoice_cache = self.invoice_cache.lock().unwrap();
220+
let attempts = invoice_cache
231221
.remove(&payment_hash)
232-
.map_or(1, |attempts| attempts + 1);
222+
.map_or(1, |(_, attempts)| attempts + 1);
233223
log_trace!(self.logger, "Payment {} succeeded (attempts: {})", log_bytes!(payment_hash.0), attempts);
234-
235-
self.remove_cached_invoice(&payment_hash);
236224
},
237225
_ => {},
238226
}

0 commit comments

Comments
 (0)