Skip to content

Commit e4486fe

Browse files
committed
Support receiving multiple funding_locked messages
As a part of adding SCID aliases to channels, we now have to accept otherwise-redundant funding_locked messages which serve only to update the SCID alias. Previously, we'd failt he channel as such an update used to be bogus.
1 parent 84fa127 commit e4486fe

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

lightning/src/ln/channel.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,17 +2188,28 @@ impl<Signer: Sign> Channel<Signer> {
21882188
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
21892189
self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS);
21902190
self.update_time_counter += 1;
2191-
} else if (self.channel_state & (ChannelState::ChannelFunded as u32) != 0 &&
2192-
// Note that funding_signed/funding_created will have decremented both by 1!
2193-
self.cur_holder_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 &&
2194-
self.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1) ||
2195-
// If we reconnected before sending our funding locked they may still resend theirs:
2196-
(self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) ==
2197-
(ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32)) {
2198-
if self.counterparty_cur_commitment_point != Some(msg.next_per_commitment_point) {
2191+
} else if self.channel_state & (ChannelState::ChannelFunded as u32) != 0 ||
2192+
// If we reconnected before sending our funding locked they may still resend theirs:
2193+
(self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) ==
2194+
(ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32))
2195+
{
2196+
// They probably disconnected/reconnected and re-sent the funding_locked, which is
2197+
// required, or they're sending a fresh SCID alias.
2198+
let expected_point =
2199+
if self.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 {
2200+
// If they haven't ever sent an updated point, the point they send should match
2201+
// the current one.
2202+
self.counterparty_cur_commitment_point
2203+
} else {
2204+
// If they have sent updated points, funding_locked is always supposed to match
2205+
// their "first" point, which we re-derive here.
2206+
Some(PublicKey::from_secret_key(&self.secp_ctx, &SecretKey::from_slice(
2207+
&self.commitment_secrets.get_secret(INITIAL_COMMITMENT_NUMBER - 1).expect("We should have all prev secrets available")
2208+
).expect("We already advanced, so previous secret keys should have been validated already")))
2209+
};
2210+
if expected_point != Some(msg.next_per_commitment_point) {
21992211
return Err(ChannelError::Close("Peer sent a reconnect funding_locked with a different point".to_owned()));
22002212
}
2201-
// They probably disconnected/reconnected and re-sent the funding_locked, which is required
22022213
return Ok(None);
22032214
} else {
22042215
return Err(ChannelError::Close("Peer sent a funding_locked at a strange time".to_owned()));
@@ -4238,7 +4249,7 @@ impl<Signer: Sign> Channel<Signer> {
42384249
self.outbound_scid_alias
42394250
}
42404251
/// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0,
4241-
/// indicating we were written by an old LDK which did not set outbound SCID aliases.
4252+
/// indicating we were written by LDK prior to 0.0.106 which did not set outbound SCID aliases.
42424253
pub fn set_outbound_scid_alias(&mut self, outbound_scid_alias: u64) {
42434254
assert_eq!(self.outbound_scid_alias, 0);
42444255
self.outbound_scid_alias = outbound_scid_alias;
@@ -4492,7 +4503,8 @@ impl<Signer: Sign> Channel<Signer> {
44924503
if need_commitment_update {
44934504
if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 {
44944505
if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
4495-
let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
4506+
let next_per_commitment_point =
4507+
self.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.secp_ctx);
44964508
return Some(msgs::FundingLocked {
44974509
channel_id: self.channel_id,
44984510
next_per_commitment_point,

lightning/src/ln/priv_short_conf_tests.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ fn test_routed_scid_alias() {
249249
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
250250

251251
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known()).2;
252-
create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known());
252+
let mut as_funding_locked = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known()).0;
253253

254254
let last_hop = nodes[2].node.list_usable_channels();
255255
let hop_hints = vec![RouteHint(vec![RouteHintHop {
@@ -270,4 +270,17 @@ fn test_routed_scid_alias() {
270270

271271
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], 100_000, payment_hash, payment_secret);
272272
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
273+
274+
// Now test that if a peer sends us a second funding_locked after the channel is operational we
275+
// will use the new alias.
276+
as_funding_locked.short_channel_id_alias = Some(0xdeadbeef);
277+
nodes[2].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &as_funding_locked);
278+
// Note that we always respond to a funding_locked with a channel_update. Not a lot of reason
279+
// to bother updating that code, so just drop the message here.
280+
get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
281+
let updated_channel_info = nodes[2].node.list_usable_channels();
282+
assert_eq!(updated_channel_info.len(), 1);
283+
assert_eq!(updated_channel_info[0].inbound_scid_alias.unwrap(), 0xdeadbeef);
284+
// Note that because we never send a duplicate funding_locked we can't send a payment through
285+
// the 0xdeadbeef SCID alias.
273286
}

0 commit comments

Comments
 (0)