Skip to content

Commit 7790e30

Browse files
committed
Store info about claimed payments, incl HTLCs in ChannelMonitors
When we claim an MPP payment, then crash before persisting all the relevant `ChannelMonitor`s, we rely on the payment data being available in the `ChannelManager` on restart to re-claim any parts that haven't yet been claimed. This is fine as long as the `ChannelManager` was persisted before the `PaymentClaimable` event was processed, which is generally the case in our `lightning-background-processor`, but may not be in other cases or in a somewhat rare race. In order to fix this, we need to track where all the MPP parts of a payment are in the `ChannelMonitor`, allowing us to re-claim any missing pieces without reference to any `ChannelManager` data. Further, in order to properly generate a `PaymentClaimed` event against the re-started claim, we have to store various payment metadata with the HTLC list as well. Here we store the required MPP parts and metadata in `ChannelMonitor`s and make them available to `ChannelManager` on load.
1 parent b8661ef commit 7790e30

File tree

3 files changed

+52
-13
lines changed

3 files changed

+52
-13
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -923,8 +923,16 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
923923
/// The set of payment hashes from inbound payments for which we know the preimage. Payment
924924
/// preimages that are not included in any unrevoked local commitment transaction or unrevoked
925925
/// remote commitment transactions are automatically removed when commitment transactions are
926-
/// revoked.
927-
payment_preimages: HashMap<PaymentHash, PaymentPreimage>,
926+
/// revoked. Note that this happens one revocation after it theoretically could, leaving
927+
/// preimages present here for the previous state even when the channel is "at rest". This is a
928+
/// good safety buffer, but also is important as it ensures we retain payment preimages for the
929+
/// previous local commitment transaction, which may have been broadcast already when we see
930+
/// the revocation (in setups with redundant monitors).
931+
///
932+
/// We also store [`PaymentClaimDetails`] here, tracking the payment information(s) for this
933+
/// preimage for inbound payments. This allows us to rebuild the inbound payment information on
934+
/// startup even if we lost our `ChannelManager`.
935+
payment_preimages: HashMap<PaymentHash, (PaymentPreimage, Vec<PaymentClaimDetails>)>,
928936

929937
// Note that `MonitorEvent`s MUST NOT be generated during update processing, only generated
930938
// during chain data processing. This prevents a race in `ChainMonitor::update_channel` (and
@@ -1150,7 +1158,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
11501158
writer.write_all(&byte_utils::be48_to_array(self.current_holder_commitment_number))?;
11511159

11521160
writer.write_all(&(self.payment_preimages.len() as u64).to_be_bytes())?;
1153-
for payment_preimage in self.payment_preimages.values() {
1161+
for (payment_preimage, _) in self.payment_preimages.values() {
11541162
writer.write_all(&payment_preimage.0[..])?;
11551163
}
11561164

@@ -1228,6 +1236,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
12281236
(19, self.channel_id, required),
12291237
(21, self.balances_empty_height, option),
12301238
(23, self.holder_pays_commitment_tx_fee, option),
1239+
(25, self.payment_preimages, required),
12311240
});
12321241

