+fn fail_payment_along_path<'a, 'b, 'c>(expected_path: &[&Node<'a, 'b, 'c>]) {
+ let origin_node_id = expected_path[0].node.get_our_node_id();
+
+ // iterate from the receiving node to the origin node and handle update fail htlc.
+ for (&node, &prev_node) in expected_path.iter().rev().zip(expected_path.iter().rev().skip(1)) {
+ let updates = get_htlc_update_msgs!(node, prev_node.node.get_our_node_id());
+ prev_node.node.handle_update_fail_htlc(&node.node.get_our_node_id(), &updates.update_fail_htlcs[0]);
+ check_added_monitors!(prev_node, 0);
+
+ let is_first_hop = origin_node_id == prev_node.node.get_our_node_id();
+ // We do not want to fail backwards on the first hop. All other hops should fail backwards.
+ commitment_signed_dance!(prev_node, node, updates.commitment_signed, !is_first_hop);
+ }
+}
+
+pub struct PassAlongPathArgs<'a, 'b, 'c, 'd> {
+ pub origin_node: &'a Node<'b, 'c, 'd>,
+ pub expected_path: &'a [&'a Node<'b, 'c, 'd>],
+ pub recv_value: u64,
+ pub payment_hash: PaymentHash,
+ pub payment_secret: Option<PaymentSecret>,
+ pub event: MessageSendEvent,
+ pub payment_claimable_expected: bool,
+ pub clear_recipient_events: bool,
+ pub expected_preimage: Option<PaymentPreimage>,
+ pub is_probe: bool,
+ pub custom_tlvs: Vec<(u64, Vec<u8>)>,
+}
+
+impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
+ pub fn new(
+ origin_node: &'a Node<'b, 'c, 'd>, expected_path: &'a [&'a Node<'b, 'c, 'd>], recv_value: u64,
+ payment_hash: PaymentHash, event: MessageSendEvent,
+ ) -> Self {
+ Self {
+ origin_node, expected_path, recv_value, payment_hash, payment_secret: None, event,
+ payment_claimable_expected: true, clear_recipient_events: true, expected_preimage: None,
+ is_probe: false, custom_tlvs: Vec::new(),
+ }
+ }
+ pub fn without_clearing_recipient_events(mut self) -> Self {
+ self.clear_recipient_events = false;
+ self
+ }
+ pub fn is_probe(mut self) -> Self {
+ self.payment_claimable_expected = false;
+ self.is_probe = true;
+ self
+ }
+ pub fn without_claimable_event(mut self) -> Self {
+ self.payment_claimable_expected = false;
+ self
+ }
+ pub fn with_payment_secret(mut self, payment_secret: PaymentSecret) -> Self {
+ self.payment_secret = Some(payment_secret);
+ self
+ }
+ pub fn with_payment_preimage(mut self, payment_preimage: PaymentPreimage) -> Self {
+ self.expected_preimage = Some(payment_preimage);
+ self
+ }
+ pub fn with_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
+ self.custom_tlvs = custom_tlvs;
+ self
+ }
+}
+
+pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event> {
+ let PassAlongPathArgs {
+ origin_node, expected_path, recv_value, payment_hash: our_payment_hash,
+ payment_secret: our_payment_secret, event: ev, payment_claimable_expected,
+ clear_recipient_events, expected_preimage, is_probe, custom_tlvs
+ } = args;
+