Skip to content

Commit 27784d9

Browse files
committed
Break up calculate_our_funding_satoshis() into fee estimation and output computation
1 parent a59bcf6 commit 27784d9

File tree

1 file changed

+65
-38
lines changed

1 file changed

+65
-38
lines changed

lightning/src/ln/channel.rs

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4348,14 +4348,44 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
43484348
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
43494349
}
43504350

4351+
/// Estimate our part of the fee of the new funding transaction.
4352+
/// input_count: Number of contributed inputs.
4353+
/// witness_weight: The witness weight for contributed inputs.
4354+
#[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
4355+
fn estimate_funding_transaction_fee(
4356+
is_initiator: bool, input_count: usize, witness_weight: Weight,
4357+
funding_feerate_sat_per_1000_weight: u32,
4358+
) -> u64 {
4359+
// Inputs
4360+
let mut weight = (input_count as u64) * BASE_INPUT_WEIGHT;
4361+
4362+
// Witnesses
4363+
weight = weight.saturating_add(witness_weight.to_wu());
4364+
4365+
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4366+
if is_initiator {
4367+
weight = weight
4368+
.saturating_add(TX_COMMON_FIELDS_WEIGHT)
4369+
// The weight of the funding output, a P2WSH output
4370+
// NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4371+
// to calculate the contributed weight, so we use an all-zero hash.
4372+
.saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4373+
&WScriptHash::from_raw_hash(Hash::all_zeros())
4374+
)).to_wu())
4375+
}
4376+
4377+
fee_for_weight(funding_feerate_sat_per_1000_weight, weight)
4378+
}
4379+
43514380
#[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
43524381
pub(super) fn calculate_our_funding_satoshis(
43534382
is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
43544383
total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
43554384
holder_dust_limit_satoshis: u64,
43564385
) -> Result<u64, APIError> {
4357-
let mut total_input_satoshis = 0u64;
4386+
let estimated_fee = estimate_funding_transaction_fee(is_initiator, funding_inputs.len(), total_witness_weight, funding_feerate_sat_per_1000_weight);
43584387

4388+
let mut total_input_satoshis = 0u64;
43594389
for (idx, input) in funding_inputs.iter().enumerate() {
43604390
if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
43614391
total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
@@ -4365,26 +4395,8 @@ pub(super) fn calculate_our_funding_satoshis(
43654395
input.1.as_transaction().compute_txid(), input.0.previous_output.vout, idx) });
43664396
}
43674397
}
4368-
// inputs:
4369-
let mut our_contributed_weight = (funding_inputs.len() as u64) * BASE_INPUT_WEIGHT;
4370-
// witnesses:
4371-
our_contributed_weight = our_contributed_weight.saturating_add(total_witness_weight.to_wu());
43724398

4373-
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4374-
if is_initiator {
4375-
our_contributed_weight = our_contributed_weight
4376-
.saturating_add(TX_COMMON_FIELDS_WEIGHT)
4377-
// The weight of a P2WSH output to be added later.
4378-
//
4379-
// NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4380-
// to calculate the contributed weight, so we use an all-zero hash.
4381-
.saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4382-
&WScriptHash::from_raw_hash(Hash::all_zeros())
4383-
)).to_wu())
4384-
}
4385-
4386-
let funding_satoshis = total_input_satoshis
4387-
.saturating_sub(fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight));
4399+
let funding_satoshis = total_input_satoshis.saturating_sub(estimated_fee);
43884400
if funding_satoshis < holder_dust_limit_satoshis {
43894401
Ok(0)
43904402
} else {
@@ -12214,6 +12226,39 @@ mod tests {
1221412226
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1221512227
}
1221612228

12229+
#[test]
12230+
fn test_estimate_funding_transaction_fee() {
12231+
use crate::ln::channel::estimate_funding_transaction_fee;
12232+
use bitcoin::Weight;
12233+
12234+
let witness_weight = Weight::from_wu(300);
12235+
12236+
assert_eq!(
12237+
estimate_funding_transaction_fee(true, 2, witness_weight, 2000),
12238+
1668
12239+
);
12240+
12241+
assert_eq!(
12242+
estimate_funding_transaction_fee(true, 2, witness_weight, 3000),
12243+
2502
12244+
);
12245+
12246+
assert_eq!(
12247+
estimate_funding_transaction_fee(true, 1, witness_weight, 2000),
12248+
1348
12249+
);
12250+
12251+
assert_eq!(
12252+
estimate_funding_transaction_fee(true, 1, Weight::from_wu(0), 2000),
12253+
748
12254+
);
12255+
12256+
assert_eq!(
12257+
estimate_funding_transaction_fee(false, 1, Weight::from_wu(0), 2000),
12258+
320
12259+
);
12260+
}
12261+
1221712262
fn prepare_input(value: u64) -> (TxIn, TransactionU16LenLimited) {
1221812263
let input_1_prev_out = TxOut { value: Amount::from_sat(value), script_pubkey: ScriptBuf::default() };
1221912264
let input_1_prev_tx = Transaction {
@@ -12248,24 +12293,6 @@ mod tests {
1224812293
298332
1224912294
);
1225012295

12251-
assert_eq!(
12252-
calculate_our_funding_satoshis(true, &inputs_1, witness_weight, 2000, 1000)
12253-
.unwrap(),
12254-
18652
12255-
);
12256-
12257-
assert_eq!(
12258-
calculate_our_funding_satoshis(true, &inputs_1, Weight::from_wu(0), 2000, 1000)
12259-
.unwrap(),
12260-
19252
12261-
);
12262-
12263-
assert_eq!(
12264-
calculate_our_funding_satoshis(false, &inputs_1, Weight::from_wu(0), 2000, 1000)
12265-
.unwrap(),
12266-
19680
12267-
);
12268-
1226912296
// below dust limit
1227012297
assert_eq!(
1227112298
calculate_our_funding_satoshis(true, &inputs_1, witness_weight, 2000, 20_000)

0 commit comments

Comments
 (0)