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