X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fpayment_tests.rs;h=fcfdd5cb5a02f64e688ddd7cdb9b375029907226;hb=05e6252b20ac3a3412d4da38f732191724f30bc0;hp=0950644369866bf5e8a263af528ae05f6fd5924e;hpb=b6ff46daabc2d942f300efcbe9aca8bc541f0ff7;p=rust-lightning diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index 09506443..fcfdd5cb 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -34,7 +34,7 @@ use crate::util::string::UntrustedString; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::network::constants::Network; +use bitcoin::network::Network; use bitcoin::secp256k1::{Secp256k1, SecretKey}; use crate::prelude::*; @@ -160,7 +160,9 @@ fn mpp_retry() { 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]], 2_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None); - claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage) + ); } #[test] @@ -351,7 +353,9 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) { nodes[3].node.timer_tick_occurred(); } - claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage) + ); } } @@ -466,7 +470,9 @@ fn test_mpp_keysend() { let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events); pass_along_path(&nodes[0], expected_route[1], recv_value, payment_hash.clone(), Some(payment_secret), ev.clone(), true, Some(payment_preimage)); - claim_payment_along_route(&nodes[0], expected_route, false, payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], expected_route, payment_preimage) + ); } #[test] @@ -1050,14 +1056,15 @@ fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(persist_manager_post_event: bo let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1); + let error_message = "Channel force-closed"; // 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); - nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap(); + nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap(); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); - check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000); + check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, [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()); @@ -1247,7 +1254,9 @@ fn get_ldk_payment_preimage() { let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); pass_along_path(&nodes[0], &[&nodes[1]], amt_msat, payment_hash, Some(payment_secret), events.pop().unwrap(), true, Some(payment_preimage)); - claim_payment_along_route(&nodes[0], &[&[&nodes[1]]], false, payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage) + ); } #[test] @@ -2044,22 +2053,28 @@ fn accept_underpaying_htlcs_config() { fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) { let chanmon_cfgs = create_chanmon_cfgs(3); let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let max_in_flight_percent = 10; let mut intercept_forwards_config = test_default_channel_config(); intercept_forwards_config.accept_intercept_htlcs = true; + intercept_forwards_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = max_in_flight_percent; let mut underpay_config = test_default_channel_config(); underpay_config.channel_config.accept_underpaying_htlcs = true; + underpay_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = max_in_flight_percent; let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(intercept_forwards_config), Some(underpay_config)]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + let amt_msat = 900_000; + let mut chan_ids = Vec::new(); for _ in 0..num_mpp_parts { - let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000, 0); - let channel_id = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 2_000_000, 0).0.channel_id; + // We choose the channel size so that there can be at most one part pending on each channel. + let channel_size = amt_msat / 1000 / num_mpp_parts as u64 * 100 / max_in_flight_percent as u64 + 100; + let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_size, 0); + let channel_id = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, channel_size, 0).0.channel_id; chan_ids.push(channel_id); } // Send the initial payment. - let amt_msat = 900_000; let skimmed_fee_msat = 20; let mut route_hints = Vec::new(); for _ in 0..num_mpp_parts { @@ -2276,7 +2291,9 @@ fn do_automatic_retries(test: AutoRetry) { let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, Some(payment_secret), msg_events.pop().unwrap(), true, None); - claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + ); } else if test == AutoRetry::Spontaneous { nodes[0].node.send_spontaneous_payment_with_retry(Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, @@ -2293,7 +2310,9 @@ fn do_automatic_retries(test: AutoRetry) { let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(msg_events.len(), 1); pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, None, msg_events.pop().unwrap(), true, Some(payment_preimage)); - claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + ); } else if test == AutoRetry::FailAttempts { // Ensure ChannelManager will not retry a payment if it has run out of payment attempts. nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret), @@ -3587,6 +3606,7 @@ fn do_claim_from_closed_chan(fail_payment: bool) { // height. connect_blocks(&nodes[3], final_cltv - HTLC_FAIL_BACK_BUFFER - nodes[3].best_block_info().1 - if fail_payment { 0 } else { 2 }); + let error_message = "Channel force-closed"; if fail_payment { // We fail the HTLC on the A->B->D path first as it expires 4 blocks earlier. We go ahead // and expire both immediately, though, by connecting another 4 blocks. @@ -3596,8 +3616,8 @@ fn do_claim_from_closed_chan(fail_payment: bool) { expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[3], [reason]); 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, + nodes[1].node.force_close_broadcasting_latest_txn(&chan_bd, &nodes[3].node.get_our_node_id(), error_message.to_string()).unwrap(); + check_closed_event!(&nodes[1], 1, ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true) }, 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); @@ -3720,11 +3740,17 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) { 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(ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage)); + let expected_total_fee_msat = pass_claimed_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage) + .with_custom_tlvs(custom_tlvs) + ); expect_payment_sent!(&nodes[0], our_payment_preimage, Some(expected_total_fee_msat)); }, (false, false) => { - claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage) + .with_custom_tlvs(custom_tlvs) + ); }, (false, true) => { nodes[1].node.claim_funds(our_payment_preimage); @@ -3811,9 +3837,12 @@ fn test_retry_custom_tlvs() { let path = &[&nodes[1], &nodes[2]]; let args = PassAlongPathArgs::new(&nodes[0], path, 1_000_000, payment_hash, events.pop().unwrap()) .with_payment_secret(payment_secret) - .with_custom_tlvs(custom_tlvs); + .with_custom_tlvs(custom_tlvs.clone()); do_pass_along_path(args); - claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + .with_custom_tlvs(custom_tlvs) + ); } #[test] @@ -3946,6 +3975,7 @@ fn do_test_custom_tlvs_consistency(first_tlvs: Vec<(u64, Vec)>, second_tlvs: do_claim_payment_along_route( ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], our_payment_preimage) + .with_custom_tlvs(expected_tlvs) ); expect_payment_sent(&nodes[0], our_payment_preimage, Some(Some(2000)), true, true); } else { @@ -4074,7 +4104,7 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { // Create a new channel between C and D as A will refuse to retry on the existing one because // it just failed. - let chan_id_cd_2 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).2; + create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0); // Now retry the failed HTLC. nodes[0].node.process_pending_htlc_forwards(); @@ -4086,6 +4116,7 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { expect_pending_htlcs_forwardable!(nodes[2]); check_added_monitors(&nodes[2], 1); let cs_forward = SendEvent::from_node(&nodes[2]); + let cd_channel_used = cs_forward.msgs[0].channel_id; nodes[3].node.handle_update_add_htlc(&nodes[2].node.get_our_node_id(), &cs_forward.msgs[0]); commitment_signed_dance!(nodes[3], nodes[2], cs_forward.commitment_msg, false, true); @@ -4105,11 +4136,13 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) { nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &ds_fail.update_fail_htlcs[0]); commitment_signed_dance!(nodes[2], nodes[3], ds_fail.commitment_signed, false, true); expect_pending_htlcs_forwardable_conditions(nodes[2].node.get_and_clear_pending_events(), - &[HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_id_cd_2 }]); + &[HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: cd_channel_used }]); } else { expect_pending_htlcs_forwardable!(nodes[3]); expect_payment_claimable!(nodes[3], payment_hash, payment_secret, amt_msat); - claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage); + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage) + ); } } @@ -4268,3 +4301,94 @@ fn peel_payment_onion_custom_tlvs() { _ => panic!() } } + +#[test] +fn test_non_strict_forwarding() { + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let mut config = test_default_channel_config(); + config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100; + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config), Some(config), Some(config)]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + // Create a routing node with two outbound channels, each of which can forward 2 payments of + // the given value. + let payment_value = 1_500_000; + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0); + let (chan_update_1, _, channel_id_1, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 4_950, 0); + let (chan_update_2, _, channel_id_2, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 5_000, 0); + + // Create a route once. + let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV) + .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap(); + let route_params = RouteParameters::from_payment_params_and_value(payment_params, payment_value); + let route = functional_test_utils::get_route(&nodes[0], &route_params).unwrap(); + + // Send 4 payments over the same route. + for i in 0..4 { + let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(payment_value), None); + 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 msg_events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), 1); + let mut send_event = SendEvent::from_event(msg_events.remove(0)); + nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]); + commitment_signed_dance!(nodes[1], nodes[0], &send_event.commitment_msg, false); + + expect_pending_htlcs_forwardable!(nodes[1]); + check_added_monitors!(nodes[1], 1); + msg_events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), 1); + send_event = SendEvent::from_event(msg_events.remove(0)); + // The HTLC will be forwarded over the most appropriate channel with the corresponding peer, + // applying non-strict forwarding. + // The channel with the least amount of outbound liquidity will be used to maximize the + // probability of being able to successfully forward a subsequent HTLC. + assert_eq!(send_event.msgs[0].channel_id, if i < 2 { + channel_id_1 + } else { + channel_id_2 + }); + nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &send_event.msgs[0]); + commitment_signed_dance!(nodes[2], nodes[1], &send_event.commitment_msg, false); + + expect_pending_htlcs_forwardable!(nodes[2]); + let events = nodes[2].node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + assert!(matches!(events[0], Event::PaymentClaimable { .. })); + + claim_payment_along_route( + ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage) + ); + } + + // Send a 5th payment which will fail. + let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(payment_value), None); + 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 msg_events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), 1); + let mut send_event = SendEvent::from_event(msg_events.remove(0)); + nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]); + commitment_signed_dance!(nodes[1], nodes[0], &send_event.commitment_msg, false); + + expect_pending_htlcs_forwardable!(nodes[1]); + check_added_monitors!(nodes[1], 1); + let routed_scid = route.paths[0].hops[1].short_channel_id; + let routed_channel_id = match routed_scid { + scid if scid == chan_update_1.contents.short_channel_id => channel_id_1, + scid if scid == chan_update_2.contents.short_channel_id => channel_id_2, + _ => panic!("Unexpected short channel id in route"), + }; + // The failure to forward will refer to the channel given in the onion. + expect_pending_htlcs_forwardable_conditions(nodes[1].node.get_and_clear_pending_events(), + &[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: routed_channel_id }]); + + 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]); + commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false); + let events = nodes[0].node.get_and_clear_pending_events(); + expect_payment_failed_conditions_event(events, payment_hash, false, PaymentFailedConditions::new().blamed_scid(routed_scid)); +}