Skip to content

Commit 7d6c3e2

Browse files
committed
Workaround lnd sending funding_locked before channel_reestablish
lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed they will not send a channel_reestablish until the channel locks in. Then, they will send a funding_locked *before* sending the channel_reestablish (which is clearly a violation of the BOLT specs). We copy c-lightning's workaround here and simply store the funding_locked message until we receive a channel_reestablish. See-also lightningnetwork/lnd#4006 Fixes lightningdevkit#963
1 parent edd0da5 commit 7d6c3e2

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

lightning/src/ln/channel.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,15 @@ pub(super) struct Channel<Signer: Sign> {
434434
next_local_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
435435
#[cfg(any(test, feature = "fuzztarget"))]
436436
next_remote_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
437+
438+
/// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed
439+
/// they will not send a channel_reestablish until the channel locks in. Then, they will send a
440+
/// funding_locked *before* sending the channel_reestablish (which is clearly a violation of
441+
/// the BOLT specs). We copy c-lightning's workaround here and simply store the funding_locked
442+
/// message until we receive a channel_reestablish.
443+
///
444+
/// See-also <https://github.com/lightningnetwork/lnd/issues/4006>
445+
pub workaround_lnd_bug_4006: Option<msgs::FundingLocked>,
437446
}
438447

439448
#[cfg(any(test, feature = "fuzztarget"))]
@@ -633,6 +642,8 @@ impl<Signer: Sign> Channel<Signer> {
633642
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
634643
#[cfg(any(test, feature = "fuzztarget"))]
635644
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
645+
646+
workaround_lnd_bug_4006: None,
636647
})
637648
}
638649

@@ -876,6 +887,8 @@ impl<Signer: Sign> Channel<Signer> {
876887
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
877888
#[cfg(any(test, feature = "fuzztarget"))]
878889
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
890+
891+
workaround_lnd_bug_4006: None,
879892
};
880893

881894
Ok(chan)
@@ -1703,7 +1716,8 @@ impl<Signer: Sign> Channel<Signer> {
17031716

17041717
pub fn funding_locked<L: Deref>(&mut self, msg: &msgs::FundingLocked, logger: &L) -> Result<(), ChannelError> where L::Target: Logger {
17051718
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
1706-
return Err(ChannelError::Close("Peer sent funding_locked when we needed a channel_reestablish".to_owned()));
1719+
self.workaround_lnd_bug_4006 = Some(msg.clone());
1720+
return Err(ChannelError::Ignore("Peer sent funding_locked when we needed a channel_reestablish. The peer is likely lnd, see their bug #4006.".to_owned()));
17071721
}
17081722

17091723
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
@@ -4903,6 +4917,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
49034917
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
49044918
#[cfg(any(test, feature = "fuzztarget"))]
49054919
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
4920+
4921+
workaround_lnd_bug_4006: None,
49064922
})
49074923
}
49084924
}

lightning/src/ln/channelmanager.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3375,7 +3375,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33753375
}
33763376

33773377
fn internal_channel_reestablish(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReestablish) -> Result<(), MsgHandleErrInternal> {
3378-
let (htlcs_failed_forward, chan_restoration_res) = {
3378+
let (htlcs_failed_forward, need_lnd_workaround, chan_restoration_res) = {
33793379
let mut channel_state_lock = self.channel_state.lock().unwrap();
33803380
let channel_state = &mut *channel_state_lock;
33813381

@@ -3396,13 +3396,19 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33963396
msg,
33973397
});
33983398
}
3399-
(htlcs_failed_forward, handle_chan_restoration_locked!(self, channel_state_lock, channel_state, chan, revoke_and_ack, commitment_update, order, monitor_update_opt, Vec::new(), None, funding_locked))
3399+
let need_lnd_workaround = chan.get_mut().workaround_lnd_bug_4006.take();
3400+
(htlcs_failed_forward, need_lnd_workaround,
3401+
handle_chan_restoration_locked!(self, channel_state_lock, channel_state, chan, revoke_and_ack, commitment_update, order, monitor_update_opt, Vec::new(), None, funding_locked))
34003402
},
34013403
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
34023404
}
34033405
};
34043406
post_handle_chan_restoration!(self, chan_restoration_res);
34053407
self.fail_holding_cell_htlcs(htlcs_failed_forward, msg.channel_id);
3408+
3409+
if let Some(funding_locked_msg) = need_lnd_workaround {
3410+
self.internal_funding_locked(counterparty_node_id, &funding_locked_msg)?;
3411+
}
34063412
Ok(())
34073413
}
34083414

0 commit comments

Comments
 (0)