Skip to content

Commit fae7817

Browse files
channelmanager: Add retry data to pending_outbound_payments
1 parent 6b3b25f commit fae7817

File tree

1 file changed

+101
-19
lines changed

1 file changed

+101
-19
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 101 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,48 @@ struct PendingInboundPayment {
400400
min_value_msat: Option<u64>,
401401
}
402402

403+
/// XXX
404+
enum PendingOutboundPayment {
405+
Legacy {
406+
session_privs: HashSet<[u8; 32]>,
407+
},
408+
Retryable {
409+
session_privs: HashSet<[u8; 32]>,
410+
payment_hash: PaymentHash,
411+
total_msat: u64,
412+
// XXX add payment_secret
413+
},
414+
}
415+
416+
impl PendingOutboundPayment {
417+
fn remove(&mut self, session_priv: &[u8; 32]) -> bool {
418+
match self {
419+
PendingOutboundPayment::Legacy { session_privs } |
420+
PendingOutboundPayment::Retryable { session_privs, .. } => {
421+
session_privs.remove(session_priv)
422+
}
423+
}
424+
}
425+
426+
fn insert(&mut self, session_priv: [u8; 32]) -> bool {
427+
match self {
428+
PendingOutboundPayment::Legacy { session_privs } |
429+
PendingOutboundPayment::Retryable { session_privs, .. } => {
430+
session_privs.insert(session_priv)
431+
}
432+
}
433+
}
434+
435+
fn num_parts(&self) -> usize {
436+
match self {
437+
PendingOutboundPayment::Legacy { session_privs } |
438+
PendingOutboundPayment::Retryable { session_privs, .. } => {
439+
session_privs.len()
440+
}
441+
}
442+
}
443+
}
444+
403445
/// SimpleArcChannelManager is useful when you need a ChannelManager with a static lifetime, e.g.
404446
/// when you're using lightning-net-tokio (since tokio::spawn requires parameters with static
405447
/// lifetimes). Other times you can afford a reference, which is more efficient, in which case
@@ -486,6 +528,8 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
486528
/// Locked *after* channel_state.
487529
pending_inbound_payments: Mutex<HashMap<PaymentHash, PendingInboundPayment>>,
488530

531+
/// XXX update these
532+
///
489533
/// The session_priv bytes of outbound payments which are pending resolution.
490534
/// The authoritative state of these HTLCs resides either within Channels or ChannelMonitors
491535
/// (if the channel has been force-closed), however we track them here to prevent duplicative
@@ -499,7 +543,7 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
499543
/// payments over a single path).
500544
///
501545
/// Locked *after* channel_state.
502-
pending_outbound_payments: Mutex<HashMap<PaymentId, HashSet<[u8; 32]>>>,
546+
pending_outbound_payments: Mutex<HashMap<PaymentId, PendingOutboundPayment>>,
503547

504548
our_network_key: SecretKey,
505549
our_network_pubkey: PublicKey,
@@ -1894,8 +1938,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
18941938

18951939
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
18961940
let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
1897-
let sessions = pending_outbounds.entry(payment_id).or_insert(HashSet::new());
1898-
assert!(sessions.insert(session_priv_bytes));
1941+
let payment = pending_outbounds.entry(payment_id).or_insert(PendingOutboundPayment::Retryable {
1942+
session_privs: HashSet::new(),
1943+
payment_hash: *payment_hash,
1944+
total_msat: total_value,
1945+
});
1946+
payment.insert(session_priv_bytes);
18991947

