Clarify policy applied in send htlc error msgs
[rust-lightning] / src / ln / channel.rs
index 92469b4fa8d714a1be39aa3e9363685b4ac32f45..07fb3474a5321419db09ca222fd1f10dea6d23df 100644 (file)
@@ -25,7 +25,7 @@ use chain::transaction::OutPoint;
 use chain::keysinterface::{ChannelKeys, KeysInterface};
 use util::transaction_utils;
 use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor};
-use util::logger::Logger;
+use util::logger::{Logger, LogHolder};
 use util::errors::APIError;
 use util::config::{UserConfig,ChannelConfig};
 
@@ -1225,6 +1225,7 @@ impl Channel {
                                        _ => {}
                                }
                        }
+                       log_trace!(self, "Adding HTLC claim to holding_cell! Current state: {}", self.channel_state);
                        self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::ClaimHTLC {
                                payment_preimage: payment_preimage_arg, htlc_id: htlc_id_arg,
                        });
@@ -1238,6 +1239,7 @@ impl Channel {
                                debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to");
                                return Ok((None, Some(self.channel_monitor.clone())));
                        }
+                       log_trace!(self, "Upgrading HTLC {} to LocalRemoved with a Fulfill!", log_bytes!(htlc.payment_hash.0));
                        htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(payment_preimage_arg.clone()));
                }
 
@@ -1588,10 +1590,9 @@ impl Channel {
                if inbound_htlc_count + 1 > OUR_MAX_HTLCS as u32 {
                        return Err(ChannelError::Close("Remote tried to push more than our max accepted HTLCs"));
                }
-               //TODO: Spec is unclear if this is per-direction or in total (I assume per direction):
                // Check our_max_htlc_value_in_flight_msat
                if htlc_inbound_value_msat + msg.amount_msat > Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis) {
-                       return Err(ChannelError::Close("Remote HTLC add would put them over their max HTLC value in flight"));
+                       return Err(ChannelError::Close("Remote HTLC add would put them over our max HTLC value"));
                }
                // Check our_channel_reserve_satoshis (we're getting paid, so they have to at least meet
                // the reserve_satoshis we told them to always have as direct payment so that they lose
@@ -1992,74 +1993,89 @@ impl Channel {
                        self.monitor_pending_order = None;
                }
 
+               log_trace!(self, "Updating HTLCs on receipt of RAA...");
                let mut to_forward_infos = Vec::new();
                let mut revoked_htlcs = Vec::new();
                let mut update_fail_htlcs = Vec::new();
                let mut update_fail_malformed_htlcs = Vec::new();
                let mut require_commitment = false;
                let mut value_to_self_msat_diff: i64 = 0;
