X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannelmonitor.rs;h=73ae060df72c10a051bd076a2afd644fa5022fe4;hb=0faf7bb094ef393376ba74439ce4aaf5a236ab47;hp=5415fefec3057c7ec1809fa171864086e6d88742;hpb=f5dc762754b59c475f3b6e7b734e17567545a62d;p=rust-lightning diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index 5415fefe..73ae060d 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -989,9 +989,6 @@ impl ChannelMonitor { self.write(writer, false) } - //TODO: Functions to serialize/deserialize (with different forms depending on which information - //we want to leave out (eg funding_txo, etc). - /// Can only fail if idx is < get_min_seen_secret pub(super) fn get_secret(&self, idx: u64) -> Option<[u8; 32]> { for i in 0..self.old_secrets.len() { @@ -1250,6 +1247,42 @@ impl ChannelMonitor { log_trace!(self, "Got broadcast of non-revoked remote commitment transaction {}", commitment_txid); + // TODO: We really should only fail backwards after our revocation claims have been + // confirmed, but we also need to do more other tracking of in-flight pre-confirm + // on-chain claims, so we can do that at the same time. + macro_rules! check_htlc_fails { + ($txid: expr, $commitment_tx: expr, $id: tt) => { + if let Some(&(_, ref latest_outpoints)) = self.remote_claimable_outpoints.get(&$txid) { + $id: for &(ref payment_hash, ref source, _) in latest_outpoints.iter() { + // Check if the HTLC is present in the commitment transaction that was + // broadcast, but not if it was below the dust limit, which we should + // fail backwards immediately as there is no way for us to learn the + // payment_preimage. + // Note that if the dust limit were allowed to change between + // commitment transactions we'd want to be check whether *any* + // broadcastable commitment transaction has the HTLC in it, but it + // cannot currently change after channel initialization, so we don't + // need to here. + for &(_, ref broadcast_source, ref output_idx) in per_commitment_data.1.iter() { + if output_idx.is_some() && source == broadcast_source { + continue $id; + } + } + log_trace!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of remote commitment transaction", log_bytes!(payment_hash.0), $commitment_tx); + htlc_updated.push(((*source).clone(), None, payment_hash.clone())); + } + } + } + } + if let Storage::Local { ref current_remote_commitment_txid, ref prev_remote_commitment_txid, .. } = self.key_storage { + if let &Some(ref txid) = current_remote_commitment_txid { + check_htlc_fails!(txid, "current", 'current_loop); + } + if let &Some(ref txid) = prev_remote_commitment_txid { + check_htlc_fails!(txid, "previous", 'prev_loop); + } + } + if let Some(revocation_points) = self.their_cur_revocation_points { let revocation_point_option = if revocation_points.0 == commitment_number { Some(&revocation_points.1) } @@ -1410,10 +1443,6 @@ impl ChannelMonitor { output: spend_tx.output[0].clone(), }); txn_to_broadcast.push(spend_tx); - - // TODO: We need to fail back HTLCs that were't included in the broadcast - // commitment transaction, either because they didn't meet dust or because a - // stale (but not yet revoked) commitment transaction was broadcast! } } } @@ -1815,9 +1844,12 @@ impl ChannelMonitor { } if payment_data.is_none() { for htlc_output in $htlc_outputs { - if input.previous_output.vout == htlc_output.transaction_output_index { + if input.previous_output.vout == htlc_output.transaction_output_index && !htlc_output.offered { log_info!(self, "Input spending {}:{} in {} resolves inbound HTLC with timeout from {}", input.previous_output.txid, input.previous_output.vout, tx.txid(), $source); continue 'outer_loop; + } else if input.previous_output.vout == htlc_output.transaction_output_index && tx.lock_time > 0 { + log_info!(self, "Input spending {}:{} in {} resolves offered HTLC with HTLC-timeout from {}", input.previous_output.txid, input.previous_output.vout, tx.txid(), $source); + continue 'outer_loop; } } }