Skip to content

Commit 7a60be2

Browse files
committed
Handle duplicate payment claims during initialization
In the next commit we'll start using (much of) the normal HTLC claim pipeline to replay payment claims on startup. In order to do so, however, we have to properly handle cases where we get a `DuplicateClaim` back from the channel for an inbound-payment HTLC. Here we do so, handling the `MonitorUpdateCompletionAction` and allowing an already-completed RAA blocker.
1 parent 22d39f9 commit 7a60be2

File tree

1 file changed

+37
-25
lines changed

1 file changed

+37
-25
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6964,7 +6964,16 @@ where
69646964
UpdateFulfillCommitFetch::DuplicateClaim {} => {
69656965
let (action_opt, raa_blocker_opt) = completion_action(None, true);
69666966
if let Some(raa_blocker) = raa_blocker_opt {
6967-
debug_assert!(peer_state.actions_blocking_raa_monitor_updates.get(&chan_id).unwrap().contains(&raa_blocker));
6967+
// If we're making a claim during startup, its a replay of a
6968+
// payment claim from a `ChannelMonitor`. In some cases (MPP or
6969+
// if the HTLC was only recently removed) we make such claims
6970+
// after an HTLC has been removed from a channel entirely, and
6971+
// thus the RAA blocker has long since completed.
6972+
//
6973+
// In any other case, the RAA blocker must still be present and
6974+
// blocking RAAs.
6975+
debug_assert!(during_init ||
6976+
peer_state.actions_blocking_raa_monitor_updates.get(&chan_id).unwrap().contains(&raa_blocker));
69686977
}
69696978
let action = if let Some(action) = action_opt {
69706979
action
@@ -6976,38 +6985,41 @@ where
69766985

69776986
log_trace!(logger, "Completing monitor update completion action for channel {} as claim was redundant: {:?}",
69786987
chan_id, action);
6979-
let (node_id, _funding_outpoint, channel_id, blocker) =
69806988
if let MonitorUpdateCompletionAction::FreeOtherChannelImmediately {
69816989
downstream_counterparty_node_id: node_id,
6982-
downstream_funding_outpoint: funding_outpoint,
6990+
downstream_funding_outpoint: _,
69836991
blocking_action: blocker, downstream_channel_id: channel_id,
69846992
} = action {
6985-
(node_id, funding_outpoint, channel_id, blocker)
6993+
if let Some(peer_state_mtx) = per_peer_state.get(&node_id) {
6994+
let mut peer_state = peer_state_mtx.lock().unwrap();
6995+
if let Some(blockers) = peer_state
6996+
.actions_blocking_raa_monitor_updates
6997+
.get_mut(&channel_id)
6998+
{
6999+
let mut found_blocker = false;
7000+
blockers.retain(|iter| {
7001+
// Note that we could actually be blocked, in
7002+
// which case we need to only remove the one
7003+
// blocker which was added duplicatively.
7004+
let first_blocker = !found_blocker;
7005+
if *iter == blocker { found_blocker = true; }
7006+
*iter != blocker || !first_blocker
7007+
});
7008+
debug_assert!(found_blocker);
7009+
}
7010+
} else {
7011+
debug_assert!(false);
7012+
}
7013+
} else if matches!(action, MonitorUpdateCompletionAction::PaymentClaimed { .. }) {
7014+
debug_assert!(during_init,
7015+
"Duplicate claims should always either be for forwarded payments(freeing another channel immediately) or during init (for claim replay)");
7016+
mem::drop(per_peer_state);
7017+
self.handle_monitor_update_completion_actions([action]);
69867018
} else {
69877019
debug_assert!(false,
6988-
"Duplicate claims should always free another channel immediately");
7020+
"Duplicate claims should always either be for forwarded payments(freeing another channel immediately) or during init (for claim replay)");
69897021
return;
69907022
};
6991-
if let Some(peer_state_mtx) = per_peer_state.get(&node_id) {
6992-
let mut peer_state = peer_state_mtx.lock().unwrap();
6993-
if let Some(blockers) = peer_state
6994-
.actions_blocking_raa_monitor_updates
6995-
.get_mut(&channel_id)
6996-
{
6997-
let mut found_blocker = false;
6998-
blockers.retain(|iter| {
6999-
// Note that we could actually be blocked, in
7000-
// which case we need to only remove the one
7001-
// blocker which was added duplicatively.
7002-
let first_blocker = !found_blocker;
7003-
if *iter == blocker { found_blocker = true; }
7004-
*iter != blocker || !first_blocker
7005-
});
7006-
debug_assert!(found_blocker);
7007-
}
7008-
} else {
7009-
debug_assert!(false);
7010-
}
70117023
}
70127024
}
70137025
}

0 commit comments

Comments
 (0)