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