X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=b9a40df91a0117ceb2ff6c9f0f80b16d6fe109c6;hb=62fd36d795f99887260aa962a0e8f30e3b5504fa;hp=d14a868539f68f173fcb79e481e2056aa3f8f090;hpb=3e1e393f61aa4725b7a66e895af40d0c89e37d6b;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index d14a8685..b9a40df9 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -7,6 +7,7 @@ // You may not use this file except in accordance with one or both of these // licenses. +use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::script::{Script,Builder}; use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType}; use bitcoin::util::sighash; @@ -66,6 +67,8 @@ pub struct ChannelValueStat { } 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. @@ -1655,6 +1658,14 @@ impl ChannelContext where SP::Target: SignerProvider { let inbound_stats = context.get_inbound_pending_htlc_stats(None); let outbound_stats = context.get_outbound_pending_htlc_stats(None); + let mut balance_msat = context.value_to_self_msat; + for ref htlc in context.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; + let outbound_capacity_msat = context.value_to_self_msat .saturating_sub(outbound_stats.pending_htlcs_value_msat) .saturating_sub( @@ -1771,6 +1782,7 @@ impl ChannelContext where SP::Target: SignerProvider { outbound_capacity_msat, next_outbound_htlc_limit_msat: available_capacity_msat, next_outbound_htlc_minimum_msat, + balance_msat, } } @@ -2650,7 +2662,7 @@ impl Channel where /// and the channel is now usable (and public), this may generate an announcement_signatures to /// reply with. pub fn channel_ready( - &mut self, msg: &msgs::ChannelReady, node_signer: &NS, genesis_block_hash: BlockHash, + &mut self, msg: &msgs::ChannelReady, node_signer: &NS, chain_hash: ChainHash, user_config: &UserConfig, best_block: &BestBlock, logger: &L ) -> Result, ChannelError> where @@ -2721,7 +2733,7 @@ impl Channel where log_info!(logger, "Received channel_ready from peer for channel {}", &self.context.channel_id()); - Ok(self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger)) + Ok(self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block.height(), logger)) } pub fn update_add_htlc( @@ -3755,7 +3767,7 @@ impl Channel where /// successfully and we should restore normal operation. Returns messages which should be sent /// to the remote side. pub fn monitor_updating_restored( - &mut self, logger: &L, node_signer: &NS, genesis_block_hash: BlockHash, + &mut self, logger: &L, node_signer: &NS, chain_hash: ChainHash, user_config: &UserConfig, best_block_height: u32 ) -> MonitorRestoreUpdates where @@ -3796,7 +3808,7 @@ impl Channel where }) } else { None }; - let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block_height, logger); + let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block_height, logger); let mut accepted_htlcs = Vec::new(); mem::swap(&mut accepted_htlcs, &mut self.context.monitor_pending_forwards); @@ -3966,7 +3978,7 @@ impl Channel where /// [`super::channelmanager::ChannelManager::force_close_all_channels_without_broadcasting_txn`]. pub fn channel_reestablish( &mut self, msg: &msgs::ChannelReestablish, logger: &L, node_signer: &NS, - genesis_block_hash: BlockHash, user_config: &UserConfig, best_block: &BestBlock + chain_hash: ChainHash, user_config: &UserConfig, best_block: &BestBlock ) -> Result where L::Target: Logger, @@ -3981,7 +3993,7 @@ impl Channel where if msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER || msg.next_local_commitment_number == 0 { - return Err(ChannelError::Close("Peer sent a garbage channel_reestablish (usually an lnd node with lost state asking us to force-close for them)".to_owned())); + return Err(ChannelError::Close("Peer sent an invalid channel_reestablish to force close in a non-standard way".to_owned())); } if msg.next_remote_commitment_number > 0 { @@ -4025,7 +4037,7 @@ impl Channel where let shutdown_msg = self.get_outbound_shutdown(); - let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger); + let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block.height(), logger); if self.context.channel_state & (ChannelState::FundingSent as u32) == ChannelState::FundingSent as u32 { // If we're waiting on a monitor update, we shouldn't re-send any channel_ready's. @@ -4802,12 +4814,13 @@ impl Channel where /// In the second, we simply return an Err indicating we need to be force-closed now. pub fn transactions_confirmed( &mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData, - genesis_block_hash: BlockHash, node_signer: &NS, user_config: &UserConfig, logger: &L + chain_hash: ChainHash, node_signer: &NS, user_config: &UserConfig, logger: &L ) -> Result<(Option, Option), ClosureReason> where NS::Target: NodeSigner, L::Target: Logger { + let mut msgs = (None, None); if let Some(funding_txo) = self.context.get_funding_txo() { for &(index_in_block, tx) in txdata.iter() { // Check if the transaction is the expected funding transaction, and if it is, @@ -4862,8 +4875,8 @@ impl Channel where // may have already happened for this block). if let Some(channel_ready) = self.check_get_channel_ready(height) { log_info!(logger, "Sending a channel_ready to our peer for channel {}", &self.context.channel_id); - let announcement_sigs = self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger); - return Ok((Some(channel_ready), announcement_sigs)); + let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger); + msgs = (Some(channel_ready), announcement_sigs); } } for inp in tx.input.iter() { @@ -4874,7 +4887,7 @@ impl Channel where } } } - Ok((None, None)) + Ok(msgs) } /// When a new block is connected, we check the height of the block against outbound holding @@ -4889,19 +4902,19 @@ impl Channel where /// May return some HTLCs (and their payment_hash) which have timed out and should be failed /// back. pub fn best_block_updated( - &mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash, + &mut self, height: u32, highest_header_time: u32, chain_hash: ChainHash, node_signer: &NS, user_config: &UserConfig, logger: &L ) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where NS::Target: NodeSigner, L::Target: Logger { - self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_signer, user_config)), logger) + self.do_best_block_updated(height, highest_header_time, Some((chain_hash, node_signer, user_config)), logger) } fn do_best_block_updated( &mut self, height: u32, highest_header_time: u32, - genesis_node_signer: Option<(BlockHash, &NS, &UserConfig)>, logger: &L + chain_node_signer: Option<(ChainHash, &NS, &UserConfig)>, logger: &L ) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where NS::Target: NodeSigner, @@ -4927,8 +4940,8 @@ impl Channel where self.context.update_time_counter = cmp::max(self.context.update_time_counter, highest_header_time); if let Some(channel_ready) = self.check_get_channel_ready(height) { - let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer { - self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger) + let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer { + self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger) } else { None }; log_info!(logger, "Sending a channel_ready to our peer for channel {}", &self.context.channel_id); return Ok((Some(channel_ready), timed_out_htlcs, announcement_sigs)); @@ -4968,8 +4981,8 @@ impl Channel where return Err(ClosureReason::FundingTimedOut); } - let announcement_sigs = if let Some((genesis_block_hash, node_signer, user_config)) = genesis_node_signer { - self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, height, logger) + let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer { + self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger) } else { None }; Ok((None, timed_out_htlcs, announcement_sigs)) } @@ -4986,7 +4999,7 @@ impl Channel where // larger. If we don't know that time has moved forward, we can just set it to the last // time we saw and it will be ignored. let best_time = self.context.update_time_counter; - match self.do_best_block_updated(reorg_height, best_time, None::<(BlockHash, &&NodeSigner, &UserConfig)>, logger) { + match self.do_best_block_updated(reorg_height, best_time, None::<(ChainHash, &&NodeSigner, &UserConfig)>, logger) { Ok((channel_ready, timed_out_htlcs, announcement_sigs)) => { assert!(channel_ready.is_none(), "We can't generate a funding with 0 confirmations?"); assert!(timed_out_htlcs.is_empty(), "We can't have accepted HTLCs with a timeout before our funding confirmation?"); @@ -5016,7 +5029,7 @@ impl Channel where /// /// [`ChannelReady`]: crate::ln::msgs::ChannelReady fn get_channel_announcement( - &self, node_signer: &NS, chain_hash: BlockHash, user_config: &UserConfig, + &self, node_signer: &NS, chain_hash: ChainHash, user_config: &UserConfig, ) -> Result where NS::Target: NodeSigner { if !self.context.config.announced_channel { return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned())); @@ -5047,7 +5060,7 @@ impl Channel where } fn get_announcement_sigs( - &mut self, node_signer: &NS, genesis_block_hash: BlockHash, user_config: &UserConfig, + &mut self, node_signer: &NS, chain_hash: ChainHash, user_config: &UserConfig, best_block_height: u32, logger: &L ) -> Option where @@ -5072,7 +5085,7 @@ impl Channel where } log_trace!(logger, "Creating an announcement_signatures message for channel {}", &self.context.channel_id()); - let announcement = match self.get_channel_announcement(node_signer, genesis_block_hash, user_config) { + let announcement = match self.get_channel_announcement(node_signer, chain_hash, user_config) { Ok(a) => a, Err(e) => { log_trace!(logger, "{:?}", e); @@ -5146,7 +5159,7 @@ impl Channel where /// channel_announcement message which we can broadcast and storing our counterparty's /// signatures for later reconstruction/rebroadcast of the channel_announcement. pub fn announcement_signatures( - &mut self, node_signer: &NS, chain_hash: BlockHash, best_block_height: u32, + &mut self, node_signer: &NS, chain_hash: ChainHash, best_block_height: u32, msg: &msgs::AnnouncementSignatures, user_config: &UserConfig ) -> Result where NS::Target: NodeSigner { let announcement = self.get_channel_announcement(node_signer, chain_hash, user_config)?; @@ -5176,7 +5189,7 @@ impl Channel where /// Gets a signed channel_announcement for this channel, if we previously received an /// announcement_signatures from our counterparty. pub fn get_signed_channel_announcement( - &self, node_signer: &NS, chain_hash: BlockHash, best_block_height: u32, user_config: &UserConfig + &self, node_signer: &NS, chain_hash: ChainHash, best_block_height: u32, user_config: &UserConfig ) -> Option where NS::Target: NodeSigner { if self.context.funding_tx_confirmation_height == 0 || self.context.funding_tx_confirmation_height + 5 > best_block_height { return None; @@ -5537,17 +5550,20 @@ impl Channel where } } - pub fn channel_update(&mut self, msg: &msgs::ChannelUpdate) -> Result<(), ChannelError> { - if msg.contents.htlc_minimum_msat >= self.context.channel_value_satoshis * 1000 { - return Err(ChannelError::Close("Minimum htlc value is greater than channel value".to_string())); - } - self.context.counterparty_forwarding_info = Some(CounterpartyForwardingInfo { + /// Applies the `ChannelUpdate` and returns a boolean indicating whether a change actually + /// happened. + pub fn channel_update(&mut self, msg: &msgs::ChannelUpdate) -> Result { + let new_forwarding_info = Some(CounterpartyForwardingInfo { fee_base_msat: msg.contents.fee_base_msat, fee_proportional_millionths: msg.contents.fee_proportional_millionths, cltv_expiry_delta: msg.contents.cltv_expiry_delta }); + let did_change = self.context.counterparty_forwarding_info != new_forwarding_info; + if did_change { + self.context.counterparty_forwarding_info = new_forwarding_info; + } - Ok(()) + Ok(did_change) } /// Begins the shutdown process, getting a message for the remote peer and returning all @@ -5983,7 +5999,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { /// 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, fee_estimator: &LowerBoundedFeeEstimator + &mut self, chain_hash: ChainHash, fee_estimator: &LowerBoundedFeeEstimator ) -> Result where F::Target: FeeEstimator @@ -6015,7 +6031,7 @@ impl OutboundV1Channel where SP::Target: SignerProvider { Ok(self.get_open_channel(chain_hash)) } - pub fn get_open_channel(&self, chain_hash: BlockHash) -> msgs::OpenChannel { + pub fn get_open_channel(&self, chain_hash: ChainHash) -> msgs::OpenChannel { if !self.context.is_outbound() { panic!("Tried to open a channel for an inbound channel?"); } @@ -7618,9 +7634,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch #[cfg(test)] mod tests { use std::cmp; + use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::transaction::{Transaction, TxOut}; - use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::opcodes; use bitcoin::network::constants::Network; use hex; @@ -7764,7 +7780,7 @@ mod tests { // Now change the fee so we can check that the fee in the open_channel message is the // same as the old fee. fee_est.fee_est = 500; - let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); + let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); assert_eq!(open_channel_msg.feerate_per_kw, original_fee); } @@ -7790,7 +7806,7 @@ mod tests { // 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 open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); @@ -7908,7 +7924,7 @@ mod tests { let seed = [42; 32]; let network = Network::Testnet; let best_block = BestBlock::from_network(network); - let chain_hash = best_block.block_hash(); + let chain_hash = ChainHash::using_genesis_block(network); let keys_provider = test_utils::TestKeysInterface::new(&seed, network); // Go through the flow of opening a channel between two nodes. @@ -7988,7 +8004,7 @@ mod tests { let chan_2_value_msat = chan_2.context.channel_value_satoshis * 1000; assert_eq!(chan_2.context.holder_max_htlc_value_in_flight_msat, (chan_2_value_msat as f64 * 0.99) as u64); - let chan_1_open_channel_msg = chan_1.get_open_channel(genesis_block(network).header.block_hash()); + let chan_1_open_channel_msg = chan_1.get_open_channel(ChainHash::using_genesis_block(network)); // Test that `InboundV1Channel::new` creates a channel with the correct value for // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value, @@ -8069,7 +8085,7 @@ mod tests { let expected_outbound_selected_chan_reserve = cmp::max(MIN_THEIR_CHAN_RESERVE_SATOSHIS, (chan.context.channel_value_satoshis as f64 * outbound_selected_channel_reserve_perc) as u64); assert_eq!(chan.context.holder_selected_channel_reserve_satoshis, expected_outbound_selected_chan_reserve); - let chan_open_channel_msg = chan.get_open_channel(genesis_block(network).header.block_hash()); + let chan_open_channel_msg = chan.get_open_channel(ChainHash::using_genesis_block(network)); let mut inbound_node_config = UserConfig::default(); inbound_node_config.channel_handshake_config.their_channel_reserve_proportional_millionths = (inbound_selected_channel_reserve_perc * 1_000_000.0) as u32; @@ -8095,7 +8111,7 @@ mod tests { let seed = [42; 32]; let network = Network::Testnet; let best_block = BestBlock::from_network(network); - let chain_hash = genesis_block(network).header.block_hash(); + let chain_hash = ChainHash::using_genesis_block(network); let keys_provider = test_utils::TestKeysInterface::new(&seed, network); // Create Node A's channel pointing to Node B's pubkey @@ -8105,7 +8121,7 @@ mod tests { // 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 open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, node_b_node_id, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), &open_channel_msg, 7, &config, 0, &&logger, /*is_0conf=*/false).unwrap(); @@ -8143,7 +8159,7 @@ mod tests { }, signature: Signature::from(unsafe { FFISignature::new() }) }; - node_a_chan.channel_update(&update).unwrap(); + assert!(node_a_chan.channel_update(&update).unwrap()); // The counterparty can send an update with a higher minimum HTLC, but that shouldn't // change our official htlc_minimum_msat. @@ -8156,6 +8172,8 @@ mod tests { }, None => panic!("expected counterparty forwarding info to be Some") } + + assert!(!node_a_chan.channel_update(&update).unwrap()); } #[cfg(feature = "_test_vectors")] @@ -8940,7 +8958,7 @@ mod tests { let mut channel_type_features = ChannelTypeFeatures::only_static_remote_key(); channel_type_features.set_zero_conf_required(); - let mut open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); + let mut open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); open_channel_msg.channel_type = Some(channel_type_features); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let res = InboundV1Channel::<&TestKeysInterface>::new(&feeest, &&keys_provider, &&keys_provider, @@ -8983,7 +9001,7 @@ mod tests { &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42 ).unwrap(); - let open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash()); + let open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network)); let channel_b = InboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, &channelmanager::provided_channel_type_features(&config), &channelmanager::provided_init_features(&config), @@ -9021,7 +9039,7 @@ mod tests { ).unwrap(); // Set `channel_type` to `None` to force the implicit feature negotiation. - let mut open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash()); + let mut open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network)); open_channel_msg.channel_type = None; // Since A supports both `static_remote_key` and `option_anchors`, but B only accepts @@ -9066,7 +9084,7 @@ mod tests { &channelmanager::provided_init_features(&config), 10000000, 100000, 42, &config, 0, 42 ).unwrap(); - let mut open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash()); + let mut open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network)); open_channel_msg.channel_type = Some(simple_anchors_channel_type.clone()); let res = InboundV1Channel::<&TestKeysInterface>::new( @@ -9085,7 +9103,7 @@ mod tests { 10000000, 100000, 42, &config, 0, 42 ).unwrap(); - let open_channel_msg = channel_a.get_open_channel(genesis_block(network).header.block_hash()); + let open_channel_msg = channel_a.get_open_channel(ChainHash::using_genesis_block(network)); let channel_b = InboundV1Channel::<&TestKeysInterface>::new( &fee_estimator, &&keys_provider, &&keys_provider, node_id_a, @@ -9110,7 +9128,7 @@ mod tests { let seed = [42; 32]; let network = Network::Testnet; let best_block = BestBlock::from_network(network); - let chain_hash = genesis_block(network).header.block_hash(); + let chain_hash = ChainHash::using_genesis_block(network); let keys_provider = test_utils::TestKeysInterface::new(&seed, network); let mut config = UserConfig::default(); @@ -9134,7 +9152,7 @@ mod tests { 42, ).unwrap(); - let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); + let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network)); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new( &feeest,