@@ -13515,20 +13515,24 @@ mod tests {
1351513515 use bitcoin::hashes::sha256::Hash as Sha256;
1351613516 use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
1351713517 use core::sync::atomic::Ordering;
13518+ use crate::chain::chaininterface::{ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
1351813519 use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
1351913520 use crate::ln::types::ChannelId;
1352013521 use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
13522+ use crate::ln::chan_utils::{make_funding_redeemscript, ChannelPublicKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters};
13523+ use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint};
13524+ use crate::ln::channel::{calculate_our_funding_satoshis, OutboundV2Channel, MIN_CHAN_DUST_LIMIT_SATOSHIS};
1352113525 use crate::ln::channelmanager::{create_recv_pending_htlc_info, HTLCForwardInfo, inbound_payment, PaymentId, PaymentSendFailure, RecipientOnionFields, InterceptId};
1352213526 use crate::ln::functional_test_utils::*;
13523- use crate::ln::msgs::{self, ErrorAction};
13527+ use crate::ln::msgs::{self, CommitmentSigned, ErrorAction, TxAddInput, TxAddOutput, TxComplete };
1352413528 use crate::ln::msgs::ChannelMessageHandler;
1352513529 use crate::prelude::*;
1352613530 use crate::routing::router::{PaymentParameters, RouteParameters, find_route};
1352713531 use crate::util::errors::APIError;
13528- use crate::util::ser::Writeable;
13532+ use crate::util::ser::{TransactionU16LenLimited, Writeable} ;
1352913533 use crate::util::test_utils;
1353013534 use crate::util::config::{ChannelConfig, ChannelConfigUpdate};
13531- use crate::sign::EntropySource;
13535+ use crate::sign::{ EntropySource, ChannelSigner as _} ;
1353213536
1353313537 #[test]
1353413538 fn test_notify_limits() {
@@ -14919,7 +14923,153 @@ mod tests {
1491914923 }
1492014924
1492114925 // Dual-funding: V2 Channel Establishment Tests
14922- // TODO(dual_funding): Complete these.
14926+ struct V2ChannelEstablishmentTestSession {
14927+ initiator_input_value_satoshis: u64,
14928+ }
14929+
14930+ // TODO(dual_funding): Use real node and API for creating V2 channels as initiator when available,
14931+ // instead of manually constructing messages.
14932+ fn do_test_v2_channel_establishment(session: V2ChannelEstablishmentTestSession) {
14933+ let chanmon_cfgs = create_chanmon_cfgs(2);
14934+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
14935+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
14936+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
14937+ let logger_a = test_utils::TestLogger::with_id("node a".to_owned());
14938+
14939+ // Create a funding input for the new channel along with its previous transaction.
14940+ let initiator_funding_inputs: Vec<_> = create_dual_funding_utxos_with_prev_txs(
14941+ &nodes[0], &[session.initiator_input_value_satoshis]
14942+ ).into_iter().map(|(txin, tx)| (txin, TransactionU16LenLimited::new(tx).unwrap())).collect();
14943+
14944+ // Alice creates a dual-funded channel as initiator.
14945+ let funding_feerate = node_cfgs[0].fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee);
14946+ let funding_satoshis = calculate_our_funding_satoshis(
14947+ true, &initiator_funding_inputs[..], funding_feerate, MIN_CHAN_DUST_LIMIT_SATOSHIS
14948+ ).unwrap();
14949+ let mut channel = OutboundV2Channel::new(
14950+ &LowerBoundedFeeEstimator(node_cfgs[0].fee_estimator), &nodes[0].node.entropy_source, &nodes[0].node.signer_provider,
14951+ nodes[1].node.get_our_node_id(), &nodes[1].node.init_features(), funding_satoshis,
14952+ initiator_funding_inputs.clone(), 42 /* user_channel_id */, &nodes[0].node.default_configuration, nodes[0].best_block_info().1,
14953+ nodes[0].node.create_and_insert_outbound_scid_alias(), ConfirmationTarget::NonAnchorChannelFee, &logger_a).unwrap();
14954+ let open_channel_v2_msg = channel.get_open_channel_v2(nodes[0].chain_source.chain_hash);
14955+
14956+ nodes[1].node.handle_open_channel_v2(nodes[0].node.get_our_node_id(), &open_channel_v2_msg);
14957+
14958+ let accept_channel_v2_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannelV2, nodes[0].node.get_our_node_id());
14959+ let channel_id = ChannelId::v2_from_revocation_basepoints(
14960+ &RevocationBasepoint::from(accept_channel_v2_msg.common_fields.revocation_basepoint),
14961+ &RevocationBasepoint::from(open_channel_v2_msg.common_fields.revocation_basepoint),
14962+ );
14963+
14964+ let tx_add_input_msg = TxAddInput {
14965+ channel_id,
14966+ serial_id: 2, // Even serial_id from initiator.
14967+ prevtx: initiator_funding_inputs[0].1.clone(),
14968+ prevtx_out: 0,
14969+ sequence: initiator_funding_inputs[0].0.sequence.0,
14970+ shared_input_txid: None,
14971+ };
14972+ let input_value = tx_add_input_msg.prevtx.as_transaction().output[tx_add_input_msg.prevtx_out as usize].value;
14973+ assert_eq!(input_value.to_sat(), session.initiator_input_value_satoshis);
14974+
14975+ nodes[1].node.handle_tx_add_input(nodes[0].node.get_our_node_id(), &tx_add_input_msg);
14976+
14977+ let _tx_complete_msg = get_event_msg!(nodes[1], MessageSendEvent::SendTxComplete, nodes[0].node.get_our_node_id());
14978+
14979+ let tx_add_output_msg = TxAddOutput {
14980+ channel_id,
14981+ serial_id: 4,
14982+ sats: funding_satoshis,
14983+ script: make_funding_redeemscript(
14984+ &open_channel_v2_msg.common_fields.funding_pubkey,
14985+ &accept_channel_v2_msg.common_fields.funding_pubkey,
14986+ ).to_p2wsh(),
14987+ };
14988+ nodes[1].node.handle_tx_add_output(nodes[0].node.get_our_node_id(), &tx_add_output_msg);
14989+
14990+ let _tx_complete_msg = get_event_msg!(nodes[1], MessageSendEvent::SendTxComplete, nodes[0].node.get_our_node_id());
14991+
14992+ let tx_complete_msg = TxComplete {
14993+ channel_id,
14994+ };
14995+
14996+ nodes[1].node.handle_tx_complete(nodes[0].node.get_our_node_id(), &tx_complete_msg);
14997+ let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
14998+ assert_eq!(msg_events.len(), 1);
14999+ let _msg_commitment_signed_from_1 = match msg_events[0] {
15000+ MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => {
15001+ assert_eq!(*node_id, nodes[0].node.get_our_node_id());
15002+ updates.commitment_signed.clone()
15003+ },
15004+ _ => panic!("Unexpected event"),
15005+ };
15006+
15007+ let (funding_outpoint, channel_type_features) = {
15008+ let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
15009+ let peer_state = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
15010+ let channel_context = peer_state
15011+ .channel_by_id.get(&tx_complete_msg.channel_id).unwrap().context();
15012+ (channel_context.get_funding_txo(), channel_context.get_channel_type().clone())
15013+ };
15014+
15015+ let channel_transaction_parameters = ChannelTransactionParameters {
15016+ counterparty_parameters: Some(CounterpartyChannelTransactionParameters {
15017+ pubkeys: ChannelPublicKeys {
15018+ funding_pubkey: accept_channel_v2_msg.common_fields.funding_pubkey,
15019+ revocation_basepoint: RevocationBasepoint(accept_channel_v2_msg.common_fields.revocation_basepoint),
15020+ payment_point: accept_channel_v2_msg.common_fields.payment_basepoint,
15021+ delayed_payment_basepoint: DelayedPaymentBasepoint(accept_channel_v2_msg.common_fields.delayed_payment_basepoint),
15022+ htlc_basepoint: HtlcBasepoint(accept_channel_v2_msg.common_fields.htlc_basepoint),
15023+ },
15024+ selected_contest_delay: accept_channel_v2_msg.common_fields.to_self_delay,
15025+ }),
15026+ holder_pubkeys: ChannelPublicKeys {
15027+ funding_pubkey: open_channel_v2_msg.common_fields.funding_pubkey,
15028+ revocation_basepoint: RevocationBasepoint(open_channel_v2_msg.common_fields.revocation_basepoint),
15029+ payment_point: open_channel_v2_msg.common_fields.payment_basepoint,
15030+ delayed_payment_basepoint: DelayedPaymentBasepoint(open_channel_v2_msg.common_fields.delayed_payment_basepoint),
15031+ htlc_basepoint: HtlcBasepoint(open_channel_v2_msg.common_fields.htlc_basepoint),
15032+ },
15033+ holder_selected_contest_delay: open_channel_v2_msg.common_fields.to_self_delay,
15034+ is_outbound_from_holder: true,
15035+ funding_outpoint,
15036+ channel_type_features,
15037+ };
15038+
15039+ channel.context.get_mut_signer().as_mut_ecdsa().unwrap().provide_channel_parameters(&channel_transaction_parameters);
15040+
15041+ let msg_commitment_signed_from_0 = CommitmentSigned {
15042+ channel_id,
15043+ signature: channel.context.get_initial_counterparty_commitment_signature_for_test(
15044+ &&logger_a,
15045+ channel_transaction_parameters,
15046+ accept_channel_v2_msg.common_fields.first_per_commitment_point,
15047+ ).unwrap(),
15048+ htlc_signatures: vec![],
15049+ batch: None,
15050+ #[cfg(taproot)]
15051+ partial_signature_with_nonce: None,
15052+ };
15053+
15054+ // Handle the initial commitment_signed exchange. Order is not important here.
15055+ nodes[1].node.handle_commitment_signed(nodes[0].node.get_our_node_id(), &msg_commitment_signed_from_0);
15056+ check_added_monitors(&nodes[1], 1);
15057+
15058+ let events = nodes[1].node.get_and_clear_pending_events();
15059+ assert_eq!(events.len(), 1);
15060+ match events[0] {
15061+ Event::ChannelPending { channel_id, .. } => channel_id == channel.context.channel_id(),
15062+ _ => panic!("Unexpected event"),
15063+ };
15064+ }
15065+
15066+ #[test]
15067+ fn test_v2_channel_establishment() {
15068+ // Only initiator contributes
15069+ do_test_v2_channel_establishment(V2ChannelEstablishmentTestSession {
15070+ initiator_input_value_satoshis: 100_000,
15071+ });
15072+ }
1492315073}
1492415074
1492515075#[cfg(ldk_bench)]
0 commit comments