Skip to content

Commit 78d6c3c

Browse files
authored
Merge pull request lightningdevkit#1066 from valentinewallace/2021-08-fix-double-temp-failure
Allow multiple calls to `monitor_update_failed`
2 parents 24065c8 + 3d77cc7 commit 78d6c3c

File tree

3 files changed

+102
-7
lines changed

3 files changed

+102
-7
lines changed

fuzz/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ mkdir -p ./test_cases/$TARGET
8080
echo $HEX | xxd -r -p > ./test_cases/$TARGET/any_filename_works
8181

8282
export RUST_BACKTRACE=1
83+
export RUSTFLAGS="--cfg=fuzzing"
8384
cargo test
8485
```
8586

lightning/src/ln/chanmon_update_fail_tests.rs

+97
Original file line numberDiff line numberDiff line change
@@ -2653,3 +2653,100 @@ fn test_permanent_error_during_handling_shutdown() {
26532653
check_closed_broadcast!(nodes[1], true);
26542654
check_added_monitors!(nodes[1], 2);
26552655
}
2656+
2657+
#[test]
2658+
fn double_temp_error() {
2659+
// Test that it's OK to have multiple `ChainMonitor::update_channel` calls fail in a row.
2660+
let chanmon_cfgs = create_chanmon_cfgs(2);
2661+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
2662+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
2663+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
2664+
2665+
let (_, _, channel_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
2666+
2667+
let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
2668+
let (payment_preimage_2, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
2669+
2670+
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
2671+
// `claim_funds` results in a ChannelMonitorUpdate.
2672+
assert!(nodes[1].node.claim_funds(payment_preimage_1));
2673+
check_added_monitors!(nodes[1], 1);
2674+
let (funding_tx, latest_update_1) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
2675+
2676+
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
2677+
// Previously, this would've panicked due to a double-call to `Channel::monitor_update_failed`,
2678+
// which had some asserts that prevented it from being called twice.
2679+
assert!(nodes[1].node.claim_funds(payment_preimage_2));
2680+
check_added_monitors!(nodes[1], 1);
2681+
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Ok(()));
2682+
2683+
let (_, latest_update_2) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
2684+
nodes[1].node.channel_monitor_updated(&funding_tx, latest_update_1);
2685+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
2686+
check_added_monitors!(nodes[1], 0);
2687+
nodes[1].node.channel_monitor_updated(&funding_tx, latest_update_2);
2688+
2689+
// Complete the first HTLC.
2690+
let events = nodes[1].node.get_and_clear_pending_msg_events();
2691+
assert_eq!(events.len(), 1);
2692+
let (update_fulfill_1, commitment_signed_b1, node_id) = {
2693+
match &events[0] {
2694+
&MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
2695+
assert!(update_add_htlcs.is_empty());
2696+
assert_eq!(update_fulfill_htlcs.len(), 1);
2697+
assert!(update_fail_htlcs.is_empty());
2698+
assert!(update_fail_malformed_htlcs.is_empty());
2699+
assert!(update_fee.is_none());
2700+
(update_fulfill_htlcs[0].clone(), commitment_signed.clone(), node_id.clone())
2701+
},
2702+
_ => panic!("Unexpected event"),
2703+
}
2704+
};
2705+
assert_eq!(node_id, nodes[0].node.get_our_node_id());
2706+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_fulfill_1);
2707+
check_added_monitors!(nodes[0], 0);
2708+
expect_payment_sent!(nodes[0], payment_preimage_1);
2709+
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &commitment_signed_b1);
2710+
check_added_monitors!(nodes[0], 1);
2711+
nodes[0].node.process_pending_htlc_forwards();
2712+
let (raa_a1, commitment_signed_a1) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
2713+
check_added_monitors!(nodes[1], 0);
2714+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
2715+
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &raa_a1);
2716+
check_added_monitors!(nodes[1], 1);
2717+
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &commitment_signed_a1);
2718+
check_added_monitors!(nodes[1], 1);
2719+
2720+
// Complete the second HTLC.
2721+
let ((update_fulfill_2, commitment_signed_b2), raa_b2) = {
2722+
let events = nodes[1].node.get_and_clear_pending_msg_events();
2723+
assert_eq!(events.len(), 2);
2724+
(match &events[0] {
2725+
MessageSendEvent::UpdateHTLCs { node_id, updates } => {
2726+
assert_eq!(*node_id, nodes[0].node.get_our_node_id());
2727+
assert!(updates.update_add_htlcs.is_empty());
2728+
assert!(updates.update_fail_htlcs.is_empty());
2729+
assert!(updates.update_fail_malformed_htlcs.is_empty());
2730+
assert!(updates.update_fee.is_none());
2731+
assert_eq!(updates.update_fulfill_htlcs.len(), 1);
2732+
(updates.update_fulfill_htlcs[0].clone(), updates.commitment_signed.clone())
2733+
},
2734+
_ => panic!("Unexpected event"),
2735+
},
2736+
match events[1] {
2737+
MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
2738+
assert_eq!(*node_id, nodes[0].node.get_our_node_id());
2739+
(*msg).clone()
2740+
},
2741+
_ => panic!("Unexpected event"),
2742+
})
2743+
};
2744+
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &raa_b2);
2745+
check_added_monitors!(nodes[0], 1);
2746+
2747+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_fulfill_2);
2748+
check_added_monitors!(nodes[0], 0);
2749+
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
2750+
commitment_signed_dance!(nodes[0], nodes[1], commitment_signed_b2, false);
2751+
expect_payment_sent!(nodes[0], payment_preimage_2);
2752+
}

lightning/src/ln/channel.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -3060,13 +3060,10 @@ impl<Signer: Sign> Channel<Signer> {
30603060
/// monitor update failure must *not* have been sent to the remote end, and must instead
30613061
/// have been dropped. They will be regenerated when monitor_updating_restored is called.
30623062
pub fn monitor_update_failed(&mut self, resend_raa: bool, resend_commitment: bool, mut pending_forwards: Vec<(PendingHTLCInfo, u64)>, mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>) {
3063-
assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, 0);
3064-
self.monitor_pending_revoke_and_ack = resend_raa;
3065-
self.monitor_pending_commitment_signed = resend_commitment;
3066-
assert!(self.monitor_pending_forwards.is_empty());
3067-
mem::swap(&mut pending_forwards, &mut self.monitor_pending_forwards);
3068-
assert!(self.monitor_pending_failures.is_empty());
3069-
mem::swap(&mut pending_fails, &mut self.monitor_pending_failures);
3063+
self.monitor_pending_revoke_and_ack |= resend_raa;
3064+
self.monitor_pending_commitment_signed |= resend_commitment;
3065+
self.monitor_pending_forwards.append(&mut pending_forwards);
3066+
self.monitor_pending_failures.append(&mut pending_fails);
30703067
self.channel_state |= ChannelState::MonitorUpdateFailed as u32;
30713068
}
30723069

0 commit comments

Comments
 (0)