]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Close channels on Err returns inside the same channel_state lock
authorMatt Corallo <git@bluematt.me>
Mon, 19 Nov 2018 03:01:32 +0000 (22:01 -0500)
committerMatt Corallo <git@bluematt.me>
Fri, 23 Nov 2018 04:57:54 +0000 (23:57 -0500)
If we never accessed channels for a peer outside of a message
handler for that peer then this wouldn't be a problem since message
handlers are required to be serialized per-peer. However, that
isn't the world we live in - we may want to forward payments or we
may get a send_payment call.

src/ln/channelmanager.rs

index d920825cb5e1e8facd44c6340ed9fae620b676fd..9c6a93b63f3697b7aad2a5537448d187f907e6f6 100644 (file)
@@ -133,9 +133,12 @@ mod channel_held_info {
 }
 pub(super) use self::channel_held_info::*;
 
+type ShutdownResult = (Vec<Transaction>, Vec<(HTLCSource, [u8; 32])>);
+
 struct MsgHandleErrInternal {
        err: msgs::HandleError,
        needs_channel_force_close: bool,
+       shutdown_finish: Option<(ShutdownResult, Option<msgs::ChannelUpdate>)>,
 }
 impl MsgHandleErrInternal {
        #[inline]
@@ -151,6 +154,7 @@ impl MsgHandleErrInternal {
                                }),
                        },
                        needs_channel_force_close: false,
+                       shutdown_finish: None,
                }
        }
        #[inline]
@@ -166,11 +170,28 @@ impl MsgHandleErrInternal {
                                }),
                        },
                        needs_channel_force_close: true,
+                       shutdown_finish: None,
                }
        }
        #[inline]
        fn from_no_close(err: msgs::HandleError) -> Self {
-               Self { err, needs_channel_force_close: false }
+               Self { err, needs_channel_force_close: false, shutdown_finish: None }
+       }
+       #[inline]
+       fn from_finish_shutdown(err: &'static str, channel_id: [u8; 32], shutdown_res: ShutdownResult, channel_update: Option<msgs::ChannelUpdate>) -> Self {
+               Self {
+                       err: HandleError {
+                               err,
+                               action: Some(msgs::ErrorAction::SendErrorMessage {
+                                       msg: msgs::ErrorMessage {
+                                               channel_id,
+                                               data: err.to_string()
+                                       },
+                               }),
+                       },
+                       needs_channel_force_close: false,
+                       shutdown_finish: Some((shutdown_res, channel_update)),
+               }
        }
        #[inline]
        fn from_chan_no_close(err: ChannelError, channel_id: [u8; 32]) -> Self {
@@ -191,6 +212,7 @@ impl MsgHandleErrInternal {
                                },
                        },
                        needs_channel_force_close: false,
+                       shutdown_finish: None,
                }
        }
        #[inline]
@@ -212,6 +234,7 @@ impl MsgHandleErrInternal {
                                },
                        },
                        needs_channel_force_close: true,
+                       shutdown_finish: None,
                }
        }
 }
