|  | 
| 10 | 10 | use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; | 
| 11 | 11 | use crate::blinded_path::BlindedPath; | 
| 12 | 12 | use crate::blinded_path::payment::{ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs}; | 
| 13 |  | -use crate::events::{HTLCDestination, MessageSendEvent, MessageSendEventsProvider}; | 
|  | 13 | +use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentFailureReason}; | 
| 14 | 14 | use crate::ln::PaymentSecret; | 
| 15 | 15 | use crate::ln::channelmanager; | 
| 16 | 16 | use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; | 
| @@ -708,3 +708,108 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { | 
| 708 | 708 | 	expect_payment_failed_conditions(&nodes[0], payment_hash, false, | 
| 709 | 709 | 		PaymentFailedConditions::new().expected_htlc_error_data(INVALID_ONION_BLINDING, &[0; 32])); | 
| 710 | 710 | } | 
|  | 711 | + | 
|  | 712 | +#[test] | 
|  | 713 | +fn blinded_path_retries() { | 
|  | 714 | +	let chanmon_cfgs = create_chanmon_cfgs(4); | 
|  | 715 | +	// Make one blinded path's fees slightly higher so they are tried in a deterministic order. | 
|  | 716 | +	let mut higher_fee_chan_cfg = test_default_channel_config(); | 
|  | 717 | +	higher_fee_chan_cfg.channel_config.forwarding_fee_base_msat += 1; | 
|  | 718 | +	let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); | 
|  | 719 | +	let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, Some(higher_fee_chan_cfg), None]); | 
|  | 720 | +	let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs); | 
|  | 721 | + | 
|  | 722 | +	// Create this network topology so nodes[0] has a blinded route hint to retry over. | 
|  | 723 | +	//      n1 | 
|  | 724 | +	//    /    \ | 
|  | 725 | +	// n0       n3 | 
|  | 726 | +	//    \    / | 
|  | 727 | +	//      n2 | 
|  | 728 | +	create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0); | 
|  | 729 | +	create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1_000_000, 0); | 
|  | 730 | +	let chan_1_3 = create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 1_000_000, 0); | 
|  | 731 | +	let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0); | 
|  | 732 | + | 
|  | 733 | +	let amt_msat = 5000; | 
|  | 734 | +	let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None); | 
|  | 735 | +	let route_params = { | 
|  | 736 | +		let pay_params = PaymentParameters::blinded( | 
|  | 737 | +			vec![ | 
|  | 738 | +				blinded_payment_path(payment_secret, | 
|  | 739 | +					vec![nodes[1].node.get_our_node_id(), nodes[3].node.get_our_node_id()], &[&chan_1_3.0.contents], | 
|  | 740 | +					&chanmon_cfgs[3].keys_manager | 
|  | 741 | +				), | 
|  | 742 | +				blinded_payment_path(payment_secret, | 
|  | 743 | +					vec![nodes[2].node.get_our_node_id(), nodes[3].node.get_our_node_id()], &[&chan_2_3.0.contents], | 
|  | 744 | +					&chanmon_cfgs[3].keys_manager | 
|  | 745 | +				), | 
|  | 746 | +			] | 
|  | 747 | +		) | 
|  | 748 | +			.with_bolt12_features(channelmanager::provided_bolt12_invoice_features(&UserConfig::default())) | 
|  | 749 | +			.unwrap(); | 
|  | 750 | +		RouteParameters::from_payment_params_and_value(pay_params, amt_msat) | 
|  | 751 | +	}; | 
|  | 752 | + | 
|  | 753 | +	nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(2)).unwrap(); | 
|  | 754 | +	check_added_monitors(&nodes[0], 1); | 
|  | 755 | +	pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]]], amt_msat, payment_hash, payment_secret); | 
|  | 756 | + | 
|  | 757 | +	macro_rules! fail_payment_back { | 
|  | 758 | +		($intro_node: expr) => { | 
|  | 759 | +			nodes[3].node.fail_htlc_backwards(&payment_hash); | 
|  | 760 | +			expect_pending_htlcs_forwardable_conditions( | 
|  | 761 | +				nodes[3].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }] | 
|  | 762 | +			); | 
|  | 763 | +			nodes[3].node.process_pending_htlc_forwards(); | 
|  | 764 | +			check_added_monitors!(nodes[3], 1); | 
|  | 765 | + | 
|  | 766 | +			let updates = get_htlc_update_msgs!(nodes[3], $intro_node.node.get_our_node_id()); | 
|  | 767 | +			assert_eq!(updates.update_fail_malformed_htlcs.len(), 1); | 
|  | 768 | +			let update_malformed = &updates.update_fail_malformed_htlcs[0]; | 
|  | 769 | +			assert_eq!(update_malformed.sha256_of_onion, [0; 32]); | 
|  | 770 | +			assert_eq!(update_malformed.failure_code, INVALID_ONION_BLINDING); | 
|  | 771 | +			$intro_node.node.handle_update_fail_malformed_htlc(&nodes[3].node.get_our_node_id(), update_malformed); | 
|  | 772 | +			do_commitment_signed_dance(&$intro_node, &nodes[3], &updates.commitment_signed, true, false); | 
|  | 773 | + | 
|  | 774 | +			let updates =  get_htlc_update_msgs!($intro_node, nodes[0].node.get_our_node_id()); | 
|  | 775 | +			assert_eq!(updates.update_fail_htlcs.len(), 1); | 
|  | 776 | +			nodes[0].node.handle_update_fail_htlc(&$intro_node.node.get_our_node_id(), &updates.update_fail_htlcs[0]); | 
|  | 777 | +			do_commitment_signed_dance(&nodes[0], &$intro_node, &updates.commitment_signed, false, false); | 
|  | 778 | + | 
|  | 779 | +			let mut events = nodes[0].node.get_and_clear_pending_events(); | 
|  | 780 | +			assert_eq!(events.len(), 2); | 
|  | 781 | +			match events[0] { | 
|  | 782 | +				Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, ..  } => { | 
|  | 783 | +					assert_eq!(payment_hash, ev_payment_hash); | 
|  | 784 | +					assert_eq!(payment_failed_permanently, false); | 
|  | 785 | +				}, | 
|  | 786 | +				_ => panic!("Unexpected event"), | 
|  | 787 | +			} | 
|  | 788 | +			match events[1] { | 
|  | 789 | +				Event::PendingHTLCsForwardable { .. } => {}, | 
|  | 790 | +				_ => panic!("Unexpected event"), | 
|  | 791 | +			} | 
|  | 792 | +			nodes[0].node.process_pending_htlc_forwards(); | 
|  | 793 | +		} | 
|  | 794 | +	} | 
|  | 795 | + | 
|  | 796 | +	fail_payment_back!(nodes[1]); | 
|  | 797 | + | 
|  | 798 | +	// Pass the retry along. | 
|  | 799 | +	check_added_monitors!(nodes[0], 1); | 
|  | 800 | +	let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events(); | 
|  | 801 | +	assert_eq!(msg_events.len(), 1); | 
|  | 802 | +	pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], amt_msat, payment_hash, Some(payment_secret), msg_events.pop().unwrap(), true, None); | 
|  | 803 | + | 
|  | 804 | +	fail_payment_back!(nodes[2]); | 
|  | 805 | +	let evs = nodes[0].node.get_and_clear_pending_events(); | 
|  | 806 | +	assert_eq!(evs.len(), 1); | 
|  | 807 | +	match evs[0] { | 
|  | 808 | +		Event::PaymentFailed { payment_hash: ev_payment_hash, reason, .. } => { | 
|  | 809 | +			assert_eq!(ev_payment_hash, payment_hash); | 
|  | 810 | +			// We have 1 retry attempt remaining, but we're out of blinded paths to try. | 
|  | 811 | +			assert_eq!(reason, Some(PaymentFailureReason::RouteNotFound)); | 
|  | 812 | +		}, | 
|  | 813 | +		_ => panic!() | 
|  | 814 | +	} | 
|  | 815 | +} | 
0 commit comments