19001948
let err: Result<(), _> = loop {
19011949
let mut channel_lock = self.channel_state.lock().unwrap();
@@ -2883,23 +2931,23 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28832931
let mut session_priv_bytes = [0; 32];
28842932
session_priv_bytes.copy_from_slice(&session_priv[..]);
28852933
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
2886-
if let hash_map::Entry::Occupied(mut sessions) = outbounds.entry(payment_id) {
2887-
if sessions.get_mut().remove(&session_priv_bytes) {
2934+
if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
2935+
if payment.get_mut().remove(&session_priv_bytes) {
28882936
self.pending_events.lock().unwrap().push(
28892937
events::Event::PaymentPathFailed {
28902938
payment_hash,
28912939
rejected_by_dest: false,
28922940
network_update: None,
2893-
all_paths_failed: sessions.get().len() == 0,
2941+
all_paths_failed: payment.get().num_parts() == 0,
28942942
path: path.clone(),
28952943
#[cfg(test)]
28962944
error_code: None,
28972945
#[cfg(test)]
28982946
error_data: None,
28992947
}
29002948
);
2901-
if sessions.get().len() == 0 {
2902-
sessions.remove();
2949+
if payment.get().num_parts() == 0 {
2950+
payment.remove();
29032951
}
29042952
}
29052953
} else {
@@ -2936,7 +2984,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
29362984
log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
29372985
return;
29382986
}
2939-
if sessions.get().len() == 0 {
2987+
if sessions.get().num_parts() == 0 {
29402988
all_paths_failed = true;
29412989
sessions.remove();
29422990
}
@@ -5161,6 +5209,17 @@ impl_writeable_tlv_based!(PendingInboundPayment, {
51615209
(8, min_value_msat, required),
51625210
});
51635211

5212+
impl_writeable_tlv_based_enum!(PendingOutboundPayment,
5213+
(0, Legacy) => {
5214+
(0, session_privs, required),
5215+
},
5216+
(2, Retryable) => {
5217+
(0, session_privs, required),
5218+
(2, payment_hash, required),
5219+
(4, total_msat, required),
5220+
},
5221+
;);
5222+
51645223
impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<Signer, M, T, K, F, L>
51655224
where M::Target: chain::Watch<Signer>,
51665225
T::Target: BroadcasterInterface,
@@ -5251,18 +5310,30 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
52515310
let pending_outbound_payments = self.pending_outbound_payments.lock().unwrap();
52525311
// For backwards compat, write the session privs and their total length.
52535312
let mut num_pending_outbounds_compat: u64 = 0;
5254-
for (_, outbounds) in pending_outbound_payments.iter() {
5255-
num_pending_outbounds_compat += outbounds.len() as u64;
5313+
for (_, outbound) in pending_outbound_payments.iter() {
5314+
match outbound {
5315+
PendingOutboundPayment::Legacy { session_privs } |
5316+
PendingOutboundPayment::Retryable { session_privs, .. } => {
5317+
num_pending_outbounds_compat += session_privs.len() as u64;
5318+
}
5319+
}
52565320
}
52575321
num_pending_outbounds_compat.write(writer)?;
5258-
for (_, outbounds) in pending_outbound_payments.iter() {
5259-
for outbound in outbounds.iter() {
5260-
outbound.write(writer)?;
5322+
for (_, outbound) in pending_outbound_payments.iter() {
5323+
match outbound {
5324+
PendingOutboundPayment::Legacy { session_privs } |
5325+
PendingOutboundPayment::Retryable { session_privs, .. } => {
5326+
for session_priv in session_privs.iter() {
5327+
session_priv.write(writer)?;
5328+
}
5329+
}
52615330
}
52625331
}
52635332

5333+
let pending_outbound_payments_compat_2: HashMap<PaymentId, HashSet<[u8; 32]>> = HashMap::new();
52645334
write_tlv_fields!(writer, {
5265-
(1, pending_outbound_payments, required),
5335+
(1, pending_outbound_payments_compat_2, required),
5336+
(3, pending_outbound_payments, required),
52665337
});
52675338

52685339
Ok(())
@@ -5522,21 +5593,32 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
55225593
}
55235594

55245595
let pending_outbound_payments_count_compat: u64 = Readable::read(reader)?;
5525-
let mut pending_outbound_payments_compat: HashMap<PaymentId, HashSet<[u8; 32]>> =
5596+
let mut pending_outbound_payments_compat: HashMap<PaymentId, PendingOutboundPayment> =
55265597
HashMap::with_capacity(cmp::min(pending_outbound_payments_count_compat as usize, MAX_ALLOC_SIZE/32));
55275598
for _ in 0..pending_outbound_payments_count_compat {
55285599
let session_priv = Readable::read(reader)?;
5529-
if pending_outbound_payments_compat.insert(PaymentId(session_priv), [session_priv].iter().cloned().collect()).is_some() {
5600+
let payment = PendingOutboundPayment::Legacy {
5601+
session_privs: [session_priv].iter().cloned().collect()
5602+
};
5603+
if pending_outbound_payments_compat.insert(PaymentId(session_priv), payment).is_some() {
55305604
return Err(DecodeError::InvalidValue)
55315605
};
55325606
}
55335607

5608+
let mut pending_outbound_payments_compat_2: Option<HashMap<PaymentId, HashSet<[u8; 32]>>> = None;
55345609
let mut pending_outbound_payments = None;
55355610
read_tlv_fields!(reader, {
5536-
(1, pending_outbound_payments, option),
5611+
(1, pending_outbound_payments_compat_2, option),
5612+
(3, pending_outbound_payments, option),
55375613
});
5538-
if pending_outbound_payments.is_none() {
5614+
if pending_outbound_payments.is_none() && pending_outbound_payments_compat_2.is_none() {
55395615
pending_outbound_payments = Some(pending_outbound_payments_compat);
5616+
} else if pending_outbound_payments.is_none() {
5617+
let mut outbounds = HashMap::new();
5618+
for (id, session_privs) in pending_outbound_payments_compat_2.unwrap().drain() {
5619+
outbounds.insert(id, PendingOutboundPayment::Legacy { session_privs });
5620+
}
5621+
pending_outbound_payments = Some(outbounds);
55405622
}
55415623

55425624
let mut secp_ctx = Secp256k1::new();

0 commit comments

Comments
 (0)