Skip to content

Commit 3c2da41

Browse files
Move monitor<>outbound_payments startup htlc syncing code.
Move the code that ensures that HTLCs locked into ChannelMonitors are synchronized with the ChannelManager's OutboundPayments store to the outbound_payments module. This is useful both because ChannelManager::read is very long/confusing method, so it's nice to encapsulate some of its functionality, and because we need to fix an existing bug in this logic where we may risk double-paying an offer due to outbound_payments being stale on startup. See the next commit for this bugfix.
1 parent 8c356d8 commit 3c2da41

File tree

2 files changed

+39
-30
lines changed

2 files changed

+39
-30
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING};
6161
use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
6262
#[cfg(test)]
6363
use crate::ln::outbound_payment;
64-
use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, RetryableInvoiceRequest, SendAlongPathArgs, StaleExpiration};
64+
use crate::ln::outbound_payment::{OutboundPayments, PendingOutboundPayment, RetryableInvoiceRequest, SendAlongPathArgs, StaleExpiration};
6565
use crate::ln::wire::Encode;
6666
use crate::offers::invoice::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
6767
use crate::offers::invoice_error::InvoiceError;
@@ -12569,37 +12569,11 @@ where
1256912569
return Err(DecodeError::InvalidValue);
1257012570
}
1257112571

12572-
let path_amt = path.final_value_msat();
1257312572
let mut session_priv_bytes = [0; 32];
1257412573
session_priv_bytes[..].copy_from_slice(&session_priv[..]);
12575-
match pending_outbounds.pending_outbound_payments.lock().unwrap().entry(payment_id) {
12576-
hash_map::Entry::Occupied(mut entry) => {
12577-
let newly_added = entry.get_mut().insert(session_priv_bytes, &path);
12578-
log_info!(logger, "{} a pending payment path for {} msat for session priv {} on an existing pending payment with payment hash {}",
12579-
if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), htlc.payment_hash);
12580-
},
12581-
hash_map::Entry::Vacant(entry) => {
12582-
let path_fee = path.fee_msat();
12583-
entry.insert(PendingOutboundPayment::Retryable {
12584-
retry_strategy: None,
12585-
attempts: PaymentAttempts::new(),
12586-
payment_params: None,
12587-
session_privs: hash_set_from_iter([session_priv_bytes]),
12588-
payment_hash: htlc.payment_hash,
12589-
payment_secret: None, // only used for retries, and we'll never retry on startup
12590-
payment_metadata: None, // only used for retries, and we'll never retry on startup
12591-
keysend_preimage: None, // only used for retries, and we'll never retry on startup
12592-
custom_tlvs: Vec::new(), // only used for retries, and we'll never retry on startup
12593-
pending_amt_msat: path_amt,
12594-
pending_fee_msat: Some(path_fee),
12595-
total_msat: path_amt,
12596-
starting_block_height: best_block_height,
12597-
remaining_max_total_routing_fee_msat: None, // only used for retries, and we'll never retry on startup
12598-
});
12599-
log_info!(logger, "Added a pending payment for {} msat with payment hash {} for path with session priv {}",
12600-
path_amt, &htlc.payment_hash, log_bytes!(session_priv_bytes));
12601-
}
12602-
}
12574+
pending_outbounds.insert_from_monitor_on_startup(
12575+
payment_id, htlc.payment_hash, session_priv_bytes, &path, best_block_height, logger
12576+
);
1260312577
}
1260412578
}
1260512579
for (htlc_source, (htlc, preimage_opt)) in monitor.get_all_current_outbound_htlcs() {

lightning/src/ln/outbound_payment.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,6 +2121,41 @@ impl OutboundPayments {
21212121
self.awaiting_invoice.store(false, Ordering::Release);
21222122
invoice_requests
21232123
}
2124+
2125+
pub(super) fn insert_from_monitor_on_startup<L: Logger>(
2126+
&self, payment_id: PaymentId, payment_hash: PaymentHash, session_priv_bytes: [u8; 32],
2127+
path: &Path, best_block_height: u32, logger: L
2128+
) {
2129+
let path_amt = path.final_value_msat();
2130+
match self.pending_outbound_payments.lock().unwrap().entry(payment_id) {
2131+
hash_map::Entry::Occupied(mut entry) => {
2132+
let newly_added = entry.get_mut().insert(session_priv_bytes, &path);
2133+
log_info!(logger, "{} a pending payment path for {} msat for session priv {} on an existing pending payment with payment hash {}",
2134+
if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), payment_hash);
2135+
},
2136+
hash_map::Entry::Vacant(entry) => {
2137+
let path_fee = path.fee_msat();
2138+
entry.insert(PendingOutboundPayment::Retryable {
2139+
retry_strategy: None,
2140+
attempts: PaymentAttempts::new(),
2141+
payment_params: None,
2142+
session_privs: hash_set_from_iter([session_priv_bytes]),
2143+
payment_hash,
2144+
payment_secret: None, // only used for retries, and we'll never retry on startup
2145+
payment_metadata: None, // only used for retries, and we'll never retry on startup
2146+
keysend_preimage: None, // only used for retries, and we'll never retry on startup
2147+
custom_tlvs: Vec::new(), // only used for retries, and we'll never retry on startup
2148+
pending_amt_msat: path_amt,
2149+
pending_fee_msat: Some(path_fee),
2150+
total_msat: path_amt,
2151+
starting_block_height: best_block_height,
2152+
remaining_max_total_routing_fee_msat: None, // only used for retries, and we'll never retry on startup
2153+
});
2154+
log_info!(logger, "Added a pending payment for {} msat with payment hash {} for path with session priv {}",
2155+
path_amt, payment_hash, log_bytes!(session_priv_bytes));
2156+
}
2157+
}
2158+
}
21242159
}
21252160

21262161
/// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a

0 commit comments

Comments
 (0)