Narrow check_spend_remote_htlc input/output count check.
[rust-lightning] / src / ln / channelmanager.rs
index 333d4257564041dff3becfef7e8b0c61174c3b3d..ba535d007bc0f8c64678a07008ba41ce6af53760 100644 (file)
@@ -1,3 +1,13 @@
+//! The top-level channel management and payment tracking stuff lives here.
+//!
+//! The ChannelManager is the main chunk of logic implementing the lightning protocol and is
+//! responsible for tracking which channels are open, HTLCs are in flight and reestablishing those
+//! upon reconnect to the relevant peer(s).
+//!
+//! It does not manage routing logic (see ln::router for that) nor does it manage constructing
+//! on-chain transactions (it only monitors the chain to watch for any force-closes that might
+//! imply it needs to fail HTLCs/payments/channels it manages).
+
 use bitcoin::blockdata::block::BlockHeader;
 use bitcoin::blockdata::transaction::Transaction;
 use bitcoin::blockdata::constants::genesis_block;
@@ -16,9 +26,10 @@ use ln::channel::{Channel, ChannelKeys};
 use ln::channelmonitor::ManyChannelMonitor;
 use ln::router::{Route,RouteHop};
 use ln::msgs;
-use ln::msgs::{HandleError,ChannelMessageHandler,MsgEncodable,MsgDecodable};
+use ln::msgs::{HandleError,ChannelMessageHandler};
 use util::{byte_utils, events, internal_traits, rng};
 use util::sha2::Sha256;
+use util::ser::{Readable, Writeable};
 use util::chacha20poly1305rfc::ChaCha20;
 use util::logger::Logger;
 use util::errors::APIError;
@@ -32,6 +43,7 @@ use crypto::symmetriccipher::SynchronousStreamCipher;
 use std::{ptr, mem};
 use std::collections::HashMap;
 use std::collections::hash_map;
+use std::io::Cursor;
 use std::sync::{Mutex,MutexGuard,Arc};
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::time::{Instant,Duration};
@@ -78,23 +90,6 @@ mod channel_held_info {
                Fail(HTLCFailureMsg),
        }
 
-       #[cfg(feature = "fuzztarget")]
-       impl PendingHTLCStatus {
-               pub fn dummy() -> Self {
-                       let secp_ctx = ::secp256k1::Secp256k1::signing_only();
-                       PendingHTLCStatus::Forward(PendingForwardHTLCInfo {
-                               onion_packet: None,
-                               incoming_shared_secret: SharedSecret::new(&secp_ctx,
-                                               &::secp256k1::key::PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &[1; 32]).unwrap()),
-                                               &SecretKey::from_slice(&secp_ctx, &[1; 32]).unwrap()),
-                               payment_hash: [0; 32],
-                               short_channel_id: 0,
-                               amt_to_forward: 0,
-                               outgoing_cltv_value: 0,
-                       })
-               }
-       }
-
        /// Tracks the inbound corresponding to an outbound HTLC
        #[derive(Clone)]
        pub struct HTLCPreviousHopData {
@@ -112,7 +107,7 @@ mod channel_held_info {
                        session_priv: SecretKey,
                },
        }