@@ -404,7 +427,7 @@ macro_rules! handle_error {
        ($self: ident, $internal: expr, $their_node_id: expr) => {
                match $internal {
                        Ok(msg) => Ok(msg),
-                       Err(MsgHandleErrInternal { err, needs_channel_force_close }) => {
+                       Err(MsgHandleErrInternal { err, needs_channel_force_close, shutdown_finish }) => {
                                if needs_channel_force_close {
                                        match &err.action {
                                                &Some(msgs::ErrorAction::DisconnectPeer { msg: Some(ref msg) }) => {
@@ -426,12 +449,39 @@ macro_rules! handle_error {
                                                &None => {},
                                        }
                                }
+                               if let Some((shutdown_res, update_option)) = shutdown_finish {
+                                       $self.finish_force_close_channel(shutdown_res);
+                                       if let Some(update) = update_option {
+                                               let mut channel_state = $self.channel_state.lock().unwrap();
+                                               channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
+                                                       msg: update
+                                               });
+                                       }
+                               }
                                Err(err)
                        },
                }
        }
 }
 
+macro_rules! try_chan_entry {
+       ($self: ident, $res: expr, $channel_state: expr, $entry: expr) => {
+               match $res {
+                       Ok(res) => res,
+                       Err(ChannelError::Ignore(msg)) => {
+                               return Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), $entry.key().clone()))
+                       },
+                       Err(ChannelError::Close(msg)) => {
+                               let (channel_id, mut chan) = $entry.remove_entry();
+                               if let Some(short_id) = chan.get_short_channel_id() {
+                                       $channel_state.short_to_id.remove(&short_id);
+                               }
+                               return Err(MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, chan.force_shutdown(), $self.get_channel_update(&chan).ok()))
+                       },
+               }
+       }
+}
+
 impl ChannelManager {
        /// Constructs a new ChannelManager to hold several channels and route between them.
        ///
@@ -605,7 +655,7 @@ impl ChannelManager {
        }
 
        #[inline]
-       fn finish_force_close_channel(&self, shutdown_res: (Vec<Transaction>, Vec<(HTLCSource, [u8; 32])>)) {
+       fn finish_force_close_channel(&self, shutdown_res: ShutdownResult) {
                let (local_txn, mut failed_htlcs) = shutdown_res;
                for htlc_source in failed_htlcs.drain(..) {
                        // unknown_next_peer...I dunno who that is anymore....
@@ -1748,19 +1798,19 @@ impl ChannelManager {
 
        fn internal_accept_channel(&self, their_node_id: &PublicKey, msg: &msgs::AcceptChannel) -> Result<(), MsgHandleErrInternal> {
                let (value, output_script, user_id) = {
-                       let mut channel_state = self.channel_state.lock().unwrap();
-                       match channel_state.by_id.get_mut(&msg.temporary_channel_id) {
-                               Some(chan) => {
-                                       if chan.get_their_node_id() != *their_node_id {
+                       let mut channel_lock = self.channel_state.lock().unwrap();
+                       let channel_state = channel_lock.borrow_parts();
+                       match channel_state.by_id.entry(msg.temporary_channel_id) {
+                               hash_map::Entry::Occupied(mut chan) => {
+                                       if chan.get().get_their_node_id() != *their_node_id {
                                                //TODO: see issue #153, need a consistent behavior on obnoxious behavior from random node
                                                return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.temporary_channel_id));
                                        }
-                                       chan.accept_channel(&msg, &self.default_configuration)
-                                               .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.temporary_channel_id))?;
-                                       (chan.get_value_satoshis(), chan.get_funding_redeemscript().to_v0_p2wsh(), chan.get_user_id())
+                                       try_chan_entry!(self, chan.get_mut().accept_channel(&msg, &self.default_configuration), channel_state, chan);
+                                       (chan.get().get_value_satoshis(), chan.get().get_funding_redeemscript().to_v0_p2wsh(), chan.get().get_user_id())
                                },
                                //TODO: same as above
-                               None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.temporary_channel_id))
+                               hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.temporary_channel_id))
                        }
                };
                let mut pending_events = self.pending_events.lock().unwrap();
@@ -1774,22 +1824,16 @@ impl ChannelManager {
        }
 
        fn internal_funding_created(&self, their_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> {
-               let (chan, funding_msg, monitor_update) = {
-                       let mut channel_state = self.channel_state.lock().unwrap();
+               let ((funding_msg, monitor_update), chan) = {
+                       let mut channel_lock = self.channel_state.lock().unwrap();
+                       let channel_state = channel_lock.borrow_parts();
                        match channel_state.by_id.entry(msg.temporary_channel_id.clone()) {
                                hash_map::Entry::Occupied(mut chan) => {
                                        if chan.get().get_their_node_id() != *their_node_id {
                                                //TODO: here and below MsgHandleErrInternal, #153 case
                                                return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.temporary_channel_id));
                                        }
-                                       match chan.get_mut().funding_created(msg) {
-                                               Ok((funding_msg, monitor_update)) => {
-                                                       (chan.remove(), funding_msg, monitor_update)
-                                               },
-                                               Err(e) => {
-                                                       return Err(e).map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.temporary_channel_id))
-                                               }
-                                       }
+                                       (try_chan_entry!(self, chan.get_mut().funding_created(msg), channel_state, chan), chan.remove())
                                },
                                hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.temporary_channel_id))
                        }
