X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=b940b45f7013e976e0c36d9abe1fde4de1c56ec1;hb=c7e198e6fca8fc31e004b51368978b109c1caff6;hp=413dc8313a6c5d18c73b92f74c5ee9d685c44dda;hpb=c60543c0ed9f1c469fb8b1836ef7796c696642f3;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 413dc831..b940b45f 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -39,9 +39,8 @@ use util::errors::APIError; use util::config::{UserConfig,ChannelConfig}; use util::scid_utils::scid_from_parts; -use std; -use std::{cmp,mem,fmt}; -use std::ops::Deref; +use core::{cmp,mem,fmt}; +use core::ops::Deref; #[cfg(any(test, feature = "fuzztarget"))] use std::sync::Mutex; use bitcoin::hashes::hex::ToHex; @@ -248,18 +247,21 @@ const MULTI_STATE_FLAGS: u32 = BOTH_SIDES_SHUTDOWN_MASK | ChannelState::PeerDisc pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; -/// Liveness is called to fluctuate given peer disconnecton/monitor failures/closing. -/// If channel is public, network should have a liveness view announced by us on a -/// best-effort, which means we may filter out some status transitions to avoid spam. -/// See further timer_tick_occurred. -#[derive(PartialEq)] -enum UpdateStatus { - /// Status has been gossiped. - Fresh, - /// Status has been changed. - DisabledMarked, - /// Status has been marked to be gossiped at next flush +/// The "channel disabled" bit in channel_update must be set based on whether we are connected to +/// our counterparty or not. However, we don't want to announce updates right away to avoid +/// spamming the network with updates if the connection is flapping. Instead, we "stage" updates to +/// our channel_update message and track the current state here. +/// See implementation at [`super::channelmanager::ChannelManager::timer_tick_occurred`]. +#[derive(Clone, Copy, PartialEq)] +pub(super) enum ChannelUpdateStatus { + /// We've announced the channel as enabled and are connected to our peer. + Enabled, + /// Our channel is no longer live, but we haven't announced the channel as disabled yet. DisabledStaged, + /// Our channel is live again, but we haven't announced the channel as enabled yet. + EnabledStaged, + /// We've announced the channel as disabled. + Disabled, } /// An enum indicating whether the local or remote side offered a given HTLC. @@ -416,7 +418,7 @@ pub(super) struct Channel { commitment_secrets: CounterpartyCommitmentSecrets, - network_sync: UpdateStatus, + channel_update_status: ChannelUpdateStatus, // We save these values so we can make sure `next_local_commit_tx_fee_msat` and // `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will @@ -617,7 +619,7 @@ impl Channel { commitment_secrets: CounterpartyCommitmentSecrets::new(), - network_sync: UpdateStatus::Fresh, + channel_update_status: ChannelUpdateStatus::Enabled, #[cfg(any(test, feature = "fuzztarget"))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), @@ -858,7 +860,7 @@ impl Channel { commitment_secrets: CounterpartyCommitmentSecrets::new(), - network_sync: UpdateStatus::Fresh, + channel_update_status: ChannelUpdateStatus::Enabled, #[cfg(any(test, feature = "fuzztarget"))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), @@ -1217,7 +1219,7 @@ impl Channel { // on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop // these, but for now we just have to treat them as normal. - let mut pending_idx = std::usize::MAX; + let mut pending_idx = core::usize::MAX; for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() { if htlc.htlc_id == htlc_id_arg { assert_eq!(htlc.payment_hash, payment_hash_calc); @@ -1240,7 +1242,7 @@ impl Channel { break; } } - if pending_idx == std::usize::MAX { + if pending_idx == core::usize::MAX { return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned())); } @@ -1339,7 +1341,7 @@ impl Channel { // on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop // these, but for now we just have to treat them as normal. - let mut pending_idx = std::usize::MAX; + let mut pending_idx = core::usize::MAX; for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() { if htlc.htlc_id == htlc_id_arg { match htlc.state { @@ -1356,7 +1358,7 @@ impl Channel { pending_idx = idx; } } - if pending_idx == std::usize::MAX { + if pending_idx == core::usize::MAX { return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned())); } @@ -3495,24 +3497,12 @@ impl Channel { } else { false } } - pub fn to_disabled_staged(&mut self) { - self.network_sync = UpdateStatus::DisabledStaged; + pub fn channel_update_status(&self) -> ChannelUpdateStatus { + self.channel_update_status } - pub fn to_disabled_marked(&mut self) { - self.network_sync = UpdateStatus::DisabledMarked; - } - - pub fn to_fresh(&mut self) { - self.network_sync = UpdateStatus::Fresh; - } - - pub fn is_disabled_staged(&self) -> bool { - self.network_sync == UpdateStatus::DisabledStaged - } - - pub fn is_disabled_marked(&self) -> bool { - self.network_sync == UpdateStatus::DisabledMarked + pub fn set_channel_update_status(&mut self, status: ChannelUpdateStatus) { + self.channel_update_status = status; } fn check_get_funding_locked(&mut self, height: u32) -> Option { @@ -4375,6 +4365,31 @@ impl Readable for InboundHTLCRemovalReason { } } +impl Writeable for ChannelUpdateStatus { + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + // We only care about writing out the current state as it was announced, ie only either + // Enabled or Disabled. In the case of DisabledStaged, we most recently announced the + // channel as enabled, so we write 0. For EnabledStaged, we similarly write a 1. + match self { + ChannelUpdateStatus::Enabled => 0u8.write(writer)?, + ChannelUpdateStatus::DisabledStaged => 0u8.write(writer)?, + ChannelUpdateStatus::EnabledStaged => 1u8.write(writer)?, + ChannelUpdateStatus::Disabled => 1u8.write(writer)?, + } + Ok(()) + } +} + +impl Readable for ChannelUpdateStatus { + fn read(reader: &mut R) -> Result { + Ok(match ::read(reader)? { + 0 => ChannelUpdateStatus::Enabled, + 1 => ChannelUpdateStatus::Disabled, + _ => return Err(DecodeError::InvalidValue), + }) + } +} + impl Writeable for Channel { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been @@ -4394,8 +4409,8 @@ impl Writeable for Channel { let mut key_data = VecWriter(Vec::new()); self.holder_signer.write(&mut key_data)?; - assert!(key_data.0.len() < std::usize::MAX); - assert!(key_data.0.len() < std::u32::MAX as usize); + assert!(key_data.0.len() < core::usize::MAX); + assert!(key_data.0.len() < core::u32::MAX as usize); (key_data.0.len() as u32).write(writer)?; writer.write_all(&key_data.0[..])?; @@ -4568,6 +4583,8 @@ impl Writeable for Channel { self.counterparty_shutdown_scriptpubkey.write(writer)?; self.commitment_secrets.write(writer)?; + + self.channel_update_status.write(writer)?; Ok(()) } } @@ -4740,6 +4757,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel let counterparty_shutdown_scriptpubkey = Readable::read(reader)?; let commitment_secrets = Readable::read(reader)?; + let channel_update_status = Readable::read(reader)?; + let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&keys_source.get_secure_random_bytes()); @@ -4814,7 +4833,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel commitment_secrets, - network_sync: UpdateStatus::Fresh, + channel_update_status, #[cfg(any(test, feature = "fuzztarget"))] next_local_commitment_tx_fee_info_cached: Mutex::new(None),