Skip to content

Commit 9886bba

Browse files
committed
Review comments
1 parent 7816cf6 commit 9886bba

File tree

3 files changed

+59
-37
lines changed

3 files changed

+59
-37
lines changed

lightning/src/ln/channel.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -3652,17 +3652,17 @@ impl<SP: Deref> Channel<SP> where
36523652
/// resent.
36533653
/// No further message handling calls may be made until a channel_reestablish dance has
36543654
/// completed.
3655-
pub fn remove_uncommitted_htlcs_and_mark_paused<L: Deref>(&mut self, logger: &L) where L::Target: Logger {
3655+
/// May return `Err(())`, which implies [`Self::force_shutdown`] should be called immediately.
3656+
pub fn remove_uncommitted_htlcs_and_mark_paused<L: Deref>(&mut self, logger: &L) -> Result<(), ()> where L::Target: Logger {
36563657
assert_eq!(self.context.channel_state & ChannelState::ShutdownComplete as u32, 0);
36573658
if self.context.channel_state & !STATE_FLAGS < ChannelState::FundingSent as u32 {
3658-
self.context.channel_state = ChannelState::ShutdownComplete as u32;
3659-
return;
3659+
return Err(());
36603660
}
36613661

36623662
if self.context.channel_state & (ChannelState::PeerDisconnected as u32) == (ChannelState::PeerDisconnected as u32) {
36633663
// While the below code should be idempotent, it's simpler to just return early, as
36643664
// redundant disconnect events can fire, though they should be rare.
3665-
return;
3665+
return Ok(());
36663666
}
36673667

36683668
if self.context.announcement_sigs_state == AnnouncementSigsState::MessageSent || self.context.announcement_sigs_state == AnnouncementSigsState::Committed {
@@ -3723,6 +3723,7 @@ impl<SP: Deref> Channel<SP> where
37233723

37243724
self.context.channel_state |= ChannelState::PeerDisconnected as u32;
37253725
log_trace!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops on channel {}", inbound_drop_count, &self.context.channel_id());
3726+
Ok(())
37263727
}
37273728

37283729
/// Indicates that a ChannelMonitor update is in progress and has not yet been fully persisted.
@@ -7940,15 +7941,15 @@ mod tests {
79407941

79417942
// Now disconnect the two nodes and check that the commitment point in
79427943
// Node B's channel_reestablish message is sane.
7943-
node_b_chan.remove_uncommitted_htlcs_and_mark_paused(&&logger);
7944+
assert!(node_b_chan.remove_uncommitted_htlcs_and_mark_paused(&&logger).is_ok());
79447945
let msg = node_b_chan.get_channel_reestablish(&&logger);
79457946
assert_eq!(msg.next_local_commitment_number, 1); // now called next_commitment_number
79467947
assert_eq!(msg.next_remote_commitment_number, 0); // now called next_revocation_number
79477948
assert_eq!(msg.your_last_per_commitment_secret, [0; 32]);
79487949

79497950
// Check that the commitment point in Node A's channel_reestablish message
79507951
// is sane.
7951-
node_a_chan.remove_uncommitted_htlcs_and_mark_paused(&&logger);
7952+
assert!(node_a_chan.remove_uncommitted_htlcs_and_mark_paused(&&logger).is_ok());
79527953
let msg = node_a_chan.get_channel_reestablish(&&logger);
79537954
assert_eq!(msg.next_local_commitment_number, 1); // now called next_commitment_number
79547955
assert_eq!(msg.next_remote_commitment_number, 0); // now called next_revocation_number

lightning/src/ln/channelmanager.rs

+30-22
Original file line numberDiff line numberDiff line change
@@ -2047,8 +2047,12 @@ macro_rules! handle_monitor_update_completion {
20472047
));
20482048
if let Some(channel_state) = channel_state {
20492049
channel_state.2 = true;
2050+
} else {
2051+
debug_assert!(false, "Missing channel batch state for channel which completed initial monitor update");
20502052
}
20512053
batch_completed = batch_state.iter().all(|(_, _, completed)| *completed);
2054+
} else {
2055+
debug_assert!(false, "Missing batch state for channel which completed initial monitor update");
20522056
}
20532057

20542058
// When all channels in a batched funding transaction have become ready, it is not necessary
@@ -2707,7 +2711,8 @@ where
27072711
let mut funding_batch_states = self.funding_batch_states.lock().unwrap();
27082712
let affected_channels = funding_batch_states.remove(&txid).into_iter().flatten();
27092713
let per_peer_state = self.per_peer_state.read().unwrap();
2710-
for (channel_id, counterparty_node_id, _state) in affected_channels {
2714+
let mut has_uncompleted_channel = None;
2715+
for (channel_id, counterparty_node_id, state) in affected_channels {
27112716
if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) {
27122717
let mut peer_state = peer_state_mutex.lock().unwrap();
27132718
if let Some(mut chan) = peer_state.channel_by_id.remove(&channel_id) {
@@ -2716,7 +2721,12 @@ where
27162721
shutdown_results.push(chan.context_mut().force_shutdown(false));
27172722
}
27182723
}
2724+
has_uncompleted_channel = Some(has_uncompleted_channel.map_or(!state, |v| v || !state));
27192725
}
2726+
debug_assert!(
2727+
has_uncompleted_channel.unwrap_or(true),
2728+
"Closing a batch where all channels have completed initial monitor update",
2729+
);
27202730
}
27212731
for shutdown_result in shutdown_results.drain(..) {
27222732
self.finish_close_channel(shutdown_result);
@@ -3867,7 +3877,6 @@ where
38673877
}
38683878
}
38693879

