Skip to content

Commit 95ebe0a

Browse files
committed
Send update_channel messages to re-enable a disabled channel
Currently, we only send an update_channel message after disconnecting a peer and waiting some time. We do not send a followup when the peer has been reconnected for some time. This changes that behavior to make the disconnect and reconnect channel updates symmetric, and also simplifies the state machine somewhat to make it more clear. Finally, it serializes the current announcement state so that we usually know when we need to send a new update_channel.
1 parent 7297e13 commit 95ebe0a

File tree

3 files changed

+71
-42
lines changed

3 files changed

+71
-42
lines changed

lightning/src/ln/channel.rs

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -251,15 +251,17 @@ pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
251251
/// Liveness is called to fluctuate given peer disconnecton/monitor failures/closing.
252252
/// If channel is public, network should have a liveness view announced by us on a
253253
/// best-effort, which means we may filter out some status transitions to avoid spam.
254-
/// See further timer_tick_occurred.
255-
#[derive(PartialEq)]
256-
enum UpdateStatus {
257-
/// Status has been gossiped.
258-
Fresh,
259-
/// Status has been changed.
260-
DisabledMarked,
261-
/// Status has been marked to be gossiped at next flush
254+
/// See implementation at [`ChannelManager::timer_tick_occurred`].
255+
#[derive(Clone, Copy, PartialEq)]
256+
pub(super) enum UpdateStatus {
257+
/// We've announced the channel as enabled and are connected to our peer.
258+
Enabled,
259+
/// Our channel is no longer live, but we haven't announced the channel as disabled yet.
262260
DisabledStaged,
261+
/// Our channel is live again, but we haven't announced the channel as enabled yet.
262+
EnabledStaged,
263+
/// We've announced the channel as disabled.
264+
Disabled,
263265
}
264266

265267
/// An enum indicating whether the local or remote side offered a given HTLC.
@@ -617,7 +619,7 @@ impl<Signer: Sign> Channel<Signer> {
617619

618620
commitment_secrets: CounterpartyCommitmentSecrets::new(),
619621

620-
network_sync: UpdateStatus::Fresh,
622+
network_sync: UpdateStatus::Enabled,
621623

622624
#[cfg(any(test, feature = "fuzztarget"))]
623625
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
@@ -858,7 +860,7 @@ impl<Signer: Sign> Channel<Signer> {
858860

859861
commitment_secrets: CounterpartyCommitmentSecrets::new(),
860862

861-
network_sync: UpdateStatus::Fresh,
863+
network_sync: UpdateStatus::Enabled,
862864

863865
#[cfg(any(test, feature = "fuzztarget"))]
864866
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
@@ -3495,24 +3497,12 @@ impl<Signer: Sign> Channel<Signer> {
34953497
} else { false }
34963498
}
34973499

3498-
pub fn to_disabled_staged(&mut self) {
3499-
self.network_sync = UpdateStatus::DisabledStaged;
3500+
pub fn get_update_status(&self) -> UpdateStatus {
3501+
self.network_sync
35003502
}
35013503

3502-
pub fn to_disabled_marked(&mut self) {
3503-
self.network_sync = UpdateStatus::DisabledMarked;
3504-
}
3505-
3506-
pub fn to_fresh(&mut self) {
3507-
self.network_sync = UpdateStatus::Fresh;
3508-
}
3509-
3510-
pub fn is_disabled_staged(&self) -> bool {
3511-
self.network_sync == UpdateStatus::DisabledStaged
3512-
}
3513-
3514-
pub fn is_disabled_marked(&self) -> bool {
3515-
self.network_sync == UpdateStatus::DisabledMarked
3504+
pub fn set_update_status(&mut self, status: UpdateStatus) {
3505+
self.network_sync = status;
35163506
}
35173507

35183508
fn check_get_funding_locked(&mut self, height: u32) -> Option<msgs::FundingLocked> {
@@ -4375,6 +4365,31 @@ impl Readable for InboundHTLCRemovalReason {
43754365
}
43764366
}
43774367

4368+
impl Writeable for UpdateStatus {
4369+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
4370+
// We only care about writing out the current state as it was announced, ie only either
4371+
// Enabled or Disabled. In the case of DisabledStaged, we most recently announced the
4372+
// channel as enabled, so we write 0. For EnabledStaged, we similarly write a 1.
4373+
match self {
4374+
UpdateStatus::Enabled => 0u8.write(writer)?,
4375+
UpdateStatus::DisabledStaged => 0u8.write(writer)?,
4376+
UpdateStatus::EnabledStaged => 1u8.write(writer)?,
4377+
UpdateStatus::Disabled => 1u8.write(writer)?,
4378+
}
4379+
Ok(())
4380+
}
4381+
}
4382+
4383+
impl Readable for UpdateStatus {
4384+
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
4385+
Ok(match <u8 as Readable>::read(reader)? {
4386+
0 => UpdateStatus::Enabled,
4387+
1 => UpdateStatus::Disabled,
4388+
_ => return Err(DecodeError::InvalidValue),
4389+
})
4390+
}
4391+
}
4392+
43784393
impl<Signer: Sign> Writeable for Channel<Signer> {
43794394
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
43804395
// Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been
@@ -4568,6 +4583,8 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
45684583
self.counterparty_shutdown_scriptpubkey.write(writer)?;
45694584

45704585
self.commitment_secrets.write(writer)?;
4586+
4587+
self.network_sync.write(writer)?;
45714588
Ok(())
45724589
}
45734590
}
@@ -4740,6 +4757,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
47404757
let counterparty_shutdown_scriptpubkey = Readable::read(reader)?;
47414758
let commitment_secrets = Readable::read(reader)?;
47424759

4760+
let network_sync = Readable::read(reader)?;
4761+
47434762
let mut secp_ctx = Secp256k1::new();
47444763
secp_ctx.seeded_randomize(&keys_source.get_secure_random_bytes());
47454764

@@ -4814,7 +4833,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
48144833

48154834
commitment_secrets,
48164835

4817-
network_sync: UpdateStatus::Fresh,
4836+
network_sync,
48184837

48194838
#[cfg(any(test, feature = "fuzztarget"))]
48204839
next_local_commitment_tx_fee_info_cached: Mutex::new(None),

lightning/src/ln/channelmanager.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use chain::transaction::{OutPoint, TransactionData};
4545
// construct one themselves.
4646
use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
4747
pub use ln::channel::CounterpartyForwardingInfo;
48-
use ln::channel::{Channel, ChannelError};
48+
use ln::channel::{Channel, ChannelError, UpdateStatus};
4949
use ln::features::{InitFeatures, NodeFeatures};
5050
use routing::router::{Route, RouteHop};
5151
use ln::msgs;
@@ -2127,17 +2127,28 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
21272127
let mut channel_state_lock = self.channel_state.lock().unwrap();
21282128
let channel_state = &mut *channel_state_lock;
21292129
for (_, chan) in channel_state.by_id.iter_mut() {
2130-
if chan.is_disabled_staged() && !chan.is_live() {
2131-
if let Ok(update) = self.get_channel_update(&chan) {
2132-
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
2133-
msg: update
2134-
});
2135-
}
2136-
chan.to_fresh();
2137-
} else if chan.is_disabled_staged() && chan.is_live() {
2138-
chan.to_fresh();
2139-
} else if chan.is_disabled_marked() {
2140-
chan.to_disabled_staged();
2130+
match chan.get_update_status() {
2131+
UpdateStatus::Enabled if !chan.is_live() => chan.set_update_status(UpdateStatus::DisabledStaged),
2132+
UpdateStatus::Disabled if chan.is_live() => chan.set_update_status(UpdateStatus::EnabledStaged),
2133+
UpdateStatus::DisabledStaged if chan.is_live() => chan.set_update_status(UpdateStatus::Enabled),
2134+
UpdateStatus::EnabledStaged if !chan.is_live() => chan.set_update_status(UpdateStatus::Disabled),
2135+
UpdateStatus::DisabledStaged if !chan.is_live() => {
2136+
if let Ok(update) = self.get_channel_update(&chan) {
2137+
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
2138+
msg: update
2139+
});
2140+
}
2141+
chan.set_update_status(UpdateStatus::Disabled);
2142+
},
2143+
UpdateStatus::EnabledStaged if chan.is_live() => {
2144+
if let Ok(update) = self.get_channel_update(&chan) {
2145+
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
2146+
msg: update
2147+
});
2148+
}
2149+
chan.set_update_status(UpdateStatus::Enabled);
2150+
},
2151+
_ => {},
21412152
}
21422153
}
21432154
}
@@ -3916,7 +3927,6 @@ impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
39163927
// on peer disconnect here, there will need to be corresponding changes in
39173928
// reestablish logic.
39183929
let failed_adds = chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger);
3919-
chan.to_disabled_marked();
39203930
if !failed_adds.is_empty() {
39213931
let chan_update = self.get_channel_update(&chan).map(|u| u.encode_with_len()).unwrap(); // Cannot add/recv HTLCs before we have a short_id so unwrap is safe
39223932
failed_payments.push((chan_update, failed_adds));

lightning/src/ln/functional_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7582,8 +7582,8 @@ fn test_announce_disable_channels() {
75827582
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
75837583
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
75847584

7585-
nodes[0].node.timer_tick_occurred(); // dirty -> stagged
7586-
nodes[0].node.timer_tick_occurred(); // staged -> fresh
7585+
nodes[0].node.timer_tick_occurred(); // enabled -> disabledstagged
7586+
nodes[0].node.timer_tick_occurred(); // disabledstaged -> disabled
75877587
let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
75887588
assert_eq!(msg_events.len(), 3);
75897589
for e in msg_events {

0 commit comments

Comments
 (0)