@@ -1818,20 +1862,21 @@ impl ChannelManager {
 
        fn internal_funding_signed(&self, their_node_id: &PublicKey, msg: &msgs::FundingSigned) -> Result<(), MsgHandleErrInternal> {
                let (funding_txo, user_id) = {
-                       let mut channel_state = self.channel_state.lock().unwrap();
-                       match channel_state.by_id.get_mut(&msg.channel_id) {
-                               Some(chan) => {
-                                       if chan.get_their_node_id() != *their_node_id {
+                       let mut channel_lock = self.channel_state.lock().unwrap();
+                       let channel_state = channel_lock.borrow_parts();
+                       match channel_state.by_id.entry(msg.channel_id) {
+                               hash_map::Entry::Occupied(mut chan) => {
+                                       if chan.get().get_their_node_id() != *their_node_id {
                                                //TODO: here and below MsgHandleErrInternal, #153 case
                                                return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                        }
-                                       let chan_monitor = chan.funding_signed(&msg).map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
+                                       let chan_monitor = try_chan_entry!(self, chan.get_mut().funding_signed(&msg), channel_state, chan);
                                        if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
                                                unimplemented!();
                                        }
-                                       (chan.get_funding_txo().unwrap(), chan.get_user_id())
+                                       (chan.get().get_funding_txo().unwrap(), chan.get().get_user_id())
                                },
-                               None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                               hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                        }
                };
                let mut pending_events = self.pending_events.lock().unwrap();
@@ -1845,15 +1890,14 @@ impl ChannelManager {
        fn internal_funding_locked(&self, their_node_id: &PublicKey, msg: &msgs::FundingLocked) -> Result<(), MsgHandleErrInternal> {
                let mut channel_state_lock = self.channel_state.lock().unwrap();
                let channel_state = channel_state_lock.borrow_parts();
-               match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
+               match channel_state.by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               if chan.get().get_their_node_id() != *their_node_id {
                                        //TODO: here and below MsgHandleErrInternal, #153 case
                                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                }
-                               chan.funding_locked(&msg)
-                                       .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
-                               if let Some(announcement_sigs) = self.get_announcement_sigs(chan) {
+                               try_chan_entry!(self, chan.get_mut().funding_locked(&msg), channel_state, chan);
+                               if let Some(announcement_sigs) = self.get_announcement_sigs(chan.get()) {
                                        channel_state.pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
                                                node_id: their_node_id.clone(),
                                                msg: announcement_sigs,
@@ -1861,7 +1905,7 @@ impl ChannelManager {
                                }
                                Ok(())
                        },
-                       None => Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       hash_map::Entry::Vacant(_) => Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                }
        }
 
@@ -1876,7 +1920,7 @@ impl ChannelManager {
                                                //TODO: here and below MsgHandleErrInternal, #153 case
                                                return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                        }
-                                       let (shutdown, closing_signed, dropped_htlcs) = chan_entry.get_mut().shutdown(&*self.fee_estimator, &msg).map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
+                                       let (shutdown, closing_signed, dropped_htlcs) = try_chan_entry!(self, chan_entry.get_mut().shutdown(&*self.fee_estimator, &msg), channel_state, chan_entry);
                                        if let Some(msg) = shutdown {
                                                channel_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown {
                                                        node_id: their_node_id.clone(),
@@ -1924,7 +1968,7 @@ impl ChannelManager {
                                                //TODO: here and below MsgHandleErrInternal, #153 case
                                                return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                        }
-                                       let (closing_signed, tx) = chan_entry.get_mut().closing_signed(&*self.fee_estimator, &msg).map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
+                                       let (closing_signed, tx) = try_chan_entry!(self, chan_entry.get_mut().closing_signed(&*self.fee_estimator, &msg), channel_state, chan_entry);
                                        if let Some(msg) = closing_signed {
                                                channel_state.pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
                                                        node_id: their_node_id.clone(),
@@ -1973,18 +2017,18 @@ impl ChannelManager {
                let (mut pending_forward_info, mut channel_state_lock) = self.decode_update_add_htlc_onion(msg);
                let channel_state = channel_state_lock.borrow_parts();
 
-               match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
+               match channel_state.by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               if chan.get().get_their_node_id() != *their_node_id {
                                        //TODO: here MsgHandleErrInternal, #153 case
                                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                }
-                               if !chan.is_usable() {
+                               if !chan.get().is_usable() {
                                        // If the update_add is completely bogus, the call will Err and we will close,
                                        // but if we've sent a shutdown and they haven't acknowledged it yet, we just
                                        // want to reject the new HTLC and fail it backwards instead of forwarding.
                                        if let PendingHTLCStatus::Forward(PendingForwardHTLCInfo { incoming_shared_secret, .. }) = pending_forward_info {
-                                               let chan_update = self.get_channel_update(chan);
+                                               let chan_update = self.get_channel_update(chan.get());
                                                pending_forward_info = PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
                                                        channel_id: msg.channel_id,
                                                        htlc_id: msg.htlc_id,
@@ -2001,26 +2045,29 @@ impl ChannelManager {
                                                }));
                                        }
                                }
-                               chan.update_add_htlc(&msg, pending_forward_info).map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))
+                               try_chan_entry!(self, chan.get_mut().update_add_htlc(&msg, pending_forward_info), channel_state, chan);
                        },
-                       None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                }
+               Ok(())
        }
 
        fn internal_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> {
-               let mut channel_state = self.channel_state.lock().unwrap();
-               let htlc_source = match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
-                                       //TODO: here and below MsgHandleErrInternal, #153 case
-                                       return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
-                               }
-                               chan.update_fulfill_htlc(&msg)
-                                       .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?
-                       },
-                       None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+               let mut channel_lock = self.channel_state.lock().unwrap();
+               let htlc_source = {
+                       let channel_state = channel_lock.borrow_parts();
+                       match channel_state.by_id.entry(msg.channel_id) {
+                               hash_map::Entry::Occupied(mut chan) => {
+                                       if chan.get().get_their_node_id() != *their_node_id {
+                                               //TODO: here and below MsgHandleErrInternal, #153 case
+                                               return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
+                                       }
+                                       try_chan_entry!(self, chan.get_mut().update_fulfill_htlc(&msg), channel_state, chan)
+                               },
+                               hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       }
                };
-               self.claim_funds_internal(channel_state, htlc_source, msg.payment_preimage.clone());
+               self.claim_funds_internal(channel_lock, htlc_source, msg.payment_preimage.clone());
                Ok(())
        }
 
@@ -2222,51 +2269,51 @@ impl ChannelManager {
        }
 
        fn internal_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<(), MsgHandleErrInternal> {
-               let mut channel_state = self.channel_state.lock().unwrap();
-               match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
+               let mut channel_lock = self.channel_state.lock().unwrap();
+               let channel_state = channel_lock.borrow_parts();
+               match channel_state.by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               if chan.get().get_their_node_id() != *their_node_id {
                                        //TODO: here and below MsgHandleErrInternal, #153 case
                                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                }
-                               chan.update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() })
-                                       .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))
+                               try_chan_entry!(self, chan.get_mut().update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() }), channel_state, chan);
                        },
