Skip to content

Commit 1beccf1

Browse files
authored
Merge pull request #1143 from TheBlueMatt/2021-10-no-payment-id-leaks
Fix a minor memory leak on PermanentFailure mon errs when sending
2 parents 081ce7c + 0ec13f6 commit 1beccf1

File tree

1 file changed

+23
-16
lines changed

1 file changed

+23
-16
lines changed

lightning/src/ln/channelmanager.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,21 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
20852085
Some(id) => id.clone(),
20862086
};
20872087

2088+
macro_rules! insert_outbound_payment {
2089+
() => {
2090+
let payment = payment_entry.or_insert_with(|| PendingOutboundPayment::Retryable {
2091+
session_privs: HashSet::new(),
2092+
pending_amt_msat: 0,
2093+
pending_fee_msat: Some(0),
2094+
payment_hash: *payment_hash,
2095+
payment_secret: *payment_secret,
2096+
starting_block_height: self.best_block.read().unwrap().height(),
2097+
total_msat: total_value,
2098+
});
2099+
assert!(payment.insert(session_priv_bytes, path));
2100+
}
2101+
}
2102+
20882103
let channel_state = &mut *channel_lock;
20892104
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(id) {
20902105
match {
@@ -2094,7 +2109,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
20942109
if !chan.get().is_live() {
20952110
return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected/pending monitor update!".to_owned()});
20962111
}
2097-
let send_res = break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(
2112+
break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(
20982113
htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
20992114
path: path.clone(),
21002115
session_priv: session_priv.clone(),
@@ -2103,20 +2118,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
21032118
payment_secret: payment_secret.clone(),
21042119
payee: payee.clone(),
21052120
}, onion_packet, &self.logger),
2106-
channel_state, chan);
2107-
2108-
let payment = payment_entry.or_insert_with(|| PendingOutboundPayment::Retryable {
2109-
session_privs: HashSet::new(),
2110-
pending_amt_msat: 0,
2111-
pending_fee_msat: Some(0),
2112-
payment_hash: *payment_hash,
2113-
payment_secret: *payment_secret,
2114-
starting_block_height: self.best_block.read().unwrap().height(),
2115-
total_msat: total_value,
2116-
});
2117-
assert!(payment.insert(session_priv_bytes, path));
2118-
2119-
send_res
2121+
channel_state, chan)
21202122
} {
21212123
Some((update_add, commitment_signed, monitor_update)) => {
21222124
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
@@ -2126,8 +2128,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
21262128
// is restored. Therefore, we must return an error indicating that
21272129
// it is unsafe to retry the payment wholesale, which we do in the
21282130
// send_payment check for MonitorUpdateFailed, below.
2131+
insert_outbound_payment!(); // Only do this after possibly break'ing on Perm failure above.
21292132
return Err(APIError::MonitorUpdateFailed);
21302133
}
2134+
insert_outbound_payment!();
21312135

21322136
log_debug!(self.logger, "Sending payment along path resulted in a commitment_signed for channel {}", log_bytes!(chan.get().channel_id()));
21332137
channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
@@ -2142,7 +2146,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
21422146
},
21432147
});
21442148
},
2145-
None => {},
2149+
None => { insert_outbound_payment!(); },
21462150
}
21472151
} else { unreachable!(); }
21482152
return Ok(());
@@ -2275,6 +2279,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
22752279
} else { None },
22762280
})
22772281
} else if has_err {
2282+
// If we failed to send any paths, we shouldn't have inserted the new PaymentId into
2283+
// our `pending_outbound_payments` map at all.
2284+
debug_assert!(self.pending_outbound_payments.lock().unwrap().get(&payment_id).is_none());
22782285
Err(PaymentSendFailure::AllFailedRetrySafe(results.drain(..).map(|r| r.unwrap_err()).collect()))
22792286
} else {
22802287
Ok(payment_id)

0 commit comments

Comments
 (0)