+
+/// 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<UserConfig>)],
+) -> (Transaction, Vec<msgs::FundingCreated>) {
+ 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,
+ None,
+ *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: LockTime::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::<Vec<_>>().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);
+}