@@ -57,6 +57,7 @@ use crate::chain::transaction::{OutPoint, TransactionData};
5757use crate::sign::ecdsa::EcdsaChannelSigner;
5858use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
5959use crate::events::{ClosureReason, Event};
60+ use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
6061use crate::routing::gossip::NodeId;
6162use crate::util::ser::{Readable, ReadableArgs, TransactionU16LenLimited, Writeable, Writer};
6263use crate::util::logger::{Logger, Record, WithContext};
@@ -4470,46 +4471,33 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
44704471 cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
44714472}
44724473
4473- #[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
4474- pub(super) fn calculate_our_funding_satoshis(
4475- is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
4476- total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
4477- holder_dust_limit_satoshis: u64,
4478- ) -> Result<u64, APIError> {
4479- let mut total_input_satoshis = 0u64;
4480- let mut our_contributed_weight = 0u64;
4474+ /// Estimate our part of the fee of the new funding transaction.
4475+ /// input_count: Number of contributed inputs.
4476+ /// witness_weight: The witness weight for contributed inputs.
4477+ #[allow(dead_code)] // TODO(dual_funding): TODO(splicing): Remove allow once used.
4478+ fn estimate_v2_funding_transaction_fee(
4479+ is_initiator: bool, input_count: usize, witness_weight: Weight,
4480+ funding_feerate_sat_per_1000_weight: u32,
4481+ ) -> u64 {
4482+ // Inputs
4483+ let mut weight = (input_count as u64) * BASE_INPUT_WEIGHT;
44814484
4482- for (idx, input) in funding_inputs.iter().enumerate() {
4483- if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
4484- total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
4485- } else {
4486- return Err(APIError::APIMisuseError {
4487- err: format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
4488- input.1.as_transaction().compute_txid(), input.0.previous_output.vout, idx) });
4489- }
4490- }
4491- our_contributed_weight = our_contributed_weight.saturating_add(total_witness_weight.to_wu());
4485+ // Witnesses
4486+ weight = weight.saturating_add(witness_weight.to_wu());
44924487
44934488 // If we are the initiator, we must pay for weight of all common fields in the funding transaction.
44944489 if is_initiator {
4495- our_contributed_weight = our_contributed_weight
4490+ weight = weight
44964491 .saturating_add(TX_COMMON_FIELDS_WEIGHT)
4497- // The weight of a P2WSH output to be added later.
4498- //
4492+ // The weight of the funding output, a P2WSH output
44994493 // NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
45004494 // to calculate the contributed weight, so we use an all-zero hash.
45014495 .saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
45024496 &WScriptHash::from_raw_hash(Hash::all_zeros())
45034497 )).to_wu())
45044498 }
45054499
4506- let funding_satoshis = total_input_satoshis
4507- .saturating_sub(fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight));
4508- if funding_satoshis < holder_dust_limit_satoshis {
4509- Ok(0)
4510- } else {
4511- Ok(funding_satoshis)
4512- }
4500+ fee_for_weight(funding_feerate_sat_per_1000_weight, weight)
45134501}
45144502
45154503/// Context for dual-funded channels.
@@ -9249,27 +9237,23 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
92499237
92509238 /// Creates a new dual-funded channel from a remote side's request for one.
92519239 /// Assumes chain_hash has already been checked and corresponds with what we expect!
9240+ /// TODO(dual_funding): Allow contributions, pass intended amount and inputs
92529241 #[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
92539242 pub fn new_inbound<ES: Deref, F: Deref, L: Deref>(
92549243 fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
92559244 holder_node_id: PublicKey, counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
92569245 their_features: &InitFeatures, msg: &msgs::OpenChannelV2,
9257- funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>, total_witness_weight: Weight,
92589246 user_id: u128, config: &UserConfig, current_chain_height: u32, logger: &L,
92599247 ) -> Result<Self, ChannelError>
92609248 where ES::Target: EntropySource,
92619249 F::Target: FeeEstimator,
92629250 L::Target: Logger,
92639251 {
9264- let funding_satoshis = calculate_our_funding_satoshis(
9265- false, &funding_inputs, total_witness_weight, msg.funding_feerate_sat_per_1000_weight,
9266- msg.common_fields.dust_limit_satoshis
9267- ).map_err(|_| ChannelError::Close(
9268- (
9269- "Failed to accept channel".to_string(),
9270- ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
9271- )))?;
9272- let channel_value_satoshis = funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
9252+ // TODO(dual_funding): Take these as input once supported
9253+ let our_funding_satoshis = 0u64;
9254+ let our_funding_inputs = Vec::new();
9255+
9256+ let channel_value_satoshis = our_funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
92739257 let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
92749258 channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
92759259 let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
@@ -9303,7 +9287,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
93039287 logger,
93049288 false,
93059289
9306- funding_satoshis ,
9290+ our_funding_satoshis ,
93079291
93089292 counterparty_pubkeys,
93099293 channel_type,
@@ -9318,10 +9302,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
93189302 context.channel_id = channel_id;
93199303
93209304 let dual_funding_context = DualFundingChannelContext {
9321- our_funding_satoshis: funding_satoshis ,
9305+ our_funding_satoshis: our_funding_satoshis ,
93229306 funding_tx_locktime: LockTime::from_consensus(msg.locktime),
93239307 funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
9324- our_funding_inputs: funding_inputs .clone(),
9308+ our_funding_inputs: our_funding_inputs .clone(),
93259309 };
93269310
93279311 let interactive_tx_constructor = Some(InteractiveTxConstructor::new(
@@ -9333,7 +9317,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
93339317 feerate_sat_per_kw: dual_funding_context.funding_feerate_sat_per_1000_weight,
93349318 funding_tx_locktime: dual_funding_context.funding_tx_locktime,
93359319 is_initiator: false,
9336- inputs_to_contribute: funding_inputs ,
9320+ inputs_to_contribute: our_funding_inputs ,
93379321 outputs_to_contribute: Vec::new(),
93389322 expected_remote_shared_funding_output: Some((context.get_funding_redeemscript().to_p2wsh(), context.channel_value_satoshis)),
93399323 }
@@ -12238,4 +12222,40 @@ mod tests {
1223812222 assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
1223912223 assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1224012224 }
12225+
12226+ #[test]
12227+ fn test_estimate_v2_funding_transaction_fee() {
12228+ use crate::ln::channel::estimate_v2_funding_transaction_fee;
12229+ use bitcoin::Weight;
12230+
12231+ // 2 inputs with weight 300, initiator, 2000 sat/kw feerate
12232+ assert_eq!(
12233+ estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 2000),
12234+ 1668
12235+ );
12236+
12237+ // higher feerate
12238+ assert_eq!(
12239+ estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 3000),
12240+ 2502
12241+ );
12242+
12243+ // only 1 input
12244+ assert_eq!(
12245+ estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(300), 2000),
12246+ 1348
12247+ );
12248+
12249+ // 0 input weight
12250+ assert_eq!(
12251+ estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(0), 2000),
12252+ 748
12253+ );
12254+
12255+ // not initiator
12256+ assert_eq!(
12257+ estimate_v2_funding_transaction_fee(false, 1, Weight::from_wu(0), 2000),
12258+ 320
12259+ );
12260+ }
1224112261}
0 commit comments