X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=42403f89c7d17b267af97633a6e2b3b895315fa7;hb=62fd36d795f99887260aa962a0e8f30e3b5504fa;hp=82fa06f5c80b8a5494b9b546d4e5ccb0d4287999;hpb=a37a16a3ce25023fe9ff3c45dcba7e6b942f2de8;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 82fa06f5..42403f89 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -15,7 +15,7 @@ use crate::sign::EntropySource; use crate::chain::channelmonitor::ChannelMonitor; use crate::chain::transaction::OutPoint; use crate::events::{ClaimedHTLC, ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, PaymentFailureReason}; -use crate::events::bump_transaction::{BumpTransactionEventHandler, Wallet, WalletSource}; +use crate::events::bump_transaction::{BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource}; use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret}; use crate::ln::channelmanager::{AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, PaymentId, MIN_CLTV_EXPIRY_DELTA}; use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate}; @@ -665,6 +665,12 @@ pub fn get_err_msg(node: &Node, recipient: &PublicKey) -> msgs::ErrorMessage { assert_eq!(node_id, recipient); (*msg).clone() }, + MessageSendEvent::HandleError { + action: msgs::ErrorAction::DisconnectPeer { ref msg }, ref node_id + } => { + assert_eq!(node_id, recipient); + msg.as_ref().unwrap().clone() + }, _ => panic!("Unexpected event"), } } @@ -1446,10 +1452,15 @@ pub fn check_closed_broadcast(node: &Node, num_channels: usize, with_error_msg: assert_eq!(msg.contents.flags & 2, 2); None }, - MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => { + MessageSendEvent::HandleError { action: msgs::ErrorAction::SendErrorMessage { msg }, node_id: _ } => { assert!(with_error_msg); // TODO: Check node_id - Some(msg.clone()) + Some(msg) + }, + MessageSendEvent::HandleError { action: msgs::ErrorAction::DisconnectPeer { msg }, node_id: _ } => { + assert!(with_error_msg); + // TODO: Check node_id + Some(msg.unwrap()) }, _ => panic!("Unexpected event"), } @@ -1473,12 +1484,12 @@ pub fn check_closed_event(node: &Node, events_count: usize, expected_reason: Clo let events = node.node.get_and_clear_pending_events(); assert_eq!(events.len(), events_count, "{:?}", events); let mut issues_discard_funding = false; - for (idx, event) in events.into_iter().enumerate() { + for event in events { match event { - Event::ChannelClosed { ref reason, counterparty_node_id, + Event::ChannelClosed { ref reason, counterparty_node_id, channel_capacity_sats, .. } => { assert_eq!(*reason, expected_reason); - assert_eq!(counterparty_node_id.unwrap(), expected_counterparty_node_ids[idx]); + assert!(expected_counterparty_node_ids.iter().any(|id| id == &counterparty_node_id.unwrap())); assert_eq!(channel_capacity_sats.unwrap(), expected_channel_capacity); }, Event::DiscardFunding { .. } => { @@ -1499,11 +1510,26 @@ macro_rules! check_closed_event { check_closed_event!($node, $events, $reason, false, $counterparty_node_ids, $channel_capacity); }; ($node: expr, $events: expr, $reason: expr, $is_check_discard_funding: expr, $counterparty_node_ids: expr, $channel_capacity: expr) => { - $crate::ln::functional_test_utils::check_closed_event(&$node, $events, $reason, + $crate::ln::functional_test_utils::check_closed_event(&$node, $events, $reason, $is_check_discard_funding, &$counterparty_node_ids, $channel_capacity); } } +pub fn handle_bump_htlc_event(node: &Node, count: usize) { + let events = node.chain_monitor.chain_monitor.get_and_clear_pending_events(); + assert_eq!(events.len(), count); + for event in events { + match event { + Event::BumpTransaction(bump_event) => { + if let BumpTransactionEvent::HTLCResolution { .. } = &bump_event {} + else { panic!(); } + node.bump_tx_handler.handle_event(&bump_event); + }, + _ => panic!(), + } + } +} + pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: &Node<'a, 'b, 'c>, channel_id: &ChannelId, funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, Transaction) { let (node_a, broadcaster_a, struct_a) = if close_inbound_first { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) } else { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) }; let (node_b, broadcaster_b, struct_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) } else { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) }; @@ -1882,7 +1908,11 @@ macro_rules! get_route_and_payment_hash { $crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value) }}; ($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr) => {{ - let route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value($payment_params, $recv_value); + $crate::get_route_and_payment_hash!($send_node, $recv_node, $payment_params, $recv_value, None) + }}; + ($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr, $max_total_routing_fee_msat: expr) => {{ + let mut route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value($payment_params, $recv_value); + route_params.max_total_routing_fee_msat = $max_total_routing_fee_msat; let (payment_preimage, payment_hash, payment_secret) = $crate::ln::functional_test_utils::get_payment_preimage_hash(&$recv_node, Some($recv_value), None); let route = $crate::ln::functional_test_utils::get_route(&$send_node, &route_params); @@ -2776,7 +2806,8 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec(nodes: &Vec { + assert_eq!(node_id, nodes[b].node.get_our_node_id()); + assert_eq!(msg.as_ref().unwrap().data, expected_error); + if needs_err_handle { + nodes[b].node.handle_error(&nodes[a].node.get_our_node_id(), msg.as_ref().unwrap()); + } + }, _ => panic!("Unexpected event"), } @@ -2918,6 +2956,10 @@ pub fn handle_announce_close_broadcast_events<'a, 'b, 'c>(nodes: &Vec { + assert_eq!(node_id, nodes[a].node.get_our_node_id()); + assert_eq!(msg.as_ref().unwrap().data, expected_error); + }, _ => panic!("Unexpected event"), } } @@ -3262,3 +3304,76 @@ pub fn reconnect_nodes<'a, 'b, 'c, 'd>(args: ReconnectArgs<'a, 'b, 'c, 'd>) { } } } + +/// Initiates channel opening and creates a single batch funding transaction. +/// This will go through the open_channel / accept_channel flow, and return the batch funding +/// transaction with corresponding funding_created messages. +pub fn create_batch_channel_funding<'a, 'b, 'c>( + funding_node: &Node<'a, 'b, 'c>, + params: &[(&Node<'a, 'b, 'c>, u64, u64, u128, Option)], +) -> (Transaction, Vec) { + let mut tx_outs = Vec::new(); + let mut temp_chan_ids = Vec::new(); + let mut funding_created_msgs = Vec::new(); + + for (other_node, channel_value_satoshis, push_msat, user_channel_id, override_config) in params { + // 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, + *override_config, + ).unwrap(); + let open_channel_msg = get_event_msg!(funding_node, MessageSendEvent::SendOpenChannel, other_node.node.get_our_node_id()); + other_node.node.handle_open_channel(&funding_node.node.get_our_node_id(), &open_channel_msg); + let accept_channel_msg = get_event_msg!(other_node, MessageSendEvent::SendAcceptChannel, funding_node.node.get_our_node_id()); + funding_node.node.handle_accept_channel(&other_node.node.get_our_node_id(), &accept_channel_msg); + + // Create the corresponding funding output. + let events = funding_node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match events[0] { + Event::FundingGenerationReady { + ref temporary_channel_id, + ref counterparty_node_id, + channel_value_satoshis: ref event_channel_value_satoshis, + ref output_script, + user_channel_id: ref event_user_channel_id + } => { + assert_eq!(temporary_channel_id, &temp_chan_id); + assert_eq!(counterparty_node_id, &other_node.node.get_our_node_id()); + assert_eq!(channel_value_satoshis, event_channel_value_satoshis); + assert_eq!(user_channel_id, event_user_channel_id); + tx_outs.push(TxOut { + value: *channel_value_satoshis, script_pubkey: output_script.clone(), + }); + }, + _ => panic!("Unexpected event"), + }; + temp_chan_ids.push((temp_chan_id, other_node.node.get_our_node_id())); + } + + // Compose the batch funding transaction and give it to the ChannelManager. + let tx = Transaction { + version: 2, + lock_time: PackedLockTime::ZERO, + input: Vec::new(), + output: tx_outs, + }; + assert!(funding_node.node.batch_funding_transaction_generated( + temp_chan_ids.iter().map(|(a, b)| (a, b)).collect::>().as_slice(), + tx.clone(), + ).is_ok()); + check_added_monitors!(funding_node, 0); + let events = funding_node.node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), params.len()); + for (other_node, ..) in params { + let funding_created = events + .iter() + .find_map(|event| match event { + MessageSendEvent::SendFundingCreated { node_id, msg } if node_id == &other_node.node.get_our_node_id() => Some(msg.clone()), + _ => None, + }) + .unwrap(); + funding_created_msgs.push(funding_created); + } + return (tx, funding_created_msgs); +}