@@ -54,8 +54,9 @@ use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBounde
5454use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
5555use crate::chain::transaction::{OutPoint, TransactionData};
5656use crate::sign::ecdsa::EcdsaChannelSigner;
57- use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
57+ use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient, P2WPKH_WITNESS_WEIGHT };
5858use crate::events::{ClosureReason, Event};
59+ use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
5960use crate::routing::gossip::NodeId;
6061use crate::util::ser::{Readable, ReadableArgs, TransactionU16LenLimited, Writeable, Writer};
6162use crate::util::logger::{Logger, Record, WithContext};
@@ -4429,15 +4430,41 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
44294430 cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
44304431}
44314432
4433+ #[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
4434+ fn estimate_funding_transaction_fee(
4435+ is_initiator: bool, funding_input_count: usize,
4436+ total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
4437+ ) -> u64 {
4438+ // Inputs
4439+ let mut weight = (funding_input_count as u64) * BASE_INPUT_WEIGHT;
4440+
4441+ // Witnesses
4442+ weight = weight.saturating_add(total_witness_weight.to_wu());
4443+
4444+ // If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4445+ if is_initiator {
4446+ weight = weight
4447+ .saturating_add(TX_COMMON_FIELDS_WEIGHT)
4448+ // The weight of the funding output, a P2WSH output
4449+ // NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4450+ // to calculate the contributed weight, so we use an all-zero hash.
4451+ .saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4452+ &WScriptHash::from_raw_hash(Hash::all_zeros())
4453+ )).to_wu())
4454+ }
4455+
4456+ fee_for_weight(funding_feerate_sat_per_1000_weight, weight)
4457+ }
4458+
44324459#[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
44334460pub(super) fn calculate_our_funding_satoshis(
44344461 is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
44354462 total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
44364463 holder_dust_limit_satoshis: u64,
44374464) -> Result<u64, APIError> {
4438- let mut total_input_satoshis = 0u64;
4439- let mut our_contributed_weight = 0u64;
4465+ let estimated_fee = estimate_funding_transaction_fee(is_initiator, funding_inputs.len(), total_witness_weight, funding_feerate_sat_per_1000_weight);
44404466
4467+ let mut total_input_satoshis = 0u64;
44414468 for (idx, input) in funding_inputs.iter().enumerate() {
44424469 if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
44434470 total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
@@ -4447,23 +4474,8 @@ pub(super) fn calculate_our_funding_satoshis(
44474474 input.1.as_transaction().compute_txid(), input.0.previous_output.vout, idx) });
44484475 }
44494476 }
4450- our_contributed_weight = our_contributed_weight.saturating_add(total_witness_weight.to_wu());
4451-
4452- // If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4453- if is_initiator {
4454- our_contributed_weight = our_contributed_weight
4455- .saturating_add(TX_COMMON_FIELDS_WEIGHT)
4456- // The weight of a P2WSH output to be added later.
4457- //
4458- // NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4459- // to calculate the contributed weight, so we use an all-zero hash.
4460- .saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4461- &WScriptHash::from_raw_hash(Hash::all_zeros())
4462- )).to_wu())
4463- }
44644477
4465- let funding_satoshis = total_input_satoshis
4466- .saturating_sub(fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight));
4478+ let funding_satoshis = total_input_satoshis.saturating_sub(estimated_fee);
44674479 if funding_satoshis < holder_dust_limit_satoshis {
44684480 Ok(0)
44694481 } else {
@@ -8153,10 +8165,21 @@ impl<SP: Deref> FundedChannel<SP> where
81538165
81548166 // Pre-check that inputs are sufficient to cover our contribution.
81558167 // Note: fees are not taken into account here.
8156- let sum_input: i64 = our_funding_inputs.into_iter ().map(
8157- |(txin, tx)| tx.output.get(txin.previous_output.vout as usize).map(|tx| tx.value.to_sat() as i64 ).unwrap_or(0)
8168+ let sum_input: u64 = our_funding_inputs.iter ().map(
8169+ |(txin, tx)| tx.output.get(txin.previous_output.vout as usize).map(|tx| tx.value.to_sat()).unwrap_or(0)
81588170 ).sum();
8159- if sum_input < our_funding_contribution_satoshis {
8171+
8172+ // The +1 is to include the input of the old funding
8173+ let funding_input_count = our_funding_inputs.len() + 1;
8174+ // Add weight for spending inputs *and* old funding
8175+ let total_witness_weight = Weight::from_wu(
8176+ our_funding_inputs.len() as u64 * P2WPKH_WITNESS_WEIGHT +
8177+ 2 * P2WPKH_WITNESS_WEIGHT
8178+ );
8179+ let estimated_fee = estimate_funding_transaction_fee(true, funding_input_count, total_witness_weight, funding_feerate_per_kw);
8180+ let available_input = sum_input.saturating_sub(estimated_fee);
8181+
8182+ if (available_input as i64) < our_funding_contribution_satoshis {
81608183 return Err(ChannelError::Warn(format!(
81618184 "Provided inputs are insufficient for our contribution, {} {}",
81628185 sum_input, our_funding_contribution_satoshis,
0 commit comments