use chain::keysinterface::{ChannelKeys, KeysInterface, SpendableOutputDescriptor};
use chain::chaininterface::{ChainListener, ChainWatchInterfaceUtil, BlockNotifier};
use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
-use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, BREAKDOWN_TIMEOUT};
+use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure, BREAKDOWN_TIMEOUT};
use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
use ln::channel::{Channel, ChannelError};
use ln::{chan_utils, onion_utils};
// ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]...
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[1].node.send_payment(nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 40000, TEST_FINAL_CLTV).unwrap(), our_payment_hash, &None).unwrap();
+ nodes[1].node.send_payment(&nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 40000, TEST_FINAL_CLTV).unwrap(), our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[1], 1);
let payment_event = {
// ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]...
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[1].node.send_payment(nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 40000, TEST_FINAL_CLTV).unwrap(), our_payment_hash, &None).unwrap();
+ nodes[1].node.send_payment(&nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 40000, TEST_FINAL_CLTV).unwrap(), our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[1], 1);
let payment_event = {
let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[1]);
// nothing happens since node[1] is in AwaitingRemoteRevoke
- nodes[1].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[1].node.send_payment(&route, our_payment_hash, &None).unwrap();
{
let mut added_monitors = nodes[0].chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 0);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
- if let Err(APIError::ChannelUnavailable {..}) = nodes[0].node.send_payment(route_1, payment_hash, &None) {}
- else { panic!("New sends should fail!") };
- if let Err(APIError::ChannelUnavailable {..}) = nodes[1].node.send_payment(route_2, payment_hash, &None) {}
- else { panic!("New sends should fail!") };
+ unwrap_send_err!(nodes[0].node.send_payment(&route_1, payment_hash, &None), true, APIError::ChannelUnavailable {..}, {});
+ unwrap_send_err!(nodes[1].node.send_payment(&route_2, payment_hash, &None), true, APIError::ChannelUnavailable {..}, {});
assert!(nodes[2].node.claim_funds(our_payment_preimage, &None, 100_000));
check_added_monitors!(nodes[2], 1);
let route = nodes[0].router.get_route(&nodes[2].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &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);
});
hops[1].fee_msat = chan_4.1.contents.fee_base_msat as u64 + chan_4.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
hops[0].fee_msat = chan_3.0.contents.fee_base_msat as u64 + chan_3.0.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
- let payment_preimage_1 = send_along_route(&nodes[1], Route { hops }, &vec!(&nodes[2], &nodes[3], &nodes[1])[..], 1000000).0;
+ let payment_preimage_1 = send_along_route(&nodes[1], Route { paths: vec![hops] }, &vec!(&nodes[2], &nodes[3], &nodes[1])[..], 1000000).0;
let mut hops = Vec::with_capacity(3);
hops.push(RouteHop {
});
hops[1].fee_msat = chan_2.1.contents.fee_base_msat as u64 + chan_2.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
hops[0].fee_msat = chan_3.1.contents.fee_base_msat as u64 + chan_3.1.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
- let payment_hash_2 = send_along_route(&nodes[1], Route { hops }, &vec!(&nodes[3], &nodes[2], &nodes[1])[..], 1000000).1;
+ let payment_hash_2 = send_along_route(&nodes[1], Route { paths: vec![hops] }, &vec!(&nodes[3], &nodes[2], &nodes[1])[..], 1000000).1;
// Claim the rebalances...
fail_payment(&nodes[1], &vec!(&nodes[3], &nodes[2], &nodes[1])[..], payment_hash_2);
for _ in 0..::ln::channel::OUR_MAX_HTLCS {
let route = nodes[1].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 100000, TEST_FINAL_CLTV).unwrap();
let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[1].node.send_payment(route, payment_hash, &None).unwrap();
+ nodes[1].node.send_payment(&route, payment_hash, &None).unwrap();
payments.push((payment_preimage, payment_hash));
}
check_added_monitors!(nodes[1], 1);
// another HTLC.
let route = nodes[1].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 100000, TEST_FINAL_CLTV).unwrap();
let (_, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
- if let APIError::ChannelUnavailable { err } = nodes[1].node.send_payment(route, payment_hash_1, &None).unwrap_err() {
- assert_eq!(err, "Cannot push more than their max accepted HTLCs");
- } else { panic!("Unexpected event"); }
+ unwrap_send_err!(nodes[1].node.send_payment(&route, payment_hash_1, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot push more than their max accepted HTLCs"));
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot push more than their max accepted HTLCs".to_string(), 1);
// This should also be true if we try to forward a payment.
let route = nodes[0].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 100000, TEST_FINAL_CLTV).unwrap();
let (_, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, payment_hash_2, &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
// attempt to send amt_msat > their_max_htlc_value_in_flight_msat
{
let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_0 + 1);
- assert!(route.hops.iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
- let err = nodes[0].node.send_payment(route, our_payment_hash, &None).err().unwrap();
- match err {
- APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"),
- _ => panic!("Unknown error variants"),
- }
+ assert!(route.paths[0].iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over the max HTLC value in flight our peer will accept".to_string(), 1);
}
let recv_value = stat01.value_to_self_msat - stat01.channel_reserve_msat - total_fee_msat;
// attempt to get channel_reserve violation
let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value + 1);
- let err = nodes[0].node.send_payment(route.clone(), our_payment_hash, &None).err().unwrap();
- match err {
- APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over their reserve value"),
- _ => panic!("Unknown error variants"),
- }
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot send value that would put us over their reserve value"));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over their reserve value".to_string(), 1);
}
let (route_1, our_payment_hash_1, our_payment_preimage_1) = get_route_and_payment_hash!(recv_value_1);
let payment_event_1 = {
- nodes[0].node.send_payment(route_1, our_payment_hash_1, &None).unwrap();
+ nodes[0].node.send_payment(&route_1, our_payment_hash_1, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
let recv_value_2 = stat01.value_to_self_msat - amt_msat_1 - stat01.channel_reserve_msat - total_fee_msat;
{
let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_2 + 1);
- match nodes[0].node.send_payment(route, our_payment_hash, &None).err().unwrap() {
- APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over their reserve value"),
- _ => panic!("Unknown error variants"),
- }
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot send value that would put us over their reserve value"));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over their reserve value".to_string(), 2);
}
}).expect("RNG is bad!");
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
- let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
- let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, cur_height).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
+ let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], recv_value_2 + 1, &None, cur_height).unwrap();
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash);
let msg = msgs::UpdateAddHTLC {
channel_id: chan_1.2,
// now see if they go through on both sides
let (route_21, our_payment_hash_21, our_payment_preimage_21) = get_route_and_payment_hash!(recv_value_21);
// but this will stuck in the holding cell
- nodes[0].node.send_payment(route_21, our_payment_hash_21, &None).unwrap();
+ nodes[0].node.send_payment(&route_21, our_payment_hash_21, &None).unwrap();
check_added_monitors!(nodes[0], 0);
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 0);
// test with outbound holding cell amount > 0
{
let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_22+1);
- match nodes[0].node.send_payment(route, our_payment_hash, &None).err().unwrap() {
- APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over their reserve value"),
- _ => panic!("Unknown error variants"),
- }
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot send value that would put us over their reserve value"));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over their reserve value".to_string(), 3);
}
let (route_22, our_payment_hash_22, our_payment_preimage_22) = get_route_and_payment_hash!(recv_value_22);
// this will also stuck in the holding cell
- nodes[0].node.send_payment(route_22, our_payment_hash_22, &None).unwrap();
+ nodes[0].node.send_payment(&route_22, our_payment_hash_22, &None).unwrap();
check_added_monitors!(nodes[0], 0);
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
let (payment_preimage_3, payment_hash_3) = get_payment_preimage_hash!(nodes[0]);
let send_1 = {
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
- nodes[0].node.send_payment(route, payment_hash_3, &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_3, &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);
let (payment_preimage_4, payment_hash_4) = get_payment_preimage_hash!(nodes[1]);
let send_2 = {
let route = nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &[], 10000, TEST_FINAL_CLTV).unwrap();
- nodes[1].node.send_payment(route, payment_hash_4, &None).unwrap();
+ nodes[1].node.send_payment(&route, payment_hash_4, &None).unwrap();
check_added_monitors!(nodes[1], 1);
let mut events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
// on nodes[2]'s RAA.
let route = nodes[1].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
let (_, fourth_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[1].node.send_payment(route, fourth_payment_hash, &None).unwrap();
+ nodes[1].node.send_payment(&route, fourth_payment_hash, &None).unwrap();
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
check_added_monitors!(nodes[1], 0);
{
let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 50_000, TEST_FINAL_CLTV).unwrap();
- nodes[0].node.send_payment(route, payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let payment_event = {
let (_, failed_payment_hash) = get_payment_preimage_hash!(nodes[0]);
{
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 50_000, TEST_FINAL_CLTV).unwrap();
- nodes[0].node.send_payment(route, failed_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, failed_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 0);
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
};
let current_height = nodes[1].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
- let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route, &None, current_height).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
+ let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &None, current_height).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
// Send a 0-msat update_add_htlc to fail the channel.
let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
let mut payment_event = {
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
let payment_event = {
- nodes[0].node.send_payment(route.clone(), payment_hash_1, &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_1, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route.clone(), payment_hash_2, &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), if use_dust { 50000 } else { 3000000 }, TEST_FINAL_CLTV).unwrap();
let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let _as_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
}
// 0 ~~> 2 send payment
- nodes[0].node.send_payment(route.clone(), payment_hash.clone(), &None).unwrap();
+ nodes[0].node.send_payment(&route, payment_hash.clone(), &None).unwrap();
check_added_monitors!(nodes[0], 1);
let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
// temper update_add (0 => 1)
run_onion_failure_test("invalid_realm", 0, &nodes, &route, &payment_hash, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
- let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, cur_height).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
+ let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height).unwrap();
let mut new_payloads = Vec::new();
for payload in onion_payloads.drain(..) {
new_payloads.push(BogusOnionHopData::new(payload));
run_onion_failure_test("invalid_realm", 3, &nodes, &route, &payment_hash, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
- let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, cur_height).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
+ let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height).unwrap();
let mut new_payloads = Vec::new();
for payload in onion_payloads.drain(..) {
new_payloads.push(BogusOnionHopData::new(payload));
}, |msg| {
// and tamper returning error message
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], NODE|2, &[0;0]);
- }, ||{}, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[0].pubkey, is_permanent: false}));
+ }, ||{}, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: false}));
// final node failure
run_onion_failure_test_with_fail_intercept("temporary_node_failure", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
// and tamper returning error message
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], NODE|2, &[0;0]);
}, ||{
nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
- }, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: false}));
+ }, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: false}));
// intermediate node failure
run_onion_failure_test_with_fail_intercept("permanent_node_failure", 100, &nodes, &route, &payment_hash, |msg| {
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|NODE|2, &[0;0]);
- }, ||{}, true, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[0].pubkey, is_permanent: true}));
+ }, ||{}, true, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: true}));
// final node failure
run_onion_failure_test_with_fail_intercept("permanent_node_failure", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], PERM|NODE|2, &[0;0]);
}, ||{
nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
- }, false, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: true}));
+ }, false, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: true}));
// intermediate node failure
run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 100, &nodes, &route, &payment_hash, |msg| {
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|NODE|3, &[0;0]);
}, ||{
nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
- }, true, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[0].pubkey, is_permanent: true}));
+ }, true, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: true}));
// final node failure
run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], PERM|NODE|3, &[0;0]);
}, ||{
nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
- }, false, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: true}));
+ }, false, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: true}));
run_onion_failure_test("invalid_onion_version", 0, &nodes, &route, &payment_hash, |msg| { msg.onion_routing_packet.version = 1; }, ||{}, true,
Some(BADONION|PERM|4), None);
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], UPDATE|7, &ChannelUpdate::dummy().encode_with_len()[..]);
}, ||{}, true, Some(UPDATE|7), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|8, &[0;0]);
// short_channel_id from the processing node
}, ||{}, true, Some(PERM|8), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|9, &[0;0]);
// short_channel_id from the processing node
}, ||{}, true, Some(PERM|9), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));
let mut bogus_route = route.clone();
- bogus_route.hops[1].short_channel_id -= 1;
+ bogus_route.paths[0][1].short_channel_id -= 1;
run_onion_failure_test("unknown_next_peer", 0, &nodes, &bogus_route, &payment_hash, |_| {}, ||{}, true, Some(PERM|10),
- Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: bogus_route.hops[1].short_channel_id, is_permanent:true}));
+ Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: bogus_route.paths[0][1].short_channel_id, is_permanent:true}));
let amt_to_forward = nodes[1].node.channel_state.lock().unwrap().by_id.get(&channels[1].2).unwrap().get_their_htlc_minimum_msat() - 1;
let mut bogus_route = route.clone();
- let route_len = bogus_route.hops.len();
- bogus_route.hops[route_len-1].fee_msat = amt_to_forward;
+ let route_len = bogus_route.paths[0].len();
+ bogus_route.paths[0][route_len-1].fee_msat = amt_to_forward;
run_onion_failure_test("amount_below_minimum", 0, &nodes, &bogus_route, &payment_hash, |_| {}, ||{}, true, Some(UPDATE|11), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
//TODO: with new config API, we will be able to generate both valid and
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let mut route = route.clone();
let height = 1;
- route.hops[1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.hops[0].cltv_expiry_delta + 1;
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
- let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, height).unwrap();
+ route.paths[0][1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.paths[0][0].cltv_expiry_delta + 1;
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
+ let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, height).unwrap();
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
msg.cltv_expiry = htlc_cltv;
msg.onion_routing_packet = onion_packet;
let mut route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- route.hops[0].fee_msat = 100;
+ route.paths[0][0].fee_msat = 100;
- let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
-
- if let Err(APIError::ChannelUnavailable{err}) = err {
- assert_eq!(err, "Cannot send less than their minimum HTLC value");
- } else {
- assert!(false);
- }
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot send less than their minimum HTLC value"));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send less than their minimum HTLC value".to_string(), 1);
}
let mut route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- route.hops[0].fee_msat = 0;
-
- let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
+ route.paths[0][0].fee_msat = 0;
- if let Err(APIError::ChannelUnavailable{err}) = err {
- assert_eq!(err, "Cannot send 0-msat HTLC");
- } else {
- assert!(false);
- }
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot send 0-msat HTLC"));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send 0-msat HTLC".to_string(), 1);
}
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
updates.update_add_htlcs[0].amount_msat = 0;
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000000, 500000001).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
-
- if let Err(APIError::RouteError{err}) = err {
- assert_eq!(err, "Channel CLTV overflowed?!");
- } else {
- assert!(false);
- }
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::RouteError { err },
+ assert_eq!(err, "Channel CLTV overflowed?!"));
}
#[test]
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
let payment_event = {
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
}
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot push more than their max accepted HTLCs"));
- if let Err(APIError::ChannelUnavailable{err}) = err {
- assert_eq!(err, "Cannot push more than their max accepted HTLCs");
- } else {
- assert!(false);
- }
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot push more than their max accepted HTLCs".to_string(), 1);
}
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], max_in_flight+1, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
+ unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+ assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
- if let Err(APIError::ChannelUnavailable{err}) = err {
- assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept");
- } else {
- assert!(false);
- }
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over the max HTLC value in flight our peer will accept".to_string(), 1);
}
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], htlc_minimum_msat, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
updates.update_add_htlcs[0].amount_msat = htlc_minimum_msat-1;
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 5000000-their_channel_reserve, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
}).expect("RNG is bad!");
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
- let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route, &session_priv).unwrap();
- let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, cur_height).unwrap();
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route.paths[0], &session_priv).unwrap();
+ let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &None, cur_height).unwrap();
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash);
let mut msg = msgs::UpdateAddHTLC {
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::supported(), InitFeatures::supported());
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
updates.update_add_htlcs[0].amount_msat = get_channel_value_stat!(nodes[1], chan.2).their_max_htlc_value_in_flight_msat + 1;
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::supported(), InitFeatures::supported());
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 3999999, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
updates.update_add_htlcs[0].cltv_expiry = 500000000;
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported());
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::supported(), InitFeatures::supported());
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
check_added_monitors!(nodes[0], 1);
let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
//First hop
let mut payment_event = {
- nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+ nodes[0].node.send_payment(&route, our_payment_hash, &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);
let (payment_preimage, payment_hash) = get_payment_preimage_hash!(&nodes[0]);
let payment_secret = PaymentSecret([0xdb; 32]);
let route = nodes[0].router.get_route(&nodes[2].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
- send_along_route_with_secret(&nodes[0], route, &[&nodes[1], &nodes[2]], 100000, payment_hash, Some(payment_secret.clone()));
+ send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2]]], 100000, payment_hash, Some(payment_secret.clone()));
// Claiming with all the correct values but the wrong secret should result in nothing...
assert_eq!(nodes[2].node.claim_funds(payment_preimage, &None, 100_000), false);
assert_eq!(nodes[2].node.claim_funds(payment_preimage, &Some(PaymentSecret([42; 32])), 100_000), false);
// ...but with the right secret we should be able to claim all the way back
- claim_payment_along_route_with_secret(&nodes[0], &[&nodes[1], &nodes[2]], false, payment_preimage, Some(payment_secret.clone()), 100_000);
+ claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage, Some(payment_secret.clone()), 100_000);
+}
+
+#[test]
+fn test_simple_mpp() {
+ // Simple test of sending a multi-path payment.
+ 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::supported(), InitFeatures::supported()).0.contents.short_channel_id;
+ let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
+ let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
+ let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
+
+ let (payment_preimage, payment_hash) = get_payment_preimage_hash!(&nodes[0]);
+ let payment_secret = PaymentSecret([0xdb; 32]);
+ let mut route = nodes[0].router.get_route(&nodes[3].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
+ 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;
+ send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 200_000, payment_hash, Some(payment_secret.clone()));
+ // Claiming with all the correct values but the wrong secret should result in nothing...
+ assert_eq!(nodes[3].node.claim_funds(payment_preimage, &None, 200_000), false);
+ assert_eq!(nodes[3].node.claim_funds(payment_preimage, &Some(PaymentSecret([42; 32])), 200_000), false);
+ // ...but with the right secret we should be able to claim all the way back
+ claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage, Some(payment_secret), 200_000);
}