+
+ #[test]
+ fn test_notify_limits() {
+ // Check that a few cases which don't require the persistence of a new ChannelManager,
+ // indeed, do not cause the persistence of a new ChannelManager.
+ 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);
+
+ // All nodes start with a persistable update pending as `create_network` connects each node
+ // with all other nodes to make most tests simpler.
+ assert!(nodes[0].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert!(nodes[1].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert!(nodes[2].node.await_persistable_update_timeout(Duration::from_millis(1)));
+
+ let mut chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+
+ // We check that the channel info nodes have doesn't change too early, even though we try
+ // to connect messages with new values
+ chan.0.contents.fee_base_msat *= 2;
+ chan.1.contents.fee_base_msat *= 2;
+ let node_a_chan_info = nodes[0].node.list_channels()[0].clone();
+ let node_b_chan_info = nodes[1].node.list_channels()[0].clone();
+
+ // The first two nodes (which opened a channel) should now require fresh persistence
+ assert!(nodes[0].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert!(nodes[1].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ // ... but the last node should not.
+ assert!(!nodes[2].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ // After persisting the first two nodes they should no longer need fresh persistence.
+ assert!(!nodes[0].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert!(!nodes[1].node.await_persistable_update_timeout(Duration::from_millis(1)));
+
+ // Node 3, unrelated to the only channel, shouldn't care if it receives a channel_update
+ // about the channel.
+ nodes[2].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan.0);
+ nodes[2].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan.1);
+ assert!(!nodes[2].node.await_persistable_update_timeout(Duration::from_millis(1)));
+
+ // The nodes which are a party to the channel should also ignore messages from unrelated
+ // parties.
+ nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan.0);
+ nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan.1);
+ nodes[1].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan.0);
+ nodes[1].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan.1);
+ assert!(!nodes[0].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert!(!nodes[1].node.await_persistable_update_timeout(Duration::from_millis(1)));
+
+ // At this point the channel info given by peers should still be the same.
+ assert_eq!(nodes[0].node.list_channels()[0], node_a_chan_info);
+ assert_eq!(nodes[1].node.list_channels()[0], node_b_chan_info);
+
+ // An earlier version of handle_channel_update didn't check the directionality of the
+ // update message and would always update the local fee info, even if our peer was
+ // (spuriously) forwarding us our own channel_update.
+ let as_node_one = nodes[0].node.get_our_node_id().serialize()[..] < nodes[1].node.get_our_node_id().serialize()[..];
+ let as_update = if as_node_one == (chan.0.contents.flags & 1 == 0 /* chan.0 is from node one */) { &chan.0 } else { &chan.1 };
+ let bs_update = if as_node_one == (chan.0.contents.flags & 1 == 0 /* chan.0 is from node one */) { &chan.1 } else { &chan.0 };
+
+ // First deliver each peers' own message, checking that the node doesn't need to be
+ // persisted and that its channel info remains the same.
+ nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &as_update);
+ nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &bs_update);
+ assert!(!nodes[0].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert!(!nodes[1].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert_eq!(nodes[0].node.list_channels()[0], node_a_chan_info);
+ assert_eq!(nodes[1].node.list_channels()[0], node_b_chan_info);
+
+ // Finally, deliver the other peers' message, ensuring each node needs to be persisted and
+ // the channel info has updated.
+ nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &bs_update);
+ nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &as_update);
+ assert!(nodes[0].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert!(nodes[1].node.await_persistable_update_timeout(Duration::from_millis(1)));
+ assert_ne!(nodes[0].node.list_channels()[0], node_a_chan_info);
+ assert_ne!(nodes[1].node.list_channels()[0], node_b_chan_info);
+ }
+
+ #[test]
+ fn test_keysend_dup_hash_partial_mpp() {
+ // Test that a keysend payment with a duplicate hash to an existing partial MPP payment fails as
+ // expected.
+ 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, InitFeatures::known(), InitFeatures::known());
+
+ // First, send a partial MPP payment.
+ let (route, our_payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], 100_000);
+ let payment_id = PaymentId([42; 32]);
+ // Use the utility function send_payment_along_path to send the payment with MPP data which
+ // indicates there are more HTLCs coming.
+ let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
+ nodes[0].node.send_payment_along_path(&route.paths[0], &route.payment_params, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).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]], 200_000, our_payment_hash, Some(payment_secret), events.drain(..).next().unwrap(), false, None);
+
+ // Next, send a keysend payment with the same payment_hash and make sure it fails.
+ nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).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 ev = events.drain(..).next().unwrap();
+ let 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]);
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ check_added_monitors!(nodes[1], 1);
+ let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert_eq!(updates.update_fail_htlcs.len(), 1);
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ 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, true, true);
+ expect_payment_failed!(nodes[0], our_payment_hash, true);
+
+ // Send the second half of the original MPP payment.
+ nodes[0].node.send_payment_along_path(&route.paths[0], &route.payment_params, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).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]], 200_000, our_payment_hash, Some(payment_secret), events.drain(..).next().unwrap(), true, None);
+
+ // Claim the full MPP payment. Note that we can't use a test utility like
+ // claim_funds_along_route because the ordering of the messages causes the second half of the
+ // payment to be put in the holding cell, which confuses the test utilities. So we exchange the
+ // lightning messages manually.
+ assert!(nodes[1].node.claim_funds(payment_preimage));
+ check_added_monitors!(nodes[1], 2);
+ let bs_first_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(), &bs_first_updates.update_fulfill_htlcs[0]);
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_first_updates.commitment_signed);
+ check_added_monitors!(nodes[0], 1);
+ let (as_first_raa, as_first_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_first_raa);
+ check_added_monitors!(nodes[1], 1);
+ let bs_second_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_first_cs);
+ check_added_monitors!(nodes[1], 1);
+ let bs_first_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+ nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_second_updates.update_fulfill_htlcs[0]);
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_updates.commitment_signed);
+ check_added_monitors!(nodes[0], 1);
+ let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_first_raa);
+ let as_second_updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+ check_added_monitors!(nodes[0], 1);
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_second_raa);
+ check_added_monitors!(nodes[1], 1);
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_second_updates.commitment_signed);
+ check_added_monitors!(nodes[1], 1);
+ let bs_third_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa);
+ check_added_monitors!(nodes[0], 1);
+
+ // Note that successful MPP payments will generate a single PaymentSent event upon the first
+ // path's success and a PaymentPathSuccessful event for each path's success.
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 3);
+ match events[0] {
+ Event::PaymentSent { payment_id: ref id, payment_preimage: ref preimage, payment_hash: ref hash, .. } => {
+ assert_eq!(Some(payment_id), *id);
+ assert_eq!(payment_preimage, *preimage);
+ assert_eq!(our_payment_hash, *hash);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ match events[1] {
+ Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path } => {
+ assert_eq!(payment_id, *actual_payment_id);
+ assert_eq!(our_payment_hash, *payment_hash.as_ref().unwrap());
+ assert_eq!(route.paths[0], *path);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ match events[2] {
+ Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path } => {
+ assert_eq!(payment_id, *actual_payment_id);
+ assert_eq!(our_payment_hash, *payment_hash.as_ref().unwrap());
+ assert_eq!(route.paths[0], *path);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ }
+
+ #[test]
+ fn test_keysend_dup_payment_hash() {
+ // (1): Test that a keysend payment with a duplicate payment hash to an existing pending
+ // outbound regular payment fails as expected.
+ // (2): Test that a regular payment with a duplicate payment hash to an existing keysend payment
+ // fails as expected.
+ 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, InitFeatures::known(), InitFeatures::known());
+ let scorer = test_utils::TestScorer::with_penalty(0);
+ let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
+
+ // To start (1), send a regular payment but don't claim it.
+ let expected_route = [&nodes[1]];
+ let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &expected_route, 100_000);
+
+ // Next, attempt a keysend payment and make sure it fails.
+ let route_params = RouteParameters {
+ payment_params: PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id()),
+ final_value_msat: 100_000,
+ final_cltv_expiry_delta: TEST_FINAL_CLTV,
+ };
+ let route = find_route(
+ &nodes[0].node.get_our_node_id(), &route_params, nodes[0].network_graph, None,
+ nodes[0].logger, &scorer, &random_seed_bytes
+ ).unwrap();
+ nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).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 ev = events.drain(..).next().unwrap();
+ let 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]);
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ check_added_monitors!(nodes[1], 1);
+ let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert_eq!(updates.update_fail_htlcs.len(), 1);
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ 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, true, true);
+ expect_payment_failed!(nodes[0], payment_hash, true);
+
+ // Finally, claim the original payment.
+ claim_payment(&nodes[0], &expected_route, payment_preimage);
+
+ // To start (2), send a keysend payment but don't claim it.
+ let payment_preimage = PaymentPreimage([42; 32]);
+ let route = find_route(
+ &nodes[0].node.get_our_node_id(), &route_params, nodes[0].network_graph, None,
+ nodes[0].logger, &scorer, &random_seed_bytes
+ ).unwrap();
+ let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).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 event = events.pop().unwrap();
+ let path = vec![&nodes[1]];
+ pass_along_path(&nodes[0], &path, 100_000, payment_hash, None, event, true, Some(payment_preimage));
+
+ // Next, attempt a regular payment and make sure it fails.
+ let payment_secret = PaymentSecret([43; 32]);
+ nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).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 ev = events.drain(..).next().unwrap();
+ let 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]);
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ check_added_monitors!(nodes[1], 1);
+ let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert_eq!(updates.update_fail_htlcs.len(), 1);
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ 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, true, true);
+ expect_payment_failed!(nodes[0], payment_hash, true);
+
+ // Finally, succeed the keysend payment.
+ claim_payment(&nodes[0], &expected_route, payment_preimage);
+ }
+
+ #[test]
+ fn test_keysend_hash_mismatch() {
+ // Test that if we receive a keysend `update_add_htlc` msg, we fail as expected if the keysend
+ // preimage doesn't match the msg's payment hash.
+ 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);
+
+ let payer_pubkey = nodes[0].node.get_our_node_id();
+ let payee_pubkey = nodes[1].node.get_our_node_id();
+ nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
+
+ let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
+ let route_params = RouteParameters {
+ payment_params: PaymentParameters::for_keysend(payee_pubkey),
+ final_value_msat: 10000,
+ final_cltv_expiry_delta: 40,
+ };
+ let network_graph = nodes[0].network_graph;
+ let first_hops = nodes[0].node.list_usable_channels();
+ let scorer = test_utils::TestScorer::with_penalty(0);
+ let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
+ let route = find_route(
+ &payer_pubkey, &route_params, network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
+ nodes[0].logger, &scorer, &random_seed_bytes
+ ).unwrap();
+
+ let test_preimage = PaymentPreimage([42; 32]);
+ let mismatch_payment_hash = PaymentHash([43; 32]);
+ let _ = nodes[0].node.send_payment_internal(&route, mismatch_payment_hash, &None, Some(test_preimage), None, None).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+ assert_eq!(updates.update_add_htlcs.len(), 1);
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert!(updates.update_fail_htlcs.is_empty());
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
+
+ nodes[1].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "Payment preimage didn't match payment hash".to_string(), 1);
+ }
+
+ #[test]
+ fn test_keysend_msg_with_secret_err() {
+ // Test that we error as expected if we receive a keysend payment that includes a payment secret.
+ 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);
+
+ let payer_pubkey = nodes[0].node.get_our_node_id();
+ let payee_pubkey = nodes[1].node.get_our_node_id();
+ nodes[0].node.peer_connected(&payee_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
+ nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known(), remote_network_address: None });
+
+ let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known());
+ let route_params = RouteParameters {
+ payment_params: PaymentParameters::for_keysend(payee_pubkey),
+ final_value_msat: 10000,
+ final_cltv_expiry_delta: 40,
+ };
+ let network_graph = nodes[0].network_graph;
+ let first_hops = nodes[0].node.list_usable_channels();
+ let scorer = test_utils::TestScorer::with_penalty(0);
+ let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
+ let route = find_route(
+ &payer_pubkey, &route_params, network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
+ nodes[0].logger, &scorer, &random_seed_bytes
+ ).unwrap();
+
+ let test_preimage = PaymentPreimage([42; 32]);
+ let test_secret = PaymentSecret([43; 32]);
+ let payment_hash = PaymentHash(Sha256::hash(&test_preimage.0).into_inner());
+ let _ = nodes[0].node.send_payment_internal(&route, payment_hash, &Some(test_secret), Some(test_preimage), None, None).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+ assert_eq!(updates.update_add_htlcs.len(), 1);
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert!(updates.update_fail_htlcs.is_empty());
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
+
+ nodes[1].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "We don't support MPP keysend payments".to_string(), 1);
+ }
+
+ #[test]
+ fn test_multi_hop_missing_secret() {
+ 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);
+
+ let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+ let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+
+ // Marshall an MPP route.
+ let (mut route, payment_hash, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[3], 100000);
+ let path = route.paths[0].clone();
+ route.paths.push(path);
+ route.paths[0][0].pubkey = nodes[1].node.get_our_node_id();
+ route.paths[0][0].short_channel_id = chan_1_id;
+ route.paths[0][1].short_channel_id = chan_3_id;
+ route.paths[1][0].pubkey = nodes[2].node.get_our_node_id();
+ route.paths[1][0].short_channel_id = chan_2_id;
+ route.paths[1][1].short_channel_id = chan_4_id;
+
+ match nodes[0].node.send_payment(&route, payment_hash, &None).unwrap_err() {
+ PaymentSendFailure::ParameterError(APIError::APIMisuseError { ref err }) => {
+ assert!(regex::Regex::new(r"Payment secret is required for multi-path payments").unwrap().is_match(err)) },
+ _ => panic!("unexpected error")
+ }
+ }
+
+ #[test]
+ fn bad_inbound_payment_hash() {
+ // Add coverage for checking that a user-provided payment hash matches the payment secret.
+ 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);
+
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[0]);
+ let payment_data = msgs::FinalOnionHopData {
+ payment_secret,
+ total_msat: 100_000,
+ };
+
+ // Ensure that if the payment hash given to `inbound_payment::verify` differs from the original,
+ // payment verification fails as expected.
+ let mut bad_payment_hash = payment_hash.clone();
+ bad_payment_hash.0[0] += 1;
+ match inbound_payment::verify(bad_payment_hash, &payment_data, nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, &nodes[0].node.inbound_payment_key, &nodes[0].logger) {
+ Ok(_) => panic!("Unexpected ok"),
+ Err(()) => {
+ nodes[0].logger.assert_log_contains("lightning::ln::inbound_payment".to_string(), "Failing HTLC with user-generated payment_hash".to_string(), 1);
+ }
+ }
+
+ // Check that using the original payment hash succeeds.
+ assert!(inbound_payment::verify(payment_hash, &payment_data, nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, &nodes[0].node.inbound_payment_key, &nodes[0].logger).is_ok());
+ }