3870-
38713880
let txid = funding_transaction.txid();
38723881
let is_batch_funding = temporary_channels.len() > 1;
38733882
let mut funding_batch_states = if is_batch_funding {
@@ -3876,8 +3885,15 @@ where
38763885
None
38773886
};
38783887
let mut funding_batch_state = funding_batch_states.as_mut().and_then(|states| {
3879-
states.insert(txid, Vec::new());
3880-
states.get_mut(&txid)
3888+
if states.contains_key(&txid) {
3889+
result = result.clone().and(Err(APIError::APIMisuseError {
3890+
err: "Batch funding transaction with the same txid already exists".to_owned()
3891+
}));
3892+
None
3893+
} else {
3894+
states.insert(txid, Vec::new());
3895+
states.get_mut(&txid)
3896+
}
38813897
});
38823898
for (channel_idx, &(temporary_channel_id, counterparty_node_id)) in temporary_channels.iter().enumerate() {
38833899
result = result.and_then(|_| self.funding_transaction_generated_intern(
@@ -7995,35 +8011,24 @@ where
79958011
peer_state.channel_by_id.retain(|_, phase| {
79968012
let context = match phase {
79978013
ChannelPhase::Funded(chan) => {
7998-
if !chan.context.is_funding_broadcast() {
7999-
update_maps_on_chan_removal!(self, &chan.context);
8000-
self.issue_channel_close_events(&chan.context, ClosureReason::DisconnectedPeer);
8001-
// It is possible to have persisted the monitor upon funding_signed
8002-
// but not have broadcast the transaction, especially for batch funding.
8003-
// The monitor should be moved to the correct state.
8004-
failed_channels.push(chan.context.force_shutdown(false));
8005-
return false;
8006-
} else {
8007-
chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger);
8014+
if chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger).is_ok() {
80088015
// We only retain funded channels that are not shutdown.
8009-
if !chan.is_shutdown() {
8010-
return true;
8011-
}
8016+
return true;
80128017
}
8013-
&chan.context
8018+
&mut chan.context
80148019
},
80158020
// Unfunded channels will always be removed.
80168021
ChannelPhase::UnfundedOutboundV1(chan) => {
8017-
&chan.context
8022+
&mut chan.context
80188023
},
80198024
ChannelPhase::UnfundedInboundV1(chan) => {
8020-
&chan.context
8025+
&mut chan.context
80218026
},
80228027
};
80238028
// Clean up for removal.
80248029
update_maps_on_chan_removal!(self, &context);
80258030
self.issue_channel_close_events(&context, ClosureReason::DisconnectedPeer);
8026-
failed_channels.push((None, Vec::new(), None));
8031+
failed_channels.push(context.force_shutdown(false));
80278032
false
80288033
});
80298034
// Note that we don't bother generating any events for pre-accept channels -
@@ -9262,7 +9267,10 @@ where
92629267
log_error!(args.logger, " The ChannelMonitor for channel {} is at counterparty commitment transaction number {} but the ChannelManager is at counterparty commitment transaction number {}.",
92639268
&channel.context.channel_id(), monitor.get_cur_counterparty_commitment_number(), channel.get_cur_counterparty_commitment_transaction_number());
92649269
}
9265-
let (monitor_update, mut new_failed_htlcs, _batch_funding_txid) = channel.context.force_shutdown(true);
9270+
let (monitor_update, mut new_failed_htlcs, batch_funding_txid) = channel.context.force_shutdown(true);
9271+
if batch_funding_txid.is_some() {
9272+
return Err(DecodeError::InvalidValue);
9273+
}
92669274
if let Some((counterparty_node_id, funding_txo, update)) = monitor_update {
92679275
close_background_events.push(BackgroundEvent::MonitorUpdateRegeneratedOnStartup {
92689276
counterparty_node_id, funding_txo, update

lightning/src/ln/functional_tests.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -10514,10 +10514,10 @@ fn test_disconnect_in_funding_batch() {
1051410514
..
1051510515
} if channel_id == &channel_id_2
1051610516
)));
10517-
assert!(events.iter().any(|e| matches!(
10517+
assert_eq!(events.iter().filter(|e| matches!(
1051810518
e,
1051910519
Event::DiscardFunding { .. },
10520-
)));
10520+
)).count(), 2);
1052110521

1052210522
// The monitor should become closed.
1052310523
check_added_monitors(&nodes[0], 1);
@@ -10558,19 +10558,32 @@ fn test_batch_funding_close_after_funding_signed() {
1055810558
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
1055910559
check_added_monitors(&nodes[0], 1);
1056010560

10561+
// Go through the funding_created and funding_signed flow with node 2.
10562+
nodes[2].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msgs[1]);
10563+
check_added_monitors(&nodes[2], 1);
10564+
expect_channel_pending_event(&nodes[2], &nodes[0].node.get_our_node_id());
10565+
10566+
let funding_signed_msg = get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
10567+
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
10568+
nodes[0].node.handle_funding_signed(&nodes[2].node.get_our_node_id(), &funding_signed_msg);
10569+
check_added_monitors(&nodes[0], 1);
10570+
1056110571
// The transaction should not have been broadcast before all channels are ready.
1056210572
assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0);
1056310573

