X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=8e911876fa9bb89ba7697418eb0f3c2c3d3da9de;hb=3410f1803a77f7114c4f4e2195597578c608087f;hp=6298a0d9ae3cbf074e6d8b49f2d54df9f863c658;hpb=0d5050833d99728f0cf4799f7fbb2f2108b1ed93;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 6298a0d9..8e911876 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -45,7 +45,7 @@ use chain::transaction::{OutPoint, TransactionData}; use ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch}; use ln::features::{InitFeatures, NodeFeatures}; -use routing::router::{Route, RouteHop}; +use routing::router::{Payee, PaymentPathRetry, Route, RouteHop}; use ln::msgs; use ln::msgs::NetAddress; use ln::onion_utils; @@ -145,7 +145,7 @@ pub(super) enum HTLCForwardInfo { } /// Tracks the inbound corresponding to an outbound HTLC -#[derive(Clone, PartialEq)] +#[derive(Clone, Hash, PartialEq, Eq)] pub(crate) struct HTLCPreviousHopData { short_channel_id: u64, htlc_id: u64, @@ -189,7 +189,8 @@ impl Readable for PaymentId { } } /// Tracks the inbound corresponding to an outbound HTLC -#[derive(Clone, PartialEq)] +#[allow(clippy::derive_hash_xor_eq)] // Our Hash is faithful to the data, we just don't have SecretKey::hash +#[derive(Clone, PartialEq, Eq)] pub(crate) enum HTLCSource { PreviousHopData(HTLCPreviousHopData), OutboundRoute { @@ -200,8 +201,29 @@ pub(crate) enum HTLCSource { first_hop_htlc_msat: u64, payment_id: PaymentId, payment_secret: Option, + payee: Option, }, } +#[allow(clippy::derive_hash_xor_eq)] // Our Hash is faithful to the data, we just don't have SecretKey::hash +impl core::hash::Hash for HTLCSource { + fn hash(&self, hasher: &mut H) { + match self { + HTLCSource::PreviousHopData(prev_hop_data) => { + 0u8.hash(hasher); + prev_hop_data.hash(hasher); + }, + HTLCSource::OutboundRoute { path, session_priv, payment_id, payment_secret, first_hop_htlc_msat, payee } => { + 1u8.hash(hasher); + path.hash(hasher); + session_priv[..].hash(hasher); + payment_id.hash(hasher); + payment_secret.hash(hasher); + first_hop_htlc_msat.hash(hasher); + payee.hash(hasher); + }, + } + } +} #[cfg(test)] impl HTLCSource { pub fn dummy() -> Self { @@ -211,6 +233,7 @@ impl HTLCSource { first_hop_htlc_msat: 0, payment_id: PaymentId([2; 32]), payment_secret: None, + payee: None, } } } @@ -2001,7 +2024,7 @@ impl ChannelMana } // Only public for testing, this should otherwise never be called direcly - pub(crate) fn send_payment_along_path(&self, path: &Vec, payment_hash: &PaymentHash, payment_secret: &Option, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option) -> Result<(), APIError> { + pub(crate) fn send_payment_along_path(&self, path: &Vec, payee: &Option, payment_hash: &PaymentHash, payment_secret: &Option, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option) -> Result<(), APIError> { log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id); let prng_seed = self.keys_manager.get_secure_random_bytes(); let session_priv_bytes = self.keys_manager.get_secure_random_bytes(); @@ -2051,6 +2074,7 @@ impl ChannelMana first_hop_htlc_msat: htlc_msat, payment_id, payment_secret: payment_secret.clone(), + payee: payee.clone(), }, onion_packet, &self.logger), channel_state, chan); @@ -2189,7 +2213,7 @@ impl ChannelMana let cur_height = self.best_block.read().unwrap().height() + 1; let mut results = Vec::new(); for path in route.paths.iter() { - results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage)); + results.push(self.send_payment_along_path(&path, &route.payee, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage)); } let mut has_ok = false; let mut has_err = false; @@ -3078,14 +3102,22 @@ impl ChannelMana self.fail_htlc_backwards_internal(channel_state, htlc_src, &payment_hash, HTLCFailReason::Reason { failure_code, data: onion_failure_data}); }, - HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => { + HTLCSource::OutboundRoute { session_priv, payment_id, path, payee, .. } => { let mut session_priv_bytes = [0; 32]; session_priv_bytes.copy_from_slice(&session_priv[..]); let mut outbounds = self.pending_outbound_payments.lock().unwrap(); if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) { - if payment.get_mut().remove(&session_priv_bytes, Some(path.last().unwrap().fee_msat)) && + let path_last_hop = path.last().expect("Outbound payments must have had a valid path"); + if payment.get_mut().remove(&session_priv_bytes, Some(path_last_hop.fee_msat)) && !payment.get().is_fulfilled() { + let retry = if let Some(payee_data) = payee { + Some(PaymentPathRetry { + payee: payee_data, + final_value_msat: path_last_hop.fee_msat, + final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta, + }) + } else { None }; self.pending_events.lock().unwrap().push( events::Event::PaymentPathFailed { payment_hash, @@ -3094,6 +3126,7 @@ impl ChannelMana all_paths_failed: payment.get().remaining_parts() == 0, path: path.clone(), short_channel_id: None, + retry, #[cfg(test)] error_code: None, #[cfg(test)] @@ -3125,13 +3158,14 @@ impl ChannelMana // from block_connected which may run during initialization prior to the chain_monitor // being fully configured. See the docs for `ChannelManagerReadArgs` for more. match source { - HTLCSource::OutboundRoute { ref path, session_priv, payment_id, .. } => { + HTLCSource::OutboundRoute { ref path, session_priv, payment_id, ref payee, .. } => { let mut session_priv_bytes = [0; 32]; session_priv_bytes.copy_from_slice(&session_priv[..]); let mut outbounds = self.pending_outbound_payments.lock().unwrap(); let mut all_paths_failed = false; + let path_last_hop = path.last().expect("Outbound payments must have had a valid path"); if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) { - if !payment.get_mut().remove(&session_priv_bytes, Some(path.last().unwrap().fee_msat)) { + if !payment.get_mut().remove(&session_priv_bytes, Some(path_last_hop.fee_msat)) { log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0)); return; } @@ -3146,8 +3180,15 @@ impl ChannelMana log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0)); return; } - log_trace!(self.logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0)); mem::drop(channel_state_lock); + let retry = if let Some(payee_data) = payee { + Some(PaymentPathRetry { + payee: payee_data.clone(), + final_value_msat: path_last_hop.fee_msat, + final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta, + }) + } else { None }; + log_trace!(self.logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0)); match &onion_error { &HTLCFailReason::LightningError { ref err } => { #[cfg(test)] @@ -3165,6 +3206,7 @@ impl ChannelMana all_paths_failed, path: path.clone(), short_channel_id, + retry, #[cfg(test)] error_code: onion_error_code, #[cfg(test)] @@ -3193,6 +3235,7 @@ impl ChannelMana all_paths_failed, path: path.clone(), short_channel_id: Some(path.first().unwrap().short_channel_id), + retry, #[cfg(test)] error_code: Some(*failure_code), #[cfg(test)] @@ -3432,6 +3475,7 @@ impl ChannelMana let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner()); self.pending_events.lock().unwrap().push( events::Event::PaymentSent { + payment_id: Some(payment_id), payment_preimage, payment_hash: payment_hash } @@ -5355,12 +5399,14 @@ impl Readable for HTLCSource { let mut path = Some(Vec::new()); let mut payment_id = None; let mut payment_secret = None; + let mut payee = None; read_tlv_fields!(reader, { (0, session_priv, required), (1, payment_id, option), (2, first_hop_htlc_msat, required), (3, payment_secret, option), (4, path, vec_type), + (5, payee, option), }); if payment_id.is_none() { // For backwards compat, if there was no payment_id written, use the session_priv bytes @@ -5373,6 +5419,7 @@ impl Readable for HTLCSource { path: path.unwrap(), payment_id: payment_id.unwrap(), payment_secret, + payee, }) } 1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)), @@ -5384,7 +5431,7 @@ impl Readable for HTLCSource { impl Writeable for HTLCSource { fn write(&self, writer: &mut W) -> Result<(), ::io::Error> { match self { - HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, payment_secret } => { + HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, payment_secret, payee } => { 0u8.write(writer)?; let payment_id_opt = Some(payment_id); write_tlv_fields!(writer, { @@ -5393,6 +5440,7 @@ impl Writeable for HTLCSource { (2, first_hop_htlc_msat, required), (3, payment_secret, option), (4, path, vec_type), + (5, payee, option), }); } HTLCSource::PreviousHopData(ref field) => { @@ -5878,6 +5926,49 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> outbounds.insert(id, PendingOutboundPayment::Legacy { session_privs }); } pending_outbound_payments = Some(outbounds); + } else { + // If we're tracking pending payments, ensure we haven't lost any by looking at the + // ChannelMonitor data for any channels for which we do not have authorative state + // (i.e. those for which we just force-closed above or we otherwise don't have a + // corresponding `Channel` at all). + // This avoids several edge-cases where we would otherwise "forget" about pending + // payments which are still in-flight via their on-chain state. + // We only rebuild the pending payments map if we were most recently serialized by + // 0.0.102+ + for (_, monitor) in args.channel_monitors { + if by_id.get(&monitor.get_funding_txo().0.to_channel_id()).is_none() { + for (htlc_source, htlc) in monitor.get_pending_outbound_htlcs() { + if let HTLCSource::OutboundRoute { payment_id, session_priv, path, payment_secret, .. } = htlc_source { + if path.is_empty() { + log_error!(args.logger, "Got an empty path for a pending payment"); + return Err(DecodeError::InvalidValue); + } + let path_amt = path.last().unwrap().fee_msat; + let mut session_priv_bytes = [0; 32]; + session_priv_bytes[..].copy_from_slice(&session_priv[..]); + match pending_outbound_payments.as_mut().unwrap().entry(payment_id) { + hash_map::Entry::Occupied(mut entry) => { + let newly_added = entry.get_mut().insert(session_priv_bytes, path_amt); + log_info!(args.logger, "{} a pending payment path for {} msat for session priv {} on an existing pending payment with payment hash {}", + if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), log_bytes!(htlc.payment_hash.0)); + }, + hash_map::Entry::Vacant(entry) => { + entry.insert(PendingOutboundPayment::Retryable { + session_privs: [session_priv_bytes].iter().map(|a| *a).collect(), + payment_hash: htlc.payment_hash, + payment_secret, + pending_amt_msat: path_amt, + total_msat: path_amt, + starting_block_height: best_block_height, + }); + log_info!(args.logger, "Added a pending payment for {} msat with payment hash {} for path with session priv {}", + path_amt, log_bytes!(htlc.payment_hash.0), log_bytes!(session_priv_bytes)); + } + } + } + } + } + } } let mut secp_ctx = Secp256k1::new(); @@ -5946,7 +6037,7 @@ mod tests { use ln::functional_test_utils::*; use ln::msgs; use ln::msgs::ChannelMessageHandler; - use routing::router::{get_keysend_route, get_route}; + use routing::router::{Payee, get_keysend_route, get_route}; use routing::scorer::Scorer; use util::errors::APIError; use util::events::{Event, MessageSendEvent, MessageSendEventsProvider}; @@ -6094,7 +6185,7 @@ mod tests { // Use the utility function send_payment_along_path to send the payment with MPP data which // indicates there are more HTLCs coming. let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match. - nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap(); + nodes[0].node.send_payment_along_path(&route.paths[0], &route.payee, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -6124,7 +6215,7 @@ mod tests { expect_payment_failed!(nodes[0], our_payment_hash, true); // Send the second half of the original MPP payment. - nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap(); + nodes[0].node.send_payment_along_path(&route.paths[0], &route.payee, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -6166,7 +6257,8 @@ mod tests { // further events will be generated for subsequence path successes. let events = nodes[0].node.get_and_clear_pending_events(); match events[0] { - Event::PaymentSent { payment_preimage: ref preimage, payment_hash: ref hash } => { + Event::PaymentSent { payment_id: ref id, payment_preimage: ref preimage, payment_hash: ref hash } => { + assert_eq!(Some(payment_id), *id); assert_eq!(payment_preimage, *preimage); assert_eq!(our_payment_hash, *hash); }, @@ -6193,7 +6285,9 @@ mod tests { let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &expected_route, 100_000); // Next, attempt a keysend payment and make sure it fails. - let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); + let payee = Payee::new(expected_route.last().unwrap().node.get_our_node_id()) + .with_features(InvoiceFeatures::known()); + let route = get_route(&nodes[0].node.get_our_node_id(), &payee, &nodes[0].net_graph_msg_handler.network_graph, None, 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -6221,7 +6315,7 @@ mod tests { // To start (2), send a keysend payment but don't claim it. let payment_preimage = PaymentPreimage([42; 32]); - let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); + let route = get_route(&nodes[0].node.get_our_node_id(), &payee, &nodes[0].net_graph_msg_handler.network_graph, None, 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -6375,7 +6469,7 @@ pub mod bench { use ln::functional_test_utils::*; use ln::msgs::{ChannelMessageHandler, Init}; use routing::network_graph::NetworkGraph; - use routing::router::get_route; + use routing::router::{Payee, get_route}; use routing::scorer::Scorer; use util::test_utils; use util::config::UserConfig; @@ -6484,9 +6578,11 @@ pub mod bench { macro_rules! send_payment { ($node_a: expr, $node_b: expr) => { let usable_channels = $node_a.list_usable_channels(); + let payee = Payee::new($node_b.get_our_node_id()) + .with_features(InvoiceFeatures::known()); let scorer = Scorer::new(0); - let route = get_route(&$node_a.get_our_node_id(), &dummy_graph, &$node_b.get_our_node_id(), Some(InvoiceFeatures::known()), - Some(&usable_channels.iter().map(|r| r).collect::>()), &[], 10_000, TEST_FINAL_CLTV, &logger_a, &scorer).unwrap(); + let route = get_route(&$node_a.get_our_node_id(), &payee, &dummy_graph, + Some(&usable_channels.iter().map(|r| r).collect::>()), 10_000, TEST_FINAL_CLTV, &logger_a, &scorer).unwrap(); let mut payment_preimage = PaymentPreimage([0; 32]); payment_preimage.0[0..8].copy_from_slice(&payment_count.to_le_bytes());