+ }, our_commitment_signed, monitor_update))
+ }
+
+ /// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them
+ /// fulfilling or failing the last pending HTLC)
+ fn free_holding_cell_htlcs(&mut self) -> Result<Option<(msgs::CommitmentUpdate, ChannelMonitor)>, HandleError> {
+ if self.holding_cell_htlc_updates.len() != 0 {
+ let mut htlc_updates = Vec::new();
+ mem::swap(&mut htlc_updates, &mut self.holding_cell_htlc_updates);
+ let mut update_add_htlcs = Vec::with_capacity(htlc_updates.len());
+ let mut update_fulfill_htlcs = Vec::with_capacity(htlc_updates.len());
+ let mut update_fail_htlcs = Vec::with_capacity(htlc_updates.len());
+ let mut err = None;
+ for htlc_update in htlc_updates.drain(..) {
+ // Note that this *can* fail, though it should be due to rather-rare conditions on
+ // fee races with adding too many outputs which push our total payments just over
+ // the limit. In case its less rare than I anticipate, we may want to revisit
+ // handling this case better and maybe fufilling some of the HTLCs while attempting
+ // to rebalance channels.
+ if err.is_some() { // We're back to AwaitingRemoteRevoke (or are about to fail the channel)
+ self.holding_cell_htlc_updates.push(htlc_update);
+ } else {
+ match &htlc_update {
+ &HTLCUpdateAwaitingACK::AddHTLC {amount_msat, cltv_expiry, payment_hash, ref onion_routing_packet, ..} => {
+ match self.send_htlc(amount_msat, payment_hash, cltv_expiry, onion_routing_packet.clone()) {
+ Ok(update_add_msg_option) => update_add_htlcs.push(update_add_msg_option.unwrap()),
+ Err(e) => {
+ err = Some(e);
+ }
+ }
+ },
+ &HTLCUpdateAwaitingACK::ClaimHTLC { payment_preimage, .. } => {
+ match self.get_update_fulfill_htlc(payment_preimage) {
+ Ok(update_fulfill_msg_option) => update_fulfill_htlcs.push(update_fulfill_msg_option.unwrap().0),
+ Err(e) => {
+ err = Some(e);
+ }
+ }
+ },
+ &HTLCUpdateAwaitingACK::FailHTLC { payment_hash, ref err_packet } => {
+ match self.get_update_fail_htlc(&payment_hash, err_packet.clone()) {
+ Ok(update_fail_msg_option) => update_fail_htlcs.push(update_fail_msg_option.unwrap()),
+ Err(e) => {
+ err = Some(e);
+ }
+ }
+ },
+ }
+ if err.is_some() {
+ self.holding_cell_htlc_updates.push(htlc_update);
+ }
+ }
+ }
+ //TODO: Need to examine the type of err - if its a fee issue or similar we may want to
+ //fail it back the route, if its a temporary issue we can ignore it...
+ match err {
+ None => {
+ let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?;
+ Ok(Some((msgs::CommitmentUpdate {
+ update_add_htlcs,
+ update_fulfill_htlcs,
+ update_fail_htlcs,
+ commitment_signed,
+ }, monitor_update)))
+ },
+ Some(e) => Err(e)
+ }
+ } else {
+ Ok(None)
+ }