@@ -4469,14 +4469,44 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
4469
4469
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
4470
4470
}
4471
4471
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
+
4472
4501
#[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
4473
4502
pub(super) fn calculate_our_funding_satoshis(
4474
4503
is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
4475
4504
total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
4476
4505
holder_dust_limit_satoshis: u64,
4477
4506
) -> 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) ;
4479
4508
4509
+ let mut total_input_satoshis = 0u64;
4480
4510
for (idx, input) in funding_inputs.iter().enumerate() {
4481
4511
if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
4482
4512
total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
@@ -4486,26 +4516,8 @@ pub(super) fn calculate_our_funding_satoshis(
4486
4516
input.1.as_transaction().compute_txid(), input.0.previous_output.vout, idx) });
4487
4517
}
4488
4518
}
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());
4493
4519
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);
4509
4521
if funding_satoshis < holder_dust_limit_satoshis {
4510
4522
Ok(0)
4511
4523
} else {
@@ -12240,6 +12252,42 @@ mod tests {
12240
12252
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
12241
12253
}
12242
12254
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
+
12243
12291
fn funding_input_sats(input_value_sats: u64) -> (TxIn, TransactionU16LenLimited) {
12244
12292
let input_1_prev_out = TxOut { value: Amount::from_sat(input_value_sats), script_pubkey: ScriptBuf::default() };
12245
12293
let input_1_prev_tx = Transaction {
@@ -12273,39 +12321,6 @@ mod tests {
12273
12321
298332
12274
12322
);
12275
12323
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
-
12309
12324
// below dust limit
12310
12325
assert_eq!(
12311
12326
calculate_our_funding_satoshis(
0 commit comments