Skip to content

Commit 82fdf0f

Browse files
committed
Avoid panic when 0conf channel's ann. sigs race on-chain confirmation
A channel's `short_channel_id` is currently only set when the funding transaction is confirmed via `transactions_confirmed`, which might be well after the channel initally becomes usable, e.g., in the 0conf case. Previously we would panic due to a reachable `unwrap` when receiving a counterparty's `announcement_signatures` message for a 0conf channel pending confirmation on-chain. Here we fix this bug by avoiding unsafe `unwrap`s and just erroring out and ignoring the announcement_signatures message if the `short_channel_id` hasn't been set yet.
1 parent ae9e96e commit 82fdf0f

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

lightning/src/ln/channel.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -948,9 +948,9 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
948948
&self.channel_type
949949
}
950950

951-
/// Guaranteed to be Some after both ChannelReady messages have been exchanged (and, thus,
952-
/// is_usable() returns true).
953-
/// Allowed in any state (including after shutdown)
951+
/// Gets the channel's `short_channel_id`.
952+
///
953+
/// Will return `None` if the channel hasn't been confirmed yet.
954954
pub fn get_short_channel_id(&self) -> Option<u64> {
955955
self.short_channel_id
956956
}
@@ -4832,6 +4832,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
48324832
return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned()));
48334833
}
48344834

4835+
let short_channel_id = self.context.get_short_channel_id()
4836+
.ok_or(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel has not been confirmed yet".to_owned()))?;
48354837
let node_id = NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node)
48364838
.map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?);
48374839
let counterparty_node_id = NodeId::from_pubkey(&self.context.get_counterparty_node_id());
@@ -4840,7 +4842,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
48404842
let msg = msgs::UnsignedChannelAnnouncement {
48414843
features: channelmanager::provided_channel_features(&user_config),
48424844
chain_hash,
4843-
short_channel_id: self.context.get_short_channel_id().unwrap(),
4845+
short_channel_id,
48444846
node_id_1: if were_node_one { node_id } else { counterparty_node_id },
48454847
node_id_2: if were_node_one { counterparty_node_id } else { node_id },
48464848
bitcoin_key_1: NodeId::from_pubkey(if were_node_one { &self.context.get_holder_pubkeys().funding_pubkey } else { self.context.counterparty_funding_pubkey() }),

lightning/src/ln/priv_short_conf_tests.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,3 +1007,38 @@ fn test_connect_before_funding() {
10071007
connect_blocks(&nodes[0], 1);
10081008
connect_blocks(&nodes[1], 1);
10091009
}
1010+
1011+
#[test]
1012+
fn test_0conf_ann_sigs_racing_conf() {
1013+
// Previously we had a bug where we'd panic when receiving a counterparty's
1014+
// announcement_signatures message for a 0conf channel pending confirmation on-chain. Here we
1015+
// check that we just error out, ignore the announcement_signatures message, and proceed
1016+
// instead.
1017+
let chanmon_cfgs = create_chanmon_cfgs(2);
1018+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
1019+
let mut chan_config = test_default_channel_config();
1020+
chan_config.manually_accept_inbound_channels = true;
1021+
1022+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(chan_config)]);
1023+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
1024+
1025+
// This is the default but we force it on anyway
1026+
chan_config.channel_handshake_config.announced_channel = true;
1027+
let (tx, ..) = open_zero_conf_channel(&nodes[0], &nodes[1], Some(chan_config));
1028+
1029+
// We can use the channel immediately, but we can't announce it until we get 6+ confirmations
1030+
send_payment(&nodes[0], &[&nodes[1]], 100_000);
1031+
1032+
let scid = confirm_transaction(&nodes[0], &tx);
1033+
let as_announcement_sigs = get_event_msg!(nodes[0], MessageSendEvent::SendAnnouncementSignatures, nodes[1].node.get_our_node_id());
1034+
1035+
// Handling the announcement_signatures prior to the first confirmation would panic before.
1036+
nodes[1].node.handle_announcement_signatures(&nodes[0].node.get_our_node_id(), &as_announcement_sigs);
1037+
1038+
assert_eq!(confirm_transaction(&nodes[1], &tx), scid);
1039+
let bs_announcement_sigs = get_event_msg!(nodes[1], MessageSendEvent::SendAnnouncementSignatures, nodes[0].node.get_our_node_id());
1040+
1041+
nodes[0].node.handle_announcement_signatures(&nodes[1].node.get_our_node_id(), &bs_announcement_sigs);
1042+
let as_announcement = nodes[0].node.get_and_clear_pending_msg_events();
1043+
assert_eq!(as_announcement.len(), 1);
1044+
}

0 commit comments

Comments
 (0)