X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=71e0ea121a929f2533c3af47714a50264e83b962;hb=996d3d8058f2342b9e23d53f9dd81ae472822120;hp=19e1c8e3643b8c84b9a741ee053c5bea4e617359;hpb=d29ae1826e1d3fe39f65474532f8788413ce8737;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 19e1c8e3..71e0ea12 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -39,14 +39,14 @@ use util::events::ClosureReason; use util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter}; use util::logger::Logger; use util::errors::APIError; -use util::config::{UserConfig,ChannelConfig}; +use util::config::{UserConfig, ChannelConfig, ChannelHandshakeLimits}; use util::scid_utils::scid_from_parts; use io; use prelude::*; use core::{cmp,mem,fmt}; use core::ops::Deref; -#[cfg(any(test, feature = "fuzztarget", debug_assertions))] +#[cfg(any(test, fuzzing, debug_assertions))] use sync::Mutex; use bitcoin::hashes::hex::ToHex; @@ -484,6 +484,8 @@ pub(super) struct Channel { #[cfg(not(any(test, feature = "_test_utils")))] config: ChannelConfig, + inbound_handshake_limits_override: Option, + user_id: u64, channel_id: [u8; 32], @@ -582,6 +584,19 @@ pub(super) struct Channel { #[cfg(not(test))] closing_fee_limits: Option<(u64, u64)>, + /// Flag that ensures that `accept_inbound_channel` must be called before `funding_created` + /// is executed successfully. The reason for this flag is that when the + /// `UserConfig::manually_accept_inbound_channels` config flag is set to true, inbound channels + /// are required to be manually accepted by the node operator before the `msgs::AcceptChannel` + /// message is created and sent out. During the manual accept process, `accept_inbound_channel` + /// is called by `ChannelManager::accept_inbound_channel`. + /// + /// The flag counteracts that a counterparty node could theoretically send a + /// `msgs::FundingCreated` message before the node operator has manually accepted an inbound + /// channel request made by the counterparty node. That would execute `funding_created` before + /// `accept_inbound_channel`, and `funding_created` should therefore not execute successfully. + inbound_awaiting_accept: bool, + /// The hash of the block in which the funding transaction was included. funding_tx_confirmed_in: Option, funding_tx_confirmation_height: u32, @@ -655,9 +670,9 @@ pub(super) struct Channel { // `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will // be, by comparing the cached values to the fee of the tranaction generated by // `build_commitment_transaction`. - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] next_local_commitment_tx_fee_info_cached: Mutex>, - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] next_remote_commitment_tx_fee_info_cached: Mutex>, /// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed @@ -669,7 +684,7 @@ pub(super) struct Channel { /// See-also pub workaround_lnd_bug_4006: Option, - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] // When we receive an HTLC fulfill on an outbound path, we may immediately fulfill the // corresponding HTLC on the inbound path. If, then, the outbound path channel is // disconnected and reconnected (before we've exchange commitment_signed and revoke_and_ack @@ -680,9 +695,22 @@ pub(super) struct Channel { /// This channel's type, as negotiated during channel open channel_type: ChannelTypeFeatures, + + // Our counterparty can offer us SCID aliases which they will map to this channel when routing + // outbound payments. These can be used in invoice route hints to avoid explicitly revealing + // the channel's funding UTXO. + // We only bother storing the most recent SCID alias at any time, though our counterparty has + // to store all of them. + latest_inbound_scid_alias: Option, + + // We always offer our counterparty a static SCID alias, which we recognize as for this channel + // if we see it in HTLC forwarding instructions. We don't bother rotating the alias given we + // don't currently support node id aliases and eventually privacy should be provided with + // blinded paths instead of simple scid+node_id aliases. + outbound_scid_alias: u64, } -#[cfg(any(test, feature = "fuzztarget"))] +#[cfg(any(test, fuzzing))] struct CommitmentTxInfoCached { fee: u64, total_pending_htlcs: usize, @@ -785,7 +813,8 @@ impl Channel { // Constructors: pub fn new_outbound( fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures, - channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig, current_chain_height: u32 + channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig, current_chain_height: u32, + outbound_scid_alias: u64 ) -> Result, APIError> where K::Target: KeysInterface, F::Target: FeeEstimator, @@ -835,6 +864,7 @@ impl Channel { Ok(Channel { user_id, config: config.channel_options.clone(), + inbound_handshake_limits_override: Some(config.peer_channel_config_limits.clone()), channel_id: keys_provider.get_secure_random_bytes(), channel_state: ChannelState::OurInitSent as u32, @@ -880,6 +910,8 @@ impl Channel { closing_fee_limits: None, target_closing_feerate_sats_per_kw: None, + inbound_awaiting_accept: false, + funding_tx_confirmed_in: None, funding_tx_confirmation_height: 0, short_channel_id: None, @@ -922,14 +954,17 @@ impl Channel { announcement_sigs: None, - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] next_remote_commitment_tx_fee_info_cached: Mutex::new(None), workaround_lnd_bug_4006: None, - #[cfg(any(test, feature = "fuzztarget"))] + latest_inbound_scid_alias: None, + outbound_scid_alias, + + #[cfg(any(test, fuzzing))] historical_inbound_htlc_fulfills: HashSet::new(), // We currently only actually support one channel type, so don't retry with new types @@ -966,7 +1001,8 @@ impl Channel { /// Assumes chain_hash has already been checked and corresponds with what we expect! pub fn new_from_req( fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: &InitFeatures, - msg: &msgs::OpenChannel, user_id: u64, config: &UserConfig, current_chain_height: u32, logger: &L + msg: &msgs::OpenChannel, user_id: u64, config: &UserConfig, current_chain_height: u32, logger: &L, + outbound_scid_alias: u64 ) -> Result, ChannelError> where K::Target: KeysInterface, F::Target: FeeEstimator, @@ -1134,6 +1170,7 @@ impl Channel { let chan = Channel { user_id, config: local_config, + inbound_handshake_limits_override: None, channel_id: msg.temporary_channel_id, channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32), @@ -1178,6 +1215,8 @@ impl Channel { closing_fee_limits: None, target_closing_feerate_sats_per_kw: None, + inbound_awaiting_accept: true, + funding_tx_confirmed_in: None, funding_tx_confirmation_height: 0, short_channel_id: None, @@ -1224,14 +1263,17 @@ impl Channel { announcement_sigs: None, - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] next_remote_commitment_tx_fee_info_cached: Mutex::new(None), workaround_lnd_bug_4006: None, - #[cfg(any(test, feature = "fuzztarget"))] + latest_inbound_scid_alias: None, + outbound_scid_alias, + + #[cfg(any(test, fuzzing))] historical_inbound_htlc_fulfills: HashSet::new(), channel_type, @@ -1629,7 +1671,7 @@ impl Channel { } } if pending_idx == core::usize::MAX { - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] // If we failed to find an HTLC to fulfill, make sure it was previously fulfilled and // this is simply a duplicate claim, not previously failed and we lost funds. debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg)); @@ -1655,7 +1697,7 @@ impl Channel { if htlc_id_arg == htlc_id { // Make sure we don't leave latest_monitor_update_id incremented here: self.latest_monitor_update_id -= 1; - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg)); return UpdateFulfillFetch::DuplicateClaim {}; } @@ -1676,11 +1718,11 @@ impl Channel { self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::ClaimHTLC { payment_preimage: payment_preimage_arg, htlc_id: htlc_id_arg, }); - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] self.historical_inbound_htlc_fulfills.insert(htlc_id_arg); return UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None }; } - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] self.historical_inbound_htlc_fulfills.insert(htlc_id_arg); { @@ -1761,7 +1803,7 @@ impl Channel { } } if pending_idx == core::usize::MAX { - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] // If we failed to find an HTLC to fail, make sure it was previously fulfilled and this // is simply a duplicate fail, not previously failed and we failed-back too early. debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg)); @@ -1774,7 +1816,7 @@ impl Channel { match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg)); return Ok(None); } @@ -1811,7 +1853,9 @@ impl Channel { // Message handlers: - pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig, their_features: &InitFeatures) -> Result<(), ChannelError> { + pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, default_limits: &ChannelHandshakeLimits, their_features: &InitFeatures) -> Result<(), ChannelError> { + let peer_limits = if let Some(ref limits) = self.inbound_handshake_limits_override { limits } else { default_limits }; + // Check sanity of message fields: if !self.is_outbound() { return Err(ChannelError::Close("Got an accept_channel message from an inbound peer".to_owned())); @@ -1832,7 +1876,7 @@ impl Channel { if msg.htlc_minimum_msat >= full_channel_value_msat { return Err(ChannelError::Close(format!("Minimum htlc value ({}) is full channel value ({})", msg.htlc_minimum_msat, full_channel_value_msat))); } - let max_delay_acceptable = u16::min(config.peer_channel_config_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT); + let max_delay_acceptable = u16::min(peer_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT); if msg.to_self_delay > max_delay_acceptable { return Err(ChannelError::Close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_delay_acceptable, msg.to_self_delay))); } @@ -1844,17 +1888,17 @@ impl Channel { } // Now check against optional parameters as set by config... - if msg.htlc_minimum_msat > config.peer_channel_config_limits.max_htlc_minimum_msat { - return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg.htlc_minimum_msat, config.peer_channel_config_limits.max_htlc_minimum_msat))); + if msg.htlc_minimum_msat > peer_limits.max_htlc_minimum_msat { + return Err(ChannelError::Close(format!("htlc_minimum_msat ({}) is higher than the user specified limit ({})", msg.htlc_minimum_msat, peer_limits.max_htlc_minimum_msat))); } - if msg.max_htlc_value_in_flight_msat < config.peer_channel_config_limits.min_max_htlc_value_in_flight_msat { - return Err(ChannelError::Close(format!("max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", msg.max_htlc_value_in_flight_msat, config.peer_channel_config_limits.min_max_htlc_value_in_flight_msat))); + if msg.max_htlc_value_in_flight_msat < peer_limits.min_max_htlc_value_in_flight_msat { + return Err(ChannelError::Close(format!("max_htlc_value_in_flight_msat ({}) is less than the user specified limit ({})", msg.max_htlc_value_in_flight_msat, peer_limits.min_max_htlc_value_in_flight_msat))); } - if msg.channel_reserve_satoshis > config.peer_channel_config_limits.max_channel_reserve_satoshis { - return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg.channel_reserve_satoshis, config.peer_channel_config_limits.max_channel_reserve_satoshis))); + if msg.channel_reserve_satoshis > peer_limits.max_channel_reserve_satoshis { + return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is higher than the user specified limit ({})", msg.channel_reserve_satoshis, peer_limits.max_channel_reserve_satoshis))); } - if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs { - return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.peer_channel_config_limits.min_max_accepted_htlcs))); + if msg.max_accepted_htlcs < peer_limits.min_max_accepted_htlcs { + return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, peer_limits.min_max_accepted_htlcs))); } if msg.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS))); @@ -1862,8 +1906,8 @@ impl Channel { if msg.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS { return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS))); } - if msg.minimum_depth > config.peer_channel_config_limits.max_minimum_depth { - return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", config.peer_channel_config_limits.max_minimum_depth, msg.minimum_depth))); + if msg.minimum_depth > peer_limits.max_minimum_depth { + return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", peer_limits.max_minimum_depth, msg.minimum_depth))); } if msg.minimum_depth == 0 { // Note that if this changes we should update the serialization minimum version to @@ -1872,6 +1916,16 @@ impl Channel { return Err(ChannelError::Close("Minimum confirmation depth must be at least 1".to_owned())); } + if let Some(ty) = &msg.channel_type { + if *ty != self.channel_type { + return Err(ChannelError::Close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned())); + } + } else if their_features.supports_channel_type() { + // Assume they've accepted the channel type as they said they understand it. + } else { + self.channel_type = ChannelTypeFeatures::from_counterparty_init(&their_features) + } + let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() { match &msg.shutdown_scriptpubkey { &OptionalField::Present(ref script) => { @@ -1916,6 +1970,7 @@ impl Channel { self.counterparty_shutdown_scriptpubkey = counterparty_shutdown_scriptpubkey; self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32; + self.inbound_handshake_limits_override = None; // We're done enforcing limits on our peer's handshake now. Ok(()) } @@ -1966,6 +2021,9 @@ impl Channel { // channel. return Err(ChannelError::Close("Received funding_created after we got the channel!".to_owned())); } + if self.inbound_awaiting_accept { + return Err(ChannelError::Close("FundingCreated message received before the channel was accepted".to_owned())); + } if self.commitment_secrets.get_min_seen_secret() != (1 << 48) || self.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || self.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { @@ -2114,6 +2172,15 @@ impl Channel { return Err(ChannelError::Ignore("Peer sent funding_locked when we needed a channel_reestablish. The peer is likely lnd, see https://github.com/lightningnetwork/lnd/issues/4006".to_owned())); } + if let Some(scid_alias) = msg.short_channel_id_alias { + if Some(scid_alias) != self.short_channel_id { + // The scid alias provided can be used to route payments *from* our counterparty, + // i.e. can be used for inbound payments and provided in invoices, but is not used + // when routing outbound payments. + self.latest_inbound_scid_alias = Some(scid_alias); + } + } + let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); if non_shutdown_state == ChannelState::FundingSent as u32 { @@ -2121,17 +2188,28 @@ impl Channel { } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) { self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS); self.update_time_counter += 1; - } else if (self.channel_state & (ChannelState::ChannelFunded as u32) != 0 && - // Note that funding_signed/funding_created will have decremented both by 1! - self.cur_holder_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 && - self.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1) || - // If we reconnected before sending our funding locked they may still resend theirs: - (self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) == - (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32)) { - if self.counterparty_cur_commitment_point != Some(msg.next_per_commitment_point) { + } else if self.channel_state & (ChannelState::ChannelFunded as u32) != 0 || + // If we reconnected before sending our funding locked they may still resend theirs: + (self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) == + (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32)) + { + // They probably disconnected/reconnected and re-sent the funding_locked, which is + // required, or they're sending a fresh SCID alias. + let expected_point = + if self.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 { + // If they haven't ever sent an updated point, the point they send should match + // the current one. + self.counterparty_cur_commitment_point + } else { + // If they have sent updated points, funding_locked is always supposed to match + // their "first" point, which we re-derive here. + Some(PublicKey::from_secret_key(&self.secp_ctx, &SecretKey::from_slice( + &self.commitment_secrets.get_secret(INITIAL_COMMITMENT_NUMBER - 1).expect("We should have all prev secrets available") + ).expect("We already advanced, so previous secret keys should have been validated already"))) + }; + if expected_point != Some(msg.next_per_commitment_point) { return Err(ChannelError::Close("Peer sent a reconnect funding_locked with a different point".to_owned())); } - // They probably disconnected/reconnected and re-sent the funding_locked, which is required return Ok(None); } else { return Err(ChannelError::Close("Peer sent a funding_locked at a strange time".to_owned())); @@ -2147,11 +2225,11 @@ impl Channel { /// Returns transaction if there is pending funding transaction that is yet to broadcast pub fn unbroadcasted_funding(&self) -> Option { - if self.channel_state & (ChannelState::FundingCreated as u32) != 0 { - self.funding_transaction.clone() - } else { - None - } + if self.channel_state & (ChannelState::FundingCreated as u32) != 0 { + self.funding_transaction.clone() + } else { + None + } } /// Returns a HTLCStats about inbound pending htlcs @@ -2245,8 +2323,15 @@ impl Channel { /// This is the amount that would go to us if we close the channel, ignoring any on-chain fees. /// See also [`Channel::get_inbound_outbound_available_balance_msat`] pub fn get_balance_msat(&self) -> u64 { - self.value_to_self_msat - - self.get_outbound_pending_htlc_stats(None).pending_htlcs_value_msat + // Include our local balance, plus any inbound HTLCs we know the preimage for, minus any + // HTLCs sent or which will be sent after commitment signed's are exchanged. + let mut balance_msat = self.value_to_self_msat; + for ref htlc in self.pending_inbound_htlcs.iter() { + if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_)) = htlc.state { + balance_msat += htlc.amount_msat; + } + } + balance_msat - self.get_outbound_pending_htlc_stats(None).pending_htlcs_value_msat } pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option) { @@ -2333,7 +2418,7 @@ impl Channel { let num_htlcs = included_htlcs + addl_htlcs; let res = Self::commit_tx_fee_msat(self.feerate_per_kw, num_htlcs, self.opt_anchors()); - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] { let mut fee = res; if fee_spike_buffer_htlc.is_some() { @@ -2411,7 +2496,7 @@ impl Channel { let num_htlcs = included_htlcs + addl_htlcs; let res = Self::commit_tx_fee_msat(self.feerate_per_kw, num_htlcs, self.opt_anchors()); - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] { let mut fee = res; if fee_spike_buffer_htlc.is_some() { @@ -2694,7 +2779,7 @@ impl Channel { return Err((None, ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned()))); } } - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] { if self.is_outbound() { let projected_commit_tx_info = self.next_local_commitment_tx_fee_info_cached.lock().unwrap().take(); @@ -3001,7 +3086,7 @@ impl Channel { return Err(ChannelError::Close("Received an unexpected revoke_and_ack".to_owned())); } - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] { *self.next_local_commitment_tx_fee_info_cached.lock().unwrap() = None; *self.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None; @@ -3413,6 +3498,7 @@ impl Channel { Some(msgs::FundingLocked { channel_id: self.channel_id(), next_per_commitment_point, + short_channel_id_alias: Some(self.outbound_scid_alias), }) } else { None }; @@ -3634,6 +3720,7 @@ impl Channel { funding_locked: Some(msgs::FundingLocked { channel_id: self.channel_id(), next_per_commitment_point, + short_channel_id_alias: Some(self.outbound_scid_alias), }), raa: None, commitment_update: None, mon_update: None, order: RAACommitmentOrder::CommitmentFirst, @@ -3669,6 +3756,7 @@ impl Channel { Some(msgs::FundingLocked { channel_id: self.channel_id(), next_per_commitment_point, + short_channel_id_alias: Some(self.outbound_scid_alias), }) } else { None }; @@ -4151,6 +4239,22 @@ impl Channel { self.short_channel_id } + /// Allowed in any state (including after shutdown) + pub fn latest_inbound_scid_alias(&self) -> Option { + self.latest_inbound_scid_alias + } + + /// Allowed in any state (including after shutdown) + pub fn outbound_scid_alias(&self) -> u64 { + self.outbound_scid_alias + } + /// Only allowed immediately after deserialization if get_outbound_scid_alias returns 0, + /// indicating we were written by LDK prior to 0.0.106 which did not set outbound SCID aliases. + pub fn set_outbound_scid_alias(&mut self, outbound_scid_alias: u64) { + assert_eq!(self.outbound_scid_alias, 0); + self.outbound_scid_alias = outbound_scid_alias; + } + /// Returns the funding_txo we either got from our peer, or were given by /// get_outbound_funding_created. pub fn get_funding_txo(&self) -> Option { @@ -4399,10 +4503,12 @@ impl Channel { if need_commitment_update { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { - let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); + let next_per_commitment_point = + self.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.secp_ctx); return Some(msgs::FundingLocked { channel_id: self.channel_id, next_per_commitment_point, + short_channel_id_alias: Some(self.outbound_scid_alias), }); } } else { @@ -4432,9 +4538,9 @@ impl Channel { // If we generated the funding transaction and it doesn't match what it // should, the client is really broken and we should just panic and // tell them off. That said, because hash collisions happen with high - // probability in fuzztarget mode, if we're fuzzing we just close the + // probability in fuzzing mode, if we're fuzzing we just close the // channel and move on. - #[cfg(not(feature = "fuzztarget"))] + #[cfg(not(fuzzing))] panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); } self.update_time_counter += 1; @@ -4446,7 +4552,7 @@ impl Channel { if input.witness.is_empty() { // We generated a malleable funding transaction, implying we've // just exposed ourselves to funds loss to our counterparty. - #[cfg(not(feature = "fuzztarget"))] + #[cfg(not(fuzzing))] panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); } } @@ -4631,7 +4737,15 @@ impl Channel { } } - pub fn get_accept_channel(&self) -> msgs::AcceptChannel { + pub fn inbound_is_awaiting_accept(&self) -> bool { + self.inbound_awaiting_accept + } + + /// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannel`] message which + /// should be sent back to the counterparty node. + /// + /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel + pub fn accept_inbound_channel(&mut self) -> msgs::AcceptChannel { if self.is_outbound() { panic!("Tried to send accept_channel for an outbound channel?"); } @@ -4641,7 +4755,21 @@ impl Channel { if self.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { panic!("Tried to send an accept_channel for a channel that has already advanced"); } + if !self.inbound_awaiting_accept { + panic!("The inbound channel has already been accepted"); + } + + self.inbound_awaiting_accept = false; + + self.generate_accept_channel_message() + } + /// This function is used to explicitly generate a [`msgs::AcceptChannel`] message for an + /// inbound channel. If the intention is to accept an inbound channel, use + /// [`Channel::accept_inbound_channel`] instead. + /// + /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel + fn generate_accept_channel_message(&self) -> msgs::AcceptChannel { let first_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); let keys = self.get_holder_pubkeys(); @@ -4664,9 +4792,19 @@ impl Channel { Some(script) => script.clone().into_inner(), None => Builder::new().into_script(), }), + channel_type: Some(self.channel_type.clone()), } } + /// Enables the possibility for tests to extract a [`msgs::AcceptChannel`] message for an + /// inbound channel without accepting it. + /// + /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel + #[cfg(test)] + pub fn get_accept_channel_message(&self) -> msgs::AcceptChannel { + self.generate_accept_channel_message() + } + /// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created) fn get_outbound_funding_created_signature(&mut self, logger: &L) -> Result where L::Target: Logger { let counterparty_keys = self.build_remote_transaction_keys()?; @@ -4872,9 +5010,9 @@ impl Channel { // Prior to static_remotekey, my_current_per_commitment_point was critical to claiming // current to_remote balances. However, it no longer has any use, and thus is now simply // set to a dummy (but valid, as required by the spec) public key. - // fuzztarget mode marks a subset of pubkeys as invalid so that we can hit "invalid pubkey" + // fuzzing mode marks a subset of pubkeys as invalid so that we can hit "invalid pubkey" // branches, but we unwrap it below, so we arbitrarily select a dummy pubkey which is both - // valid, and valid in fuzztarget mode's arbitrary validity criteria: + // valid, and valid in fuzzing mode's arbitrary validity criteria: let mut pk = [2; 33]; pk[1] = 0xff; let dummy_pubkey = PublicKey::from_slice(&pk).unwrap(); let data_loss_protect = if self.cur_counterparty_commitment_transaction_number + 1 < INITIAL_COMMITMENT_NUMBER { @@ -5160,7 +5298,7 @@ impl Channel { let counterparty_commitment_txid = commitment_stats.tx.trust().txid(); let (signature, htlc_signatures); - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] { if !self.is_outbound() { let projected_commit_tx_info = self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().take(); @@ -5646,9 +5784,9 @@ impl Writeable for Channel { self.channel_update_status.write(writer)?; - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] (self.historical_inbound_htlc_fulfills.len() as u64).write(writer)?; - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] for htlc in self.historical_inbound_htlc_fulfills.iter() { htlc.write(writer)?; } @@ -5689,6 +5827,8 @@ impl Writeable for Channel { (13, self.channel_creation_height, required), (15, preimages, vec_type), (17, self.announcement_sigs_state, required), + (19, self.latest_inbound_scid_alias, option), + (21, self.outbound_scid_alias, required), }); Ok(()) @@ -5910,9 +6050,9 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel let channel_update_status = Readable::read(reader)?; - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] let mut historical_inbound_htlc_fulfills = HashSet::new(); - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] { let htlc_fulfills_len: u64 = Readable::read(reader)?; for _ in 0..htlc_fulfills_len { @@ -5944,6 +6084,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel // If we read an old Channel, for simplicity we just treat it as "we never sent an // AnnouncementSignatures" which implies we'll re-send it on reconnect, but that's fine. let mut announcement_sigs_state = Some(AnnouncementSigsState::NotSent); + let mut latest_inbound_scid_alias = None; + let mut outbound_scid_alias = None; read_tlv_fields!(reader, { (0, announcement_sigs, option), @@ -5959,6 +6101,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel (13, channel_creation_height, option), (15, preimages_opt, vec_type), (17, announcement_sigs_state, option), + (19, latest_inbound_scid_alias, option), + (21, outbound_scid_alias, option), }); if let Some(preimages) = preimages_opt { @@ -5999,6 +6143,11 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel user_id, config: config.unwrap(), + + // Note that we don't care about serializing handshake limits as we only ever serialize + // channel data after the handshake has completed. + inbound_handshake_limits_override: None, + channel_id, channel_state, announcement_sigs_state: announcement_sigs_state.unwrap(), @@ -6045,6 +6194,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel closing_fee_limits: None, target_closing_feerate_sats_per_kw, + inbound_awaiting_accept: false, + funding_tx_confirmed_in, funding_tx_confirmation_height, short_channel_id, @@ -6079,14 +6230,18 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel announcement_sigs, - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] next_local_commitment_tx_fee_info_cached: Mutex::new(None), - #[cfg(any(test, feature = "fuzztarget"))] + #[cfg(any(test, fuzzing))] next_remote_commitment_tx_fee_info_cached: Mutex::new(None), workaround_lnd_bug_4006: None, - #[cfg(any(test, feature = "fuzztarget"))] + latest_inbound_scid_alias, + // Later in the ChannelManager deserialization phase we scan for channels and assign scid aliases if its missing + outbound_scid_alias: outbound_scid_alias.unwrap_or(0), + + #[cfg(any(test, fuzzing))] historical_inbound_htlc_fulfills, channel_type: channel_type.unwrap(), @@ -6116,7 +6271,7 @@ mod tests { use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, htlc_success_tx_weight, htlc_timeout_tx_weight}; use chain::BestBlock; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; - use chain::keysinterface::{InMemorySigner, KeyMaterial, KeysInterface, BaseSign}; + use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface, BaseSign}; use chain::transaction::OutPoint; use util::config::UserConfig; use util::enforcing_trait_impls::EnforcingSigner; @@ -6164,7 +6319,7 @@ mod tests { impl KeysInterface for Keys { type Signer = InMemorySigner; - fn get_node_secret(&self) -> SecretKey { panic!(); } + fn get_node_secret(&self, _recipient: Recipient) -> Result { panic!(); } fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); } fn get_destination_script(&self) -> Script { let secp_ctx = Secp256k1::signing_only(); @@ -6184,7 +6339,7 @@ mod tests { } fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] } fn read_chan_signer(&self, _data: &[u8]) -> Result { panic!(); } - fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result { panic!(); } + fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { panic!(); } } fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { @@ -6208,7 +6363,7 @@ mod tests { let secp_ctx = Secp256k1::new(); let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - match Channel::::new_outbound(&&fee_estimator, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0) { + match Channel::::new_outbound(&&fee_estimator, &&keys_provider, node_id, &features, 10000000, 100000, 42, &config, 0, 42) { Err(APIError::IncompatibleShutdownScript { script }) => { assert_eq!(script.into_inner(), non_v0_segwit_shutdown_script.into_inner()); }, @@ -6230,7 +6385,7 @@ mod tests { let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let node_a_chan = Channel::::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap(); + let node_a_chan = Channel::::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap(); // Now change the fee so we can check that the fee in the open_channel message is the // same as the old fee. @@ -6256,18 +6411,18 @@ mod tests { // Create Node A's channel pointing to Node B's pubkey let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap(); + let mut node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap(); // Create Node B's channel by receiving Node A's open_channel message // Make sure A's dust limit is as we expect. let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let node_b_chan = Channel::::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger).unwrap(); + let mut node_b_chan = Channel::::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap(); // Node B --> Node A: accept channel, explicitly setting B's dust limit. - let mut accept_channel_msg = node_b_chan.get_accept_channel(); + let mut accept_channel_msg = node_b_chan.accept_inbound_channel(); accept_channel_msg.dust_limit_satoshis = 546; - node_a_chan.accept_channel(&accept_channel_msg, &config, &InitFeatures::known()).unwrap(); + node_a_chan.accept_channel(&accept_channel_msg, &config.peer_channel_config_limits, &InitFeatures::known()).unwrap(); node_a_chan.holder_dust_limit_satoshis = 1560; // Put some inbound and outbound HTLCs in A's channel. @@ -6326,7 +6481,7 @@ mod tests { let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut chan = Channel::::new_outbound(&&fee_est, &&keys_provider, node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap(); + let mut chan = Channel::::new_outbound(&&fee_est, &&keys_provider, node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap(); let commitment_tx_fee_0_htlcs = Channel::::commit_tx_fee_msat(chan.feerate_per_kw, 0, chan.opt_anchors()); let commitment_tx_fee_1_htlc = Channel::::commit_tx_fee_msat(chan.feerate_per_kw, 1, chan.opt_anchors()); @@ -6375,16 +6530,16 @@ mod tests { // Create Node A's channel pointing to Node B's pubkey let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap(); + let mut node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap(); // Create Node B's channel by receiving Node A's open_channel message let open_channel_msg = node_a_chan.get_open_channel(chain_hash); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); - let mut node_b_chan = Channel::::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger).unwrap(); + let mut node_b_chan = Channel::::new_from_req(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), &open_channel_msg, 7, &config, 0, &&logger, 42).unwrap(); // Node B --> Node A: accept channel - let accept_channel_msg = node_b_chan.get_accept_channel(); - node_a_chan.accept_channel(&accept_channel_msg, &config, &InitFeatures::known()).unwrap(); + let accept_channel_msg = node_b_chan.accept_inbound_channel(); + node_a_chan.accept_channel(&accept_channel_msg, &config.peer_channel_config_limits, &InitFeatures::known()).unwrap(); // Node A --> Node B: funding created let output_script = node_a_chan.get_funding_redeemscript(); @@ -6437,7 +6592,7 @@ mod tests { // Create a channel. let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let config = UserConfig::default(); - let mut node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0).unwrap(); + let mut node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, node_b_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config, 0, 42).unwrap(); assert!(node_a_chan.counterparty_forwarding_info.is_none()); assert_eq!(node_a_chan.holder_htlc_minimum_msat, 1); // the default assert!(node_a_chan.counterparty_forwarding_info().is_none()); @@ -6502,7 +6657,7 @@ mod tests { let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let mut config = UserConfig::default(); config.channel_options.announced_channel = false; - let mut chan = Channel::::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, &InitFeatures::known(), 10_000_000, 100000, 42, &config, 0).unwrap(); // Nothing uses their network key in this test + let mut chan = Channel::::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, &InitFeatures::known(), 10_000_000, 100000, 42, &config, 0, 42).unwrap(); // Nothing uses their network key in this test chan.holder_dust_limit_satoshis = 546; chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel