@@ -54,7 +54,7 @@ use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBounde
54
54
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
55
55
use crate::chain::transaction::{OutPoint, TransactionData};
56
56
use 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 };
58
58
use crate::events::{ClosureReason, Event};
59
59
use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
60
60
use crate::routing::gossip::NodeId;
@@ -4708,6 +4708,33 @@ fn estimate_v2_funding_transaction_fee(
4708
4708
fee_for_weight(funding_feerate_sat_per_1000_weight, weight)
4709
4709
}
4710
4710
4711
+ #[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
4712
+ pub(super) fn calculate_our_funding_satoshis(
4713
+ is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
4714
+ total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
4715
+ holder_dust_limit_satoshis: u64,
4716
+ ) -> Result<u64, APIError> {
4717
+ let estimated_fee = estimate_v2_funding_transaction_fee(is_initiator, funding_inputs.len(), total_witness_weight, funding_feerate_sat_per_1000_weight);
4718
+
4719
+ let mut total_input_satoshis = 0u64;
4720
+ for (idx, input) in funding_inputs.iter().enumerate() {
4721
+ if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
4722
+ total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
4723
+ } else {
4724
+ return Err(APIError::APIMisuseError {
4725
+ err: format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
4726
+ input.1.as_transaction().compute_txid(), input.0.previous_output.vout, idx) });
4727
+ }
4728
+ }
4729
+
4730
+ let funding_satoshis = total_input_satoshis.saturating_sub(estimated_fee);
4731
+ if funding_satoshis < holder_dust_limit_satoshis {
4732
+ Ok(0)
4733
+ } else {
4734
+ Ok(funding_satoshis)
4735
+ }
4736
+ }
4737
+
4711
4738
/// Context for dual-funded channels.
4712
4739
pub(super) struct DualFundingChannelContext {
4713
4740
/// The amount in satoshis we will be contributing to the channel.
@@ -8404,10 +8431,21 @@ impl<SP: Deref> FundedChannel<SP> where
8404
8431
8405
8432
// Pre-check that inputs are sufficient to cover our contribution.
8406
8433
// Note: fees are not taken into account here.
8407
- let sum_input: i64 = our_funding_inputs.into_iter ().map(
8408
- |(txin, tx)| tx.output.get(txin.previous_output.vout as usize).map(|tx| tx.value.to_sat() as i64 ).unwrap_or(0)
8434
+ let sum_input: u64 = our_funding_inputs.iter ().map(
8435
+ |(txin, tx)| tx.output.get(txin.previous_output.vout as usize).map(|tx| tx.value.to_sat()).unwrap_or(0)
8409
8436
).sum();
8410
- if sum_input < our_funding_contribution_satoshis {
8437
+
8438
+ // The +1 is to include the input of the old funding
8439
+ let funding_input_count = our_funding_inputs.len() + 1;
8440
+ // Add weight for inputs (estimated as P2WPKH) *and* spending old funding
8441
+ let total_witness_weight = Weight::from_wu(
8442
+ our_funding_inputs.len() as u64 * P2WPKH_WITNESS_WEIGHT +
8443
+ 2 * P2WPKH_WITNESS_WEIGHT
8444
+ );
8445
+ let estimated_fee = estimate_v2_funding_transaction_fee(true, funding_input_count, total_witness_weight, funding_feerate_per_kw);
8446
+ let available_input = sum_input.saturating_sub(estimated_fee);
8447
+
8448
+ if (available_input as i64) < our_funding_contribution_satoshis {
8411
8449
return Err(ChannelError::Warn(format!(
8412
8450
"Provided inputs are insufficient for our contribution, {} {}",
8413
8451
sum_input, our_funding_contribution_satoshis,
0 commit comments