X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;ds=sidebyside;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=98eb984fa4c3d6b07b9ea0e34f6c627d3f9fb8ea;hb=fe12a57464609ae43f42e029baa0dac6dfb40c24;hp=ae5df9a1507c78058d4d94d5ed06e79ef272668d;hpb=0cdea66b0e73d45b2a137eed145a294b7d713cc4;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index ae5df9a1..98eb984f 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -281,6 +281,26 @@ pub(super) enum ChannelUpdateStatus { Disabled, } +/// We track when we sent an `AnnouncementSignatures` to our peer in a few states, described here. +#[derive(PartialEq)] +pub enum AnnouncementSigsState { + /// We have not sent our peer an `AnnouncementSignatures` yet, or our peer disconnected since + /// we sent the last `AnnouncementSignatures`. + NotSent, + /// We sent an `AnnouncementSignatures` to our peer since the last time our peer disconnected. + /// This state never appears on disk - instead we write `NotSent`. + MessageSent, + /// We sent a `CommitmentSigned` after the last `AnnouncementSignatures` we sent. Because we + /// only ever have a single `CommitmentSigned` pending at once, if we sent one after sending + /// `AnnouncementSignatures` then we know the peer received our `AnnouncementSignatures` if + /// they send back a `RevokeAndACK`. + /// This state never appears on disk - instead we write `NotSent`. + Committed, + /// We received a `RevokeAndACK`, effectively ack-ing our `AnnouncementSignatures`, at this + /// point we no longer need to re-send our `AnnouncementSignatures` again on reconnect. + PeerReceived, +} + /// An enum indicating whether the local or remote side offered a given HTLC. enum HTLCInitiator { LocalOffered, @@ -374,6 +394,19 @@ pub(super) struct MonitorRestoreUpdates { pub finalized_claimed_htlcs: Vec, pub funding_broadcastable: Option, pub funding_locked: Option, + pub announcement_sigs: Option, +} + +/// The return value of `channel_reestablish` +pub(super) struct ReestablishResponses { + pub funding_locked: Option, + pub raa: Option, + pub commitment_update: Option, + pub order: RAACommitmentOrder, + pub mon_update: Option, + pub holding_cell_failed_htlcs: Vec<(HTLCSource, PaymentHash)>, + pub announcement_sigs: Option, + pub shutdown: Option, } /// If the majority of the channels funds are to the fundee and the initiator holds only just @@ -430,6 +463,19 @@ pub(super) struct Channel { channel_id: [u8; 32], channel_state: u32, + + // When we reach max(6 blocks, minimum_depth), we need to send an AnnouncementSigs message to + // our peer. However, we want to make sure they received it, or else rebroadcast it when we + // next connect. + // We do so here, see `AnnouncementSigsSent` for more details on the state(s). + // Note that a number of our tests were written prior to the behavior here which retransmits + // AnnouncementSignatures until after an RAA completes, so the behavior is short-circuited in + // many tests. + #[cfg(any(test, feature = "_test_utils"))] + pub(crate) announcement_sigs_state: AnnouncementSigsState, + #[cfg(not(any(test, feature = "_test_utils")))] + announcement_sigs_state: AnnouncementSigsState, + secp_ctx: Secp256k1, channel_value_satoshis: u64, @@ -481,9 +527,14 @@ pub(super) struct Channel { holding_cell_update_fee: Option, next_holder_htlc_id: u64, next_counterparty_htlc_id: u64, - update_time_counter: u32, feerate_per_kw: u32, + /// The timestamp set on our latest `channel_update` message for this channel. It is updated + /// when the channel is updated in ways which may impact the `channel_update` message or when a + /// new block is received, ensuring it's always at least moderately close to the current real + /// time. + update_time_counter: u32, + #[cfg(debug_assertions)] /// Max to_local and to_remote outputs in a locally-generated commitment transaction holder_max_commitment_tx_output: Mutex<(u64, u64)>, @@ -758,6 +809,7 @@ impl Channel { channel_id: keys_provider.get_secure_random_bytes(), channel_state: ChannelState::OurInitSent as u32, + announcement_sigs_state: AnnouncementSigsState::NotSent, secp_ctx, channel_value_satoshis, @@ -862,8 +914,12 @@ impl Channel { where F::Target: FeeEstimator { let lower_limit = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - if feerate_per_kw < lower_limit { - return Err(ChannelError::Close(format!("Peer's feerate much too low. Actual: {}. Our expected lower limit: {}", feerate_per_kw, lower_limit))); + // 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. @@ -1050,6 +1106,7 @@ impl Channel { channel_id: msg.temporary_channel_id, channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32), + announcement_sigs_state: AnnouncementSigsState::NotSent, secp_ctx, latest_monitor_update_id: 0, @@ -2002,7 +2059,10 @@ impl Channel { Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap())) } - pub fn funding_locked(&mut self, msg: &msgs::FundingLocked, logger: &L) -> Result<(), ChannelError> where L::Target: Logger { + /// Handles a funding_locked message from our peer. If we've already sent our funding_locked + /// and the channel is now usable (and public), this may generate an announcement_signatures to + /// reply with. + pub fn funding_locked(&mut self, msg: &msgs::FundingLocked, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block: &BestBlock, logger: &L) -> Result, ChannelError> where L::Target: Logger { if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { self.workaround_lnd_bug_4006 = Some(msg.clone()); 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())); @@ -2026,7 +2086,7 @@ impl Channel { 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(()); + return Ok(None); } else { return Err(ChannelError::Close("Peer sent a funding_locked at a strange time".to_owned())); } @@ -2036,7 +2096,7 @@ impl Channel { log_info!(logger, "Received funding_locked from peer for channel {}", log_bytes!(self.channel_id())); - Ok(()) + Ok(self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height()).ok()) } /// Returns transaction if there is pending funding transaction that is yet to broadcast @@ -2118,6 +2178,8 @@ impl Channel { /// 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) { // Note that we have to handle overflow due to the above case. ( @@ -2133,6 +2195,14 @@ impl Channel { ) } + /// 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 + } + pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option) { (self.holder_selected_channel_reserve_satoshis, self.counterparty_selected_channel_reserve_satoshis) } @@ -2911,6 +2981,10 @@ impl Channel { self.counterparty_cur_commitment_point = Some(msg.next_per_commitment_point); self.cur_counterparty_commitment_transaction_number -= 1; + if self.announcement_sigs_state == AnnouncementSigsState::Committed { + self.announcement_sigs_state = AnnouncementSigsState::PeerReceived; + } + log_trace!(logger, "Updating HTLCs on receipt of RAA in channel {}...", log_bytes!(self.channel_id())); let mut to_forward_infos = Vec::new(); let mut revoked_htlcs = Vec::new(); @@ -3186,6 +3260,11 @@ impl Channel { self.channel_state = ChannelState::ShutdownComplete as u32; return; } + + if self.announcement_sigs_state == AnnouncementSigsState::MessageSent || self.announcement_sigs_state == AnnouncementSigsState::Committed { + self.announcement_sigs_state = AnnouncementSigsState::NotSent; + } + // Upon reconnect we have to start the closing_signed dance over, but shutdown messages // will be retransmitted. self.last_sent_closing_fee = None; @@ -3262,7 +3341,7 @@ impl Channel { /// Indicates that the latest ChannelMonitor update has been committed by the client /// 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) -> MonitorRestoreUpdates where L::Target: Logger { + pub fn monitor_updating_restored(&mut self, logger: &L, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block_height: u32) -> MonitorRestoreUpdates where L::Target: Logger { assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, ChannelState::MonitorUpdateFailed as u32); self.channel_state &= !(ChannelState::MonitorUpdateFailed as u32); @@ -3285,6 +3364,8 @@ impl Channel { }) } else { None }; + let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block_height).ok(); + let mut accepted_htlcs = Vec::new(); mem::swap(&mut accepted_htlcs, &mut self.monitor_pending_forwards); let mut failed_htlcs = Vec::new(); @@ -3297,7 +3378,7 @@ impl Channel { self.monitor_pending_commitment_signed = false; return MonitorRestoreUpdates { raa: None, commitment_update: None, order: RAACommitmentOrder::RevokeAndACKFirst, - accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, funding_locked + accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, funding_locked, announcement_sigs }; } @@ -3316,7 +3397,7 @@ impl Channel { if commitment_update.is_some() { "a" } else { "no" }, if raa.is_some() { "an" } else { "no" }, match order { RAACommitmentOrder::CommitmentFirst => "commitment", RAACommitmentOrder::RevokeAndACKFirst => "RAA"}); MonitorRestoreUpdates { - raa, commitment_update, order, accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, funding_locked + raa, commitment_update, order, accepted_htlcs, failed_htlcs, finalized_claimed_htlcs, funding_broadcastable, funding_locked, announcement_sigs } } @@ -3430,7 +3511,9 @@ impl Channel { /// May panic if some calls other than message-handling calls (which will all Err immediately) /// have been called between remove_uncommitted_htlcs_and_mark_paused and this call. - pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish, logger: &L) -> Result<(Option, Option, Option, Option, RAACommitmentOrder, Vec<(HTLCSource, PaymentHash)>, Option), ChannelError> where L::Target: Logger { + pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish, logger: &L, + node_pk: PublicKey, genesis_block_hash: BlockHash, best_block: &BestBlock) + -> Result where L::Target: Logger { if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { // While BOLT 2 doesn't indicate explicitly we should error this channel here, it // almost certainly indicates we are going to end up out-of-sync in some way, so we @@ -3466,7 +3549,7 @@ impl Channel { // remaining cases either succeed or ErrorMessage-fail). self.channel_state &= !(ChannelState::PeerDisconnected as u32); - let shutdown_msg = if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 { + let shutdown = if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 { assert!(self.shutdown_scriptpubkey.is_some()); Some(msgs::Shutdown { channel_id: self.channel_id, @@ -3474,6 +3557,8 @@ impl Channel { }) } else { None }; + let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, best_block.height()).ok(); + 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. if self.channel_state & (ChannelState::OurFundingLocked as u32) == 0 || @@ -3482,15 +3567,27 @@ impl Channel { return Err(ChannelError::Close("Peer claimed they saw a revoke_and_ack but we haven't sent funding_locked yet".to_owned())); } // Short circuit the whole handler as there is nothing we can resend them - return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst, Vec::new(), shutdown_msg)); + return Ok(ReestablishResponses { + funding_locked: None, + raa: None, commitment_update: None, mon_update: None, + order: RAACommitmentOrder::CommitmentFirst, + holding_cell_failed_htlcs: Vec::new(), + shutdown, announcement_sigs, + }); } // We have OurFundingLocked set! let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); - return Ok((Some(msgs::FundingLocked { - channel_id: self.channel_id(), - next_per_commitment_point, - }), None, None, None, RAACommitmentOrder::CommitmentFirst, Vec::new(), shutdown_msg)); + return Ok(ReestablishResponses { + funding_locked: Some(msgs::FundingLocked { + channel_id: self.channel_id(), + next_per_commitment_point, + }), + raa: None, commitment_update: None, mon_update: None, + order: RAACommitmentOrder::CommitmentFirst, + holding_cell_failed_htlcs: Vec::new(), + shutdown, announcement_sigs, + }); } let required_revoke = if msg.next_remote_commitment_number + 1 == INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number { @@ -3514,7 +3611,7 @@ impl Channel { // the corresponding revoke_and_ack back yet. let next_counterparty_commitment_number = INITIAL_COMMITMENT_NUMBER - self.cur_counterparty_commitment_transaction_number + if (self.channel_state & ChannelState::AwaitingRemoteRevoke as u32) != 0 { 1 } else { 0 }; - let resend_funding_locked = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number == 1 { + let funding_locked = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number == 1 { // We should never have to worry about MonitorUpdateFailed resending FundingLocked let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); Some(msgs::FundingLocked { @@ -3536,18 +3633,39 @@ impl Channel { // have received some updates while we were disconnected. Free the holding cell // now! match self.free_holding_cell_htlcs(logger) { - Err(ChannelError::Close(msg)) => return Err(ChannelError::Close(msg)), + Err(ChannelError::Close(msg)) => Err(ChannelError::Close(msg)), Err(ChannelError::Warn(_)) | Err(ChannelError::Ignore(_)) | Err(ChannelError::CloseDelayBroadcast(_)) => panic!("Got non-channel-failing result from free_holding_cell_htlcs"), - Ok((Some((commitment_update, monitor_update)), htlcs_to_fail)) => { - return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(monitor_update), self.resend_order.clone(), htlcs_to_fail, shutdown_msg)); + Ok((Some((commitment_update, monitor_update)), holding_cell_failed_htlcs)) => { + Ok(ReestablishResponses { + funding_locked, shutdown, announcement_sigs, + raa: required_revoke, + commitment_update: Some(commitment_update), + order: self.resend_order.clone(), + mon_update: Some(monitor_update), + holding_cell_failed_htlcs, + }) }, - Ok((None, htlcs_to_fail)) => { - return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), htlcs_to_fail, shutdown_msg)); + Ok((None, holding_cell_failed_htlcs)) => { + Ok(ReestablishResponses { + funding_locked, shutdown, announcement_sigs, + raa: required_revoke, + commitment_update: None, + order: self.resend_order.clone(), + mon_update: None, + holding_cell_failed_htlcs, + }) }, } } else { - return Ok((resend_funding_locked, required_revoke, None, None, self.resend_order.clone(), Vec::new(), shutdown_msg)); + Ok(ReestablishResponses { + funding_locked, shutdown, announcement_sigs, + raa: required_revoke, + commitment_update: None, + order: self.resend_order.clone(), + mon_update: None, + holding_cell_failed_htlcs: Vec::new(), + }) } } else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 { if required_revoke.is_some() { @@ -3558,12 +3676,24 @@ impl Channel { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 { self.monitor_pending_commitment_signed = true; - return Ok((resend_funding_locked, None, None, None, self.resend_order.clone(), Vec::new(), shutdown_msg)); + Ok(ReestablishResponses { + funding_locked, shutdown, announcement_sigs, + commitment_update: None, raa: None, mon_update: None, + order: self.resend_order.clone(), + holding_cell_failed_htlcs: Vec::new(), + }) + } else { + Ok(ReestablishResponses { + funding_locked, shutdown, announcement_sigs, + raa: required_revoke, + commitment_update: Some(self.get_last_commitment_update(logger)), + order: self.resend_order.clone(), + mon_update: None, + holding_cell_failed_htlcs: Vec::new(), + }) } - - return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update(logger)), None, self.resend_order.clone(), Vec::new(), shutdown_msg)); } else { - return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction".to_owned())); + Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction".to_owned())) } } @@ -4132,7 +4262,7 @@ impl Channel { /// Allowed in any state (including after shutdown) pub fn is_usable(&self) -> bool { let mask = ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK; - (self.channel_state & mask) == (ChannelState::ChannelFunded as u32) + (self.channel_state & mask) == (ChannelState::ChannelFunded as u32) && !self.monitor_pending_funding_locked } /// Returns true if this channel is currently available for use. This is a superset of @@ -4178,6 +4308,7 @@ impl Channel { } pub fn set_channel_update_status(&mut self, status: ChannelUpdateStatus) { + self.update_time_counter += 1; self.channel_update_status = status; } @@ -4215,11 +4346,13 @@ impl Channel { if need_commitment_update { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { - let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); - return Some(msgs::FundingLocked { - channel_id: self.channel_id, - next_per_commitment_point, - }); + 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); + return Some(msgs::FundingLocked { + channel_id: self.channel_id, + next_per_commitment_point, + }); + } } else { self.monitor_pending_funding_locked = true; } @@ -4230,8 +4363,9 @@ impl Channel { /// When a transaction is confirmed, we check whether it is or spends the funding transaction /// In the first case, we store the confirmation height and calculating the short channel id. /// 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, logger: &L) - -> Result, ClosureReason> where L::Target: Logger { + pub fn transactions_confirmed(&mut self, block_hash: &BlockHash, height: u32, + 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() { @@ -4278,7 +4412,8 @@ 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)); - return Ok(Some(funding_locked)); + let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, height).ok(); + return Ok((Some(funding_locked), announcement_sigs)); } } for inp in tx.input.iter() { @@ -4289,7 +4424,7 @@ impl Channel { } } } - Ok(None) + Ok((None, None)) } /// When a new block is connected, we check the height of the block against outbound holding @@ -4303,8 +4438,13 @@ impl Channel { /// /// 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, logger: &L) - -> Result<(Option, Vec<(HTLCSource, PaymentHash)>), ClosureReason> where L::Target: Logger { + pub fn best_block_updated(&mut self, height: u32, highest_header_time: u32, genesis_block_hash: BlockHash, node_pk: PublicKey, logger: &L) + -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where L::Target: Logger { + self.do_best_block_updated(height, highest_header_time, Some((genesis_block_hash, node_pk)), logger) + } + + fn do_best_block_updated(&mut self, height: u32, highest_header_time: u32, genesis_node_pk: Option<(BlockHash, PublicKey)>, logger: &L) + -> Result<(Option, Vec<(HTLCSource, PaymentHash)>, Option), ClosureReason> where L::Target: Logger { let mut timed_out_htlcs = Vec::new(); // This mirrors the check in ChannelManager::decode_update_add_htlc_onion, refusing to // forward an HTLC when our counterparty should almost certainly just fail it for expiring @@ -4325,8 +4465,11 @@ impl Channel { self.update_time_counter = cmp::max(self.update_time_counter, highest_header_time); 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() + } 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)); + return Ok((Some(funding_locked), timed_out_htlcs, announcement_sigs)); } let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); @@ -4358,7 +4501,10 @@ impl Channel { return Err(ClosureReason::FundingTimedOut); } - Ok((None, timed_out_htlcs)) + 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() + } else { None }; + Ok((None, timed_out_htlcs, announcement_sigs)) } /// Indicates the funding transaction is no longer confirmed in the main chain. This may @@ -4373,10 +4519,11 @@ impl Channel { // 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.update_time_counter; - match self.best_block_updated(reorg_height, best_time, logger) { - Ok((funding_locked, timed_out_htlcs)) => { + match self.do_best_block_updated(reorg_height, best_time, None, logger) { + Ok((funding_locked, timed_out_htlcs, announcement_sigs)) => { assert!(funding_locked.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?"); + assert!(announcement_sigs.is_none(), "We can't generate an announcement_sigs with 0 confirmations?"); Ok(()) }, Err(e) => Err(e) @@ -4524,25 +4671,24 @@ impl Channel { }) } - /// Gets an UnsignedChannelAnnouncement, as well as a signature covering it using our - /// bitcoin_key, if available, 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. + /// 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. + /// /// 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. - pub fn get_channel_announcement(&self, node_id: PublicKey, chain_hash: BlockHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), ChannelError> { + fn get_channel_announcement(&self, node_id: PublicKey, chain_hash: BlockHash) -> Result { if !self.config.announced_channel { return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned())); } - if self.channel_state & (ChannelState::ChannelFunded as u32) == 0 { - return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement until the channel funding has been locked".to_owned())); - } - if (self.channel_state & (ChannelState::LocalShutdownSent as u32 | ChannelState::ShutdownComplete as u32)) != 0 { - return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement once the channel is closing".to_owned())); + if !self.is_usable() { + return Err(ChannelError::Ignore("Cannot get a ChannelAnnouncement if the channel is not currently usable".to_owned())); } let were_node_one = node_id.serialize()[..] < self.counterparty_node_id.serialize()[..]; @@ -4558,19 +4704,47 @@ impl Channel { excess_data: Vec::new(), }; - let sig = self.holder_signer.sign_channel_announcement(&msg, &self.secp_ctx) + Ok(msg) + } + + fn get_announcement_sigs(&mut self, node_pk: PublicKey, genesis_block_hash: BlockHash, best_block_height: u32) -> Result { + 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())); + } + + if !self.is_usable() { + return Err(ChannelError::Ignore("Channel not yet available for use".to_owned())); + } + + if self.channel_state & ChannelState::PeerDisconnected as u32 != 0 { + return Err(ChannelError::Ignore("Peer currently disconnected".to_owned())); + } + + if self.announcement_sigs_state != AnnouncementSigsState::NotSent { + return Err(ChannelError::Ignore("Announcement signatures already sent".to_owned())); + } + + 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()))?; + self.announcement_sigs_state = AnnouncementSigsState::MessageSent; - Ok((msg, sig)) + Ok(msgs::AnnouncementSignatures { + channel_id: self.channel_id(), + short_channel_id: self.get_short_channel_id().unwrap(), + node_signature: our_node_sig, + bitcoin_signature: our_bitcoin_sig, + }) } /// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are /// available. - fn sign_channel_announcement(&self, our_node_secret: &SecretKey, our_node_id: PublicKey, msghash: secp256k1::Message, announcement: msgs::UnsignedChannelAnnouncement, our_bitcoin_sig: Signature) -> Result { + fn sign_channel_announcement(&self, our_node_id: PublicKey, announcement: msgs::UnsignedChannelAnnouncement) -> Result { if let Some((their_node_sig, their_bitcoin_sig)) = self.announcement_sigs { let were_node_one = announcement.node_id_1 == our_node_id; - let our_node_sig = self.secp_ctx.sign(&msghash, our_node_secret); + 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()))?; Ok(msgs::ChannelAnnouncement { node_signature_1: if were_node_one { our_node_sig } else { their_node_sig }, node_signature_2: if were_node_one { their_node_sig } else { our_node_sig }, @@ -4586,8 +4760,8 @@ impl Channel { /// Processes an incoming announcement_signatures message, providing a fully-signed /// 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, our_node_secret: &SecretKey, our_node_id: PublicKey, chain_hash: BlockHash, msg: &msgs::AnnouncementSignatures) -> Result { - let (announcement, our_bitcoin_sig) = self.get_channel_announcement(our_node_id.clone(), chain_hash)?; + pub fn announcement_signatures(&mut self, our_node_id: PublicKey, chain_hash: BlockHash, best_block_height: u32, msg: &msgs::AnnouncementSignatures) -> Result { + let announcement = self.get_channel_announcement(our_node_id.clone(), chain_hash)?; let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]); @@ -4603,19 +4777,25 @@ impl Channel { } self.announcement_sigs = Some((msg.node_signature, msg.bitcoin_signature)); + if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height { + return Err(ChannelError::Ignore( + "Got announcement_signatures prior to the required six confirmations - we may not have received a block yet that our peer has".to_owned())); + } - self.sign_channel_announcement(our_node_secret, our_node_id, msghash, announcement, our_bitcoin_sig) + self.sign_channel_announcement(our_node_id, announcement) } /// 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, our_node_secret: &SecretKey, our_node_id: PublicKey, chain_hash: BlockHash) -> Option { - let (announcement, our_bitcoin_sig) = match self.get_channel_announcement(our_node_id.clone(), chain_hash) { + pub fn get_signed_channel_announcement(&self, our_node_id: PublicKey, chain_hash: BlockHash, best_block_height: u32) -> Option { + if self.funding_tx_confirmation_height == 0 || self.funding_tx_confirmation_height + 5 > best_block_height { + return None; + } + let announcement = match self.get_channel_announcement(our_node_id.clone(), chain_hash) { Ok(res) => res, Err(_) => return None, }; - let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]); - match self.sign_channel_announcement(our_node_secret, our_node_id, msghash, announcement, our_bitcoin_sig) { + match self.sign_channel_announcement(our_node_id, announcement) { Ok(res) => Some(res), Err(_) => None, } @@ -4890,6 +5070,10 @@ impl Channel { Err(e) => return Err(e), }; + if self.announcement_sigs_state == AnnouncementSigsState::MessageSent { + self.announcement_sigs_state = AnnouncementSigsState::Committed; + } + self.latest_monitor_update_id += 1; let monitor_update = ChannelMonitorUpdate { update_id: self.latest_monitor_update_id, @@ -5149,6 +5333,29 @@ impl Readable for ChannelUpdateStatus { } } +impl Writeable for AnnouncementSigsState { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + // We only care about writing out the current state as if we had just disconnected, at + // which point we always set anything but AnnouncementSigsReceived to NotSent. + match self { + AnnouncementSigsState::NotSent => 0u8.write(writer), + AnnouncementSigsState::MessageSent => 0u8.write(writer), + AnnouncementSigsState::Committed => 0u8.write(writer), + AnnouncementSigsState::PeerReceived => 1u8.write(writer), + } + } +} + +impl Readable for AnnouncementSigsState { + fn read(reader: &mut R) -> Result { + Ok(match ::read(reader)? { + 0 => AnnouncementSigsState::NotSent, + 1 => AnnouncementSigsState::PeerReceived, + _ => return Err(DecodeError::InvalidValue), + }) + } +} + impl Writeable for Channel { fn write(&self, writer: &mut W) -> Result<(), io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been @@ -5406,6 +5613,7 @@ impl Writeable for Channel { (9, self.target_closing_feerate_sats_per_kw, option), (11, self.monitor_pending_finalized_fulfills, vec_type), (13, self.channel_creation_height, required), + (15, self.announcement_sigs_state, required), }); Ok(()) @@ -5647,6 +5855,9 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel // only, so we default to that if none was written. let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key()); let mut channel_creation_height = Some(serialized_height); + // 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); read_tlv_fields!(reader, { (0, announcement_sigs, option), (1, minimum_depth, option), @@ -5659,6 +5870,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel (9, target_closing_feerate_sats_per_kw, option), (11, monitor_pending_finalized_fulfills, vec_type), (13, channel_creation_height, option), + (15, announcement_sigs_state, option), }); let chan_features = channel_type.as_ref().unwrap(); @@ -5682,6 +5894,7 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel config: config.unwrap(), channel_id, channel_state, + announcement_sigs_state: announcement_sigs_state.unwrap(), secp_ctx, channel_value_satoshis, @@ -5796,7 +6009,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, KeysInterface, BaseSign}; + use chain::keysinterface::{InMemorySigner, KeyMaterial, KeysInterface, BaseSign}; use chain::transaction::OutPoint; use util::config::UserConfig; use util::enforcing_trait_impls::EnforcingSigner; @@ -5837,6 +6050,7 @@ mod tests { type Signer = InMemorySigner; fn get_node_secret(&self) -> SecretKey { panic!(); } + fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); } fn get_destination_script(&self) -> Script { let secp_ctx = Secp256k1::signing_only(); let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); @@ -6153,6 +6367,7 @@ mod tests { let mut signer = InMemorySigner::new( &secp_ctx, + SecretKey::from_slice(&hex::decode("4242424242424242424242424242424242424242424242424242424242424242").unwrap()[..]).unwrap(), SecretKey::from_slice(&hex::decode("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(), SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(), SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(),