-                       None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
-               }?;
+                       hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+               }
                Ok(())
        }
 
        fn internal_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), MsgHandleErrInternal> {
-               let mut channel_state = self.channel_state.lock().unwrap();
-               match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
+               let mut channel_lock = self.channel_state.lock().unwrap();
+               let channel_state = channel_lock.borrow_parts();
+               match channel_state.by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               if chan.get().get_their_node_id() != *their_node_id {
                                        //TODO: here and below MsgHandleErrInternal, #153 case
                                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                }
                                if (msg.failure_code & 0x8000) == 0 {
                                        return Err(MsgHandleErrInternal::send_err_msg_close_chan("Got update_fail_malformed_htlc with BADONION not set", msg.channel_id));
                                }
-                               chan.update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() })
-                                       .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
+                               try_chan_entry!(self, chan.get_mut().update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() }), channel_state, chan);
                                Ok(())
                        },
-                       None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                }
        }
 
        fn internal_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(), MsgHandleErrInternal> {
                let mut channel_state_lock = self.channel_state.lock().unwrap();
                let channel_state = channel_state_lock.borrow_parts();
-               match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
+               match channel_state.by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               if chan.get().get_their_node_id() != *their_node_id {
                                        //TODO: here and below MsgHandleErrInternal, #153 case
                                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                }
-                               let (revoke_and_ack, commitment_signed, closing_signed, chan_monitor) = chan.commitment_signed(&msg, &*self.fee_estimator)
-                                       .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
+                               let (revoke_and_ack, commitment_signed, closing_signed, chan_monitor) =
+                                       try_chan_entry!(self, chan.get_mut().commitment_signed(&msg, &*self.fee_estimator), channel_state, chan);
                                if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
                                        unimplemented!();
                                }
@@ -2295,7 +2342,7 @@ impl ChannelManager {
                                }
                                Ok(())
                        },
-                       None => Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                }
        }
 
