+
+#[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,
+ 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!()
+ }
+}
+
+#[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));
+}