-       #[cfg(any(test, feature = "fuzztarget"))]
+       #[cfg(test)]
        impl HTLCSource {
                pub fn dummy() -> Self {
                        HTLCSource::OutboundRoute {
@@ -123,7 +118,7 @@ mod channel_held_info {
        }
 
        #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
-       pub enum HTLCFailReason {
+       pub(crate) enum HTLCFailReason {
                ErrorPacket {
                        err: msgs::OnionErrorPacket,
                },
@@ -132,20 +127,8 @@ mod channel_held_info {
                        data: Vec<u8>,
                }
        }
-
-       #[cfg(feature = "fuzztarget")]
-       impl HTLCFailReason {
-               pub fn dummy() -> Self {
-                       HTLCFailReason::Reason {
-                               failure_code: 0, data: Vec::new(),
-                       }
-               }
-       }
 }
-#[cfg(feature = "fuzztarget")]
-pub use self::channel_held_info::*;
-#[cfg(not(feature = "fuzztarget"))]
-pub(crate) use self::channel_held_info::*;
+pub(super) use self::channel_held_info::*;
 
 struct MsgHandleErrInternal {
        err: msgs::HandleError,
@@ -242,6 +225,7 @@ const ERR: () = "You need at least 32 bit pointers (well, usize, but we'll assum
 
 /// Manager which keeps track of a number of channels and sends messages to the appropriate
 /// channel, also tracking HTLC preimages and forwarding onion packets appropriately.
+///
 /// Implements ChannelMessageHandler, handling the multi-channel parts and passing things through
 /// to individual Channels.
 pub struct ChannelManager {
@@ -285,6 +269,7 @@ struct OnionKeys {
        mu: [u8; 32],
 }
 
+/// Details of a channel, as returned by ChannelManager::list_channels and ChannelManager::list_usable_channels
 pub struct ChannelDetails {
        /// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
        /// thereafter this is the txid of the funding transaction xor the funding transaction output).
@@ -294,17 +279,23 @@ pub struct ChannelDetails {
        /// The position of the funding transaction in the chain. None if the funding transaction has
        /// not yet been confirmed and the channel fully opened.
        pub short_channel_id: Option<u64>,
+       /// The node_id of our counterparty
        pub remote_network_id: PublicKey,
+       /// The value, in satoshis, of this channel as appears in the funding output
        pub channel_value_satoshis: u64,
        /// The user_id passed in to create_channel, or 0 if the channel was inbound.
        pub user_id: u64,
 }
 
 impl ChannelManager {
-       /// Constructs a new ChannelManager to hold several channels and route between them. This is
-       /// the main "logic hub" for all channel-related actions, and implements ChannelMessageHandler.
+       /// Constructs a new ChannelManager to hold several channels and route between them.
+       ///
+       /// This is the main "logic hub" for all channel-related actions, and implements
+       /// ChannelMessageHandler.
+       ///
        /// fee_proportional_millionths is an optional fee to charge any payments routed through us.
        /// Non-proportional fees are fixed according to our risk using the provided fee estimator.
+       ///
        /// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`!
        pub fn new(our_network_key: SecretKey, fee_proportional_millionths: u32, announce_channels_publicly: bool, network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor>, chain_monitor: Arc<ChainWatchInterface>, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>) -> Result<Arc<ChannelManager>, secp256k1::Error> {
                let secp_ctx = Secp256k1::new();
@@ -340,12 +331,15 @@ impl ChannelManager {
        }
 
        /// Creates a new outbound channel to the given remote node and with the given value.
+       ///
        /// user_id will be provided back as user_channel_id in FundingGenerationReady and
        /// FundingBroadcastSafe events to allow tracking of which events correspond with which
        /// create_channel call. Note that user_channel_id defaults to 0 for inbound channels, so you
        /// may wish to avoid using 0 for user_id here.
+       ///
        /// If successful, will generate a SendOpenChannel event, so you should probably poll
        /// PeerManager::process_events afterwards.
+       ///
        /// Raises APIError::APIMisuseError when channel_value_satoshis > 2**24 or push_msat being greater than channel_value_satoshis * 1k
        pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64) -> Result<(), APIError> {
                let chan_keys = if cfg!(feature = "fuzztarget") {
@@ -423,6 +417,7 @@ impl ChannelManager {
        /// Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs
        /// will be accepted on the given channel, and after additional timeout/the closing of all
        /// pending HTLCs, the channel will be closed on chain.
+       ///
        /// May generate a SendShutdown event on success, which should be relayed.
        pub fn close_channel(&self, channel_id: &[u8; 32]) -> Result<(), HandleError> {
                let (mut res, node_id, chan_option) = {
@@ -819,10 +814,10 @@ impl ChannelManager {
                let next_hop_data = {
                        let mut decoded = [0; 65];
                        chacha.process(&msg.onion_routing_packet.hop_data[0..65], &mut decoded);
-                       match msgs::OnionHopData::decode(&decoded[..]) {
+                       match msgs::OnionHopData::read(&mut Cursor::new(&decoded[..])) {
                                Err(err) => {
                                        let error_code = match err {
-                                               msgs::DecodeError::UnknownRealmByte => 0x4000 | 1,
+                                               msgs::DecodeError::UnknownVersion => 0x4000 | 1, // unknown realm byte
                                                _ => 0x2000 | 2, // Should never happen
                                        };
                                        return_err!("Unable to decode our hop data", error_code, &[0;0]);
@@ -963,16 +958,19 @@ impl ChannelManager {
        }
 
        /// Sends a payment along a given route.
+       ///
        /// Value parameters are provided via the last hop in route, see documentation for RouteHop
        /// fields for more info.
+       ///
        /// Note that if the payment_hash already exists elsewhere (eg you're sending a duplicative
        /// payment), we don't do anything to stop you! We always try to ensure that if the provided
        /// next hop knows the preimage to payment_hash they can claim an additional amount as
        /// specified in the last hop in the route! Thus, you should probably do your own
        /// payment_preimage tracking (which you should already be doing as they represent "proof of
        /// payment") and prevent double-sends yourself.
-       /// See-also docs on Channel::send_htlc_and_commit.
+       ///
        /// May generate a SendHTLCs event on success, which should be relayed.
+       ///
        /// Raises APIError::RoutError when invalid route or forward parameter
        /// (cltv_delta, fee, node public key) is specified
        pub fn send_payment(&self, route: Route, payment_hash: [u8; 32]) -> Result<(), APIError> {
@@ -1049,7 +1047,9 @@ impl ChannelManager {
        }
 
        /// Call this upon creation of a funding transaction for the given channel.
+       ///
        /// Panics if a funding transaction has already been provided for this channel.
+       ///
        /// May panic if the funding_txo is duplicative with some other channel (note that this should
        /// be trivially prevented by using unique funding transaction keys per-channel).
        pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint) {
@@ -1123,6 +1123,7 @@ impl ChannelManager {
        }
 
        /// Processes HTLCs which are pending waiting on random forward delay.
+       ///
        /// Should only really ever be called in response to an PendingHTLCsForwardable event.
        /// Will likely generate further events.
        pub fn process_pending_htlc_forwards(&self) {
@@ -1339,6 +1340,7 @@ impl ChannelManager {
        /// Provides a payment preimage in response to a PaymentReceived event, returning true and
        /// generating message events for the net layer to claim the payment, if possible. Thus, you
        /// should probably kick the net layer to go send messages if this returns true!
+       ///
        /// May panic if called except in response to a PaymentReceived event.
        pub fn claim_funds(&self, payment_preimage: [u8; 32]) -> bool {
                let mut sha = Sha256::new();
@@ -1717,7 +1719,7 @@ impl ChannelManager {
                                        chacha.process(&packet_decrypted, &mut decryption_tmp[..]);
                                        packet_decrypted = decryption_tmp;
 
-                                       if let Ok(err_packet) = msgs::DecodedOnionErrorPacket::decode(&packet_decrypted) {
+                                       if let Ok(err_packet) = msgs::DecodedOnionErrorPacket::read(&mut Cursor::new(&packet_decrypted)) {
                                                if err_packet.failuremsg.len() >= 2 {
                                                        let um = ChannelManager::gen_um_from_shared_secret(&shared_secret);
 
@@ -1733,7 +1735,7 @@ impl ChannelManager {
                                                                                if err_packet.failuremsg.len() >= 4 {
                                                                                        let update_len = byte_utils::slice_to_be16(&err_packet.failuremsg[2..4]) as usize;
                                                                                        if err_packet.failuremsg.len() >= 4 + update_len {
-                                                                                               if let Ok(chan_update) = msgs::ChannelUpdate::decode(&err_packet.failuremsg[4..4 + update_len]) {
+                                                                                               if let Ok(chan_update) = msgs::ChannelUpdate::read(&mut Cursor::new(&err_packet.failuremsg[4..4 + update_len])) {
                                                                                                        res = Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage {
                                                                                                                msg: chan_update,
                                                                                                        });
@@ -1902,7 +1904,27 @@ impl ChannelManager {
                Ok(())
        }
 
-
+       fn internal_channel_reestablish(&self, their_node_id: &PublicKey, msg: &msgs::ChannelReestablish) -> Result<(Option<msgs::FundingLocked>, Option<msgs::RevokeAndACK>, Option<msgs::CommitmentUpdate>), MsgHandleErrInternal> {
+               let (res, chan_monitor) = {
+                       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 {
+                                               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) = chan.channel_reestablish(msg).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?;
+                                       (Ok((funding_locked, revoke_and_ack, commitment_update)), channel_monitor)
+                               },
+                               None => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
+                       }
+               };
+               if let Some(monitor) = chan_monitor {
+                       if let Err(_e) = self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor) {
+                               unimplemented!();
+                       }
+               }
+               res
+       }
 }
 
 impl events::EventsProvider for ChannelManager {
@@ -2123,6 +2145,10 @@ impl ChannelMessageHandler for ChannelManager {
                handle_error!(self, self.internal_announcement_signatures(their_node_id, msg), their_node_id)
        }
 
+       fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &msgs::ChannelReestablish) -> Result<(Option<msgs::FundingLocked>, Option<msgs::RevokeAndACK>, Option<msgs::CommitmentUpdate>), HandleError> {
+               handle_error!(self, self.internal_channel_reestablish(their_node_id, msg), their_node_id)
+       }
+
        fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool) {
                let mut new_events = Vec::new();
                let mut failed_channels = Vec::new();
@@ -2152,7 +2178,7 @@ impl ChannelMessageHandler for ChannelManager {
                                channel_state.by_id.retain(|_, chan| {
                                        if chan.get_their_node_id() == *their_node_id {
                                                //TODO: mark channel disabled (and maybe announce such after a timeout).
-                                               let failed_adds = chan.remove_uncommitted_htlcs();
+                                               let failed_adds = chan.remove_uncommitted_htlcs_and_mark_paused();
                                                if !failed_adds.is_empty() {
                                                        let chan_update = self.get_channel_update(&chan).map(|u| u.encode_with_len()).unwrap(); // Cannot add/recv HTLCs before we have a short_id so unwrap is safe
                                                        failed_payments.push((chan_update, failed_adds));
@@ -2184,6 +2210,27 @@ impl ChannelMessageHandler for ChannelManager {
                }
        }
 
+       fn peer_connected(&self, their_node_id: &PublicKey) -> Vec<msgs::ChannelReestablish> {
+               let mut res = Vec::new();
+               let mut channel_state = self.channel_state.lock().unwrap();
+               channel_state.by_id.retain(|_, chan| {
+                       if chan.get_their_node_id() == *their_node_id {
+                               if !chan.have_received_message() {
+                                       // If we created this (outbound) channel while we were disconnected from the
+                                       // peer we probably failed to send the open_channel message, which is now
+                                       // lost. We can't have had anything pending related to this channel, so we just
+                                       // drop it.
+                                       false
+                               } else {
+                                       res.push(chan.get_channel_reestablish());
+                                       true
+                               }
+                       } else { true }
+               });
+               //TODO: Also re-broadcast announcement_signatures
+               res
+       }
+
        fn handle_error(&self, their_node_id: &PublicKey, msg: &msgs::ErrorMessage) {
                if msg.channel_id == [0; 32] {
                        for chan in self.list_channels() {
@@ -2205,11 +2252,12 @@ mod tests {
        use ln::channelmanager::{ChannelManager,OnionKeys};
        use ln::router::{Route, RouteHop, Router};
        use ln::msgs;
-       use ln::msgs::{MsgEncodable,ChannelMessageHandler,RoutingMessageHandler};
+       use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler};
        use util::test_utils;
        use util::events::{Event, EventsProvider};
-       use util::logger::Logger;
        use util::errors::APIError;
+       use util::logger::Logger;
+       use util::ser::Writeable;
 
        use bitcoin::util::hash::Sha256dHash;
        use bitcoin::blockdata::block::{Block, BlockHeader};
@@ -3593,6 +3641,149 @@ mod tests {
                assert_eq!(channel_state.short_to_id.len(), 0);
        }
 
+       fn reconnect_nodes(node_a: &Node, node_b: &Node, pre_all_htlcs: bool, pending_htlc_claims: (usize, usize), pending_htlc_fails: (usize, usize)) {
+               let reestablish_1 = node_a.node.peer_connected(&node_b.node.get_our_node_id());
+               let reestablish_2 = node_b.node.peer_connected(&node_a.node.get_our_node_id());
+
+               let mut resp_1 = Vec::new();
+               for msg in reestablish_1 {
+                       resp_1.push(node_b.node.handle_channel_reestablish(&node_a.node.get_our_node_id(), &msg).unwrap());
+               }
+               {
+                       let mut added_monitors = node_b.chan_monitor.added_monitors.lock().unwrap();
+                       if pending_htlc_claims.0 != 0 || pending_htlc_fails.0 != 0 {
+                               assert_eq!(added_monitors.len(), 1);
+                       } else {
+                               assert!(added_monitors.is_empty());
+                       }
+                       added_monitors.clear();
+               }
+
+               let mut resp_2 = Vec::new();
+               for msg in reestablish_2 {
+                       resp_2.push(node_a.node.handle_channel_reestablish(&node_b.node.get_our_node_id(), &msg).unwrap());
+               }
+               {
+                       let mut added_monitors = node_a.chan_monitor.added_monitors.lock().unwrap();
+                       if pending_htlc_claims.1 != 0 || pending_htlc_fails.1 != 0 {
+                               assert_eq!(added_monitors.len(), 1);
+                       } else {
+                               assert!(added_monitors.is_empty());
+                       }
+                       added_monitors.clear();
+               }
+
+               // We dont yet support both needing updates, as that would require a different commitment dance:
+               assert!((pending_htlc_claims.0 == 0 && pending_htlc_fails.0 == 0) || (pending_htlc_claims.1 == 0 && pending_htlc_fails.1 == 0));
+
+               for chan_msgs in resp_1.drain(..) {
+                       if pre_all_htlcs {
+                               let _announcement_sigs_opt = node_a.node.handle_funding_locked(&node_b.node.get_our_node_id(), &chan_msgs.0.unwrap()).unwrap();
+                               //TODO: Test announcement_sigs re-sending when we've implemented it
+                       } else {
+                               assert!(chan_msgs.0.is_none());
+                       }
+                       assert!(chan_msgs.1.is_none());
+                       if pending_htlc_claims.0 != 0 || pending_htlc_fails.0 != 0 {
+                               let commitment_update = chan_msgs.2.unwrap();
+                               assert!(commitment_update.update_add_htlcs.is_empty()); // We can't relay while disconnected
+                               assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0);
+                               assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.0);
+                               assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
+                               for update_fulfill in commitment_update.update_fulfill_htlcs {
+                                       node_a.node.handle_update_fulfill_htlc(&node_b.node.get_our_node_id(), &update_fulfill).unwrap();
+                               }
+                               for update_fail in commitment_update.update_fail_htlcs {
+                                       node_a.node.handle_update_fail_htlc(&node_b.node.get_our_node_id(), &update_fail).unwrap();
+                               }
+
+                               commitment_signed_dance!(node_a, node_b, commitment_update.commitment_signed, false);
+                       } else {
+                               assert!(chan_msgs.2.is_none());
+                       }
+               }
+
+               for chan_msgs in resp_2.drain(..) {
+                       if pre_all_htlcs {
+                               let _announcement_sigs_opt = node_b.node.handle_funding_locked(&node_a.node.get_our_node_id(), &chan_msgs.0.unwrap()).unwrap();
+                               //TODO: Test announcement_sigs re-sending when we've implemented it
+                       } else {
+                               assert!(chan_msgs.0.is_none());
+                       }
+                       assert!(chan_msgs.1.is_none());
+                       if pending_htlc_claims.1 != 0 || pending_htlc_fails.1 != 0 {
+                               let commitment_update = chan_msgs.2.unwrap();
+                               assert!(commitment_update.update_add_htlcs.is_empty()); // We can't relay while disconnected
+                               assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0);
+                               assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.0);
+                               assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
+                               for update_fulfill in commitment_update.update_fulfill_htlcs {
+                                       node_b.node.handle_update_fulfill_htlc(&node_a.node.get_our_node_id(), &update_fulfill).unwrap();
+                               }
+                               for update_fail in commitment_update.update_fail_htlcs {
+                                       node_b.node.handle_update_fail_htlc(&node_a.node.get_our_node_id(), &update_fail).unwrap();
+                               }
+
+                               commitment_signed_dance!(node_b, node_a, commitment_update.commitment_signed, false);
+                       } else {
+                               assert!(chan_msgs.2.is_none());
+                       }
+               }
+       }
+
+       #[test]
+       fn test_simple_peer_disconnect() {
+               // Test that we can reconnect when there are no lost messages
+               let nodes = create_network(3);
+               create_announced_chan_between_nodes(&nodes, 0, 1);
+               create_announced_chan_between_nodes(&nodes, 1, 2);
+
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+               reconnect_nodes(&nodes[0], &nodes[1], true, (0, 0), (0, 0));
+
+               let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0;
+               let payment_hash_2 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
+               fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_2);
+               claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_1);
+
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+               reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0));
+
+               let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0;
+               let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0;
+               let payment_hash_5 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
+               let payment_hash_6 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
+
+               nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+               claim_payment_along_route(&nodes[0], &vec!(&nodes[1], &nodes[2]), true, payment_preimage_3);
+               fail_payment_along_route(&nodes[0], &[&nodes[1], &nodes[2]], true, payment_hash_5);
+
+               reconnect_nodes(&nodes[0], &nodes[1], false, (1, 0), (1, 0));
+               {
+                       let events = nodes[0].node.get_and_clear_pending_events();
+                       assert_eq!(events.len(), 2);
+                       match events[0] {
+                               Event::PaymentSent { payment_preimage } => {
+                                       assert_eq!(payment_preimage, payment_preimage_3);
+                               },
+                               _ => panic!("Unexpected event"),
+                       }
+                       match events[1] {
+                               Event::PaymentFailed { payment_hash } => {
+                                       assert_eq!(payment_hash, payment_hash_5);
+                               },
+                               _ => panic!("Unexpected event"),
+                       }
+               }
+
+               claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_4);
+               fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_6);
+       }
+
        #[test]
        fn test_invalid_channel_announcement() {
                //Test BOLT 7 channel_announcement msg requirement for final node, gather data to build customed channel_announcement msgs