X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fpayment_tests.rs;h=0db815a708532f590d5d7821d2f0bc156e03ad8f;hb=cf2c27800a1b30e72d4f7397c931cf6624594233;hp=fa607f680981f3d68d81229834ad1becb6ed8b66;hpb=397386539d19ea368d1f37566b6b0640b90c9668;p=rust-lightning diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index fa607f68..0db815a7 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -15,31 +15,38 @@ use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; use crate::chain::channelmonitor::{ANTI_REORG_DELAY, HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS}; use crate::sign::EntropySource; use crate::chain::transaction::OutPoint; -use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentFailureReason}; -use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS; -use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, IDEMPOTENCY_TIMEOUT_TICKS, RecentPaymentDetails, RecipientOnionFields, HTLCForwardInfo, PendingHTLCRouting, PendingAddHTLCInfo}; -use crate::ln::features::InvoiceFeatures; -use crate::ln::{msgs, PaymentSecret, PaymentPreimage}; +use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentFailureReason, PaymentPurpose}; +use crate::ln::channel::{EXPIRE_PREV_CONFIG_TICKS, commit_tx_fee_msat, get_holder_selected_channel_reserve_satoshis, ANCHOR_OUTPUT_VALUE_SATOSHI}; +use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, RecentPaymentDetails, RecipientOnionFields, HTLCForwardInfo, PendingHTLCRouting, PendingAddHTLCInfo}; +use crate::ln::features::{Bolt11InvoiceFeatures, ChannelTypeFeatures}; +use crate::ln::{msgs, ChannelId, PaymentHash, PaymentSecret, PaymentPreimage}; use crate::ln::msgs::ChannelMessageHandler; -use crate::ln::outbound_payment::Retry; +use crate::ln::onion_utils; +use crate::ln::outbound_payment::{IDEMPOTENCY_TIMEOUT_TICKS, Retry}; use crate::routing::gossip::{EffectiveCapacity, RoutingFees}; use crate::routing::router::{get_route, Path, PaymentParameters, Route, Router, RouteHint, RouteHintHop, RouteHop, RouteParameters, find_route}; use crate::routing::scoring::ChannelUsage; +use crate::util::config::UserConfig; use crate::util::test_utils; use crate::util::errors::APIError; use crate::util::ser::Writeable; use crate::util::string::UntrustedString; +use bitcoin::hashes::Hash; +use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::network::constants::Network; +use bitcoin::secp256k1::{Secp256k1, SecretKey}; use crate::prelude::*; +use crate::ln::functional_test_utils; use crate::ln::functional_test_utils::*; use crate::routing::gossip::NodeId; + #[cfg(feature = "std")] use { crate::util::time::tests::SinceEpoch, - std::time::{SystemTime, Instant, Duration} + std::time::{SystemTime, Instant, Duration}, }; #[test] @@ -82,7 +89,11 @@ fn mpp_retry() { send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000); let amt_msat = 1_000_000; - let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], amt_msat); + let max_total_routing_fee_msat = 50_000; + let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap(); + let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!( + nodes[0], nodes[3], payment_params, amt_msat, Some(max_total_routing_fee_msat)); let path = route.paths[0].clone(); route.paths.push(path); route.paths[0].hops[0].pubkey = nodes[1].node.get_our_node_id(); @@ -94,10 +105,7 @@ fn mpp_retry() { // Initiate the MPP payment. let payment_id = PaymentId(payment_hash.0); - let mut route_params = RouteParameters { - payment_params: route.payment_params.clone().unwrap(), - final_value_msat: amt_msat, - }; + let mut route_params = route.route_params.clone().unwrap(); nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), @@ -112,19 +120,9 @@ fn mpp_retry() { // Add the HTLC along the first hop. let fail_path_msgs_1 = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); - let (update_add, commitment_signed) = match fail_path_msgs_1 { - MessageSendEvent::UpdateHTLCs { node_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { - assert_eq!(update_add_htlcs.len(), 1); - assert!(update_fail_htlcs.is_empty()); - assert!(update_fulfill_htlcs.is_empty()); - assert!(update_fail_malformed_htlcs.is_empty()); - assert!(update_fee.is_none()); - (update_add_htlcs[0].clone(), commitment_signed.clone()) - }, - _ => panic!("Unexpected event"), - }; - nodes[2].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &update_add); - commitment_signed_dance!(nodes[2], nodes[0], commitment_signed, false); + let send_event = SendEvent::from_event(fail_path_msgs_1); + nodes[2].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]); + commitment_signed_dance!(nodes[2], nodes[0], &send_event.commitment_msg, false); // Attempt to forward the payment and complete the 2nd path's failure. expect_pending_htlcs_forwardable!(&nodes[2]); @@ -152,6 +150,10 @@ fn mpp_retry() { route.paths.remove(0); route_params.final_value_msat = 1_000_000; route_params.payment_params.previously_failed_channels.push(chan_4_update.contents.short_channel_id); + // Check the remaining max total routing fee for the second attempt is 50_000 - 1_000 msat fee + // used by the first path + route_params.max_total_routing_fee_msat = Some(max_total_routing_fee_msat - 1_000); + route.route_params = Some(route_params.clone()); nodes[0].router.expect_find_route(route_params, Ok(route)); nodes[0].node.process_pending_htlc_forwards(); check_added_monitors!(nodes[0], 1); @@ -161,6 +163,127 @@ fn mpp_retry() { claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage); } +#[test] +fn mpp_retry_overpay() { + // We create an MPP scenario with two paths in which we need to overpay to reach + // htlc_minimum_msat. We then fail the overpaid path and check that on retry our + // max_total_routing_fee_msat only accounts for the path's fees, but not for the fees overpaid + // in the first attempt. + let chanmon_cfgs = create_chanmon_cfgs(4); + let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); + let mut user_config = test_default_channel_config(); + user_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; + let mut limited_config_1 = user_config.clone(); + limited_config_1.channel_handshake_config.our_htlc_minimum_msat = 35_000_000; + let mut limited_config_2 = user_config.clone(); + limited_config_2.channel_handshake_config.our_htlc_minimum_msat = 34_500_000; + let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, + &[Some(user_config), Some(limited_config_1), Some(limited_config_2), Some(user_config)]); + let nodes = create_network(4, &node_cfgs, &node_chanmgrs); + + let (chan_1_update, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 40_000, 0); + let (chan_2_update, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 40_000, 0); + let (_chan_3_update, _, _, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 40_000, 0); + let (chan_4_update, _, chan_4_id, _) = create_announced_chan_between_nodes_with_value(&nodes, 3, 2, 40_000, 0); + + let amt_msat = 70_000_000; + let max_total_routing_fee_msat = Some(1_000_000); + + let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap(); + let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!( + nodes[0], nodes[3], payment_params, amt_msat, max_total_routing_fee_msat); + + // Check we overpay on the second path which we're about to fail. + assert_eq!(chan_1_update.contents.fee_proportional_millionths, 0); + let overpaid_amount_1 = route.paths[0].fee_msat() as u32 - chan_1_update.contents.fee_base_msat; + assert_eq!(overpaid_amount_1, 0); + + assert_eq!(chan_2_update.contents.fee_proportional_millionths, 0); + let overpaid_amount_2 = route.paths[1].fee_msat() as u32 - chan_2_update.contents.fee_base_msat; + + let total_overpaid_amount = overpaid_amount_1 + overpaid_amount_2; + + // Initiate the payment. + let payment_id = PaymentId(payment_hash.0); + let mut route_params = route.route_params.clone().unwrap(); + + nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); + nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), + payment_id, route_params.clone(), Retry::Attempts(1)).unwrap(); + check_added_monitors!(nodes[0], 2); // one monitor per path + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 2); + + // Pass half of the payment along the success path. + let success_path_msgs = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); + pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], amt_msat, payment_hash, + Some(payment_secret), success_path_msgs, false, None); + + // Add the HTLC along the first hop. + let fail_path_msgs_1 = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); + let send_event = SendEvent::from_event(fail_path_msgs_1); + nodes[2].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]); + commitment_signed_dance!(nodes[2], nodes[0], &send_event.commitment_msg, false); + + // Attempt to forward the payment and complete the 2nd path's failure. + expect_pending_htlcs_forwardable!(&nodes[2]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[2], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_4_id + }] + ); + let htlc_updates = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id()); + assert!(htlc_updates.update_add_htlcs.is_empty()); + assert_eq!(htlc_updates.update_fail_htlcs.len(), 1); + assert!(htlc_updates.update_fulfill_htlcs.is_empty()); + assert!(htlc_updates.update_fail_malformed_htlcs.is_empty()); + check_added_monitors!(nodes[2], 1); + nodes[0].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), + &htlc_updates.update_fail_htlcs[0]); + commitment_signed_dance!(nodes[0], nodes[2], htlc_updates.commitment_signed, false); + let mut events = nodes[0].node.get_and_clear_pending_events(); + match events[1] { + Event::PendingHTLCsForwardable { .. } => {}, + _ => panic!("Unexpected event") + } + events.remove(1); + expect_payment_failed_conditions_event(events, payment_hash, false, + PaymentFailedConditions::new().mpp_parts_remain()); + + // Rebalance the channel so the second half of the payment can succeed. + send_payment(&nodes[3], &vec!(&nodes[2])[..], 38_000_000); + + // Retry the second half of the payment and make sure it succeeds. + let first_path_value = route.paths[0].final_value_msat(); + assert_eq!(first_path_value, 36_000_000); + + route.paths.remove(0); + route_params.final_value_msat -= first_path_value; + route_params.payment_params.previously_failed_channels.push(chan_4_update.contents.short_channel_id); + // Check the remaining max total routing fee for the second attempt accounts only for 1_000 msat + // base fee, but not for overpaid value of the first try. + route_params.max_total_routing_fee_msat.as_mut().map(|m| *m -= 1000); + + route.route_params = Some(route_params.clone()); + nodes[0].router.expect_find_route(route_params, Ok(route)); + nodes[0].node.process_pending_htlc_forwards(); + + check_added_monitors!(nodes[0], 1); + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], amt_msat, payment_hash, + Some(payment_secret), events.pop().unwrap(), true, None); + + // Can't use claim_payment_along_route as it doesn't support overpayment, so we break out the + // individual steps here. + let extra_fees = vec![0, total_overpaid_amount]; + let expected_total_fee_msat = do_claim_payment_along_route_with_extra_penultimate_hop_fees( + &nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], &extra_fees[..], false, + payment_preimage); + expect_payment_sent!(&nodes[0], payment_preimage, Some(expected_total_fee_msat)); +} + fn do_mpp_receive_timeout(send_partial_mpp: bool) { let chanmon_cfgs = create_chanmon_cfgs(4); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); @@ -236,6 +359,69 @@ fn mpp_receive_timeout() { do_mpp_receive_timeout(false); } +#[test] +fn test_keysend_payments() { + do_test_keysend_payments(false, false); + do_test_keysend_payments(false, true); + do_test_keysend_payments(true, false); + do_test_keysend_payments(true, true); +} + +fn do_test_keysend_payments(public_node: bool, with_retry: bool) { + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + if public_node { + create_announced_chan_between_nodes(&nodes, 0, 1); + } else { + create_chan_between_nodes(&nodes[0], &nodes[1]); + } + let payer_pubkey = nodes[0].node.get_our_node_id(); + let payee_pubkey = nodes[1].node.get_our_node_id(); + let route_params = RouteParameters::from_payment_params_and_value( + PaymentParameters::for_keysend(payee_pubkey, 40, false), 10000); + + let network_graph = nodes[0].network_graph; + let channels = nodes[0].node.list_usable_channels(); + let first_hops = channels.iter().collect::>(); + let first_hops = if public_node { None } else { Some(first_hops.as_slice()) }; + + let scorer = test_utils::TestScorer::new(); + let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes(); + let route = find_route( + &payer_pubkey, &route_params, &network_graph, first_hops, + nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes + ).unwrap(); + + { + let test_preimage = PaymentPreimage([42; 32]); + if with_retry { + nodes[0].node.send_spontaneous_payment_with_retry(Some(test_preimage), + RecipientOnionFields::spontaneous_empty(), PaymentId(test_preimage.0), + route_params, Retry::Attempts(1)).unwrap() + } else { + nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage), + RecipientOnionFields::spontaneous_empty(), PaymentId(test_preimage.0)).unwrap() + }; + } + check_added_monitors!(nodes[0], 1); + let send_event = SendEvent::from_node(&nodes[0]); + nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]); + do_commitment_signed_dance(&nodes[1], &nodes[0], &send_event.commitment_msg, false, false); + expect_pending_htlcs_forwardable!(nodes[1]); + // Previously, a refactor caused us to stop including the payment preimage in the onion which + // is sent as a part of keysend payments. Thus, to be extra careful here, we scope the preimage + // above to demonstrate that we have no way to get the preimage at this point except by + // extracting it from the onion nodes[1] received. + let event = nodes[1].node.get_and_clear_pending_events(); + assert_eq!(event.len(), 1); + if let Event::PaymentClaimable { purpose: PaymentPurpose::SpontaneousPayment(preimage), .. } = event[0] { + claim_payment(&nodes[0], &[&nodes[1]], preimage); + } else { panic!(); } +} + #[test] fn test_mpp_keysend() { let mut mpp_keysend_config = test_default_channel_config(); @@ -249,19 +435,17 @@ fn test_mpp_keysend() { create_announced_chan_between_nodes(&nodes, 0, 2); create_announced_chan_between_nodes(&nodes, 1, 3); create_announced_chan_between_nodes(&nodes, 2, 3); - let network_graph = nodes[0].network_graph.clone(); + let network_graph = nodes[0].network_graph; let payer_pubkey = nodes[0].node.get_our_node_id(); let payee_pubkey = nodes[3].node.get_our_node_id(); let recv_value = 15_000_000; - let route_params = RouteParameters { - payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, true), - final_value_msat: recv_value, - }; + let route_params = RouteParameters::from_payment_params_and_value( + PaymentParameters::for_keysend(payee_pubkey, 40, true), recv_value); let scorer = test_utils::TestScorer::new(); let random_seed_bytes = chanmon_cfgs[0].keys_manager.get_secure_random_bytes(); let route = find_route(&payer_pubkey, &route_params, &network_graph, None, nodes[0].logger, - &scorer, &(), &random_seed_bytes).unwrap(); + &scorer, &Default::default(), &random_seed_bytes).unwrap(); let payment_preimage = PaymentPreimage([42; 32]); let payment_secret = PaymentSecret(payment_preimage.0); @@ -449,13 +633,13 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { // which has separate codepaths for "commitment transaction already confirmed" and not. let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let persister; + let new_chain_monitor; let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); - let persister: test_utils::TestPersister; - let new_chain_monitor: test_utils::TestChainMonitor; - let nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestLogger>; + let nodes_0_deserialized; let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; + let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1); let (_, _, chan_id_2, _) = create_announced_chan_between_nodes(&nodes, 1, 2); // Serialize the ChannelManager prior to sending payments @@ -466,10 +650,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { let amt_msat = 1_000_000; let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat); let (payment_preimage_1, payment_hash_1, _, payment_id_1) = send_along_route(&nodes[0], route.clone(), &[&nodes[1], &nodes[2]], 1_000_000); - let route_params = RouteParameters { - payment_params: route.payment_params.clone().unwrap(), - final_value_msat: amt_msat, - }; + let route_params = route.route_params.unwrap().clone(); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); check_added_monitors!(nodes[0], 1); @@ -490,7 +671,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { // nodes[1] now immediately fails the HTLC as the next-hop channel is disconnected let _ = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - reconnect_nodes(&nodes[1], &nodes[2], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(ReconnectArgs::new(&nodes[1], &nodes[2])); let as_commitment_tx = get_local_commitment_txn!(nodes[0], chan_id)[0].clone(); if confirm_before_reload { @@ -505,7 +686,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { // On reload, the ChannelManager should realize it is stale compared to the ChannelMonitor and // force-close the channel. - check_closed_event!(nodes[0], 1, ClosureReason::OutdatedChannelManager); + check_closed_event!(nodes[0], 1, ClosureReason::OutdatedChannelManager, [nodes[1].node.get_our_node_id()], 100000); assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[0].node.has_pending_payments()); nodes[0].node.timer_tick_occurred(); @@ -532,12 +713,13 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish); let as_err = nodes[0].node.get_and_clear_pending_msg_events(); - assert_eq!(as_err.len(), 1); - match as_err[0] { + assert_eq!(as_err.len(), 2); + match as_err[1] { MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()); nodes[1].node.handle_error(&nodes[0].node.get_our_node_id(), msg); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", &nodes[1].node.get_our_node_id())) }); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", + &nodes[1].node.get_our_node_id())) }, [nodes[0].node.get_our_node_id()], 100000); check_added_monitors!(nodes[1], 1); assert_eq!(nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0).len(), 1); }, @@ -555,7 +737,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); check_added_monitors!(nodes[1], 1); commitment_signed_dance!(nodes[1], nodes[2], htlc_fulfill_updates.commitment_signed, false); - expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], None, false, false); + expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], None, true, false); if confirm_before_reload { let best_block = nodes[0].blocks.lock().unwrap().last().unwrap().clone(); @@ -569,15 +751,22 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { assert_eq!(nodes[0].node.list_usable_channels().len(), 1); mine_transaction(&nodes[1], &as_commitment_tx); - let bs_htlc_claim_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(bs_htlc_claim_txn.len(), 1); - check_spends!(bs_htlc_claim_txn[0], as_commitment_tx); + let bs_htlc_claim_txn = { + let mut txn = nodes[1].tx_broadcaster.unique_txn_broadcast(); + assert_eq!(txn.len(), 2); + check_spends!(txn[0], funding_tx); + check_spends!(txn[1], as_commitment_tx); + txn.pop().unwrap() + }; if !confirm_before_reload { mine_transaction(&nodes[0], &as_commitment_tx); + let txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); + assert_eq!(txn.len(), 1); + assert_eq!(txn[0].txid(), as_commitment_tx.txid()); } - mine_transaction(&nodes[0], &bs_htlc_claim_txn[0]); - expect_payment_sent!(nodes[0], payment_preimage_1); + mine_transaction(&nodes[0], &bs_htlc_claim_txn); + expect_payment_sent(&nodes[0], payment_preimage_1, None, true, false); connect_blocks(&nodes[0], TEST_FINAL_CLTV*4 + 20); let (first_htlc_timeout_tx, second_htlc_timeout_tx) = { let mut txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); @@ -586,7 +775,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { }; check_spends!(first_htlc_timeout_tx, as_commitment_tx); check_spends!(second_htlc_timeout_tx, as_commitment_tx); - if first_htlc_timeout_tx.input[0].previous_output == bs_htlc_claim_txn[0].input[0].previous_output { + if first_htlc_timeout_tx.input[0].previous_output == bs_htlc_claim_txn.input[0].previous_output { confirm_transaction(&nodes[0], &second_htlc_timeout_tx); } else { confirm_transaction(&nodes[0], &first_htlc_timeout_tx); @@ -607,9 +796,9 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { let mut peer_state = per_peer_state.get(&nodes[2].node.get_our_node_id()) .unwrap().lock().unwrap(); let mut channel = peer_state.channel_by_id.get_mut(&chan_id_2).unwrap(); - let mut new_config = channel.context.config(); + let mut new_config = channel.context().config(); new_config.forwarding_fee_base_msat += 100_000; - channel.context.update_config(&new_config); + channel.context_mut().update_config(&new_config); new_route.paths[0].hops[0].fee_msat += 100_000; } @@ -648,17 +837,17 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { let mut manually_accept_config = test_default_channel_config(); manually_accept_config.manually_accept_inbound_channels = true; - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(manually_accept_config), None]); + let first_persister; + let first_new_chain_monitor; + let second_persister; + let second_new_chain_monitor; + let third_persister; + let third_new_chain_monitor; - let first_persister: test_utils::TestPersister; - let first_new_chain_monitor: test_utils::TestChainMonitor; - let first_nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestLogger>; - let second_persister: test_utils::TestPersister; - let second_new_chain_monitor: test_utils::TestChainMonitor; - let second_nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestLogger>; - let third_persister: test_utils::TestPersister; - let third_new_chain_monitor: test_utils::TestChainMonitor; - let third_nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestLogger>; + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(manually_accept_config), None]); + let first_nodes_0_deserialized; + let second_nodes_0_deserialized; + let third_nodes_0_deserialized; let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); @@ -686,7 +875,7 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // On reload, the ChannelManager should realize it is stale compared to the ChannelMonitor and // force-close the channel. - check_closed_event!(nodes[0], 1, ClosureReason::OutdatedChannelManager); + check_closed_event!(nodes[0], 1, ClosureReason::OutdatedChannelManager, [nodes[1].node.get_our_node_id()], 100000); nodes[0].node.timer_tick_occurred(); assert!(nodes[0].node.list_channels().is_empty()); assert!(nodes[0].node.has_pending_payments()); @@ -706,13 +895,14 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap(); nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish); let as_err = nodes[0].node.get_and_clear_pending_msg_events(); - assert_eq!(as_err.len(), 1); + assert_eq!(as_err.len(), 2); let bs_commitment_tx; - match as_err[0] { + match as_err[1] { MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => { assert_eq!(node_id, nodes[1].node.get_our_node_id()); nodes[1].node.handle_error(&nodes[0].node.get_our_node_id(), msg); - check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", &nodes[1].node.get_our_node_id())) }); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyForceClosed { peer_msg: UntrustedString(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", &nodes[1].node.get_our_node_id())) } + , [nodes[0].node.get_our_node_id()], 100000); check_added_monitors!(nodes[1], 1); bs_commitment_tx = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); }, @@ -737,19 +927,23 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // the HTLC-Timeout transaction beyond 1 conf). For dust HTLCs, the HTLC is considered resolved // after the commitment transaction, so always connect the commitment transaction. mine_transaction(&nodes[0], &bs_commitment_tx[0]); + if nodes[0].connect_style.borrow().updates_best_block_first() { + let _ = nodes[0].tx_broadcaster.txn_broadcast(); + } mine_transaction(&nodes[1], &bs_commitment_tx[0]); if !use_dust { connect_blocks(&nodes[0], TEST_FINAL_CLTV + (MIN_CLTV_EXPIRY_DELTA as u32)); connect_blocks(&nodes[1], TEST_FINAL_CLTV + (MIN_CLTV_EXPIRY_DELTA as u32)); let as_htlc_timeout = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - check_spends!(as_htlc_timeout[0], bs_commitment_tx[0]); assert_eq!(as_htlc_timeout.len(), 1); + check_spends!(as_htlc_timeout[0], bs_commitment_tx[0]); mine_transaction(&nodes[0], &as_htlc_timeout[0]); - // nodes[0] may rebroadcast (or RBF-bump) its HTLC-Timeout, so wipe the announced set. - nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); mine_transaction(&nodes[1], &as_htlc_timeout[0]); } + if nodes[0].connect_style.borrow().updates_best_block_first() { + let _ = nodes[0].tx_broadcaster.txn_broadcast(); + } // Create a new channel on which to retry the payment before we fail the payment via the // HTLC-Timeout transaction. This avoids ChannelManager timing out the payment due to us @@ -789,7 +983,9 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { nodes[0].node.test_process_background_events(); check_added_monitors(&nodes[0], 1); - reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + let mut reconnect_args = ReconnectArgs::new(&nodes[0], &nodes[1]); + reconnect_args.send_channel_ready = (true, true); + reconnect_nodes(reconnect_args); // Now resend the payment, delivering the HTLC and actually claiming it this time. This ensures // the payment is not (spuriously) listed as still pending. @@ -817,7 +1013,7 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { nodes[0].node.test_process_background_events(); check_added_monitors(&nodes[0], 1); - reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); match nodes[0].node.send_payment_with_route(&new_route, payment_hash, RecipientOnionFields::secret_only(payment_secret), payment_id) { Err(PaymentSendFailure::DuplicatePayment) => {}, @@ -844,53 +1040,57 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co // duplicate HTLC fail/claim (e.g. via a PaymentPathFailed event). let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let persister; + let new_chain_monitor; let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); - let persister: test_utils::TestPersister; - let new_chain_monitor: test_utils::TestChainMonitor; - let nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestLogger>; + let nodes_0_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1); // Route a payment, but force-close the channel before the HTLC fulfill message arrives at // nodes[0]. - let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 10_000_000); + let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 10_000_000); nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap(); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed); + check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id()); // Connect blocks until the CLTV timeout is up so that we get an HTLC-Timeout transaction connect_blocks(&nodes[0], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1); - let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(node_txn.len(), 3); - assert_eq!(node_txn[0].txid(), node_txn[1].txid()); - check_spends!(node_txn[1], funding_tx); - check_spends!(node_txn[2], node_txn[1]); - let timeout_txn = vec![node_txn[2].clone()]; + let (commitment_tx, htlc_timeout_tx) = { + let mut txn = nodes[0].tx_broadcaster.unique_txn_broadcast(); + assert_eq!(txn.len(), 2); + check_spends!(txn[0], funding_tx); + check_spends!(txn[1], txn[0]); + (txn.remove(0), txn.remove(0)) + }; nodes[1].node.claim_funds(payment_preimage); check_added_monitors!(nodes[1], 1); expect_payment_claimed!(nodes[1], payment_hash, 10_000_000); - connect_block(&nodes[1], &create_dummy_block(nodes[1].best_block_hash(), 42, vec![node_txn[1].clone()])); + mine_transaction(&nodes[1], &commitment_tx); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 1); - check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed); - let claim_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); - assert_eq!(claim_txn.len(), 1); - check_spends!(claim_txn[0], node_txn[1]); + check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000); + let htlc_success_tx = { + let mut txn = nodes[1].tx_broadcaster.txn_broadcast(); + assert_eq!(txn.len(), 1); + check_spends!(txn[0], commitment_tx); + txn.pop().unwrap() + }; - connect_block(&nodes[0], &create_dummy_block(nodes[0].best_block_hash(), 42, vec![node_txn[1].clone()])); + mine_transaction(&nodes[0], &commitment_tx); if confirm_commitment_tx { connect_blocks(&nodes[0], BREAKDOWN_TIMEOUT as u32 - 1); } - let claim_block = create_dummy_block(nodes[0].best_block_hash(), 42, if payment_timeout { timeout_txn } else { vec![claim_txn[0].clone()] }); + let claim_block = create_dummy_block(nodes[0].best_block_hash(), 42, if payment_timeout { vec![htlc_timeout_tx] } else { vec![htlc_success_tx] }); if payment_timeout { assert!(confirm_commitment_tx); // Otherwise we're spending below our CSV! @@ -936,7 +1136,7 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co if payment_timeout { expect_payment_failed!(nodes[0], payment_hash, false); } else { - expect_payment_sent!(nodes[0], payment_preimage); + expect_payment_sent(&nodes[0], payment_preimage, None, true, false); } // If we persist the ChannelManager after we get the PaymentSent event, we shouldn't get it @@ -953,7 +1153,7 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co } else if payment_timeout { expect_payment_failed!(nodes[0], payment_hash, false); } else { - expect_payment_sent!(nodes[0], payment_preimage); + expect_payment_sent(&nodes[0], payment_preimage, None, true, false); } // Note that if we re-connect the block which exposed nodes[0] to the payment preimage (but @@ -985,14 +1185,14 @@ fn test_fulfill_restart_failure() { // handle it, we should test the logic for it anyway. We do that here. let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let persister; + let new_chain_monitor; let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); - let persister: test_utils::TestPersister; - let new_chain_monitor: test_utils::TestChainMonitor; - let nodes_1_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestLogger>; + let nodes_1_deserialized; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1).2; - let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 100_000); + let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 100_000); // The simplest way to get a failure after a fulfill is to reload nodes[1] from a state // pre-fulfill, which we do by serializing it here. @@ -1005,13 +1205,13 @@ fn test_fulfill_restart_failure() { let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); - expect_payment_sent_without_paths!(nodes[0], payment_preimage); + expect_payment_sent(&nodes[0], payment_preimage, None, false, false); // Now reload nodes[1]... reload_node!(nodes[1], &chan_manager_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_1_deserialized); nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id()); - reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1])); nodes[1].node.fail_htlc_backwards(&payment_hash); expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]); @@ -1038,14 +1238,15 @@ fn get_ldk_payment_preimage() { let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(amt_msat), expiry_secs, None).unwrap(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.invoice_features()).unwrap(); + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); let scorer = test_utils::TestScorer::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); - let route = get_route( - &nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), - Some(&nodes[0].node.list_usable_channels().iter().collect::>()), - amt_msat, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route = get_route( &nodes[0].node.get_our_node_id(), &route_params, + &nodes[0].network_graph.read_only(), + Some(&nodes[0].node.list_usable_channels().iter().collect::>()), nodes[0].logger, + &scorer, &Default::default(), &random_seed_bytes).unwrap(); nodes[0].node.send_payment_with_route(&route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); check_added_monitors!(nodes[0], 1); @@ -1098,48 +1299,17 @@ fn successful_probe_yields_event() { create_announced_chan_between_nodes(&nodes, 0, 1); create_announced_chan_between_nodes(&nodes, 1, 2); - let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], 100_000); + let recv_value = 100_000; + let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], recv_value); - let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap(); + let res = nodes[0].node.send_probe(route.paths[0].clone()).unwrap(); - // node[0] -- update_add_htlcs -> node[1] - check_added_monitors!(nodes[0], 1); - let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); - let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), updates); - nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &probe_event.msgs[0]); - check_added_monitors!(nodes[1], 0); - commitment_signed_dance!(nodes[1], nodes[0], probe_event.commitment_msg, false); - expect_pending_htlcs_forwardable!(nodes[1]); - - // node[1] -- update_add_htlcs -> node[2] - check_added_monitors!(nodes[1], 1); - let updates = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id()); - let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), updates); - nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &probe_event.msgs[0]); - check_added_monitors!(nodes[2], 0); - commitment_signed_dance!(nodes[2], nodes[1], probe_event.commitment_msg, true, true); + let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]]; - // node[1] <- update_fail_htlcs -- node[2] - let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); - nodes[1].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]); - check_added_monitors!(nodes[1], 0); - commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, true); + send_probe_along_route(&nodes[0], expected_route); - // node[0] <- update_fail_htlcs -- node[1] - let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); - check_added_monitors!(nodes[0], 0); - commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false); + expect_probe_successful_events(&nodes[0], vec![res]); - let mut events = nodes[0].node.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - match events.drain(..).next().unwrap() { - crate::events::Event::ProbeSuccessful { payment_id: ev_pid, payment_hash: ev_ph, .. } => { - assert_eq!(payment_id, ev_pid); - assert_eq!(payment_hash, ev_ph); - }, - _ => panic!(), - }; assert!(!nodes[0].node.has_pending_payments()); } @@ -1155,7 +1325,7 @@ fn failed_probe_yields_event() { let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42); - let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], &payment_params, 9_998_000); + let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], payment_params, 9_998_000); let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap(); @@ -1204,7 +1374,7 @@ fn onchain_failed_probe_yields_event() { let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42); // Send a dust HTLC, which will be treated as if it timed out once the channel hits the chain. - let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], &payment_params, 1_000); + let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], payment_params, 1_000); let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap(); // node[0] -- update_add_htlcs -> node[1] @@ -1244,6 +1414,142 @@ fn onchain_failed_probe_yields_event() { assert!(!nodes[0].node.has_pending_payments()); } +#[test] +fn preflight_probes_yield_event_skip_private_hop() { + let chanmon_cfgs = create_chanmon_cfgs(5); + let node_cfgs = create_node_cfgs(5, &chanmon_cfgs); + + // We alleviate the HTLC max-in-flight limit, as otherwise we'd always be limited through that. + let mut no_htlc_limit_config = test_default_channel_config(); + no_htlc_limit_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; + + let user_configs = std::iter::repeat(no_htlc_limit_config).take(5).map(|c| Some(c)).collect::>>(); + let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &user_configs); + let nodes = create_network(5, &node_cfgs, &node_chanmgrs); + + // Setup channel topology: + // N0 -(1M:0)- N1 -(1M:0)- N2 -(70k:0)- N3 -(50k:0)- N4 + + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 70_000, 0); + create_unannounced_chan_between_nodes_with_value(&nodes, 3, 4, 50_000, 0); + + let mut invoice_features = Bolt11InvoiceFeatures::empty(); + invoice_features.set_basic_mpp_optional(); + + let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(invoice_features).unwrap(); + + let recv_value = 50_000_000; + let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); + let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); + + let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[2], &nodes[3]]]; + + assert_eq!(res.len(), expected_route.len()); + + send_probe_along_route(&nodes[0], expected_route); + + expect_probe_successful_events(&nodes[0], res.clone()); + + assert!(!nodes[0].node.has_pending_payments()); +} + +#[test] +fn preflight_probes_yield_event() { + let chanmon_cfgs = create_chanmon_cfgs(4); + let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); + + // We alleviate the HTLC max-in-flight limit, as otherwise we'd always be limited through that. + let mut no_htlc_limit_config = test_default_channel_config(); + no_htlc_limit_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; + + let user_configs = std::iter::repeat(no_htlc_limit_config).take(4).map(|c| Some(c)).collect::>>(); + let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &user_configs); + let nodes = create_network(4, &node_cfgs, &node_chanmgrs); + + // Setup channel topology: + // (1M:0)- N1 -(30k:0) + // / \ + // N0 N4 + // \ / + // (1M:0)- N2 -(70k:0) + // + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1_000_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 30_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 70_000, 0); + + let mut invoice_features = Bolt11InvoiceFeatures::empty(); + invoice_features.set_basic_mpp_optional(); + + let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(invoice_features).unwrap(); + + let recv_value = 50_000_000; + let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); + let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); + + let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]]; + + assert_eq!(res.len(), expected_route.len()); + + send_probe_along_route(&nodes[0], expected_route); + + expect_probe_successful_events(&nodes[0], res.clone()); + + assert!(!nodes[0].node.has_pending_payments()); +} + +#[test] +fn preflight_probes_yield_event_and_skip() { + let chanmon_cfgs = create_chanmon_cfgs(5); + let node_cfgs = create_node_cfgs(5, &chanmon_cfgs); + + // We alleviate the HTLC max-in-flight limit, as otherwise we'd always be limited through that. + let mut no_htlc_limit_config = test_default_channel_config(); + no_htlc_limit_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; + + let user_configs = std::iter::repeat(no_htlc_limit_config).take(5).map(|c| Some(c)).collect::>>(); + let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &user_configs); + let nodes = create_network(5, &node_cfgs, &node_chanmgrs); + + // Setup channel topology: + // (30k:0)- N2 -(1M:0) + // / \ + // N0 -(100k:0)-> N1 N4 + // \ / + // (70k:0)- N3 -(1M:0) + // + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 30_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 70_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 1_000_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0); + + let mut invoice_features = Bolt11InvoiceFeatures::empty(); + invoice_features.set_basic_mpp_optional(); + + let payment_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(invoice_features).unwrap(); + + let recv_value = 80_000_000; + let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value); + let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap(); + + let expected_route : &[&[&Node]] = &[&[&nodes[1], &nodes[2], &nodes[4]]]; + + // We check that only one probe was sent, the other one was skipped due to limited liquidity. + assert_eq!(res.len(), 1); + + send_probe_along_route(&nodes[0], expected_route); + + expect_probe_successful_events(&nodes[0], res.clone()); + + assert!(!nodes[0].node.has_pending_payments()); +} + #[test] fn claimed_send_payment_idempotent() { // Tests that `send_payment` (and friends) are (reasonably) idempotent. @@ -1399,7 +1705,7 @@ fn test_trivial_inflight_htlc_tracking(){ let (_, _, chan_2_id, _) = create_announced_chan_between_nodes(&nodes, 1, 2); // Send and claim the payment. Inflight HTLCs should be empty. - let payment_hash = send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 500000).1; + let (_, payment_hash, _, payment_id) = send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 500000); let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs(); { let mut node_0_per_peer_lock; @@ -1409,7 +1715,7 @@ fn test_trivial_inflight_htlc_tracking(){ let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), - channel_1.context.get_short_channel_id().unwrap() + channel_1.context().get_short_channel_id().unwrap() ); assert_eq!(chan_1_used_liquidity, None); } @@ -1421,14 +1727,14 @@ fn test_trivial_inflight_htlc_tracking(){ let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), - channel_2.context.get_short_channel_id().unwrap() + channel_2.context().get_short_channel_id().unwrap() ); assert_eq!(chan_2_used_liquidity, None); } let pending_payments = nodes[0].node.list_recent_payments(); assert_eq!(pending_payments.len(), 1); - assert_eq!(pending_payments[0], RecentPaymentDetails::Fulfilled { payment_hash: Some(payment_hash) }); + assert_eq!(pending_payments[0], RecentPaymentDetails::Fulfilled { payment_hash: Some(payment_hash), payment_id }); // Remove fulfilled payment for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS { @@ -1436,7 +1742,7 @@ fn test_trivial_inflight_htlc_tracking(){ } // Send the payment, but do not claim it. Our inflight HTLCs should contain the pending payment. - let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 500000); + let (payment_preimage, payment_hash, _, payment_id) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 500000); let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs(); { let mut node_0_per_peer_lock; @@ -1446,7 +1752,7 @@ fn test_trivial_inflight_htlc_tracking(){ let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), - channel_1.context.get_short_channel_id().unwrap() + channel_1.context().get_short_channel_id().unwrap() ); // First hop accounts for expected 1000 msat fee assert_eq!(chan_1_used_liquidity, Some(501000)); @@ -1459,14 +1765,14 @@ fn test_trivial_inflight_htlc_tracking(){ let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), - channel_2.context.get_short_channel_id().unwrap() + channel_2.context().get_short_channel_id().unwrap() ); assert_eq!(chan_2_used_liquidity, Some(500000)); } let pending_payments = nodes[0].node.list_recent_payments(); assert_eq!(pending_payments.len(), 1); - assert_eq!(pending_payments[0], RecentPaymentDetails::Pending { payment_hash, total_msat: 500000 }); + assert_eq!(pending_payments[0], RecentPaymentDetails::Pending { payment_id, payment_hash, total_msat: 500000 }); // Now, let's claim the payment. This should result in the used liquidity to return `None`. claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); @@ -1485,7 +1791,7 @@ fn test_trivial_inflight_htlc_tracking(){ let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), - channel_1.context.get_short_channel_id().unwrap() + channel_1.context().get_short_channel_id().unwrap() ); assert_eq!(chan_1_used_liquidity, None); } @@ -1497,7 +1803,7 @@ fn test_trivial_inflight_htlc_tracking(){ let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), - channel_2.context.get_short_channel_id().unwrap() + channel_2.context().get_short_channel_id().unwrap() ); assert_eq!(chan_2_used_liquidity, None); } @@ -1538,7 +1844,7 @@ fn test_holding_cell_inflight_htlcs() { let used_liquidity = inflight_htlcs.used_liquidity_msat( &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), - channel.context.get_short_channel_id().unwrap() + channel.context().get_short_channel_id().unwrap() ); assert_eq!(used_liquidity, Some(2000000)); @@ -1591,15 +1897,11 @@ fn do_test_intercepted_payment(test: InterceptTest) { htlc_maximum_msat: None, }]) ]).unwrap() - .with_bolt11_features(nodes[2].node.invoice_features()).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let route = get_route( - &nodes[0].node.get_our_node_id(), &route_params.payment_params, - &nodes[0].network_graph.read_only(), None, route_params.final_value_msat, - nodes[0].logger, &scorer, &(), &random_seed_bytes, + &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(), None, + nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes ).unwrap(); let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap(); @@ -1634,9 +1936,9 @@ fn do_test_intercepted_payment(test: InterceptTest) { }; // Check for unknown channel id error. - let unknown_chan_id_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &[42; 32], nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err(); + let unknown_chan_id_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &ChannelId::from_bytes([42; 32]), nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err(); assert_eq!(unknown_chan_id_err , APIError::ChannelUnavailable { - err: format!("Funded channel with id {} not found for the passed counterparty node_id {}. Channel may still be opening.", + err: format!("Channel with id {} not found for the passed counterparty node_id {}", log_bytes!([42; 32]), nodes[2].node.get_our_node_id()) }); if test == InterceptTest::Fail { @@ -1659,11 +1961,11 @@ fn do_test_intercepted_payment(test: InterceptTest) { expect_payment_failed_conditions(&nodes[0], payment_hash, false, fail_conditions); } else if test == InterceptTest::Forward { // Check that we'll fail as expected when sending to a channel that isn't in `ChannelReady` yet. - let temp_chan_id = nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 100_000, 0, 42, None).unwrap(); + let temp_chan_id = nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); let unusable_chan_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &temp_chan_id, nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err(); assert_eq!(unusable_chan_err , APIError::ChannelUnavailable { - err: format!("Funded channel with id {} not found for the passed counterparty node_id {}. Channel may still be opening.", - log_bytes!(temp_chan_id), nodes[2].node.get_our_node_id()) }); + err: format!("Channel with id {} for the passed counterparty node_id {} is still opening.", + temp_chan_id, nodes[2].node.get_our_node_id()) }); assert_eq!(nodes[1].node.get_and_clear_pending_msg_events().len(), 1); // Open the just-in-time channel so the payment can then be forwarded. @@ -1706,6 +2008,7 @@ fn do_test_intercepted_payment(test: InterceptTest) { }, _ => panic!("Unexpected event") } + check_added_monitors(&nodes[0], 1); } else if test == InterceptTest::Timeout { let mut block = create_dummy_block(nodes[0].best_block_hash(), 42, Vec::new()); connect_block(&nodes[0], &block); @@ -1779,11 +2082,8 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { } let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) .with_route_hints(route_hints).unwrap() - .with_bolt11_features(nodes[2].node.invoice_features()).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap(); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); @@ -1860,7 +2160,7 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { payment_preimage); // The sender doesn't know that the penultimate hop took an extra fee. expect_payment_sent(&nodes[0], payment_preimage, - Some(Some(total_fee_msat - skimmed_fee_msat * num_mpp_parts as u64)), true); + Some(Some(total_fee_msat - skimmed_fee_msat * num_mpp_parts as u64)), true, true); } #[derive(PartialEq)] @@ -1887,10 +2187,10 @@ fn do_automatic_retries(test: AutoRetry) { // below. let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); - let persister; let new_chain_monitor; + + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let node_0_deserialized; let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); @@ -1903,17 +2203,14 @@ fn do_automatic_retries(test: AutoRetry) { #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; let amt_msat = 1000; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let (_, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat); macro_rules! pass_failed_attempt_with_retry_along_path { @@ -2018,7 +2315,7 @@ fn do_automatic_retries(test: AutoRetry) { let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 0); } else if test == AutoRetry::FailTimeout { - #[cfg(not(feature = "no-std"))] { + #[cfg(feature = "std")] { // Ensure ChannelManager will not retry a payment if it times out due to Retry::Timeout. nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Timeout(Duration::from_secs(60))).unwrap(); @@ -2111,40 +2408,31 @@ fn auto_retry_partial_failure() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); + // Open three channels, the first has plenty of liquidity, the second and third have ~no + // available liquidity, causing any outbound payments routed over it to fail immediately. let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; - let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; - let chan_3_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; + let chan_2_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000).0.contents.short_channel_id; + let chan_3_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000).0.contents.short_channel_id; // Marshall data to send the payment - let amt_msat = 20_000; + let amt_msat = 10_000_000; let (_, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; - // Ensure the first monitor update (for the initial send path1 over chan_1) succeeds, but the - // second (for the initial send path2 over chan_2) fails. - chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::PermanentFailure); - // Ensure third monitor update (for the retry1's path1 over chan_1) succeeds, but the fourth (for - // the retry1's path2 over chan_3) fails, and monitor updates succeed after that. - chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::PermanentFailure); - chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); + // Configure the initial send path + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + route_params.max_total_routing_fee_msat = None; - // Configure the initial send, retry1 and retry2's paths. let send_route = Route { paths: vec![ Path { hops: vec![RouteHop { @@ -2154,6 +2442,7 @@ fn auto_retry_partial_failure() { channel_features: nodes[1].node.channel_features(), fee_msat: amt_msat / 2, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, Path { hops: vec![RouteHop { pubkey: nodes[1].node.get_our_node_id(), @@ -2162,10 +2451,19 @@ fn auto_retry_partial_failure() { channel_features: nodes[1].node.channel_features(), fee_msat: amt_msat / 2, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, ], - payment_params: Some(route_params.payment_params.clone()), + route_params: Some(route_params.clone()), }; + nodes[0].router.expect_find_route(route_params.clone(), Ok(send_route)); + + // Configure the retry1 paths + let mut payment_params = route_params.payment_params.clone(); + payment_params.previously_failed_channels.push(chan_2_id); + let mut retry_1_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 2); + retry_1_params.max_total_routing_fee_msat = None; + let retry_1_route = Route { paths: vec![ Path { hops: vec![RouteHop { @@ -2175,6 +2473,7 @@ fn auto_retry_partial_failure() { channel_features: nodes[1].node.channel_features(), fee_msat: amt_msat / 4, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, Path { hops: vec![RouteHop { pubkey: nodes[1].node.get_our_node_id(), @@ -2183,10 +2482,19 @@ fn auto_retry_partial_failure() { channel_features: nodes[1].node.channel_features(), fee_msat: amt_msat / 4, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, ], - payment_params: Some(route_params.payment_params.clone()), + route_params: Some(retry_1_params.clone()), }; + nodes[0].router.expect_find_route(retry_1_params.clone(), Ok(retry_1_route)); + + // Configure the retry2 path + let mut payment_params = retry_1_params.payment_params.clone(); + payment_params.previously_failed_channels.push(chan_3_id); + let mut retry_2_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 4); + retry_2_params.max_total_routing_fee_msat = None; + let retry_2_route = Route { paths: vec![ Path { hops: vec![RouteHop { @@ -2196,51 +2504,33 @@ fn auto_retry_partial_failure() { channel_features: nodes[1].node.channel_features(), fee_msat: amt_msat / 4, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, ], - payment_params: Some(route_params.payment_params.clone()), + route_params: Some(retry_2_params.clone()), }; - nodes[0].router.expect_find_route(route_params.clone(), Ok(send_route)); - let mut payment_params = route_params.payment_params.clone(); - payment_params.previously_failed_channels.push(chan_2_id); - nodes[0].router.expect_find_route(RouteParameters { - payment_params, final_value_msat: amt_msat / 2, - }, Ok(retry_1_route)); - let mut payment_params = route_params.payment_params.clone(); - payment_params.previously_failed_channels.push(chan_3_id); - nodes[0].router.expect_find_route(RouteParameters { - payment_params, final_value_msat: amt_msat / 4, - }, Ok(retry_2_route)); + nodes[0].router.expect_find_route(retry_2_params, Ok(retry_2_route)); // Send a payment that will partially fail on send, then partially fail on retry, then succeed. nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(3)).unwrap(); - let closed_chan_events = nodes[0].node.get_and_clear_pending_events(); - assert_eq!(closed_chan_events.len(), 4); - match closed_chan_events[0] { - Event::ChannelClosed { .. } => {}, - _ => panic!("Unexpected event"), - } - match closed_chan_events[1] { + let payment_failed_events = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(payment_failed_events.len(), 2); + match payment_failed_events[0] { Event::PaymentPathFailed { .. } => {}, _ => panic!("Unexpected event"), } - match closed_chan_events[2] { - Event::ChannelClosed { .. } => {}, - _ => panic!("Unexpected event"), - } - match closed_chan_events[3] { + match payment_failed_events[1] { Event::PaymentPathFailed { .. } => {}, _ => panic!("Unexpected event"), } // Pass the first part of the payment along the path. - check_added_monitors!(nodes[0], 5); // three outbound channel updates succeeded, two permanently failed + check_added_monitors!(nodes[0], 1); // only one HTLC actually made it out let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); - // First message is the first update_add, remaining messages are broadcasting channel updates and - // errors for the permfailed channels - assert_eq!(msg_events.len(), 5); + // Only one HTLC/channel update actually made it out + assert_eq!(msg_events.len(), 1); let mut payment_event = SendEvent::from_event(msg_events.remove(0)); nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); @@ -2284,6 +2574,7 @@ fn auto_retry_partial_failure() { assert_eq!(bs_claim_update.update_fulfill_htlcs.len(), 1); nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_claim_update.update_fulfill_htlcs[0]); + expect_payment_sent(&nodes[0], payment_preimage, None, false, false); nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_claim_update.commitment_signed); check_added_monitors!(nodes[0], 1); let (as_third_raa, as_third_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -2298,6 +2589,7 @@ fn auto_retry_partial_failure() { nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa); check_added_monitors!(nodes[0], 1); + expect_payment_path_successful!(nodes[0]); nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_second_claim_update.update_fulfill_htlcs[0]); nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_second_claim_update.update_fulfill_htlcs[1]); @@ -2314,7 +2606,10 @@ fn auto_retry_partial_failure() { nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_raa); check_added_monitors!(nodes[0], 1); - expect_payment_sent!(nodes[0], payment_preimage); + let events = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events.len(), 2); + if let Event::PaymentPathSuccessful { .. } = events[0] {} else { panic!(); } + if let Event::PaymentPathSuccessful { .. } = events[1] {} else { panic!(); } } #[test] @@ -2324,38 +2619,51 @@ fn auto_retry_zero_attempts_send_error() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; - create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; + // Open a single channel that does not have sufficient liquidity for the payment we want to + // send. + let chan_id = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 989_000_000).0.contents.short_channel_id; // Marshall data to send the payment - let amt_msat = 20_000; - let (_, payment_hash, _, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat); + let amt_msat = 10_000_000; + let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None); #[cfg(feature = "std")] let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + + // Override the route search to return a route, rather than failing at the route-finding step. + let send_route = Route { + paths: vec![ + Path { hops: vec![RouteHop { + pubkey: nodes[1].node.get_our_node_id(), + node_features: nodes[1].node.node_features(), + short_channel_id: chan_id, + channel_features: nodes[1].node.channel_features(), + fee_msat: amt_msat, + cltv_expiry_delta: 100, + maybe_announced_channel: true, + }], blinded_tail: None }, + ], + route_params: Some(route_params.clone()), }; + nodes[0].router.expect_find_route(route_params.clone(), Ok(send_route)); - chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::PermanentFailure); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap(); - assert_eq!(nodes[0].node.get_and_clear_pending_msg_events().len(), 2); // channel close messages + assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); let events = nodes[0].node.get_and_clear_pending_events(); - assert_eq!(events.len(), 3); - if let Event::ChannelClosed { .. } = events[0] { } else { panic!(); } - if let Event::PaymentPathFailed { .. } = events[1] { } else { panic!(); } - if let Event::PaymentFailed { .. } = events[2] { } else { panic!(); } - check_added_monitors!(nodes[0], 2); + assert_eq!(events.len(), 2); + if let Event::PaymentPathFailed { .. } = events[0] { } else { panic!(); } + if let Event::PaymentFailed { .. } = events[1] { } else { panic!(); } + check_added_monitors!(nodes[0], 0); } #[test] @@ -2374,17 +2682,14 @@ fn fails_paying_after_rejected_by_payee() { let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); @@ -2421,17 +2726,16 @@ fn retry_multi_path_single_failed_payment() { let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); - let route_params = RouteParameters { - payment_params: payment_params.clone(), - final_value_msat: amt_msat, - }; + let mut route_params = RouteParameters::from_payment_params_and_value( + payment_params.clone(), amt_msat); + route_params.max_total_routing_fee_msat = None; let chans = nodes[0].node.list_usable_channels(); let mut route = Route { @@ -2443,6 +2747,7 @@ fn retry_multi_path_single_failed_payment() { channel_features: nodes[1].node.channel_features(), fee_msat: 10_000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, Path { hops: vec![RouteHop { pubkey: nodes[1].node.get_our_node_id(), @@ -2451,25 +2756,25 @@ fn retry_multi_path_single_failed_payment() { channel_features: nodes[1].node.channel_features(), fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, ], - payment_params: Some(payment_params), + route_params: Some(route_params.clone()), }; nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); // On retry, split the payment across both channels. route.paths[0].hops[0].fee_msat = 50_000_001; route.paths[1].hops[0].fee_msat = 50_000_000; - let mut pay_params = route.payment_params.clone().unwrap(); + let mut pay_params = route.route_params.clone().unwrap().payment_params; pay_params.previously_failed_channels.push(chans[1].short_channel_id.unwrap()); - nodes[0].router.expect_find_route(RouteParameters { - payment_params: pay_params, - // Note that the second request here requests the amount we originally failed to send, - // not the amount remaining on the full payment, which should be changed. - final_value_msat: 100_000_001, - }, Ok(route.clone())); + + let mut retry_params = RouteParameters::from_payment_params_and_value(pay_params, 100_000_000); + retry_params.max_total_routing_fee_msat = None; + route.route_params = Some(retry_params.clone()); + nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); { - let scorer = chanmon_cfgs[0].scorer.lock().unwrap(); + let scorer = chanmon_cfgs[0].scorer.read().unwrap(); // The initial send attempt, 2 paths scorer.expect_usage(chans[0].short_channel_id.unwrap(), ChannelUsage { amount_msat: 10_000, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown }); scorer.expect_usage(chans[1].short_channel_id.unwrap(), ChannelUsage { amount_msat: 100_000_001, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown }); @@ -2514,17 +2819,14 @@ fn immediate_retry_on_failure() { let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); let chans = nodes[0].node.list_usable_channels(); let mut route = Route { @@ -2536,9 +2838,10 @@ fn immediate_retry_on_failure() { channel_features: nodes[1].node.channel_features(), fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, ], - payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)), + route_params: Some(route_params.clone()), }; nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); // On retry, split the payment across both channels. @@ -2548,9 +2851,9 @@ fn immediate_retry_on_failure() { route.paths[1].hops[0].fee_msat = 50_000_001; let mut pay_params = route_params.payment_params.clone(); pay_params.previously_failed_channels.push(chans[0].short_channel_id.unwrap()); - nodes[0].router.expect_find_route(RouteParameters { - payment_params: pay_params, final_value_msat: amt_msat, - }, Ok(route.clone())); + let retry_params = RouteParameters::from_payment_params_and_value(pay_params, amt_msat); + route.route_params = Some(retry_params.clone()); + nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); @@ -2602,17 +2905,15 @@ fn no_extra_retries_on_back_to_back_fail() { let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + route_params.max_total_routing_fee_msat = None; let mut route = Route { paths: vec![ @@ -2623,6 +2924,7 @@ fn no_extra_retries_on_back_to_back_fail() { channel_features: nodes[1].node.channel_features(), fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee cltv_expiry_delta: 100, + maybe_announced_channel: true, }, RouteHop { pubkey: nodes[2].node.get_our_node_id(), node_features: nodes[2].node.node_features(), @@ -2630,6 +2932,7 @@ fn no_extra_retries_on_back_to_back_fail() { channel_features: nodes[2].node.channel_features(), fee_msat: 100_000_000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, Path { hops: vec![RouteHop { pubkey: nodes[1].node.get_our_node_id(), @@ -2638,6 +2941,7 @@ fn no_extra_retries_on_back_to_back_fail() { channel_features: nodes[1].node.channel_features(), fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee cltv_expiry_delta: 100, + maybe_announced_channel: true, }, RouteHop { pubkey: nodes[2].node.get_our_node_id(), node_features: nodes[2].node.node_features(), @@ -2645,20 +2949,22 @@ fn no_extra_retries_on_back_to_back_fail() { channel_features: nodes[2].node.channel_features(), fee_msat: 100_000_000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None } ], - payment_params: Some(PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)), + route_params: Some(route_params.clone()), }; + route.route_params.as_mut().unwrap().max_total_routing_fee_msat = None; nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); let mut second_payment_params = route_params.payment_params.clone(); second_payment_params.previously_failed_channels = vec![chan_2_scid, chan_2_scid]; // On retry, we'll only return one path route.paths.remove(1); route.paths[0].hops[1].fee_msat = amt_msat; - nodes[0].router.expect_find_route(RouteParameters { - payment_params: second_payment_params, - final_value_msat: amt_msat, - }, Ok(route.clone())); + let mut retry_params = RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat); + retry_params.max_total_routing_fee_msat = None; + route.route_params = Some(retry_params.clone()); + nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); @@ -2804,17 +3110,15 @@ fn test_simple_partial_retry() { let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV) .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); - let route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + route_params.max_total_routing_fee_msat = None; let mut route = Route { paths: vec![ @@ -2825,6 +3129,7 @@ fn test_simple_partial_retry() { channel_features: nodes[1].node.channel_features(), fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee cltv_expiry_delta: 100, + maybe_announced_channel: true, }, RouteHop { pubkey: nodes[2].node.get_our_node_id(), node_features: nodes[2].node.node_features(), @@ -2832,6 +3137,7 @@ fn test_simple_partial_retry() { channel_features: nodes[2].node.channel_features(), fee_msat: 100_000_000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, Path { hops: vec![RouteHop { pubkey: nodes[1].node.get_our_node_id(), @@ -2840,6 +3146,7 @@ fn test_simple_partial_retry() { channel_features: nodes[1].node.channel_features(), fee_msat: 100_000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }, RouteHop { pubkey: nodes[2].node.get_our_node_id(), node_features: nodes[2].node.node_features(), @@ -2847,19 +3154,22 @@ fn test_simple_partial_retry() { channel_features: nodes[2].node.channel_features(), fee_msat: 100_000_000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None } ], - payment_params: Some(PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)), + route_params: Some(route_params.clone()), }; + nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); + let mut second_payment_params = route_params.payment_params.clone(); second_payment_params.previously_failed_channels = vec![chan_2_scid]; // On retry, we'll only be asked for one path (or 100k sats) route.paths.remove(0); - nodes[0].router.expect_find_route(RouteParameters { - payment_params: second_payment_params, - final_value_msat: amt_msat / 2, - }, Ok(route.clone())); + let mut retry_params = RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat / 2); + retry_params.max_total_routing_fee_msat = None; + route.route_params = Some(retry_params.clone()); + nodes[0].router.expect_find_route(retry_params, Ok(route.clone())); nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap(); @@ -2970,7 +3280,7 @@ fn test_threaded_payment_retries() { let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60; #[cfg(not(feature = "std"))] let payment_expiry_secs = 60 * 60; - let mut invoice_features = InvoiceFeatures::empty(); + let mut invoice_features = Bolt11InvoiceFeatures::empty(); invoice_features.set_variable_length_onion_required(); invoice_features.set_payment_secret_required(); invoice_features.set_basic_mpp_optional(); @@ -2978,8 +3288,7 @@ fn test_threaded_payment_retries() { .with_expiry_time(payment_expiry_secs as u64) .with_bolt11_features(invoice_features).unwrap(); let mut route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, + payment_params, final_value_msat: amt_msat, max_total_routing_fee_msat: Some(500_000), }; let mut route = Route { @@ -2991,6 +3300,7 @@ fn test_threaded_payment_retries() { channel_features: nodes[1].node.channel_features(), fee_msat: 0, cltv_expiry_delta: 100, + maybe_announced_channel: true, }, RouteHop { pubkey: nodes[3].node.get_our_node_id(), node_features: nodes[2].node.node_features(), @@ -2998,6 +3308,7 @@ fn test_threaded_payment_retries() { channel_features: nodes[2].node.channel_features(), fee_msat: amt_msat / 1000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None }, Path { hops: vec![RouteHop { pubkey: nodes[2].node.get_our_node_id(), @@ -3006,6 +3317,7 @@ fn test_threaded_payment_retries() { channel_features: nodes[2].node.channel_features(), fee_msat: 100_000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }, RouteHop { pubkey: nodes[3].node.get_our_node_id(), node_features: nodes[3].node.node_features(), @@ -3013,9 +3325,10 @@ fn test_threaded_payment_retries() { channel_features: nodes[3].node.channel_features(), fee_msat: amt_msat - amt_msat / 1000, cltv_expiry_delta: 100, + maybe_announced_channel: true, }], blinded_tail: None } ], - payment_params: Some(PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)), + route_params: Some(route_params.clone()), }; nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); @@ -3034,6 +3347,7 @@ fn test_threaded_payment_retries() { // from here on out, the retry `RouteParameters` amount will be amt/1000 route_params.final_value_msat /= 1000; + route.route_params = Some(route_params.clone()); route.paths.pop(); let end_time = Instant::now() + Duration::from_secs(1); @@ -3041,6 +3355,7 @@ fn test_threaded_payment_retries() { // We really want std::thread::scope, but its not stable until 1.63. Until then, we get unsafe. let node_ref = NodePtr::from_node(&nodes[0]); move || { + let _ = &node_ref; let node_a = unsafe { &*node_ref.0 }; while Instant::now() < end_time { node_a.node.get_and_clear_pending_events(); // wipe the PendingHTLCsForwardable @@ -3073,7 +3388,9 @@ fn test_threaded_payment_retries() { let mut new_route_params = route_params.clone(); previously_failed_channels.push(route.paths[0].hops[1].short_channel_id); new_route_params.payment_params.previously_failed_channels = previously_failed_channels.clone(); + new_route_params.max_total_routing_fee_msat.as_mut().map(|m| *m -= 100_000); route.paths[0].hops[1].short_channel_id += 1; + route.route_params = Some(new_route_params.clone()); nodes[0].router.expect_find_route(new_route_params, Ok(route.clone())); let bs_fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); @@ -3103,15 +3420,15 @@ fn test_threaded_payment_retries() { } } -fn do_no_missing_sent_on_midpoint_reload(persist_manager_with_payment: bool) { +fn do_no_missing_sent_on_reload(persist_manager_with_payment: bool, at_midpoint: bool) { // Test that if we reload in the middle of an HTLC claim commitment signed dance we'll still // receive the PaymentSent event even if the ChannelManager had no idea about the payment when // it was last persisted. let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let (persister_a, persister_b, persister_c); let (chain_monitor_a, chain_monitor_b, chain_monitor_c); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let (nodes_0_deserialized, nodes_0_deserialized_b, nodes_0_deserialized_c); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); @@ -3122,7 +3439,7 @@ fn do_no_missing_sent_on_midpoint_reload(persist_manager_with_payment: bool) { nodes_0_serialized = nodes[0].node.encode(); } - let (our_payment_preimage, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); + let (our_payment_preimage, our_payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000); if persist_manager_with_payment { nodes_0_serialized = nodes[0].node.encode(); @@ -3132,10 +3449,20 @@ fn do_no_missing_sent_on_midpoint_reload(persist_manager_with_payment: bool) { check_added_monitors!(nodes[1], 1); expect_payment_claimed!(nodes[1], our_payment_hash, 1_000_000); - let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); - nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); - nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &updates.commitment_signed); - check_added_monitors!(nodes[0], 1); + if at_midpoint { + let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]); + nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &updates.commitment_signed); + check_added_monitors!(nodes[0], 1); + } else { + let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); + commitment_signed_dance!(nodes[0], nodes[1], htlc_fulfill_updates.commitment_signed, false); + // Ignore the PaymentSent event which is now pending on nodes[0] - if we were to handle it we'd + // be expected to ignore the eventual conflicting PaymentFailed, but by not looking at it we + // expect to get the PaymentSent again later. + check_added_monitors(&nodes[0], 0); + } // The ChannelMonitor should always be the latest version, as we're required to persist it // during the commitment signed handling. @@ -3181,8 +3508,14 @@ fn do_no_missing_sent_on_midpoint_reload(persist_manager_with_payment: bool) { #[test] fn no_missing_sent_on_midpoint_reload() { - do_no_missing_sent_on_midpoint_reload(false); - do_no_missing_sent_on_midpoint_reload(true); + do_no_missing_sent_on_reload(false, true); + do_no_missing_sent_on_reload(true, true); +} + +#[test] +fn no_missing_sent_on_reload() { + do_no_missing_sent_on_reload(false, false); + do_no_missing_sent_on_reload(true, false); } fn do_claim_from_closed_chan(fail_payment: bool) { @@ -3212,13 +3545,11 @@ fn do_claim_from_closed_chan(fail_payment: bool) { create_announced_chan_between_nodes(&nodes, 2, 3); let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[3]); - let mut route_params = RouteParameters { - payment_params: PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.invoice_features()).unwrap(), - final_value_msat: 10_000_000, - }; + let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 10_000_000); let mut route = nodes[0].router.find_route(&nodes[0].node.get_our_node_id(), &route_params, - None, &nodes[0].node.compute_inflight_htlcs()).unwrap(); + None, nodes[0].node.compute_inflight_htlcs()).unwrap(); // Make sure the route is ordered as the B->D path before C->D route.paths.sort_by(|a, _| if a.hops[0].pubkey == nodes[1].node.get_our_node_id() { std::cmp::Ordering::Less } else { std::cmp::Ordering::Greater }); @@ -3268,7 +3599,8 @@ fn do_claim_from_closed_chan(fail_payment: bool) { pass_failed_payment_back(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_hash, PaymentFailureReason::RecipientRejected); } else { nodes[1].node.force_close_broadcasting_latest_txn(&chan_bd, &nodes[3].node.get_our_node_id()).unwrap(); - check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false); + check_closed_event!(&nodes[1], 1, ClosureReason::HolderForceClosed, false, + [nodes[3].node.get_our_node_id()], 1000000); check_closed_broadcast(&nodes[1], 1, true); let bs_tx = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(bs_tx.len(), 1); @@ -3276,7 +3608,8 @@ fn do_claim_from_closed_chan(fail_payment: bool) { mine_transaction(&nodes[3], &bs_tx[0]); check_added_monitors(&nodes[3], 1); check_closed_broadcast(&nodes[3], 1, true); - check_closed_event(&nodes[3], 1, ClosureReason::CommitmentTxConfirmed, false); + check_closed_event!(&nodes[3], 1, ClosureReason::CommitmentTxConfirmed, false, + [nodes[1].node.get_our_node_id()], 1000000); nodes[3].node.claim_funds(payment_preimage); check_added_monitors(&nodes[3], 2); @@ -3327,6 +3660,324 @@ fn claim_from_closed_chan() { do_claim_from_closed_chan(false); } +#[test] +fn test_custom_tlvs_basic() { + do_test_custom_tlvs(false, false, false); + do_test_custom_tlvs(true, false, false); +} + +#[test] +fn test_custom_tlvs_explicit_claim() { + // Test that when receiving even custom TLVs the user must explicitly accept in case they + // are unknown. + do_test_custom_tlvs(false, true, false); + do_test_custom_tlvs(false, true, true); +} + +fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) { + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None; 2]); + let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + create_announced_chan_between_nodes(&nodes, 0, 1); + + let amt_msat = 100_000; + let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(&nodes[0], &nodes[1], amt_msat); + let payment_id = PaymentId(our_payment_hash.0); + let custom_tlvs = vec![ + (if even_tlvs { 5482373482 } else { 5482373483 }, vec![1, 2, 3, 4]), + (5482373487, vec![0x42u8; 16]), + ]; + let onion_fields = RecipientOnionFields { + payment_secret: if spontaneous { None } else { Some(our_payment_secret) }, + payment_metadata: None, + custom_tlvs: custom_tlvs.clone() + }; + if spontaneous { + nodes[0].node.send_spontaneous_payment(&route, Some(our_payment_preimage), onion_fields, payment_id).unwrap(); + } else { + nodes[0].node.send_payment_with_route(&route, our_payment_hash, onion_fields, payment_id).unwrap(); + } + check_added_monitors(&nodes[0], 1); + + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events); + let mut payment_event = SendEvent::from_event(ev); + + nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + check_added_monitors!(&nodes[1], 0); + commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false); + expect_pending_htlcs_forwardable!(nodes[1]); + + let events = nodes[1].node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match events[0] { + Event::PaymentClaimable { ref onion_fields, .. } => { + assert_eq!(onion_fields.clone().unwrap().custom_tlvs().clone(), custom_tlvs); + }, + _ => panic!("Unexpected event"), + } + + match (known_tlvs, even_tlvs) { + (true, _) => { + nodes[1].node.claim_funds_with_known_custom_tlvs(our_payment_preimage); + let expected_total_fee_msat = pass_claimed_payment_along_route(&nodes[0], &[&[&nodes[1]]], &[0; 1], false, our_payment_preimage); + expect_payment_sent!(&nodes[0], our_payment_preimage, Some(expected_total_fee_msat)); + }, + (false, false) => { + claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage); + }, + (false, true) => { + nodes[1].node.claim_funds(our_payment_preimage); + let expected_destinations = vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]; + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], expected_destinations); + pass_failed_payment_back(&nodes[0], &[&[&nodes[1]]], false, our_payment_hash, PaymentFailureReason::RecipientRejected); + } + } +} + +#[test] +fn test_retry_custom_tlvs() { + // Test that custom TLVs are successfully sent on retries + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + create_announced_chan_between_nodes(&nodes, 0, 1); + let (chan_2_update, _, chan_2_id, _) = create_announced_chan_between_nodes(&nodes, 2, 1); + + // Rebalance + send_payment(&nodes[2], &vec!(&nodes[1])[..], 1_500_000); + + let amt_msat = 1_000_000; + let (mut route, payment_hash, payment_preimage, payment_secret) = + get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat); + + // Initiate the payment + let payment_id = PaymentId(payment_hash.0); + let mut route_params = route.route_params.clone().unwrap(); + + let custom_tlvs = vec![((1 << 16) + 1, vec![0x42u8; 16])]; + let onion_fields = RecipientOnionFields::secret_only(payment_secret); + let onion_fields = onion_fields.with_custom_tlvs(custom_tlvs.clone()).unwrap(); + + nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone())); + nodes[0].node.send_payment(payment_hash, onion_fields, + payment_id, route_params.clone(), Retry::Attempts(1)).unwrap(); + check_added_monitors!(nodes[0], 1); // one monitor per path + + // Add the HTLC along the first hop. + let htlc_updates = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id()); + let msgs::CommitmentUpdate { update_add_htlcs, commitment_signed, .. } = htlc_updates; + assert_eq!(update_add_htlcs.len(), 1); + nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &update_add_htlcs[0]); + commitment_signed_dance!(nodes[1], nodes[0], commitment_signed, false); + + // Attempt to forward the payment and complete the path's failure. + expect_pending_htlcs_forwardable!(&nodes[1]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[1], + vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_2_id + }]); + check_added_monitors!(nodes[1], 1); + + let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + let msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. } = htlc_updates; + assert_eq!(update_fail_htlcs.len(), 1); + nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]); + commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false); + + let mut events = nodes[0].node.get_and_clear_pending_events(); + match events[1] { + Event::PendingHTLCsForwardable { .. } => {}, + _ => panic!("Unexpected event") + } + events.remove(1); + expect_payment_failed_conditions_event(events, payment_hash, false, + PaymentFailedConditions::new().mpp_parts_remain()); + + // Rebalance the channel so the retry of the payment can succeed. + send_payment(&nodes[2], &vec!(&nodes[1])[..], 1_500_000); + + // Retry the payment and make sure it succeeds + route_params.payment_params.previously_failed_channels.push(chan_2_update.contents.short_channel_id); + route.route_params = Some(route_params.clone()); + nodes[0].router.expect_find_route(route_params, Ok(route)); + nodes[0].node.process_pending_htlc_forwards(); + check_added_monitors!(nodes[0], 1); + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let payment_claimable = pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000, + payment_hash, Some(payment_secret), events.pop().unwrap(), true, None).unwrap(); + match payment_claimable { + Event::PaymentClaimable { onion_fields, .. } => { + assert_eq!(&onion_fields.unwrap().custom_tlvs()[..], &custom_tlvs[..]); + }, + _ => panic!("Unexpected event"), + }; + claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage); +} + +#[test] +fn test_custom_tlvs_consistency() { + let even_type_1 = 1 << 16; + let odd_type_1 = (1 << 16)+ 1; + let even_type_2 = (1 << 16) + 2; + let odd_type_2 = (1 << 16) + 3; + let value_1 = || vec![1, 2, 3, 4]; + let differing_value_1 = || vec![1, 2, 3, 5]; + let value_2 = || vec![42u8; 16]; + + // Drop missing odd tlvs + do_test_custom_tlvs_consistency( + vec![(odd_type_1, value_1()), (odd_type_2, value_2())], + vec![(odd_type_1, value_1())], + Some(vec![(odd_type_1, value_1())]), + ); + // Drop non-matching odd tlvs + do_test_custom_tlvs_consistency( + vec![(odd_type_1, value_1()), (odd_type_2, value_2())], + vec![(odd_type_1, differing_value_1()), (odd_type_2, value_2())], + Some(vec![(odd_type_2, value_2())]), + ); + // Fail missing even tlvs + do_test_custom_tlvs_consistency( + vec![(odd_type_1, value_1()), (even_type_2, value_2())], + vec![(odd_type_1, value_1())], + None, + ); + // Fail non-matching even tlvs + do_test_custom_tlvs_consistency( + vec![(even_type_1, value_1()), (odd_type_2, value_2())], + vec![(even_type_1, differing_value_1()), (odd_type_2, value_2())], + None, + ); +} + +fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: Vec<(u64, Vec)>, + expected_receive_tlvs: Option)>>) { + + let chanmon_cfgs = create_chanmon_cfgs(4); + let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); + let nodes = create_network(4, &node_cfgs, &node_chanmgrs); + + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100_000, 0); + create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 100_000, 0); + let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0); + + let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap(); + let mut route = get_route!(nodes[0], payment_params, 15_000_000).unwrap(); + assert_eq!(route.paths.len(), 2); + route.paths.sort_by(|path_a, _| { + // Sort the path so that the path through nodes[1] comes first + if path_a.hops[0].pubkey == nodes[1].node.get_our_node_id() { + core::cmp::Ordering::Less } else { core::cmp::Ordering::Greater } + }); + + let (our_payment_preimage, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[3]); + let payment_id = PaymentId([42; 32]); + let amt_msat = 15_000_000; + + // Send first part + let onion_fields = RecipientOnionFields { + payment_secret: Some(our_payment_secret), + payment_metadata: None, + custom_tlvs: first_tlvs + }; + let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, + onion_fields.clone(), payment_id, &route).unwrap(); + let cur_height = nodes[0].best_block_info().1; + nodes[0].node.test_send_payment_along_path(&route.paths[0], &our_payment_hash, + onion_fields.clone(), amt_msat, cur_height, payment_id, + &None, session_privs[0]).unwrap(); + check_added_monitors!(nodes[0], 1); + + { + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], amt_msat, our_payment_hash, + Some(our_payment_secret), events.pop().unwrap(), false, None); + } + assert!(nodes[3].node.get_and_clear_pending_events().is_empty()); + + // Send second part + let onion_fields = RecipientOnionFields { + payment_secret: Some(our_payment_secret), + payment_metadata: None, + custom_tlvs: second_tlvs + }; + nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash, + onion_fields.clone(), amt_msat, cur_height, payment_id, &None, session_privs[1]).unwrap(); + check_added_monitors!(nodes[0], 1); + + { + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let payment_event = SendEvent::from_event(events.pop().unwrap()); + + nodes[2].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + commitment_signed_dance!(nodes[2], nodes[0], payment_event.commitment_msg, false); + + expect_pending_htlcs_forwardable!(nodes[2]); + check_added_monitors!(nodes[2], 1); + + let mut events = nodes[2].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let payment_event = SendEvent::from_event(events.pop().unwrap()); + + nodes[3].node.handle_update_add_htlc(&nodes[2].node.get_our_node_id(), &payment_event.msgs[0]); + check_added_monitors!(nodes[3], 0); + commitment_signed_dance!(nodes[3], nodes[2], payment_event.commitment_msg, true, true); + } + expect_pending_htlcs_forwardable_ignore!(nodes[3]); + nodes[3].node.process_pending_htlc_forwards(); + + if let Some(expected_tlvs) = expected_receive_tlvs { + // Claim and match expected + let events = nodes[3].node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match events[0] { + Event::PaymentClaimable { ref onion_fields, .. } => { + assert_eq!(onion_fields.clone().unwrap().custom_tlvs, expected_tlvs); + }, + _ => panic!("Unexpected event"), + } + + do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], + false, our_payment_preimage); + expect_payment_sent(&nodes[0], our_payment_preimage, Some(Some(2000)), true, true); + } else { + // Expect fail back + let expected_destinations = vec![HTLCDestination::FailedPayment { payment_hash: our_payment_hash }]; + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[3], expected_destinations); + check_added_monitors!(nodes[3], 1); + + let fail_updates_1 = get_htlc_update_msgs!(nodes[3], nodes[2].node.get_our_node_id()); + nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &fail_updates_1.update_fail_htlcs[0]); + commitment_signed_dance!(nodes[2], nodes[3], fail_updates_1.commitment_signed, false); + + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![ + HTLCDestination::NextHopChannel { + node_id: Some(nodes[3].node.get_our_node_id()), + channel_id: chan_2_3.2 + }]); + check_added_monitors!(nodes[2], 1); + + let fail_updates_2 = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id()); + nodes[0].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &fail_updates_2.update_fail_htlcs[0]); + commitment_signed_dance!(nodes[0], nodes[2], fail_updates_2.commitment_signed, false); + + expect_payment_failed_conditions(&nodes[0], our_payment_hash, true, + PaymentFailedConditions::new().mpp_parts_remain()); + } +} + fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { // Check that a payment metadata received on one HTLC that doesn't match the one received on // another results in the HTLC being rejected. @@ -3336,12 +3987,12 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { // modified payment metadata, which will in turn result in it being failed by the recipient. let chanmon_cfgs = create_chanmon_cfgs(4); let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); + let persister; + let new_chain_monitor; + let mut config = test_default_channel_config(); config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 50; let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, Some(config), Some(config), Some(config)]); - - let persister; - let new_chain_monitor; let nodes_0_deserialized; let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs); @@ -3358,15 +4009,12 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { let payment_metadata = vec![44, 49, 52, 142]; let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV) - .with_bolt11_features(nodes[1].node.invoice_features()).unwrap(); - let mut route_params = RouteParameters { - payment_params, - final_value_msat: amt_msat, - }; + .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap(); + let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); // Send the MPP payment, delivering the updated commitment state to nodes[1]. nodes[0].node.send_payment(payment_hash, RecipientOnionFields { - payment_secret: Some(payment_secret), payment_metadata: Some(payment_metadata), + payment_secret: Some(payment_secret), payment_metadata: Some(payment_metadata), custom_tlvs: vec![], }, payment_id, route_params.clone(), Retry::Attempts(1)).unwrap(); check_added_monitors!(nodes[0], 2); @@ -3422,9 +4070,11 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { reload_node!(nodes[3], config, &nodes[3].node.encode(), &[&mon_bd, &mon_cd], persister, new_chain_monitor, nodes_0_deserialized); nodes[1].node.peer_disconnected(&nodes[3].node.get_our_node_id()); - reconnect_nodes(&nodes[1], &nodes[3], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(ReconnectArgs::new(&nodes[1], &nodes[3])); } - reconnect_nodes(&nodes[2], &nodes[3], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + let mut reconnect_args = ReconnectArgs::new(&nodes[2], &nodes[3]); + reconnect_args.send_channel_ready = (true, true); + reconnect_nodes(reconnect_args); // Create a new channel between C and D as A will refuse to retry on the existing one because // it just failed. @@ -3474,3 +4124,151 @@ fn test_payment_metadata_consistency() { do_test_payment_metadata_consistency(false, true); do_test_payment_metadata_consistency(false, false); } + +#[test] +fn test_htlc_forward_considers_anchor_outputs_value() { + // Tests that: + // + // 1) Forwarding nodes don't forward HTLCs that would cause their balance to dip below the + // reserve when considering the value of anchor outputs. + // + // 2) Recipients of `update_add_htlc` properly reject HTLCs that would cause the initiator's + // balance to dip below the reserve when considering the value of anchor outputs. + let mut config = test_default_channel_config(); + config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true; + config.manually_accept_inbound_channels = true; + config.channel_config.forwarding_fee_base_msat = 0; + config.channel_config.forwarding_fee_proportional_millionths = 0; + + // Set up a test network of three nodes that replicates a production failure leading to the + // discovery of this bug. + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config), Some(config), Some(config)]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + const CHAN_AMT: u64 = 1_000_000; + const PUSH_MSAT: u64 = 900_000_000; + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, CHAN_AMT, 500_000_000); + let (_, _, chan_id_2, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, CHAN_AMT, PUSH_MSAT); + + let channel_reserve_msat = get_holder_selected_channel_reserve_satoshis(CHAN_AMT, &config) * 1000; + let commitment_fee_msat = commit_tx_fee_msat( + *nodes[1].fee_estimator.sat_per_kw.lock().unwrap(), 2, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() + ); + let anchor_outpus_value_msat = ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000; + let sendable_balance_msat = CHAN_AMT * 1000 - PUSH_MSAT - channel_reserve_msat - commitment_fee_msat - anchor_outpus_value_msat; + let channel_details = nodes[1].node.list_channels().into_iter().find(|channel| channel.channel_id == chan_id_2).unwrap(); + assert!(sendable_balance_msat >= channel_details.next_outbound_htlc_minimum_msat); + assert!(sendable_balance_msat <= channel_details.next_outbound_htlc_limit_msat); + + send_payment(&nodes[0], &[&nodes[1], &nodes[2]], sendable_balance_msat); + send_payment(&nodes[2], &[&nodes[1], &nodes[0]], sendable_balance_msat); + + // Send out an HTLC that would cause the forwarding node to dip below its reserve when + // considering the value of anchor outputs. + let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!( + nodes[0], nodes[2], sendable_balance_msat + anchor_outpus_value_msat + ); + nodes[0].node.send_payment_with_route( + &route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0) + ).unwrap(); + check_added_monitors!(nodes[0], 1); + + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let mut update_add_htlc = if let MessageSendEvent::UpdateHTLCs { updates, .. } = events.pop().unwrap() { + nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]); + check_added_monitors(&nodes[1], 0); + commitment_signed_dance!(nodes[1], nodes[0], &updates.commitment_signed, false); + updates.update_add_htlcs[0].clone() + } else { + panic!("Unexpected event"); + }; + + // The forwarding node should reject forwarding it as expected. + expect_pending_htlcs_forwardable!(nodes[1]); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[1], vec![HTLCDestination::NextHopChannel { + node_id: Some(nodes[2].node.get_our_node_id()), + channel_id: chan_id_2 + }]); + check_added_monitors(&nodes[1], 1); + + let mut events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + if let MessageSendEvent::UpdateHTLCs { updates, .. } = events.pop().unwrap() { + nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]); + check_added_monitors(&nodes[0], 0); + commitment_signed_dance!(nodes[0], nodes[1], &updates.commitment_signed, false); + } else { + panic!("Unexpected event"); + } + + expect_payment_failed!(nodes[0], payment_hash, false); + + // Assume that the forwarding node did forward it, and make sure the recipient rejects it as an + // invalid update and closes the channel. + update_add_htlc.channel_id = chan_id_2; + nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &update_add_htlc); + check_closed_event(&nodes[2], 1, ClosureReason::ProcessingError { + err: "Remote HTLC add would put them under remote reserve value".to_owned() + }, false, &[nodes[1].node.get_our_node_id()], 1_000_000); + check_closed_broadcast(&nodes[2], 1, true); + check_added_monitors(&nodes[2], 1); +} + +#[test] +fn peel_payment_onion_custom_tlvs() { + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + create_announced_chan_between_nodes(&nodes, 0, 1); + let secp_ctx = Secp256k1::new(); + + let amt_msat = 1000; + let payment_params = PaymentParameters::for_keysend(nodes[1].node.get_our_node_id(), + TEST_FINAL_CLTV, false); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat); + let route = functional_test_utils::get_route(&nodes[0], &route_params).unwrap(); + let mut recipient_onion = RecipientOnionFields::spontaneous_empty() + .with_custom_tlvs(vec![(414141, vec![42; 1200])]).unwrap(); + let prng_seed = chanmon_cfgs[0].keys_manager.get_secure_random_bytes(); + let session_priv = SecretKey::from_slice(&prng_seed[..]).expect("RNG is busted"); + let keysend_preimage = PaymentPreimage([42; 32]); + let payment_hash = PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array()); + + let (onion_routing_packet, first_hop_msat, cltv_expiry) = onion_utils::create_payment_onion( + &secp_ctx, &route.paths[0], &session_priv, amt_msat, recipient_onion.clone(), + nodes[0].best_block_info().1, &payment_hash, &Some(keysend_preimage), prng_seed + ).unwrap(); + + let update_add = msgs::UpdateAddHTLC { + channel_id: ChannelId([0; 32]), + htlc_id: 42, + amount_msat: first_hop_msat, + payment_hash, + cltv_expiry, + skimmed_fee_msat: None, + onion_routing_packet, + blinding_point: None, + }; + let peeled_onion = crate::ln::onion_payment::peel_payment_onion( + &update_add, &&chanmon_cfgs[1].keys_manager, &&chanmon_cfgs[1].logger, &secp_ctx, + nodes[1].best_block_info().1, true, false + ).unwrap(); + assert_eq!(peeled_onion.incoming_amt_msat, Some(amt_msat)); + match peeled_onion.routing { + PendingHTLCRouting::ReceiveKeysend { + payment_data, payment_metadata, custom_tlvs, .. + } => { + #[cfg(not(c_bindings))] + assert_eq!(&custom_tlvs, recipient_onion.custom_tlvs()); + #[cfg(c_bindings)] + assert_eq!(custom_tlvs, recipient_onion.custom_tlvs()); + assert!(payment_metadata.is_none()); + assert!(payment_data.is_none()); + }, + _ => panic!() + } +}