@@ -1461,29 +1461,10 @@ pub(super) trait InteractivelyFunded<SP: Deref> where SP::Target: SignerProvider
1461
1461
fn is_initiator(&self) -> bool;
1462
1462
1463
1463
fn begin_interactive_funding_tx_construction<ES: Deref>(
1464
- &mut self, signer_provider: &SP, entropy_source: &ES,
1464
+ &mut self, entropy_source: &ES,
1465
1465
) -> Result<Option<InteractiveTxMessageSend>, APIError>
1466
1466
where ES::Target: EntropySource
1467
1467
{
1468
- let mut funding_inputs_prev_outputs: Vec<TxOut> = Vec::with_capacity(self.dual_funding_context_mut().our_funding_inputs.len());
1469
- // Check that vouts exist for each TxIn in provided transactions.
1470
- for (idx, input) in self.dual_funding_context_mut().our_funding_inputs.iter().enumerate() {
1471
- if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
1472
- funding_inputs_prev_outputs.push(output.clone());
1473
- } else {
1474
- return Err(APIError::APIMisuseError {
1475
- err: format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
1476
- input.1.as_transaction().txid(), input.0.previous_output.vout, idx) });
1477
- }
1478
- }
1479
- let total_input_satoshis: u64 = self.dual_funding_context_mut().our_funding_inputs.iter().map(
1480
- |input| input.1.as_transaction().output[input.0.previous_output.vout as usize].value.to_sat()).sum();
1481
- if total_input_satoshis < self.dual_funding_context_mut().our_funding_satoshis {
1482
- return Err(APIError::APIMisuseError {
1483
- err: format!("Total value of funding inputs must be at least funding amount. It was {} sats",
1484
- total_input_satoshis) });
1485
- }
1486
-
1487
1468
let mut funding_outputs = Vec::new();
1488
1469
if self.is_initiator() {
1489
1470
funding_outputs.push(TxOut {
@@ -1492,11 +1473,6 @@ pub(super) trait InteractivelyFunded<SP: Deref> where SP::Target: SignerProvider
1492
1473
});
1493
1474
}
1494
1475
1495
- maybe_add_funding_change_output(signer_provider, self.is_initiator(), self.dual_funding_context_mut().our_funding_satoshis,
1496
- &funding_inputs_prev_outputs, &mut funding_outputs, self.dual_funding_context_mut().funding_feerate_sat_per_1000_weight,
1497
- total_input_satoshis, self.context().holder_dust_limit_satoshis, self.context().channel_keys_id).map_err(
1498
- |_| APIError::APIMisuseError { err: "Could not create change output".to_string() })?;
1499
-
1500
1476
let (tx_constructor, msg) = InteractiveTxConstructor::new(
1501
1477
entropy_source, self.context().channel_id(),
1502
1478
self.dual_funding_context_mut().funding_feerate_sat_per_1000_weight, self.is_initiator(),
@@ -3670,53 +3646,39 @@ pub(crate) fn per_outbound_htlc_counterparty_commit_tx_fee_msat(feerate_per_kw:
3670
3646
}
3671
3647
3672
3648
#[cfg(any(dual_funding, splicing))]
3673
- pub(super) fn maybe_add_funding_change_output<SP: Deref>(
3674
- signer_provider: &SP, is_initiator: bool, our_funding_satoshis: u64,
3675
- funding_inputs_prev_outputs: &Vec<TxOut>, funding_outputs: &mut Vec<TxOut>,
3676
- funding_feerate_sat_per_1000_weight: u32, total_input_satoshis: u64,
3677
- holder_dust_limit_satoshis: u64, channel_keys_id: [u8; 32],
3678
- ) -> Result<Option<TxOut>, ChannelError> where
3679
- SP::Target: SignerProvider,
3680
- {
3681
- // Add the total estimated weight of our contributed inputs...
3682
- let mut our_contributed_weight = funding_inputs_prev_outputs.iter().fold(0u64, |weight, prev_output| {
3683
- weight.saturating_add(estimate_input_weight(prev_output).to_wu())
3684
- }).saturating_add(
3685
- // ... with the total weight of our contributed outputs.
3686
- funding_outputs.iter().fold(0u64, |weight, txout| {
3687
- weight.saturating_add(get_output_weight(&txout.script_pubkey).to_wu())
3688
- })
3689
- );
3649
+ pub(super) fn calculate_our_funding_satoshis(
3650
+ is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
3651
+ funding_outputs: &[TxOut], funding_feerate_sat_per_1000_weight: u32,
3652
+ holder_dust_limit_satoshis: u64,
3653
+ ) -> Result<u64, APIError> {
3654
+ let mut total_input_satoshis = 0u64;
3655
+ let mut our_contributed_weight = 0u64;
3656
+
3657
+ for (idx, input) in funding_inputs.iter().enumerate() {
3658
+ if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
3659
+ total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
3660
+ our_contributed_weight = our_contributed_weight.saturating_add(estimate_input_weight(output).to_wu());
3661
+ } else {
3662
+ return Err(APIError::APIMisuseError {
3663
+ err: format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
3664
+ input.1.as_transaction().txid(), input.0.previous_output.vout, idx) });
3665
+ }
3666
+ }
3667
+ our_contributed_weight = our_contributed_weight.saturating_add(funding_outputs.iter().fold(0u64, |weight, txout| {
3668
+ weight.saturating_add(get_output_weight(&txout.script_pubkey).to_wu())
3669
+ }));
3690
3670
3691
3671
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
3692
3672
if is_initiator {
3693
- our_contributed_weight += TX_COMMON_FIELDS_WEIGHT;
3673
+ our_contributed_weight = our_contributed_weight.saturating_add( TX_COMMON_FIELDS_WEIGHT) ;
3694
3674
}
3695
3675
3696
- let remaining_value = total_input_satoshis
3697
- .saturating_sub(our_funding_satoshis)
3676
+ let funding_satoshis = total_input_satoshis
3698
3677
.saturating_sub(fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight));
3699
-
3700
- if remaining_value < holder_dust_limit_satoshis {
3701
- Ok(None)
3678
+ if funding_satoshis < holder_dust_limit_satoshis {
3679
+ Ok(0)
3702
3680
} else {
3703
- let change_script = signer_provider.get_destination_script(channel_keys_id).map_err(
3704
- |_| ChannelError::Close(
3705
- (
3706
- "Failed to get change script as new destination script".to_owned(),
3707
- ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
3708
- ))
3709
- )?;
3710
- let mut change_output = TxOut {
3711
- value: Amount::from_sat(remaining_value),
3712
- script_pubkey: change_script,
3713
- };
3714
- let change_output_weight = get_output_weight(&change_output.script_pubkey).to_wu();
3715
-
3716
- let change_output_fee = fee_for_weight(funding_feerate_sat_per_1000_weight, change_output_weight);
3717
- change_output.value = Amount::from_sat(remaining_value.saturating_sub(change_output_fee));
3718
- funding_outputs.push(change_output.clone());
3719
- Ok(Some(change_output))
3681
+ Ok(funding_satoshis)
3720
3682
}
3721
3683
}
3722
3684
@@ -8423,14 +8385,22 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
8423
8385
pub fn new<ES: Deref, F: Deref, L: Deref>(
8424
8386
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
8425
8387
counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
8426
- their_features: &InitFeatures, msg: &msgs::OpenChannelV2, funding_satoshis: u64,
8388
+ their_features: &InitFeatures, msg: &msgs::OpenChannelV2,
8427
8389
funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>, user_id: u128, config: &UserConfig,
8428
8390
current_chain_height: u32, logger: &L,
8429
8391
) -> Result<InboundV2Channel<SP>, ChannelError>
8430
8392
where ES::Target: EntropySource,
8431
8393
F::Target: FeeEstimator,
8432
8394
L::Target: Logger,
8433
8395
{
8396
+ let funding_satoshis = calculate_our_funding_satoshis(
8397
+ false, &funding_inputs, &[], msg.funding_feerate_sat_per_1000_weight,
8398
+ msg.common_fields.dust_limit_satoshis
8399
+ ).map_err(|_| ChannelError::Close(
8400
+ (
8401
+ "Failed to accept channel".to_string(),
8402
+ ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
8403
+ )))?;
8434
8404
let channel_value_satoshis = funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
8435
8405
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
8436
8406
channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
0 commit comments