Merge pull request #290 from TheBlueMatt/2019-01-monitor-update-handle-fuzz
[rust-lightning] / src / ln / channel.rs
index c6dc595f6591c39f5c4cca8d24fdc556a77494c5..ec5d83bbd3f305fcc33f71513b789a9c07f2ee25 100644 (file)
@@ -1543,14 +1543,23 @@ impl Channel {
                (self.pending_inbound_htlcs.len() as u32, htlc_inbound_value_msat)
        }
 
-       /// Returns (outbound_htlc_count, htlc_outbound_value_msat)
+       /// Returns (outbound_htlc_count, htlc_outbound_value_msat) *including* pending adds in our
+       /// holding cell.
        fn get_outbound_pending_htlc_stats(&self) -> (u32, u64) {
                let mut htlc_outbound_value_msat = 0;
                for ref htlc in self.pending_outbound_htlcs.iter() {
                        htlc_outbound_value_msat += htlc.amount_msat;
                }
 
-               (self.pending_outbound_htlcs.len() as u32, htlc_outbound_value_msat)
+               let mut htlc_outbound_count = self.pending_outbound_htlcs.len();
+               for update in self.holding_cell_htlc_updates.iter() {
+                       if let &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, .. } = update {
+                               htlc_outbound_count += 1;
+                               htlc_outbound_value_msat += amount_msat;
+                       }
+               }
+
+               (htlc_outbound_count as u32, htlc_outbound_value_msat)
        }
 
        pub fn update_add_htlc(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_state: PendingHTLCStatus) -> Result<(), ChannelError> {
@@ -1790,8 +1799,24 @@ impl Channel {
                self.received_commitment_while_awaiting_raa = (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) != 0;
 
                if (self.channel_state & ChannelState::MonitorUpdateFailed as u32) != 0 {
+                       // In case we initially failed monitor updating without requiring a response, we need
+                       // to make sure the RAA gets sent first.
+                       if !self.monitor_pending_commitment_signed {
+                               self.monitor_pending_order = Some(RAACommitmentOrder::RevokeAndACKFirst);
+                       }
                        self.monitor_pending_revoke_and_ack = true;
-                       self.monitor_pending_commitment_signed |= need_our_commitment;
+                       if need_our_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
+                               // If we were going to send a commitment_signed after the RAA, go ahead and do all
+                               // the corresponding HTLC status updates so that get_last_commitment_update
+                               // includes the right HTLCs.
+                               // Note that this generates a monitor update that we ignore! This is OK since we
+                               // won't actually send the commitment_signed that generated the update to the other
+                               // side until the latest monitor has been pulled from us and stored.
+                               self.monitor_pending_commitment_signed = true;
+                               self.send_commitment_no_status_check()?;
+                       }
+                       // TODO: Call maybe_propose_first_closing_signed on restoration (or call it here and
+                       // re-send the message on restoration)
                        return Err(ChannelError::Ignore("Previous monitor update failure prevented generation of RAA"));
                }
 
@@ -1837,6 +1862,14 @@ impl Channel {
                                                        match self.send_htlc(amount_msat, *payment_hash, cltv_expiry, source.clone(), onion_routing_packet.clone()) {
                                                                Ok(update_add_msg_option) => update_add_htlcs.push(update_add_msg_option.unwrap()),
                                                                Err(e) => {
+                                                                       match e {
+                                                                               ChannelError::Ignore(ref msg) => {
+                                                                                       log_info!(self, "Failed to send HTLC with payment_hash {} due to {}", log_bytes!(payment_hash.0), msg);
+                                                                               },
+                                                                               _ => {
+                                                                                       log_info!(self, "Failed to send HTLC with payment_hash {} resulting in a channel closure during holding_cell freeing", log_bytes!(payment_hash.0));
+                                                                               },
+                                                                       }
                                                                        err = Some(e);
                                                                }
                                                        }
@@ -1866,6 +1899,11 @@ impl Channel {
                                        }
                                        if err.is_some() {
                                                self.holding_cell_htlc_updates.push(htlc_update);
+                                               if let Some(ChannelError::Ignore(_)) = err {
+                                                       // If we failed to add the HTLC, but got an Ignore error, we should
+                                                       // still send the new commitment_signed, so reset the err to None.
+                                                       err = None;
+                                               }
                                        }
                                }
                        }
@@ -2039,6 +2077,10 @@ impl Channel {
                        // cells) while we can't update the monitor, so we just return what we have.
                        if require_commitment {
                                self.monitor_pending_commitment_signed = true;
+                               // When the monitor updating is restored we'll call get_last_commitment_update(),
+                               // which does not update state, but we're definitely now awaiting a remote revoke
+                               // before we can step forward any more, so set it here.
+                               self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32;
                        }
                        self.monitor_pending_forwards.append(&mut to_forward_infos);
                        self.monitor_pending_failures.append(&mut revoked_htlcs);
@@ -2421,9 +2463,6 @@ impl Channel {
                                log_debug!(self, "Reconnected channel {} with only lost remote commitment tx", log_bytes!(self.channel_id()));
                        }
 
-                       // If monitor_pending_order is set, it must be CommitmentSigned if we have no RAA
-                       debug_assert!(self.monitor_pending_order != Some(RAACommitmentOrder::RevokeAndACKFirst) || required_revoke.is_some());
-
                        if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 {
                                self.monitor_pending_commitment_signed = true;
                                return Ok((resend_funding_locked, None, None, None, order, shutdown_msg));
@@ -3149,30 +3188,19 @@ impl Channel {
                //TODO: Spec is unclear if this is per-direction or in total (I assume per direction):
                // Check their_max_htlc_value_in_flight_msat
                if htlc_outbound_value_msat + amount_msat > self.their_max_htlc_value_in_flight_msat {
-                       return Err(ChannelError::Ignore("Cannot send value that would put us over our max HTLC value in flight"));
-               }
-
-               let mut holding_cell_outbound_amount_msat = 0;
-               for holding_htlc in self.holding_cell_htlc_updates.iter() {
-                       match holding_htlc {
-                               &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, .. } => {
-                                       holding_cell_outbound_amount_msat += *amount_msat;
-                               }
-                               _ => {}
-                       }
+                       return Err(ChannelError::Ignore("Cannot send value that would put us over the max HTLC value in flight"));
                }
 
                // Check self.their_channel_reserve_satoshis (the amount we must keep as
                // reserve for them to have something to claim if we misbehave)
-               if self.value_to_self_msat < self.their_channel_reserve_satoshis * 1000 + amount_msat + holding_cell_outbound_amount_msat + htlc_outbound_value_msat {
-                       return Err(ChannelError::Ignore("Cannot send value that would put us over our reserve value"));
+               if self.value_to_self_msat < self.their_channel_reserve_satoshis * 1000 + amount_msat + htlc_outbound_value_msat {
+                       return Err(ChannelError::Ignore("Cannot send value that would put us over the reserve value"));
                }
 
                //TODO: Check cltv_expiry? Do this in channel manager?
 
                // Now update local state:
                if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
-                       //TODO: Check the limits *including* other pending holding cell HTLCs!
                        self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::AddHTLC {
                                amount_msat: amount_msat,
                                payment_hash: payment_hash,