Skip to content

Commit bc1a7d0

Browse files
committed
Do not fail to load ChannelManager when we see claiming payments
When we begin claiming a payment, we move the tracking of it from `claimable_payments` to `claiming_payments`. This ensures we only ever have one payment which is in the process of being claimed with a given payment hash at a time and lets us keep track of when all parts have been claimed with their `ChannelMonitor`s. However, on startup, we check that failing to move a payment from `claimable_payments` to `claiming_payments` we check that it is not present in `claiming_payments`. This is fine if the payment doesn't exist, but if the payment has already started being claimed, this will fail and we'll refuse to deserialize the `ChannelManager` (with a `debug_assert` failure in debug mode). Here we resolve this by checking if a payment is already being claimed before we attempt to initiate claiming and skip the failing check in that case.
1 parent 78fee88 commit bc1a7d0

File tree

2 files changed

+37
-22
lines changed

2 files changed

+37
-22
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14857,21 +14857,27 @@ where
1485714857
// preimages eventually timing out from ChannelMonitors to prevent us from
1485814858
// doing so forever.
1485914859

14860-
let claim_found =
14861-
channel_manager.claimable_payments.lock().unwrap().begin_claiming_payment(
14862-
payment_hash, &channel_manager.node_signer, &channel_manager.logger,
14863-
&channel_manager.inbound_payment_id_secret, true,
14864-
);
14865-
if claim_found.is_err() {
14866-
let mut claimable_payments = channel_manager.claimable_payments.lock().unwrap();
14867-
match claimable_payments.pending_claiming_payments.entry(payment_hash) {
14868-
hash_map::Entry::Occupied(_) => {
14869-
debug_assert!(false, "Entry was added in begin_claiming_payment");
14870-
return Err(DecodeError::InvalidValue);
14871-
},
14872-
hash_map::Entry::Vacant(entry) => {
14873-
entry.insert(payment_claim.claiming_payment);
14874-
},
14860+
let already_claiming = {
14861+
let payments = channel_manager.claimable_payments.lock().unwrap();
14862+
payments.pending_claiming_payments.contains_key(&payment_hash)
14863+
};
14864+
if !already_claiming {
14865+
let claim_found =
14866+
channel_manager.claimable_payments.lock().unwrap().begin_claiming_payment(
14867+
payment_hash, &channel_manager.node_signer, &channel_manager.logger,
14868+
&channel_manager.inbound_payment_id_secret, true,
14869+
);
14870+
if claim_found.is_err() {
14871+
let mut claimable_payments = channel_manager.claimable_payments.lock().unwrap();
14872+
match claimable_payments.pending_claiming_payments.entry(payment_hash) {
14873+
hash_map::Entry::Occupied(_) => {
14874+
debug_assert!(false, "Entry was added in begin_claiming_payment");
14875+
return Err(DecodeError::InvalidValue);
14876+
},
14877+
hash_map::Entry::Vacant(entry) => {
14878+
entry.insert(payment_claim.claiming_payment);
14879+
},
14880+
}
1487514881
}
1487614882
}
1487714883

lightning/src/ln/reload_tests.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ fn test_forwardable_regen() {
783783
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_2);
784784
}
785785

786-
fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
786+
fn do_test_partial_claim_before_restart(persist_both_monitors: bool, double_restart: bool) {
787787
// Test what happens if a node receives an MPP payment, claims it, but crashes before
788788
// persisting the ChannelManager. If `persist_both_monitors` is false, also crash after only
789789
// updating one of the two channels' ChannelMonitors. As a result, on startup, we'll (a) still
@@ -799,11 +799,11 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
799799
// definitely claimed.
800800
let chanmon_cfgs = create_chanmon_cfgs(4);
801801
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
802-
let persister;
803-
let new_chain_monitor;
802+
let (persist_d_1, persist_d_2);
803+
let (chain_d_1, chain_d_2);
804804

805805
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
806-
let nodes_3_deserialized;
806+
let (node_d_1, node_d_2);
807807

808808
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
809809

@@ -878,7 +878,14 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
878878
}
879879

880880
// Now restart nodes[3].
881-
reload_node!(nodes[3], original_manager, &[&updated_monitor.0, &original_monitor.0], persister, new_chain_monitor, nodes_3_deserialized);
881+
reload_node!(nodes[3], original_manager.clone(), &[&updated_monitor.0, &original_monitor.0], persit_d_1, chain_d_1, node_d_1);
882+
883+
if double_restart {
884+
// Previously, we had a bug where we'd fail to reload if we re-persist the `ChannelManager`
885+
// without updating any `ChannelMonitor`s as we'd fail to double-initiate the claim replay.
886+
// We test that here ensuring that we can reload again.
887+
reload_node!(nodes[3], node_d_1.encode(), &[&updated_monitor.0, &original_monitor.0], persist_d_2, chain_d_2, node_d_2);
888+
}
882889

883890
// Until the startup background events are processed (in `get_and_clear_pending_events`,
884891
// below), the preimage is not copied to the non-persisted monitor...
@@ -973,8 +980,10 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool) {
973980

974981
#[test]
975982
fn test_partial_claim_before_restart() {
976-
do_test_partial_claim_before_restart(false);
977-
do_test_partial_claim_before_restart(true);
983+
do_test_partial_claim_before_restart(false, false);
984+
do_test_partial_claim_before_restart(false, true);
985+
do_test_partial_claim_before_restart(true, false);
986+
do_test_partial_claim_before_restart(true, true);
978987
}
979988

980989
fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_htlc: bool, use_intercept: bool) {

0 commit comments

Comments
 (0)