X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=f44109432a581c2f28a7b3797cc187d24546ed31;hb=7c238476845fcc1115f3115a650f82d7b7f170b1;hp=59bdae041d2d739c5075fc1cce3db8fdb8410732;hpb=3ea13194e8ad3ea3493ca4ba63cd215eee105feb;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 59bdae04..f4410943 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -18,7 +18,7 @@ use secp256k1; use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; -use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep}; +use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER}; use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; use ln::chan_utils::{CounterpartyCommitmentSecrets, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys}; use ln::chan_utils; @@ -1515,10 +1515,10 @@ impl Channel { &their_pubkeys.htlc_basepoint, &their_pubkeys.delayed_payment_basepoint, self.their_to_self_delay, funding_redeemscript.clone(), self.channel_value_satoshis, self.get_commitment_transaction_number_obscure_factor(), + local_initial_commitment_tx.clone(), self.logger.clone()); channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); - channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), Vec::new()).unwrap(); channel_monitor } } } @@ -1539,22 +1539,25 @@ impl Channel { /// Handles a funding_signed message from the remote end. /// If this call is successful, broadcast the funding transaction (and not before!) - pub fn funding_signed(&mut self, msg: &msgs::FundingSigned) -> Result, ChannelError)> { + pub fn funding_signed(&mut self, msg: &msgs::FundingSigned) -> Result, ChannelError> { if !self.channel_outbound { - return Err((None, ChannelError::Close("Received funding_signed for an inbound channel?"))); + return Err(ChannelError::Close("Received funding_signed for an inbound channel?")); } if self.channel_state & !(ChannelState::MonitorUpdateFailed as u32) != ChannelState::FundingCreated as u32 { - return Err((None, ChannelError::Close("Received funding_signed in strange state!"))); + return Err(ChannelError::Close("Received funding_signed in strange state!")); } if self.commitment_secrets.get_min_seen_secret() != (1 << 48) || - self.cur_remote_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER - 1 || + self.cur_remote_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || self.cur_local_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } let funding_script = self.get_funding_redeemscript(); - let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number).map_err(|e| (None, e))?; + let remote_keys = self.build_remote_transaction_keys()?; + let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0; + + let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?; let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); @@ -1562,27 +1565,40 @@ impl Channel { // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish. if let Err(_) = self.secp_ctx.verify(&local_sighash, &msg.signature, their_funding_pubkey) { - return Err((None, ChannelError::Close("Invalid funding_signed signature from peer"))); + return Err(ChannelError::Close("Invalid funding_signed signature from peer")); } - self.latest_monitor_update_id += 1; - let monitor_update = ChannelMonitorUpdate { - update_id: self.latest_monitor_update_id, - updates: vec![ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { - commitment_tx: LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey, local_keys, self.feerate_per_kw, Vec::new()), - htlc_outputs: Vec::new(), - }] - }; - self.channel_monitor.as_mut().unwrap().update_monitor_ooo(monitor_update.clone()).unwrap(); - self.channel_state = ChannelState::FundingSent as u32 | (self.channel_state & (ChannelState::MonitorUpdateFailed as u32)); - self.cur_local_commitment_transaction_number -= 1; + let their_pubkeys = self.their_pubkeys.as_ref().unwrap(); + let funding_redeemscript = self.get_funding_redeemscript(); + let funding_txo = self.funding_txo.as_ref().unwrap(); + let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); + macro_rules! create_monitor { + () => { { + let local_commitment_tx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx.clone(), &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey, local_keys.clone(), self.feerate_per_kw, Vec::new()); + let mut channel_monitor = ChannelMonitor::new(self.local_keys.clone(), + &self.shutdown_pubkey, self.our_to_self_delay, + &self.destination_script, (funding_txo.clone(), funding_txo_script.clone()), + &their_pubkeys.htlc_basepoint, &their_pubkeys.delayed_payment_basepoint, + self.their_to_self_delay, funding_redeemscript.clone(), self.channel_value_satoshis, + self.get_commitment_transaction_number_obscure_factor(), + local_commitment_tx, + self.logger.clone()); - if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { - Ok(monitor_update) - } else { - Err((Some(monitor_update), - ChannelError::Ignore("Previous monitor update failure prevented funding_signed from allowing funding broadcast"))) + channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); + + channel_monitor + } } } + + self.channel_monitor = Some(create_monitor!()); + let channel_monitor = create_monitor!(); + + assert_eq!(self.channel_state & (ChannelState::MonitorUpdateFailed as u32), 0); // We have no had any monitor(s) yet to fail update! + self.channel_state = ChannelState::FundingSent as u32; + self.cur_local_commitment_transaction_number -= 1; + self.cur_remote_commitment_transaction_number -= 1; + + Ok(channel_monitor) } pub fn funding_locked(&mut self, msg: &msgs::FundingLocked) -> Result<(), ChannelError> { @@ -2951,7 +2967,7 @@ impl Channel { /// May only be called after funding has been initiated (ie is_funding_initiated() is true) pub fn channel_monitor(&mut self) -> &mut ChannelMonitor { - if self.channel_state < ChannelState::FundingCreated as u32 { + if self.channel_state < ChannelState::FundingSent as u32 { panic!("Can't get a channel monitor until funding has been created"); } self.channel_monitor.as_mut().unwrap() @@ -3105,7 +3121,7 @@ impl Channel { /// Returns true if funding_created was sent/received. pub fn is_funding_initiated(&self) -> bool { - self.channel_state >= ChannelState::FundingCreated as u32 + self.channel_state >= ChannelState::FundingSent as u32 } /// Returns true if this channel is fully shut down. True here implies that no further actions @@ -3138,13 +3154,33 @@ impl Channel { self.network_sync == UpdateStatus::DisabledMarked } - /// Called by channelmanager based on chain blocks being connected. - /// Note that we only need to use this to detect funding_signed, anything else is handled by - /// the channel_monitor. - /// In case of Err, the channel may have been closed, at which point the standard requirements - /// apply - no calls may be made except those explicitly stated to be allowed post-shutdown. + /// When we receive a new block, we (a) check whether the block contains the funding + /// transaction (which would start us counting blocks until we send the funding_signed), and + /// (b) check the height of the block against outbound holding cell HTLCs in case we need to + /// give up on them prematurely and time them out. Everything else (e.g. commitment + /// transaction broadcasts, channel closure detection, HTLC transaction broadcasting, etc) is + /// handled by the ChannelMonitor. + /// + /// If we return Err, the channel may have been closed, at which point the standard + /// requirements apply - no calls may be made except those explicitly stated to be allowed + /// post-shutdown. /// Only returns an ErrorAction of DisconnectPeer, if Err. - pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result, msgs::ErrorMessage> { + /// + /// May return some HTLCs (and their payment_hash) which have timed out and should be failed + /// back. + pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> { + let mut timed_out_htlcs = Vec::new(); + self.holding_cell_htlc_updates.retain(|htlc_update| { + match htlc_update { + &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, .. } => { + if *cltv_expiry <= height + HTLC_FAIL_BACK_BUFFER { + timed_out_htlcs.push((source.clone(), payment_hash.clone())); + false + } else { true } + }, + _ => true + } + }); let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); if header.bitcoin_hash() != self.last_block_connected { if self.funding_tx_confirmations > 0 { @@ -3227,19 +3263,19 @@ impl Channel { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number); let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret); - return Ok(Some(msgs::FundingLocked { + return Ok((Some(msgs::FundingLocked { channel_id: self.channel_id, next_per_commitment_point: next_per_commitment_point, - })); + }), timed_out_htlcs)); } else { self.monitor_pending_funding_locked = true; - return Ok(None); + return Ok((None, timed_out_htlcs)); } } } } } - Ok(None) + Ok((None, timed_out_htlcs)) } /// Called by channelmanager based on chain blocks being disconnected. @@ -3337,11 +3373,11 @@ impl Channel { } /// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created) - fn get_outbound_funding_created_signature(&mut self) -> Result<(Signature, Transaction), ChannelError> { + fn get_outbound_funding_created_signature(&mut self) -> Result { let remote_keys = self.build_remote_transaction_keys()?; let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0; - Ok((self.local_keys.sign_remote_commitment(self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), self.our_to_self_delay, &self.secp_ctx) - .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0, remote_initial_commitment_tx)) + Ok(self.local_keys.sign_remote_commitment(self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), self.our_to_self_delay, &self.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0) } /// Updates channel state with knowledge of the funding transaction's txid/index, and generates @@ -3351,7 +3387,7 @@ impl Channel { /// Note that channel_id changes during this call! /// Do NOT broadcast the funding transaction until after a successful funding_signed call! /// If an Err is returned, it is a ChannelError::Close. - pub fn get_outbound_funding_created(&mut self, funding_txo: OutPoint) -> Result<(msgs::FundingCreated, ChannelMonitor), ChannelError> { + pub fn get_outbound_funding_created(&mut self, funding_txo: OutPoint) -> Result { if !self.channel_outbound { panic!("Tried to create outbound funding_created message on an inbound channel!"); } @@ -3365,7 +3401,7 @@ impl Channel { } self.funding_txo = Some(funding_txo.clone()); - let (our_signature, commitment_tx) = match self.get_outbound_funding_created_signature() { + let our_signature = match self.get_outbound_funding_created_signature() { Ok(res) => res, Err(e) => { log_error!(self, "Got bad signatures: {:?}!", e); @@ -3378,37 +3414,15 @@ impl Channel { // Now that we're past error-generating stuff, update our local state: - let their_pubkeys = self.their_pubkeys.as_ref().unwrap(); - let funding_redeemscript = self.get_funding_redeemscript(); - let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); - macro_rules! create_monitor { - () => { { - let mut channel_monitor = ChannelMonitor::new(self.local_keys.clone(), - &self.shutdown_pubkey, self.our_to_self_delay, - &self.destination_script, (funding_txo, funding_txo_script.clone()), - &their_pubkeys.htlc_basepoint, &their_pubkeys.delayed_payment_basepoint, - self.their_to_self_delay, funding_redeemscript.clone(), self.channel_value_satoshis, - self.get_commitment_transaction_number_obscure_factor(), - self.logger.clone()); - - channel_monitor.provide_latest_remote_commitment_tx_info(&commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); - channel_monitor - } } - } - - self.channel_monitor = Some(create_monitor!()); - let channel_monitor = create_monitor!(); - self.channel_state = ChannelState::FundingCreated as u32; self.channel_id = funding_txo.to_channel_id(); - self.cur_remote_commitment_transaction_number -= 1; - Ok((msgs::FundingCreated { - temporary_channel_id: temporary_channel_id, + Ok(msgs::FundingCreated { + temporary_channel_id, funding_txid: funding_txo.txid, funding_output_index: funding_txo.index, signature: our_signature - }, channel_monitor)) + }) } /// Gets an UnsignedChannelAnnouncement, as well as a signature covering it using our @@ -4385,7 +4399,7 @@ mod tests { value: 10000000, script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint::new(tx.txid(), 0); - let (funding_created_msg, _) = node_a_chan.get_outbound_funding_created(funding_outpoint).unwrap(); + let funding_created_msg = node_a_chan.get_outbound_funding_created(funding_outpoint).unwrap(); let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg).unwrap(); // Node B --> Node A: funding signed