Skip to content

Commit d7e3320

Browse files
authored
Merge pull request #2439 from tnull/2023-05-fix-0conf-sigs-racing-confirms
Avoid panic when 0conf channel's ann. sigs race on-chain confirmation
2 parents a617462 + adcac97 commit d7e3320

File tree

2 files changed

+47
-5
lines changed

2 files changed

+47
-5
lines changed

lightning/src/ln/channel.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -997,9 +997,9 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
997997
&self.channel_type
998998
}
999999

1000-
/// Guaranteed to be Some after both ChannelReady messages have been exchanged (and, thus,
1001-
/// is_usable() returns true).
1002-
/// Allowed in any state (including after shutdown)
1000+
/// Gets the channel's `short_channel_id`.
1001+
///
1002+
/// Will return `None` if the channel hasn't been confirmed yet.
10031003
pub fn get_short_channel_id(&self) -> Option<u64> {
10041004
self.short_channel_id
10051005
}
@@ -4887,6 +4887,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
48874887
return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned()));
48884888
}
48894889

4890+
let short_channel_id = self.context.get_short_channel_id()
4891+
.ok_or(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel has not been confirmed yet".to_owned()))?;
48904892
let node_id = NodeId::from_pubkey(&node_signer.get_node_id(Recipient::Node)
48914893
.map_err(|_| ChannelError::Ignore("Failed to retrieve own public key".to_owned()))?);
48924894
let counterparty_node_id = NodeId::from_pubkey(&self.context.get_counterparty_node_id());
@@ -4895,7 +4897,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
48954897
let msg = msgs::UnsignedChannelAnnouncement {
48964898
features: channelmanager::provided_channel_features(&user_config),
48974899
chain_hash,
4898-
short_channel_id: self.context.get_short_channel_id().unwrap(),
4900+
short_channel_id,
48994901
node_id_1: if were_node_one { node_id } else { counterparty_node_id },
49004902
node_id_2: if were_node_one { counterparty_node_id } else { node_id },
49014903
bitcoin_key_1: NodeId::from_pubkey(if were_node_one { &self.context.get_holder_pubkeys().funding_pubkey } else { self.context.counterparty_funding_pubkey() }),
@@ -4953,11 +4955,16 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
49534955
},
49544956
Ok(v) => v
49554957
};
4958+
let short_channel_id = match self.context.get_short_channel_id() {
4959+
Some(scid) => scid,
4960+
None => return None,
4961+
};
4962+
49564963
self.context.announcement_sigs_state = AnnouncementSigsState::MessageSent;
49574964

49584965
Some(msgs::AnnouncementSignatures {
49594966
channel_id: self.context.channel_id(),
4960-
short_channel_id: self.context.get_short_channel_id().unwrap(),
4967+
short_channel_id,
49614968
node_signature: our_node_sig,
49624969
bitcoin_signature: our_bitcoin_sig,
49634970
})

lightning/src/ln/priv_short_conf_tests.rs

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

0 commit comments

Comments
 (0)