X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=19e1c8e3643b8c84b9a741ee053c5bea4e617359;hb=ba289b887211f848b2e9e9dcf66b79d5f55f7630;hp=e20bfc87cbcae087ad0168d5d18a0fbdcd5bc0bf;hpb=a265fc206260fb6909352d38c2eeef16a7f72432;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index e20bfc87..19e1c8e3 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -942,14 +942,6 @@ impl Channel { fn check_remote_fee(fee_estimator: &F, feerate_per_kw: u32) -> Result<(), ChannelError> where F::Target: FeeEstimator { - let lower_limit = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - // Some fee estimators round up to the next full sat/vbyte (ie 250 sats per kw), causing - // occasional issues with feerate disagreements between an initiator that wants a feerate - // of 1.1 sat/vbyte and a receiver that wants 1.1 rounded up to 2. Thus, we always add 250 - // sat/kw before the comparison here. - if feerate_per_kw + 250 < lower_limit { - return Err(ChannelError::Close(format!("Peer's feerate much too low. Actual: {}. Our expected lower limit: {} (- 250)", feerate_per_kw, lower_limit))); - } // We only bound the fee updates on the upper side to prevent completely absurd feerates, // always accepting up to 25 sat/vByte or 10x our fee estimator's "High Priority" fee. // We generally don't care too much if they set the feerate to something very high, but it @@ -959,6 +951,14 @@ impl Channel { if feerate_per_kw as u64 > upper_limit { return Err(ChannelError::Close(format!("Peer's feerate much too high. Actual: {}. Our expected upper limit: {}", feerate_per_kw, upper_limit))); } + let lower_limit = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); + // Some fee estimators round up to the next full sat/vbyte (ie 250 sats per kw), causing + // occasional issues with feerate disagreements between an initiator that wants a feerate + // of 1.1 sat/vbyte and a receiver that wants 1.1 rounded up to 2. Thus, we always add 250 + // sat/kw before the comparison here. + if feerate_per_kw + 250 < lower_limit { + return Err(ChannelError::Close(format!("Peer's feerate much too low. Actual: {}. Our expected lower limit: {} (- 250)", feerate_per_kw, lower_limit))); + } Ok(()) } @@ -2142,7 +2142,7 @@ impl Channel { log_info!(logger, "Received funding_locked from peer for channel {}", log_bytes!(self.channel_id())); - Ok(self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height()).ok()) + Ok(self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height(), logger)) } /// Returns transaction if there is pending funding transaction that is yet to broadcast @@ -3416,7 +3416,7 @@ impl Channel { }) } else { None }; - let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block_height).ok(); + let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block_height, logger); let mut accepted_htlcs = Vec::new(); mem::swap(&mut accepted_htlcs, &mut self.monitor_pending_forwards); @@ -3609,7 +3609,7 @@ impl Channel { }) } else { None }; - let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height()).ok(); + let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height(), logger); if self.channel_state & (ChannelState::FundingSent as u32) == ChannelState::FundingSent as u32 { // If we're waiting on a monitor update, we shouldn't re-send any funding_locked's. @@ -4419,8 +4419,8 @@ impl Channel { txdata: &TransactionData, genesis_block_hash: BlockHash, node_pk: PublicKey, logger: &L) -> Result<(Option, Option), ClosureReason> where L::Target: Logger { let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); - for &(index_in_block, tx) in txdata.iter() { - if let Some(funding_txo) = self.get_funding_txo() { + if let Some(funding_txo) = self.get_funding_txo() { + for &(index_in_block, tx) in txdata.iter() { // If we haven't yet sent a funding_locked, but are in FundingSent (ignoring // whether they've sent a funding_locked or not), check if we should send one. if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 { @@ -4464,7 +4464,7 @@ impl Channel { // may have already happened for this block). if let Some(funding_locked) = self.check_get_funding_locked(height) { log_info!(logger, "Sending a funding_locked to our peer for channel {}", log_bytes!(self.channel_id)); - let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, height).ok(); + let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger); return Ok((Some(funding_locked), announcement_sigs)); } } @@ -4518,7 +4518,7 @@ impl Channel { if let Some(funding_locked) = self.check_get_funding_locked(height) { let announcement_sigs = if let Some((genesis_block_hash, node_pk)) = genesis_node_pk { - self.get_announcement_sigs(node_pk, genesis_block_hash, height).ok() + self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger) } else { None }; log_info!(logger, "Sending a funding_locked to our peer for channel {}", log_bytes!(self.channel_id)); return Ok((Some(funding_locked), timed_out_htlcs, announcement_sigs)); @@ -4554,7 +4554,7 @@ impl Channel { } let announcement_sigs = if let Some((genesis_block_hash, node_pk)) = genesis_node_pk { - self.get_announcement_sigs(node_pk, genesis_block_hash, height).ok() + self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger) } else { None }; Ok((None, timed_out_htlcs, announcement_sigs)) } @@ -4725,15 +4725,12 @@ impl Channel { /// Gets an UnsignedChannelAnnouncement for this channel. The channel must be publicly /// announceable and available for use (have exchanged FundingLocked messages in both - /// directions). Should be used for both loose and in response to an AnnouncementSignatures - /// message from the remote peer. + /// directions). Should be used for both broadcasted announcements and in response to an + /// AnnouncementSignatures message from the remote peer. /// /// 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 { @@ -4759,29 +4756,43 @@ impl Channel { Ok(msg) } - fn get_announcement_sigs(&mut self, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block_height: u32) -> Result { + fn get_announcement_sigs(&mut self, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block_height: u32, logger: &L) + -> Option where L::Target: Logger { if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height { - return Err(ChannelError::Ignore("Funding not yet fully confirmed".to_owned())); + return None; } if !self.is_usable() { - return Err(ChannelError::Ignore("Channel not yet available for use".to_owned())); + return None; } if self.channel_state & ChannelState::PeerDisconnected as u32 != 0 { - return Err(ChannelError::Ignore("Peer currently disconnected".to_owned())); + log_trace!(logger, "Cannot create an announcement_signatures as our peer is disconnected"); + return None; } if self.announcement_sigs_state != AnnouncementSigsState::NotSent { - return Err(ChannelError::Ignore("Announcement signatures already sent".to_owned())); + return None; } - let announcement = self.get_channel_announcement(node_pk, genesis_block_hash)?; - let (our_node_sig, our_bitcoin_sig) = self.holder_signer.sign_channel_announcement(&announcement, &self.secp_ctx) - .map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement".to_owned()))?; + log_trace!(logger, "Creating an announcement_signatures message for channel {}", log_bytes!(self.channel_id())); + let announcement = match self.get_channel_announcement(node_pk, genesis_block_hash) { + Ok(a) => a, + Err(_) => { + log_trace!(logger, "Cannot create an announcement_signatures as channel is not public."); + return None; + } + }; + let (our_node_sig, our_bitcoin_sig) = match self.holder_signer.sign_channel_announcement(&announcement, &self.secp_ctx) { + Err(_) => { + log_error!(logger, "Signer rejected channel_announcement signing. Channel will not be announced!"); + return None; + }, + Ok(v) => v + }; self.announcement_sigs_state = AnnouncementSigsState::MessageSent; - Ok(msgs::AnnouncementSignatures { + Some(msgs::AnnouncementSignatures { channel_id: self.channel_id(), short_channel_id: self.get_short_channel_id().unwrap(), node_signature: our_node_sig, @@ -6140,6 +6151,13 @@ mod tests { "MAX_FUNDING_SATOSHIS is greater than all satoshis in existence"); } + #[test] + fn test_no_fee_check_overflow() { + // Previously, calling `check_remote_fee` with a fee of 0xffffffff would overflow in + // arithmetic, causing a panic with debug assertions enabled. + assert!(Channel::::check_remote_fee(&&TestFeeEstimator { fee_est: 42 }, u32::max_value()).is_err()); + } + struct Keys { signer: InMemorySigner, }