10564-
// Force-close the channel for which we've received funding_signed.
10574+
// Force-close the channel for which we've completed the initial monitor.
1056510575
let channel_id_1 = OutPoint { txid: tx.txid(), index: 0 }.to_channel_id();
1056610576
let channel_id_2 = OutPoint { txid: tx.txid(), index: 1 }.to_channel_id();
1056710577
nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id()).unwrap();
10568-
check_added_monitors(&nodes[0], 1);
10578+
check_added_monitors(&nodes[0], 2);
1056910579
{
1057010580
let mut monitor_updates = nodes[0].chain_monitor.monitor_updates.lock().unwrap();
10571-
let monitor_updates = monitor_updates.get(&channel_id_1).unwrap();
10572-
assert_eq!(monitor_updates.len(), 1);
10573-
assert_eq!(monitor_updates[0].update_id, CLOSED_CHANNEL_UPDATE_ID);
10581+
let monitor_updates_1 = monitor_updates.get(&channel_id_1).unwrap();
10582+
assert_eq!(monitor_updates_1.len(), 1);
10583+
assert_eq!(monitor_updates_1[0].update_id, CLOSED_CHANNEL_UPDATE_ID);
10584+
let monitor_updates_2 = monitor_updates.get(&channel_id_2).unwrap();
10585+
assert_eq!(monitor_updates_2.len(), 1);
10586+
assert_eq!(monitor_updates_2[0].update_id, CLOSED_CHANNEL_UPDATE_ID);
1057410587
}
1057510588
let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
1057610589
match msg_events[0] {
@@ -10604,10 +10617,10 @@ fn test_batch_funding_close_after_funding_signed() {
1060410617
..
1060510618
} if channel_id == &channel_id_2
1060610619
)));
10607-
assert!(events.iter().any(|e| matches!(
10620+
assert_eq!(events.iter().filter(|e| matches!(
1060810621
e,
1060910622
Event::DiscardFunding { .. },
10610-
)));
10623+
)).count(), 2);
1061110624

1061210625
// Ensure the channels don't exist anymore.
1061310626
assert!(nodes[0].node.list_channels().is_empty());

0 commit comments

Comments
 (0)