12331242
Ok(())
@@ -2201,7 +2210,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
22012210
outbound_payment,
22022211
});
22032212
}
2204-
} else if let Some(payment_preimage) = self.payment_preimages.get(&htlc.payment_hash) {
2213+
} else if let Some((payment_preimage, _)) = self.payment_preimages.get(&htlc.payment_hash) {
22052214
// Otherwise (the payment was inbound), only expose it as claimable if
22062215
// we know the preimage.
22072216
// Note that if there is a pending claim, but it did not use the
@@ -2422,7 +2431,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
24222431
outbound_payment,
24232432
});
24242433
}
2425-
} else if us.payment_preimages.get(&htlc.payment_hash).is_some() {
2434+
} else if us.payment_preimages.contains_key(&htlc.payment_hash) {
24262435
inbound_claiming_htlc_rounded_msat += rounded_value_msat;
24272436
if htlc.transaction_output_index.is_some() {
24282437
claimable_inbound_htlc_value_sat += htlc.amount_msat / 1000;
@@ -2577,7 +2586,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
25772586
res
25782587
}
25792588

2580-
pub(crate) fn get_stored_preimages(&self) -> HashMap<PaymentHash, PaymentPreimage> {
2589+
pub(crate) fn get_stored_preimages(&self) -> HashMap<PaymentHash, (PaymentPreimage, Vec<PaymentClaimDetails>)> {
25812590
self.inner.lock().unwrap().payment_preimages.clone()
25822591
}
25832592
}
@@ -2936,6 +2945,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
29362945

29372946
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
29382947
/// commitment_tx_infos which contain the payment hash have been revoked.
2948+
///
2949+
/// Note that this is often called multiple times for the same payment and must be idempotent.
29392950
fn provide_payment_preimage<B: Deref, F: Deref, L: Deref>(
29402951
&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage,
29412952
payment_info: &Option<PaymentClaimDetails>, broadcaster: &B,
@@ -2944,8 +2955,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
29442955
F::Target: FeeEstimator,
29452956
L::Target: Logger,
29462957
{
2947-
// TODO: Store payment_info (but do not override any existing values)
2948-
self.payment_preimages.insert(payment_hash.clone(), payment_preimage.clone());
2958+
self.payment_preimages.entry(payment_hash.clone())
2959+
.and_modify(|(_, payment_infos)| {
2960+
if let Some(payment_info) = payment_info {
2961+
if !payment_infos.contains(&payment_info) {
2962+
payment_infos.push(payment_info.clone());
2963+
}
2964+
}
2965+
})
2966+
.or_insert_with(|| {
2967+
(payment_preimage.clone(), payment_info.clone().into_iter().collect())
2968+
});
29492969

29502970
let confirmed_spend_txid = self.funding_spend_confirmed.or_else(|| {
29512971
self.onchain_events_awaiting_threshold_conf.iter().find_map(|event| match event.event {
@@ -3602,7 +3622,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
36023622
return (claimable_outpoints, to_counterparty_output_info);
36033623
}
36043624
}
3605-
let preimage = if htlc.offered { if let Some(p) = self.payment_preimages.get(&htlc.payment_hash) { Some(*p) } else { None } } else { None };
3625+
let preimage = if htlc.offered { if let Some((p, _)) = self.payment_preimages.get(&htlc.payment_hash) { Some(*p) } else { None } } else { None };
36063626
if preimage.is_some() || !htlc.offered {
36073627
let counterparty_htlc_outp = if htlc.offered {
36083628
PackageSolvingData::CounterpartyOfferedHTLCOutput(
@@ -3690,7 +3710,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
36903710
);
36913711
(htlc_output, conf_height)
36923712
} else {
3693-
let payment_preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
3713+
let payment_preimage = if let Some((preimage, _)) = self.payment_preimages.get(&htlc.payment_hash) {
36943714
preimage.clone()
36953715
} else {
36963716
// We can't build an HTLC-Success transaction without the preimage
@@ -3844,7 +3864,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38443864
for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() {
38453865
if let Some(vout) = htlc.0.transaction_output_index {
38463866
let preimage = if !htlc.0.offered {
3847-
if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(preimage.clone()) } else {
3867+
if let Some((preimage, _)) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(preimage.clone()) } else {
38483868
// We can't build an HTLC-Success transaction without the preimage
38493869
continue;
38503870
}
@@ -4817,7 +4837,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
48174837
for _ in 0..payment_preimages_len {
48184838
let preimage: PaymentPreimage = Readable::read(reader)?;
48194839
let hash = PaymentHash(Sha256::hash(&preimage.0[..]).to_byte_array());
4820-
if let Some(_) = payment_preimages.insert(hash, preimage) {
4840+
if let Some(_) = payment_preimages.insert(hash, (preimage, Vec::new())) {
48214841
return Err(DecodeError::InvalidValue);
48224842
}
48234843
}
@@ -4900,6 +4920,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
49004920
let mut balances_empty_height = None;
49014921
let mut channel_id = None;
49024922
let mut holder_pays_commitment_tx_fee = None;
4923+
let mut payment_preimages_with_info: Option<HashMap<_, _>> = None;
49034924
read_tlv_fields!(reader, {
49044925
(1, funding_spend_confirmed, option),
49054926
(3, htlcs_resolved_on_chain, optional_vec),
@@ -4913,7 +4934,24 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
49134934
(19, channel_id, option),
49144935
(21, balances_empty_height, option),
49154936
(23, holder_pays_commitment_tx_fee, option),
4937+
(25, payment_preimages_with_info, option),
49164938
});
4939+
if let Some(payment_preimages_with_info) = payment_preimages_with_info {
4940+
if payment_preimages_with_info.len() != payment_preimages.len() {
4941+
return Err(DecodeError::InvalidValue);
4942+
}
4943+
for (payment_hash, (payment_preimage, _)) in payment_preimages.iter() {
4944+
// Note that because `payment_preimages` is built back from preimages directly,
4945+
// checking that the two maps have the same hash -> preimage pairs also checks that
4946+
// the payment hashes in `payment_preimages_with_info`'s preimages match its
4947+
// hashes.
4948+
let new_preimage = payment_preimages_with_info.get(payment_hash).map(|(p, _)| p);
4949+
if new_preimage != Some(payment_preimage) {
4950+
return Err(DecodeError::InvalidValue);
4951+
}
4952+
}
4953+
payment_preimages = payment_preimages_with_info;
4954+
}
49174955

49184956
// `HolderForceClosedWithInfo` replaced `HolderForceClosed` in v0.0.122. If we have both
49194957
// events, we can remove the `HolderForceClosed` event and just keep the `HolderForceClosedWithInfo`.

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12987,7 +12987,7 @@ where
1298712987
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(args.fee_estimator);
1298812988

1298912989
for (_, monitor) in args.channel_monitors.iter() {
12990-
for (payment_hash, payment_preimage) in monitor.get_stored_preimages() {
12990+
for (payment_hash, (payment_preimage, _)) in monitor.get_stored_preimages() {
1299112991
if let Some(payment) = claimable_payments.remove(&payment_hash) {
1299212992
log_info!(args.logger, "Re-claiming HTLCs with payment hash {} as we've released the preimage to a ChannelMonitor!", &payment_hash);
1299312993
let mut claimable_amt_msat = 0;

lightning/src/util/ser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,7 @@ impl Readable for Vec<u8> {
10011001
impl_for_vec!(ecdsa::Signature);
10021002
impl_for_vec!(crate::chain::channelmonitor::ChannelMonitorUpdate);
10031003
impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction);
1004+
impl_for_vec!(crate::ln::channelmanager::PaymentClaimDetails);
10041005
impl_for_vec!(crate::ln::msgs::SocketAddress);
10051006
impl_for_vec!((A, B), A, B);
10061007
impl_writeable_for_vec!(&crate::routing::router::BlindedTail);

0 commit comments

Comments
 (0)