X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;ds=sidebyside;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=cf70749ad96b7bbc98fdca8917db77c0d03d601e;hb=f53d13bcb8220b3ce39e51a4d20beb23b3930d1f;hp=fc48a6b9a1ceb777eea964f19b89bd729072b60f;hpb=a1fedeaec2c551ac4bb3cb2362daef3d81f9e765;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index fc48a6b9..cf70749a 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; @@ -62,6 +62,17 @@ pub struct ChannelValueStat { pub counterparty_dust_limit_msat: u64, } +pub struct AvailableBalances { + /// The amount that would go to us if we close the channel, ignoring any on-chain fees. + pub balance_msat: u64, + /// Total amount available for our counterparty to send to us. + pub inbound_capacity_msat: u64, + /// Total amount available for us to send to our counterparty. + pub outbound_capacity_msat: u64, + /// The maximum value we can assign to the next outbound HTLC + pub next_outbound_htlc_limit_msat: u64, +} + #[derive(Debug, Clone, Copy, PartialEq)] enum FeeUpdateState { // Inbound states mirroring InboundHTLCState @@ -484,6 +495,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 +595,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 +681,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 +695,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 +706,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, @@ -706,9 +745,13 @@ pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; pub const ANCHOR_OUTPUT_VALUE_SATOSHI: u64 = 330; -/// Maximum `funding_satoshis` value, according to the BOLT #2 specification -/// it's 2^24. -pub const MAX_FUNDING_SATOSHIS: u64 = 1 << 24; +/// Maximum `funding_satoshis` value according to the BOLT #2 specification, if +/// `option_support_large_channel` (aka wumbo channels) is not supported. +/// It's 2^24 - 1. +pub const MAX_FUNDING_SATOSHIS_NO_WUMBO: u64 = (1 << 24) - 1; + +/// Total bitcoin supply in satoshis. +pub const TOTAL_BITCOIN_SUPPLY_SATOSHIS: u64 = 21_000_000 * 1_0000_0000; /// The maximum network dust limit for standard script formats. This currently represents the /// minimum output value for a P2SH output before Bitcoin Core 22 considers the entire @@ -782,10 +825,36 @@ impl Channel { self.channel_transaction_parameters.opt_anchors.is_some() } + fn get_initial_channel_type(config: &UserConfig) -> ChannelTypeFeatures { + // The default channel type (ie the first one we try) depends on whether the channel is + // public - if it is, we just go with `only_static_remotekey` as it's the only option + // available. If it's private, we first try `scid_privacy` as it provides better privacy + // with no other changes, and fall back to `only_static_remotekey` + let mut ret = ChannelTypeFeatures::only_static_remote_key(); + if !config.channel_options.announced_channel && config.own_channel_config.negotiate_scid_privacy { + ret.set_scid_privacy_required(); + } + ret + } + + /// If we receive an error message, it may only be a rejection of the channel type we tried, + /// not of our ability to open any channel at all. Thus, on error, we should first call this + /// and see if we get a new `OpenChannel` message, otherwise the channel is failed. + pub(crate) fn maybe_handle_error_without_close(&mut self, chain_hash: BlockHash) -> Result { + if !self.is_outbound() || self.channel_state != ChannelState::OurInitSent as u32 { return Err(()); } + if self.channel_type == ChannelTypeFeatures::only_static_remote_key() { + // We've exhausted our options + return Err(()); + } + self.channel_type = ChannelTypeFeatures::only_static_remote_key(); // We only currently support two types + Ok(self.get_open_channel(chain_hash)) + } + // 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, @@ -796,8 +865,11 @@ impl Channel { let holder_signer = keys_provider.get_channel_signer(false, channel_value_satoshis); let pubkeys = holder_signer.pubkeys().clone(); - if channel_value_satoshis >= MAX_FUNDING_SATOSHIS { - return Err(APIError::APIMisuseError{err: format!("funding_value must be smaller than {}, it was {}", MAX_FUNDING_SATOSHIS, channel_value_satoshis)}); + if !their_features.supports_wumbo() && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO { + return Err(APIError::APIMisuseError{err: format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, channel_value_satoshis)}); + } + if channel_value_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS { + return Err(APIError::APIMisuseError{err: format!("funding_value must be smaller than the total bitcoin supply, it was {}", channel_value_satoshis)}); } let channel_value_msat = channel_value_satoshis * 1000; if push_msat > channel_value_msat { @@ -835,6 +907,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 +953,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,20 +997,20 @@ 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 - // on error messages. When we support more we'll need fallback support (assuming we - // want to support old types). - channel_type: ChannelTypeFeatures::only_static_remote_key(), + channel_type: Self::get_initial_channel_type(&config), }) } @@ -966,13 +1041,15 @@ 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, L::Target: Logger, { let opt_anchors = false; // TODO - should be based on features + let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false }; // First check the channel type is known, failing before we do anything else if we don't // support this channel type. @@ -980,8 +1057,18 @@ impl Channel { if channel_type.supports_any_optional_bits() { return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned())); } - if *channel_type != ChannelTypeFeatures::only_static_remote_key() { - return Err(ChannelError::Close("Channel Type was not understood".to_owned())); + // We currently only allow two channel types, so write it all out here - we allow + // `only_static_remote_key` in all contexts, and further allow + // `static_remote_key|scid_privacy` if the channel is not publicly announced. + let mut allowed_type = ChannelTypeFeatures::only_static_remote_key(); + if *channel_type != allowed_type { + allowed_type.set_scid_privacy_required(); + if *channel_type != allowed_type { + return Err(ChannelError::Close("Channel Type was not understood".to_owned())); + } + if announced_channel { + return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned())); + } } channel_type.clone() } else { @@ -1007,8 +1094,11 @@ impl Channel { } // Check sanity of message fields: - if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS { - return Err(ChannelError::Close(format!("Funding must be smaller than {}. It was {}", MAX_FUNDING_SATOSHIS, msg.funding_satoshis))); + if msg.funding_satoshis > config.peer_channel_config_limits.max_funding_satoshis { + return Err(ChannelError::Close(format!("Per our config, funding must be at most {}. It was {}", config.peer_channel_config_limits.max_funding_satoshis, msg.funding_satoshis))); + } + if msg.funding_satoshis >= TOTAL_BITCOIN_SUPPLY_SATOSHIS { + return Err(ChannelError::Close(format!("Funding must be smaller than the total bitcoin supply. It was {}", msg.funding_satoshis))); } if msg.channel_reserve_satoshis > msg.funding_satoshis { return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must be not greater than funding_satoshis: {}", msg.channel_reserve_satoshis, msg.funding_satoshis))); @@ -1062,14 +1152,13 @@ impl Channel { // Convert things into internal flags and prep our state: - let announce = if (msg.channel_flags & 1) == 1 { true } else { false }; if config.peer_channel_config_limits.force_announced_channel_preference { - if local_config.announced_channel != announce { + if local_config.announced_channel != announced_channel { return Err(ChannelError::Close("Peer tried to open channel but their announcement preference is different from ours".to_owned())); } } // we either accept their preference or the preferences match - local_config.announced_channel = announce; + local_config.announced_channel = announced_channel; let holder_selected_channel_reserve_satoshis = Channel::::get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis); if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { @@ -1134,6 +1223,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 +1268,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 +1316,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 +1724,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 +1750,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 +1771,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 +1856,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 +1869,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 +1906,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 +1929,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 +1941,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 +1959,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 +1969,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 +2023,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 +2074,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 +2225,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 +2241,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 +2278,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 @@ -2220,33 +2351,39 @@ impl Channel { stats } - /// Get the available (ie not including pending HTLCs) inbound and outbound balance in msat. + /// Get the available balances, see [`AvailableBalances`]'s fields for more info. /// Doesn't bother handling the /// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC /// corner case properly. - /// The channel reserve is subtracted from each balance. - /// See also [`Channel::get_balance_msat`] - pub fn get_inbound_outbound_available_balance_msat(&self) -> (u64, u64) { + pub fn get_available_balances(&self) -> AvailableBalances { // Note that we have to handle overflow due to the above case. - ( - cmp::max(self.channel_value_satoshis as i64 * 1000 - - self.value_to_self_msat as i64 - - self.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64 - - self.holder_selected_channel_reserve_satoshis as i64 * 1000, - 0) as u64, - cmp::max(self.value_to_self_msat as i64 - - self.get_outbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64 - - self.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) as i64 * 1000, - 0) as u64 - ) - } + let outbound_stats = self.get_outbound_pending_htlc_stats(None); + + 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 -= outbound_stats.pending_htlcs_value_msat; - /// Get our total balance in msat. - /// 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 + let outbound_capacity_msat = cmp::max(self.value_to_self_msat as i64 + - outbound_stats.pending_htlcs_value_msat as i64 + - self.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) as i64 * 1000, + 0) as u64; + AvailableBalances { + inbound_capacity_msat: cmp::max(self.channel_value_satoshis as i64 * 1000 + - self.value_to_self_msat as i64 + - self.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64 + - self.holder_selected_channel_reserve_satoshis as i64 * 1000, + 0) as u64, + outbound_capacity_msat, + next_outbound_htlc_limit_msat: cmp::max(cmp::min(outbound_capacity_msat as i64, + self.counterparty_max_htlc_value_in_flight_msat as i64 + - outbound_stats.pending_htlcs_value_msat as i64), + 0) as u64, + balance_msat, + } } pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option) { @@ -2333,7 +2470,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 +2548,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 +2831,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 +3138,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 +3550,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 +3772,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 +3808,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 }; @@ -3990,7 +4130,7 @@ impl Channel { if !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() { return Err(ChannelError::Close("Remote end sent us a closing_signed while there were still pending HTLCs".to_owned())); } - if msg.fee_satoshis > 21_000_000 * 1_0000_0000 { //this is required to stop potential overflow in build_closing_transaction + if msg.fee_satoshis > TOTAL_BITCOIN_SUPPLY_SATOSHIS { // this is required to stop potential overflow in build_closing_transaction return Err(ChannelError::Close("Remote tried to send us a closing tx with > 21 million BTC fee".to_owned())); } @@ -4144,6 +4284,11 @@ impl Channel { self.user_id } + /// Gets the channel's type + pub fn get_channel_type(&self) -> &ChannelTypeFeatures { + &self.channel_type + } + /// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus, /// is_usable() returns true). /// Allowed in any state (including after shutdown) @@ -4151,6 +4296,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 { @@ -4180,11 +4341,15 @@ impl Channel { } /// Allowed in any state (including after shutdown) - #[cfg(test)] pub fn get_holder_htlc_minimum_msat(&self) -> u64 { self.holder_htlc_minimum_msat } + /// Allowed in any state (including after shutdown), but will return none before TheirInitSent + pub fn get_holder_htlc_maximum_msat(&self) -> Option { + self.get_htlc_maximum_msat(self.holder_max_htlc_value_in_flight_msat) + } + /// Allowed in any state (including after shutdown) pub fn get_announced_htlc_max_msat(&self) -> u64 { return cmp::min( @@ -4202,6 +4367,21 @@ impl Channel { self.counterparty_htlc_minimum_msat } + /// Allowed in any state (including after shutdown), but will return none before TheirInitSent + pub fn get_counterparty_htlc_maximum_msat(&self) -> Option { + self.get_htlc_maximum_msat(self.counterparty_max_htlc_value_in_flight_msat) + } + + fn get_htlc_maximum_msat(&self, party_max_htlc_value_in_flight_msat: u64) -> Option { + self.counterparty_selected_channel_reserve_satoshis.map(|counterparty_reserve| { + let holder_reserve = self.holder_selected_channel_reserve_satoshis; + cmp::min( + (self.channel_value_satoshis - counterparty_reserve - holder_reserve) * 1000, + party_max_htlc_value_in_flight_msat + ) + }) + } + pub fn get_value_satoshis(&self) -> u64 { self.channel_value_satoshis } @@ -4399,10 +4579,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 +4614,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 +4628,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 +4813,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, user_id: u64) -> msgs::AcceptChannel { if self.is_outbound() { panic!("Tried to send accept_channel for an outbound channel?"); } @@ -4641,7 +4831,22 @@ 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.user_id = user_id; + 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 +4869,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()?; @@ -4731,9 +4946,6 @@ impl Channel { /// Will only fail if we're not in a state where channel_announcement may be sent (including /// closing). /// - /// Note that the "channel must be funded" requirement is stricter than BOLT 7 requires - see - /// https://github.com/lightningnetwork/lightning-rfc/issues/468 - /// /// This will only return ChannelError::Ignore upon failure. fn get_channel_announcement(&self, node_id: PublicKey, chain_hash: BlockHash) -> Result { if !self.config.announced_channel { @@ -4875,9 +5087,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 { @@ -5163,7 +5375,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(); @@ -5649,9 +5861,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)?; } @@ -5692,6 +5904,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(()) @@ -5913,9 +6127,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 { @@ -5947,6 +6161,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), @@ -5962,6 +6178,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 { @@ -6002,6 +6220,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(), @@ -6048,6 +6271,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, @@ -6082,14 +6307,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(), @@ -6099,44 +6328,39 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel #[cfg(test)] mod tests { - use bitcoin::util::bip143; - use bitcoin::consensus::encode::serialize; use bitcoin::blockdata::script::{Script, Builder}; - use bitcoin::blockdata::transaction::{Transaction, TxOut, SigHashType}; + use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::opcodes; use bitcoin::network::constants::Network; - use bitcoin::hashes::hex::FromHex; use hex; - use ln::{PaymentPreimage, PaymentHash}; + use ln::PaymentHash; use ln::channelmanager::{HTLCSource, PaymentId}; - use ln::channel::{Channel,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys}; - use ln::channel::MAX_FUNDING_SATOSHIS; + use ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator}; + use ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS}; use ln::features::InitFeatures; use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate}; use ln::script::ShutdownScript; use ln::chan_utils; - use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, htlc_success_tx_weight, htlc_timeout_tx_weight}; + use ln::chan_utils::{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}; use chain::transaction::OutPoint; use util::config::UserConfig; use util::enforcing_trait_impls::EnforcingSigner; use util::errors::APIError; use util::test_utils; use util::test_utils::OnGetShutdownScriptpubkey; - use util::logger::Logger; - use bitcoin::secp256k1::{Secp256k1, Message, Signature, All}; + use bitcoin::secp256k1::{Secp256k1, Signature}; use bitcoin::secp256k1::ffi::Signature as FFISignature; use bitcoin::secp256k1::key::{SecretKey,PublicKey}; use bitcoin::secp256k1::recovery::RecoverableSignature; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; - use bitcoin::hash_types::{Txid, WPubkeyHash}; + use bitcoin::hash_types::WPubkeyHash; use core::num::NonZeroU8; use bitcoin::bech32::u5; - use sync::Arc; use prelude::*; struct TestFeeEstimator { @@ -6149,9 +6373,10 @@ mod tests { } #[test] - fn test_max_funding_satoshis() { - assert!(MAX_FUNDING_SATOSHIS <= 21_000_000 * 100_000_000, - "MAX_FUNDING_SATOSHIS is greater than all satoshis in existence"); + fn test_max_funding_satoshis_no_wumbo() { + assert_eq!(TOTAL_BITCOIN_SUPPLY_SATOSHIS, 21_000_000 * 100_000_000); + assert!(MAX_FUNDING_SATOSHIS_NO_WUMBO <= TOTAL_BITCOIN_SUPPLY_SATOSHIS, + "MAX_FUNDING_SATOSHIS_NO_WUMBO is greater than all satoshis in existence"); } #[test] @@ -6167,7 +6392,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(); @@ -6187,10 +6412,11 @@ 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 { + #[cfg(not(feature = "grind_signatures"))] + fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode(hex).unwrap()[..]).unwrap()) } @@ -6211,7 +6437,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()); }, @@ -6233,7 +6459,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. @@ -6259,18 +6485,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(0); 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. @@ -6329,7 +6555,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()); @@ -6378,16 +6604,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(0); + 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(); @@ -6440,7 +6666,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()); @@ -6476,8 +6702,22 @@ mod tests { } } + #[cfg(not(feature = "grind_signatures"))] #[test] fn outbound_commitment_test() { + use bitcoin::util::bip143; + use bitcoin::consensus::encode::serialize; + use bitcoin::blockdata::transaction::SigHashType; + use bitcoin::hashes::hex::FromHex; + use bitcoin::hash_types::Txid; + use bitcoin::secp256k1::Message; + use chain::keysinterface::BaseSign; + use ln::PaymentPreimage; + use ln::channel::{HTLCOutputInCommitment ,TxCreationKeys}; + use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; + use util::logger::Logger; + use sync::Arc; + // Test vectors from BOLT 3 Appendices C and F (anchors): let feeest = TestFeeEstimator{fee_est: 15000}; let logger : Arc = Arc::new(test_utils::TestLogger::new()); @@ -6505,7 +6745,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