@@ -2336,14 +2383,14 @@ impl ChannelManager {
                let (pending_forwards, mut pending_failures, short_channel_id) = {
                        let mut channel_state_lock = self.channel_state.lock().unwrap();
                        let channel_state = channel_state_lock.borrow_parts();
-                       match channel_state.by_id.get_mut(&msg.channel_id) {
-                               Some(chan) => {
-                                       if chan.get_their_node_id() != *their_node_id {
+                       match channel_state.by_id.entry(msg.channel_id) {
+                               hash_map::Entry::Occupied(mut chan) => {
+                                       if chan.get().get_their_node_id() != *their_node_id {
                                                //TODO: here and below MsgHandleErrInternal, #153 case
                                                return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                        }
-                                       let (commitment_update, pending_forwards, pending_failures, closing_signed, chan_monitor) = chan.revoke_and_ack(&msg, &*self.fee_estimator)
-                                                       .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
+                                       let (commitment_update, pending_forwards, pending_failures, closing_signed, chan_monitor) =
+                                               try_chan_entry!(self, chan.get_mut().revoke_and_ack(&msg, &*self.fee_estimator), channel_state, chan);
                                        if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
                                                unimplemented!();
                                        }
@@ -2359,9 +2406,9 @@ impl ChannelManager {
                                                        msg,
                                                });
                                        }
-                                       (pending_forwards, pending_failures, chan.get_short_channel_id().expect("RAA should only work on a short-id-available channel"))
+                                       (pending_forwards, pending_failures, chan.get().get_short_channel_id().expect("RAA should only work on a short-id-available channel"))
                                },
-                               None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                               hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                        }
                };
                for failure in pending_failures.drain(..) {
@@ -2373,35 +2420,37 @@ impl ChannelManager {
        }
 
        fn internal_update_fee(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFee) -> Result<(), MsgHandleErrInternal> {
-               let mut channel_state = self.channel_state.lock().unwrap();
-               match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
+               let mut channel_lock = self.channel_state.lock().unwrap();
+               let channel_state = channel_lock.borrow_parts();
+               match channel_state.by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               if chan.get().get_their_node_id() != *their_node_id {
                                        //TODO: here and below MsgHandleErrInternal, #153 case
                                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                }
-                               chan.update_fee(&*self.fee_estimator, &msg).map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))
+                               try_chan_entry!(self, chan.get_mut().update_fee(&*self.fee_estimator, &msg), channel_state, chan);
                        },
-                       None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                }
+               Ok(())
        }
 
        fn internal_announcement_signatures(&self, their_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures) -> Result<(), MsgHandleErrInternal> {
                let mut channel_state_lock = self.channel_state.lock().unwrap();
                let channel_state = channel_state_lock.borrow_parts();
 
-               match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
+               match channel_state.by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               if chan.get().get_their_node_id() != *their_node_id {
                                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                }
-                               if !chan.is_usable() {
+                               if !chan.get().is_usable() {
                                        return Err(MsgHandleErrInternal::from_no_close(HandleError{err: "Got an announcement_signatures before we were ready for it", action: Some(msgs::ErrorAction::IgnoreError)}));
                                }
 
                                let our_node_id = self.get_our_node_id();
-                               let (announcement, our_bitcoin_sig) = chan.get_channel_announcement(our_node_id.clone(), self.genesis_hash.clone())
-                                       .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
+                               let (announcement, our_bitcoin_sig) =
+                                       try_chan_entry!(self, chan.get_mut().get_channel_announcement(our_node_id.clone(), self.genesis_hash.clone()), channel_state, chan);
 
                                let were_node_one = announcement.node_id_1 == our_node_id;
                                let msghash = Message::from_slice(&Sha256dHash::from_data(&announcement.encode()[..])[..]).unwrap();
@@ -2419,10 +2468,10 @@ impl ChannelManager {
                                                bitcoin_signature_2: if were_node_one { msg.bitcoin_signature } else { our_bitcoin_sig },
                                                contents: announcement,
                                        },
-                                       update_msg: self.get_channel_update(chan).unwrap(), // can only fail if we're not in a ready state
+                                       update_msg: self.get_channel_update(chan.get()).unwrap(), // can only fail if we're not in a ready state
                                });
                        },
-                       None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                }
                Ok(())
        }
@@ -2431,13 +2480,13 @@ impl ChannelManager {
                let mut channel_state_lock = self.channel_state.lock().unwrap();
                let channel_state = channel_state_lock.borrow_parts();
 
-               match channel_state.by_id.get_mut(&msg.channel_id) {
-                       Some(chan) => {
-                               if chan.get_their_node_id() != *their_node_id {
+               match channel_state.by_id.entry(msg.channel_id) {
+                       hash_map::Entry::Occupied(mut chan) => {
+                               if chan.get().get_their_node_id() != *their_node_id {
                                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
                                }
-                               let (funding_locked, revoke_and_ack, commitment_update, channel_monitor, order, shutdown) = chan.channel_reestablish(msg)
-                                       .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.channel_id))?;
+                               let (funding_locked, revoke_and_ack, commitment_update, channel_monitor, order, shutdown) =
+                                       try_chan_entry!(self, chan.get_mut().channel_reestablish(msg), channel_state, chan);
                                if let Some(monitor) = channel_monitor {
                                        if let Err(_e) = self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor) {
                                                unimplemented!();
@@ -2483,7 +2532,7 @@ impl ChannelManager {
                                }
                                Ok(())
                        },
-                       None => Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
                }
        }