@@ -4469,14 +4469,44 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
44694469 cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
44704470}
44714471
4472+ /// Estimate our part of the fee of the new funding transaction.
4473+ /// input_count: Number of contributed inputs.
4474+ /// witness_weight: The witness weight for contributed inputs.
4475+ #[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
4476+ fn estimate_v2_funding_transaction_fee(
4477+ is_initiator: bool, input_count: usize, witness_weight: Weight,
4478+ funding_feerate_sat_per_1000_weight: u32,
4479+ ) -> u64 {
4480+ // Inputs
4481+ let mut weight = (input_count as u64) * BASE_INPUT_WEIGHT;
4482+
4483+ // Witnesses
4484+ weight = weight.saturating_add(witness_weight.to_wu());
4485+
4486+ // If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4487+ if is_initiator {
4488+ weight = weight
4489+ .saturating_add(TX_COMMON_FIELDS_WEIGHT)
4490+ // The weight of the funding output, a P2WSH output
4491+ // NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4492+ // to calculate the contributed weight, so we use an all-zero hash.
4493+ .saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4494+ &WScriptHash::from_raw_hash(Hash::all_zeros())
4495+ )).to_wu())
4496+ }
4497+
4498+ fee_for_weight(funding_feerate_sat_per_1000_weight, weight)
4499+ }
4500+
44724501#[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
44734502pub(super) fn calculate_our_funding_satoshis(
44744503 is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
44754504 total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
44764505 holder_dust_limit_satoshis: u64,
44774506) -> Result<u64, APIError> {
4478- let mut total_input_satoshis = 0u64 ;
4507+ let estimated_fee = estimate_v2_funding_transaction_fee(is_initiator, funding_inputs.len(), total_witness_weight, funding_feerate_sat_per_1000_weight) ;
44794508
4509+ let mut total_input_satoshis = 0u64;
44804510 for (idx, input) in funding_inputs.iter().enumerate() {
44814511 if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
44824512 total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
@@ -4486,26 +4516,8 @@ pub(super) fn calculate_our_funding_satoshis(
44864516 input.1.as_transaction().compute_txid(), input.0.previous_output.vout, idx) });
44874517 }
44884518 }
4489- // inputs:
4490- let mut our_contributed_weight = (funding_inputs.len() as u64) * BASE_INPUT_WEIGHT;
4491- // witnesses:
4492- our_contributed_weight = our_contributed_weight.saturating_add(total_witness_weight.to_wu());
44934519
4494- // If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4495- if is_initiator {
4496- our_contributed_weight = our_contributed_weight
4497- .saturating_add(TX_COMMON_FIELDS_WEIGHT)
4498- // The weight of a P2WSH output to be added later.
4499- //
4500- // NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4501- // to calculate the contributed weight, so we use an all-zero hash.
4502- .saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4503- &WScriptHash::from_raw_hash(Hash::all_zeros())
4504- )).to_wu())
4505- }
4506-
4507- let funding_satoshis = total_input_satoshis
4508- .saturating_sub(fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight));
4520+ let funding_satoshis = total_input_satoshis.saturating_sub(estimated_fee);
45094521 if funding_satoshis < holder_dust_limit_satoshis {
45104522 Ok(0)
45114523 } else {
@@ -12240,6 +12252,42 @@ mod tests {
1224012252 assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1224112253 }
1224212254
12255+ #[test]
12256+ fn test_estimate_v2_unding_transaction_fee() {
12257+ use crate::ln::channel::estimate_v2_funding_transaction_fee;
12258+ use bitcoin::Weight;
12259+
12260+ // 2 inputs with weight 300, initiator, 2000 sat/kw feerate
12261+ assert_eq!(
12262+ estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 2000),
12263+ 1668
12264+ );
12265+
12266+ // higher feerate
12267+ assert_eq!(
12268+ estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 3000),
12269+ 2502
12270+ );
12271+
12272+ // only 1 input
12273+ assert_eq!(
12274+ estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(300), 2000),
12275+ 1348
12276+ );
12277+
12278+ // 0 input weight
12279+ assert_eq!(
12280+ estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(0), 2000),
12281+ 748
12282+ );
12283+
12284+ // not initiator
12285+ assert_eq!(
12286+ estimate_v2_funding_transaction_fee(false, 1, Weight::from_wu(0), 2000),
12287+ 320
12288+ );
12289+ }
12290+
1224312291 fn funding_input_sats(input_value_sats: u64) -> (TxIn, TransactionU16LenLimited) {
1224412292 let input_1_prev_out = TxOut { value: Amount::from_sat(input_value_sats), script_pubkey: ScriptBuf::default() };
1224512293 let input_1_prev_tx = Transaction {
@@ -12273,39 +12321,6 @@ mod tests {
1227312321 298332
1227412322 );
1227512323
12276- assert_eq!(
12277- calculate_our_funding_satoshis(
12278- true,
12279- &[funding_input_sats(20_000)],
12280- Weight::from_wu(300),
12281- 2000,
12282- 1000,
12283- ).unwrap(),
12284- 18652
12285- );
12286-
12287- assert_eq!(
12288- calculate_our_funding_satoshis(
12289- true,
12290- &[funding_input_sats(20_000)],
12291- Weight::from_wu(0),
12292- 2000,
12293- 1000,
12294- ).unwrap(),
12295- 19252
12296- );
12297-
12298- assert_eq!(
12299- calculate_our_funding_satoshis(
12300- false,
12301- &[funding_input_sats(20_000)],
12302- Weight::from_wu(0),
12303- 2000,
12304- 1000,
12305- ).unwrap(),
12306- 19680
12307- );
12308-
1230912324 // below dust limit
1231012325 assert_eq!(
1231112326 calculate_our_funding_satoshis(
0 commit comments