X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=2b29fb5f02bafebc9141f76870ba2378b07b1223;hb=96d17ee7370af557330ccd8618648e82a6899ac0;hp=c2ec53fb353d8fad52d1e6d8d5074ed361546752;hpb=787644d795193eaae3041078030efebca1a5687c;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index c2ec53fb..2b29fb5f 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -751,7 +751,7 @@ impl Channel { /// generated by the peer which proposed adding the HTLCs, and thus we need to understand both /// which peer generated this transaction and "to whom" this transaction flows. #[inline] - fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, Vec) { + fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, Vec, Vec<([u8; 32], &HTLCSource, Option)>) { let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (INITIAL_COMMITMENT_NUMBER - commitment_number); let txins = { @@ -765,7 +765,8 @@ impl Channel { ins }; - let mut txouts: Vec<(TxOut, Option)> = Vec::with_capacity(self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len() + 2); + let mut txouts: Vec<(TxOut, Option<(HTLCOutputInCommitment, Option<&HTLCSource>)>)> = Vec::with_capacity(self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len() + 2); + let mut unincluded_htlc_sources: Vec<([u8; 32], &HTLCSource, Option)> = Vec::new(); let dust_limit_satoshis = if local { self.our_dust_limit_satoshis } else { self.their_dust_limit_satoshis }; let mut remote_htlc_total_msat = 0; @@ -773,14 +774,18 @@ impl Channel { let mut value_to_self_msat_offset = 0; macro_rules! add_htlc_output { - ($htlc: expr, $outbound: expr) => { + ($htlc: expr, $outbound: expr, $source: expr) => { if $outbound == local { // "offered HTLC output" if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000) { let htlc_in_tx = get_htlc_in_commitment!($htlc, true); txouts.push((TxOut { script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(), value: $htlc.amount_msat / 1000 - }, Some(htlc_in_tx))); + }, Some((htlc_in_tx, $source)))); + } else { + if let Some(source) = $source { + unincluded_htlc_sources.push(($htlc.payment_hash, source, None)); + } } } else { if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) { @@ -788,7 +793,11 @@ impl Channel { txouts.push((TxOut { // "received HTLC output" script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(), value: $htlc.amount_msat / 1000 - }, Some(htlc_in_tx))); + }, Some((htlc_in_tx, $source)))); + } else { + if let Some(source) = $source { + unincluded_htlc_sources.push(($htlc.payment_hash, source, None)); + } } } } @@ -804,7 +813,7 @@ impl Channel { }; if include { - add_htlc_output!(htlc, false); + add_htlc_output!(htlc, false, None); remote_htlc_total_msat += htlc.amount_msat; } else { match &htlc.state { @@ -830,7 +839,7 @@ impl Channel { }; if include { - add_htlc_output!(htlc, true); + add_htlc_output!(htlc, true, Some(&htlc.source)); local_htlc_total_msat += htlc.amount_msat; } else { match htlc.state { @@ -901,21 +910,26 @@ impl Channel { transaction_utils::sort_outputs(&mut txouts); let mut outputs: Vec = Vec::with_capacity(txouts.len()); - let mut htlcs_used: Vec = Vec::with_capacity(txouts.len()); + let mut htlcs_included: Vec = Vec::with_capacity(txouts.len()); + let mut htlc_sources: Vec<([u8; 32], &HTLCSource, Option)> = Vec::with_capacity(txouts.len() + unincluded_htlc_sources.len()); for (idx, out) in txouts.drain(..).enumerate() { outputs.push(out.0); - if let Some(out_htlc) = out.1 { - htlcs_used.push(out_htlc); - htlcs_used.last_mut().unwrap().transaction_output_index = idx as u32; + if let Some((mut htlc, source_option)) = out.1 { + htlc.transaction_output_index = idx as u32; + if let Some(source) = source_option { + htlc_sources.push((htlc.payment_hash, source, Some(idx as u32))); + } + htlcs_included.push(htlc); } } + htlc_sources.append(&mut unincluded_htlc_sources); (Transaction { version: 2, lock_time: ((0x20 as u32) << 8*3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32), input: txins, output: outputs, - }, htlcs_used) + }, htlcs_included, htlc_sources) } #[inline] @@ -1136,21 +1150,33 @@ impl Channel { let mut payment_hash_calc = [0; 32]; sha.result(&mut payment_hash_calc); + // ChannelManager may generate duplicate claims/fails due to HTLC update events from + // on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop + // these, but for now we just have to treat them as normal. + let mut pending_idx = std::usize::MAX; for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() { if htlc.htlc_id == htlc_id_arg { assert_eq!(htlc.payment_hash, payment_hash_calc); - if let InboundHTLCState::Committed = htlc.state { - } else { - debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); - // Don't return in release mode here so that we can update channel_monitor + match htlc.state { + InboundHTLCState::Committed => {}, + InboundHTLCState::LocalRemoved(ref reason) => { + if let &InboundHTLCRemovalReason::Fulfill(_) = reason { + } else { + log_warn!(self, "Have preimage and want to fulfill HTLC with payment hash {} we already failed against channel {}", log_bytes!(htlc.payment_hash), log_bytes!(self.channel_id())); + } + return Ok((None, None)); + }, + _ => { + debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); + // Don't return in release mode here so that we can update channel_monitor + } } pending_idx = idx; break; } } if pending_idx == std::usize::MAX { - debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID"); return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID")); } @@ -1165,15 +1191,14 @@ impl Channel { match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - debug_assert!(false, "Tried to fulfill an HTLC we already had a pending fulfill for"); return Ok((None, None)); } }, &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - debug_assert!(false, "Tried to fulfill an HTLC we already had a holding-cell failure on"); - // Return the new channel monitor in a last-ditch effort to hit the - // chain and claim the funds + log_warn!(self, "Have preimage and want to fulfill HTLC with pending failure against channel {}", log_bytes!(self.channel_id())); + // TODO: We may actually be able to switch to a fulfill here, though its + // rare enough it may not be worth the complexity burden. return Ok((None, Some(self.channel_monitor.clone()))); } }, @@ -1223,19 +1248,27 @@ impl Channel { } assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0); + // ChannelManager may generate duplicate claims/fails due to HTLC update events from + // on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop + // these, but for now we just have to treat them as normal. + let mut pending_idx = std::usize::MAX; for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() { if htlc.htlc_id == htlc_id_arg { - if let InboundHTLCState::Committed = htlc.state { - } else { - debug_assert!(false, "Have an inbound HTLC we tried to fail before it was fully committed to"); - return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID")); + match htlc.state { + InboundHTLCState::Committed => {}, + InboundHTLCState::LocalRemoved(_) => { + return Ok(None); + }, + _ => { + debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); + return Err(ChannelError::Ignore("Unable to find a pending HTLC which matchd the given HTLC ID")); + } } pending_idx = idx; } } if pending_idx == std::usize::MAX { - debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID"); return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID")); } @@ -1245,14 +1278,12 @@ impl Channel { match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID"); return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID")); } }, &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - debug_assert!(false, "Tried to fail an HTLC that we already had a pending failure for"); - return Ok(None); + return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID")); } }, _ => {} @@ -1424,9 +1455,9 @@ impl Channel { // Now that we're past error-generating stuff, update our local state: - self.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()); + self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); self.last_local_commitment_txn = vec![local_initial_commitment_tx.clone()]; - self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new()); + self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new(), Vec::new()); self.channel_state = ChannelState::FundingSent as u32; self.channel_id = funding_txo.to_channel_id(); self.cur_remote_commitment_transaction_number -= 1; @@ -1463,7 +1494,7 @@ impl Channel { secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid funding_signed signature from peer"); self.sign_commitment_transaction(&mut local_initial_commitment_tx, &msg.signature); - self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new()); + self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new(), Vec::new()); self.last_local_commitment_txn = vec![local_initial_commitment_tx]; self.channel_state = ChannelState::FundingSent as u32; self.cur_local_commitment_transaction_number -= 1; @@ -1668,7 +1699,11 @@ impl Channel { self.feerate_per_kw }; - let mut local_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, feerate_per_kw); + let mut local_commitment_tx = { + let mut commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, feerate_per_kw); + let htlcs_cloned: Vec<_> = commitment_tx.2.drain(..).map(|htlc_source| (htlc_source.0, htlc_source.1.clone(), htlc_source.2)).collect(); + (commitment_tx.0, commitment_tx.1, htlcs_cloned) + }; let local_commitment_txid = local_commitment_tx.0.txid(); let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap(); secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid commitment tx signature from peer"); @@ -1692,19 +1727,19 @@ impl Channel { new_local_commitment_txn.push(local_commitment_tx.0.clone()); let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.1.len()); - for (idx, ref htlc) in local_commitment_tx.1.iter().enumerate() { - let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, htlc, true, &local_keys, feerate_per_kw); + for (idx, htlc) in local_commitment_tx.1.drain(..).enumerate() { + let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys); let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap(); secp_check!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer"); let htlc_sig = if htlc.offered { - let htlc_sig = self.sign_htlc_transaction(&mut htlc_tx, &msg.htlc_signatures[idx], &None, htlc, &local_keys)?; + let htlc_sig = self.sign_htlc_transaction(&mut htlc_tx, &msg.htlc_signatures[idx], &None, &htlc, &local_keys)?; new_local_commitment_txn.push(htlc_tx); htlc_sig } else { - self.create_htlc_tx_signature(&htlc_tx, htlc, &local_keys)?.1 + self.create_htlc_tx_signature(&htlc_tx, &htlc, &local_keys)?.1 }; - htlcs_and_sigs.push(((*htlc).clone(), msg.htlc_signatures[idx], htlc_sig)); + htlcs_and_sigs.push((htlc, msg.htlc_signatures[idx], htlc_sig)); } let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number - 1)); @@ -1731,7 +1766,7 @@ impl Channel { self.monitor_pending_order = None; } - self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs); + self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs, local_commitment_tx.2); for htlc in self.pending_inbound_htlcs.iter_mut() { let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state { @@ -2410,8 +2445,7 @@ impl Channel { fn maybe_propose_first_closing_signed(&mut self, fee_estimator: &FeeEstimator) -> Option { if !self.channel_outbound || !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() || self.channel_state & (BOTH_SIDES_SHUTDOWN_MASK | ChannelState::AwaitingRemoteRevoke as u32) != BOTH_SIDES_SHUTDOWN_MASK || - self.last_sent_closing_fee.is_some() || - self.cur_remote_commitment_transaction_number != self.cur_local_commitment_transaction_number{ + self.last_sent_closing_fee.is_some() || self.pending_update_fee.is_some() { return None; } @@ -3002,7 +3036,7 @@ impl Channel { let temporary_channel_id = self.channel_id; // Now that we're past error-generating stuff, update our local state: - self.channel_monitor.provide_latest_remote_commitment_tx_info(&commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); + self.channel_monitor.provide_latest_remote_commitment_tx_info(&commitment_tx, Vec::new(), Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); self.channel_state = ChannelState::FundingCreated as u32; self.channel_id = funding_txo.to_channel_id(); self.cur_remote_commitment_transaction_number -= 1; @@ -3227,20 +3261,23 @@ impl Channel { } } - match self.send_commitment_no_state_update() { - Ok((res, remote_commitment_tx)) => { + let (res, remote_commitment_tx, htlcs, htlc_sources) = match self.send_commitment_no_state_update() { + Ok((res, (remote_commitment_tx, htlcs, mut htlc_sources))) => { // Update state now that we've passed all the can-fail calls... - self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx.0, remote_commitment_tx.1, self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); - self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32; - Ok((res, self.channel_monitor.clone())) + let htlc_sources_no_ref = htlc_sources.drain(..).map(|htlc_source| (htlc_source.0, htlc_source.1.clone(), htlc_source.2)).collect(); + (res, remote_commitment_tx, htlcs, htlc_sources_no_ref) }, - Err(e) => Err(e), - } + Err(e) => return Err(e), + }; + + self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx, htlcs, htlc_sources, self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); + self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32; + Ok((res, self.channel_monitor.clone())) } /// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation /// when we shouldn't change HTLC/channel state. - fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec)), ChannelError> { + fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec, Vec<([u8; 32], &HTLCSource, Option)>)), ChannelError> { let funding_script = self.get_funding_redeemscript(); let mut feerate_per_kw = self.feerate_per_kw; @@ -3983,7 +4020,10 @@ mod tests { macro_rules! test_commitment { ( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => { - unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw); + unsigned_tx = { + let res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw); + (res.0, res.1) + }; let their_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap(); let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap(); secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey.unwrap()).unwrap();