-               // We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
-               self.pending_inbound_htlcs.retain(|htlc| {
-                       if let &InboundHTLCState::LocalRemoved(ref reason) = &htlc.state {
-                               if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
-                                       value_to_self_msat_diff += htlc.amount_msat as i64;
-                               }
-                               false
-                       } else { true }
-               });
-               self.pending_outbound_htlcs.retain(|htlc| {
-                       if let OutboundHTLCState::AwaitingRemovedRemoteRevoke = htlc.state {
-                               if let Some(reason) = htlc.fail_reason.clone() { // We really want take() here, but, again, non-mut ref :(
-                                       revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
-                               } else {
-                                       // They fulfilled, so we sent them money
-                                       value_to_self_msat_diff -= htlc.amount_msat as i64;
-                               }
-                               false
-                       } else { true }
-               });
-               for htlc in self.pending_inbound_htlcs.iter_mut() {
-                       let swap = if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) = &htlc.state {
-                               true
-                       } else if let &InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) = &htlc.state {
-                               true
-                       } else { false };
-                       if swap {
-                               let mut state = InboundHTLCState::Committed;
-                               mem::swap(&mut state, &mut htlc.state);
-
-                               if let InboundHTLCState::AwaitingRemoteRevokeToAnnounce(forward_info) = state {
-                                       htlc.state = InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info);
-                                       require_commitment = true;
-                               } else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info) = state {
-                                       match forward_info {
-                                               PendingHTLCStatus::Fail(fail_msg) => {
-                                                       require_commitment = true;
-                                                       match fail_msg {
-                                                               HTLCFailureMsg::Relay(msg) => {
-                                                                       htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(msg.reason.clone()));
-                                                                       update_fail_htlcs.push(msg)
-                                                               },
-                                                               HTLCFailureMsg::Malformed(msg) => {
-                                                                       htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed((msg.sha256_of_onion, msg.failure_code)));
-                                                                       update_fail_malformed_htlcs.push(msg)
-                                                               },
+
+               {
+                       // Take references explicitly so that we can hold multiple references to self.
+                       let pending_inbound_htlcs: &mut Vec<_> = &mut self.pending_inbound_htlcs;
+                       let pending_outbound_htlcs: &mut Vec<_> = &mut self.pending_outbound_htlcs;
+                       let logger = LogHolder { logger: &self.logger };
+
+                       // We really shouldnt have two passes here, but retain gives a non-mutable ref (Rust bug)
+                       pending_inbound_htlcs.retain(|htlc| {
+                               if let &InboundHTLCState::LocalRemoved(ref reason) = &htlc.state {
+                                       log_trace!(logger, " ...removing inbound LocalRemoved {}", log_bytes!(htlc.payment_hash.0));
+                                       if let &InboundHTLCRemovalReason::Fulfill(_) = reason {
+                                               value_to_self_msat_diff += htlc.amount_msat as i64;
+                                       }
+                                       false
+                               } else { true }
+                       });
+                       pending_outbound_htlcs.retain(|htlc| {
+                               if let OutboundHTLCState::AwaitingRemovedRemoteRevoke = htlc.state {
+                                       log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", log_bytes!(htlc.payment_hash.0));
+                                       if let Some(reason) = htlc.fail_reason.clone() { // We really want take() here, but, again, non-mut ref :(
+                                               revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
+                                       } else {
+                                               // They fulfilled, so we sent them money
+                                               value_to_self_msat_diff -= htlc.amount_msat as i64;
+                                       }
+                                       false
+                               } else { true }
+                       });
+                       for htlc in pending_inbound_htlcs.iter_mut() {
+                               let swap = if let &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) = &htlc.state {
+                                       log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to Committed", log_bytes!(htlc.payment_hash.0));
+                                       true
+                               } else if let &InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) = &htlc.state {
+                                       log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", log_bytes!(htlc.payment_hash.0));
+                                       true
+                               } else { false };
+                               if swap {
+                                       let mut state = InboundHTLCState::Committed;
+                                       mem::swap(&mut state, &mut htlc.state);
+
+                                       if let InboundHTLCState::AwaitingRemoteRevokeToAnnounce(forward_info) = state {
+                                               htlc.state = InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info);
+                                               require_commitment = true;
+                                       } else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info) = state {
+                                               match forward_info {
+                                                       PendingHTLCStatus::Fail(fail_msg) => {
+                                                               require_commitment = true;
+                                                               match fail_msg {
+                                                                       HTLCFailureMsg::Relay(msg) => {
+                                                                               htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(msg.reason.clone()));
+                                                                               update_fail_htlcs.push(msg)
+                                                                       },
+                                                                       HTLCFailureMsg::Malformed(msg) => {
+                                                                               htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed((msg.sha256_of_onion, msg.failure_code)));
+                                                                               update_fail_malformed_htlcs.push(msg)
+                                                                       },
+                                                               }
+                                                       },
+                                                       PendingHTLCStatus::Forward(forward_info) => {
+                                                               to_forward_infos.push((forward_info, htlc.htlc_id));
+                                                               htlc.state = InboundHTLCState::Committed;
                                                        }
-                                               },
-                                               PendingHTLCStatus::Forward(forward_info) => {
-                                                       to_forward_infos.push((forward_info, htlc.htlc_id));
-                                                       htlc.state = InboundHTLCState::Committed;
                                                }
                                        }
                                }
                        }
-               }
-               for htlc in self.pending_outbound_htlcs.iter_mut() {
-                       if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
-                               htlc.state = OutboundHTLCState::Committed;
-                       } else if let OutboundHTLCState::AwaitingRemoteRevokeToRemove = htlc.state {
-                               htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke;
-                               require_commitment = true;
+                       for htlc in pending_outbound_htlcs.iter_mut() {
+                               if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
+                                       log_trace!(logger, " ...promoting outbound LocalAnnounced {} to Committed", log_bytes!(htlc.payment_hash.0));
+                                       htlc.state = OutboundHTLCState::Committed;
+                               } else if let OutboundHTLCState::AwaitingRemoteRevokeToRemove = htlc.state {
+                                       log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", log_bytes!(htlc.payment_hash.0));
+                                       htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke;
+                                       require_commitment = true;
+                               }
                        }
                }
                self.value_to_self_msat = (self.value_to_self_msat as i64 + value_to_self_msat_diff) as u64;
@@ -2356,6 +2372,8 @@ impl Channel {
                        }
                }
 
+               log_trace!(self, "Regenerated latest commitment update with {} update_adds, {} update_fulfills, {} update_fails, and {} update_fail_malformeds",
+                               update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len(), update_fail_malformed_htlcs.len());
                msgs::CommitmentUpdate {
                        update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs,
                        update_fee: None, //TODO: We need to support re-generating any update_fees in the last commitment_signed!
@@ -3195,16 +3213,15 @@ impl Channel {
                if outbound_htlc_count + 1 > self.their_max_accepted_htlcs as u32 {
                        return Err(ChannelError::Ignore("Cannot push more than their max accepted HTLCs"));
                }
-               //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 the max HTLC value in flight"));
+                       return Err(ChannelError::Ignore("Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
                }
 
                // 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 + htlc_outbound_value_msat {
-                       return Err(ChannelError::Ignore("Cannot send value that would put us over the reserve value"));
+                       return Err(ChannelError::Ignore("Cannot send value that would put us over their reserve value"));
                }
 
                //TODO: Check cltv_expiry? Do this in channel manager?