MessageSendEvent::SendOpenChannelV2 { node_id, .. } => {
node_id == msg_node_id
},
+ MessageSendEvent::SendStfu { node_id, .. } => {
+ node_id == msg_node_id
+ },
+ MessageSendEvent::SendSplice { node_id, .. } => {
+ node_id == msg_node_id
+ },
+ MessageSendEvent::SendSpliceAck { node_id, .. } => {
+ node_id == msg_node_id
+ },
+ MessageSendEvent::SendSpliceLocked { node_id, .. } => {
+ node_id == msg_node_id
+ },
MessageSendEvent::SendTxAddInput { node_id, .. } => {
node_id == msg_node_id
},
let initiator_channels = initiator.node.list_usable_channels().len();
let receiver_channels = receiver.node.list_usable_channels().len();
- initiator.node.create_channel(receiver.node.get_our_node_id(), 100_000, 10_001, 42, initiator_config).unwrap();
+ initiator.node.create_channel(receiver.node.get_our_node_id(), 100_000, 10_001, 42, None, initiator_config).unwrap();
let open_channel = get_event_msg!(initiator, MessageSendEvent::SendOpenChannel, receiver.node.get_our_node_id());
receiver.node.handle_open_channel(&initiator.node.get_our_node_id(), &open_channel);
}
pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> Transaction {
- let create_chan_id = node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None).unwrap();
+ let create_chan_id = node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None).unwrap();
let open_channel_msg = get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id());
assert_eq!(open_channel_msg.temporary_channel_id, create_chan_id);
assert_eq!(node_a.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 42);
pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, 'c, 'd>>, a: usize, b: usize, channel_value: u64, push_msat: u64) -> (msgs::ChannelReady, Transaction) {
let mut no_announce_cfg = test_default_channel_config();
no_announce_cfg.channel_handshake_config.announced_channel = false;
- nodes[a].node.create_channel(nodes[b].node.get_our_node_id(), channel_value, push_msat, 42, Some(no_announce_cfg)).unwrap();
+ nodes[a].node.create_channel(nodes[b].node.get_our_node_id(), channel_value, push_msat, 42, None, Some(no_announce_cfg)).unwrap();
let open_channel = get_event_msg!(nodes[a], MessageSendEvent::SendOpenChannel, nodes[b].node.get_our_node_id());
nodes[b].node.handle_open_channel(&nodes[a].node.get_our_node_id(), &open_channel);
let accept_channel = get_event_msg!(nodes[b], MessageSendEvent::SendAcceptChannel, nodes[a].node.get_our_node_id());
}
}
+#[cfg(any(test, feature = "_test_utils"))]
+pub fn expect_probe_successful_events(node: &Node, mut probe_results: Vec<(PaymentHash, PaymentId)>) {
+ let mut events = node.node.get_and_clear_pending_events();
+
+ for event in events.drain(..) {
+ match event {
+ Event::ProbeSuccessful { payment_hash: ev_ph, payment_id: ev_pid, ..} => {
+ let result_idx = probe_results.iter().position(|(payment_hash, payment_id)| *payment_hash == ev_ph && *payment_id == ev_pid);
+ assert!(result_idx.is_some());
+
+ probe_results.remove(result_idx.unwrap());
+ },
+ _ => panic!(),
+ }
+ };
+
+ // Ensure that we received a ProbeSuccessful event for each probe result.
+ assert!(probe_results.is_empty());
+}
+
pub struct PaymentFailedConditions<'a> {
pub(crate) expected_htlc_error_data: Option<(u16, &'a [u8])>,
pub(crate) expected_blamed_scid: Option<u64>,
payment_id
}
-pub fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<PaymentSecret>, ev: MessageSendEvent, payment_claimable_expected: bool, clear_recipient_events: bool, expected_preimage: Option<PaymentPreimage>) -> Option<Event> {
+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 fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<PaymentSecret>, ev: MessageSendEvent, payment_claimable_expected: bool, clear_recipient_events: bool, expected_preimage: Option<PaymentPreimage>, is_probe: bool) -> Option<Event> {
let mut payment_event = SendEvent::from_event(ev);
let mut prev_node = origin_node;
let mut event = None;
for (idx, &node) in expected_path.iter().enumerate() {
+ let is_last_hop = idx == expected_path.len() - 1;
assert_eq!(node.node.get_our_node_id(), payment_event.node_id);
node.node.handle_update_add_htlc(&prev_node.node.get_our_node_id(), &payment_event.msgs[0]);
check_added_monitors!(node, 0);
- commitment_signed_dance!(node, prev_node, payment_event.commitment_msg, false);
- expect_pending_htlcs_forwardable!(node);
+ if is_last_hop && is_probe {
+ commitment_signed_dance!(node, prev_node, payment_event.commitment_msg, true, true);
+ } else {
+ commitment_signed_dance!(node, prev_node, payment_event.commitment_msg, false);
+ expect_pending_htlcs_forwardable!(node);
+ }
- if idx == expected_path.len() - 1 && clear_recipient_events {
+ if is_last_hop && clear_recipient_events {
let events_2 = node.node.get_and_clear_pending_events();
if payment_claimable_expected {
assert_eq!(events_2.len(), 1);
} else {
assert!(events_2.is_empty());
}
- } else if idx != expected_path.len() - 1 {
+ } else if !is_last_hop {
let mut events_2 = node.node.get_and_clear_pending_msg_events();
assert_eq!(events_2.len(), 1);
check_added_monitors!(node, 1);
}
pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option<PaymentSecret>, ev: MessageSendEvent, payment_claimable_expected: bool, expected_preimage: Option<PaymentPreimage>) -> Option<Event> {
- do_pass_along_path(origin_node, expected_path, recv_value, our_payment_hash, our_payment_secret, ev, payment_claimable_expected, true, expected_preimage)
+ do_pass_along_path(origin_node, expected_path, recv_value, our_payment_hash, our_payment_secret, ev, payment_claimable_expected, true, expected_preimage, false)
+}
+
+pub fn send_probe_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]]) {
+ let mut events = origin_node.node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), expected_route.len());
+
+ check_added_monitors!(origin_node, expected_route.len());
+
+ for path in expected_route.iter() {
+ let ev = remove_first_msg_event_to_node(&path[0].node.get_our_node_id(), &mut events);
+
+ do_pass_along_path(origin_node, path, 0, PaymentHash([0_u8; 32]), None, ev, false, false, None, true);
+ let nodes_to_fail_payment: Vec<_> = vec![origin_node].into_iter().chain(path.iter().cloned()).collect();
+
+ fail_payment_along_path(nodes_to_fail_payment.as_slice());
+ }
}
pub fn pass_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret) {
let mut events = origin_node.node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), expected_route.len());
+
for (path_idx, expected_path) in expected_route.iter().enumerate() {
let ev = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events);
// Once we've gotten through all the HTLCs, the last one should result in a
- // PaymentClaimable (but each previous one should not!), .
+ // PaymentClaimable (but each previous one should not!).
let expect_payment = path_idx == expected_route.len() - 1;
pass_along_path(origin_node, expected_path, recv_value, our_payment_hash.clone(), Some(our_payment_secret), ev, expect_payment, None);
}
// Initialize channel opening.
let temp_chan_id = funding_node.node.create_channel(
other_node.node.get_our_node_id(), *channel_value_satoshis, *push_msat, *user_channel_id,
+ None,
*override_config,
).unwrap();
let open_channel_msg = get_event_msg!(funding_node, MessageSendEvent::SendOpenChannel, other_node.node.get_our_node_id());