@@ -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(),
@@ -3807,53 +3783,39 @@ pub(crate) fn per_outbound_htlc_counterparty_commit_tx_fee_msat(feerate_per_kw:
3807
3783
}
3808
3784
3809
3785
#[cfg(any(dual_funding, splicing))]
3810
- pub(super) fn maybe_add_funding_change_output<SP: Deref>(
3811
- signer_provider: &SP, is_initiator: bool, our_funding_satoshis: u64,
3812
- funding_inputs_prev_outputs: &Vec<TxOut>, funding_outputs: &mut Vec<TxOut>,
3813
- funding_feerate_sat_per_1000_weight: u32, total_input_satoshis: u64,
3814
- holder_dust_limit_satoshis: u64, channel_keys_id: [u8; 32],
3815
- ) -> Result<Option<TxOut>, ChannelError> where
3816
- SP::Target: SignerProvider,
3817
- {
3818
- // Add the total estimated weight of our contributed inputs...
3819
- let mut our_contributed_weight = funding_inputs_prev_outputs.iter().fold(0u64, |weight, prev_output| {
3820
- weight.saturating_add(estimate_input_weight(prev_output).to_wu())
3821
- }).saturating_add(
3822
- // ... with the total weight of our contributed outputs.
3823
- funding_outputs.iter().fold(0u64, |weight, txout| {
3824
- weight.saturating_add(get_output_weight(&txout.script_pubkey).to_wu())
3825
- })
3826
- );
3786
+ pub(super) fn calculate_our_funding_satoshis(
3787
+ is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
3788
+ funding_outputs: &[TxOut], funding_feerate_sat_per_1000_weight: u32,
3789
+ holder_dust_limit_satoshis: u64,
3790
+ ) -> Result<u64, APIError> {
3791
+ let mut total_input_satoshis = 0u64;
3792
+ let mut our_contributed_weight = 0u64;
3793
+
3794
+ for (idx, input) in funding_inputs.iter().enumerate() {
3795
+ if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
3796
+ total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
3797
+ our_contributed_weight = our_contributed_weight.saturating_add(estimate_input_weight(output).to_wu());
3798
+ } else {
3799
+ return Err(APIError::APIMisuseError {
3800
+ err: format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
3801
+ input.1.as_transaction().txid(), input.0.previous_output.vout, idx) });
3802
+ }
3803
+ }
3804
+ our_contributed_weight = our_contributed_weight.saturating_add(funding_outputs.iter().fold(0u64, |weight, txout| {
3805
+ weight.saturating_add(get_output_weight(&txout.script_pubkey).to_wu())
3806
+ }));
3827
3807
3828
3808
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
3829
3809
if is_initiator {
3830
- our_contributed_weight += TX_COMMON_FIELDS_WEIGHT;
3810
+ our_contributed_weight = our_contributed_weight.saturating_add( TX_COMMON_FIELDS_WEIGHT) ;
3831
3811
}
3832
3812
3833
- let remaining_value = total_input_satoshis
3834
- .saturating_sub(our_funding_satoshis)
3813
+ let funding_satoshis = total_input_satoshis
3835
3814
.saturating_sub(fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight));
3836
-
3837
- if remaining_value < holder_dust_limit_satoshis {
3838
- Ok(None)
3815
+ if funding_satoshis < holder_dust_limit_satoshis {
3816
+ Ok(0)
3839
3817
} else {
3840
- let change_script = signer_provider.get_destination_script(channel_keys_id).map_err(
3841
- |_| ChannelError::Close(
3842
- (
3843
- "Failed to get change script as new destination script".to_owned(),
3844
- ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
3845
- ))
3846
- )?;
3847
- let mut change_output = TxOut {
3848
- value: Amount::from_sat(remaining_value),
3849
- script_pubkey: change_script,
3850
- };
3851
- let change_output_weight = get_output_weight(&change_output.script_pubkey).to_wu();
3852
-
3853
- let change_output_fee = fee_for_weight(funding_feerate_sat_per_1000_weight, change_output_weight);
3854
- change_output.value = Amount::from_sat(remaining_value.saturating_sub(change_output_fee));
3855
- funding_outputs.push(change_output.clone());
3856
- Ok(Some(change_output))
3818
+ Ok(funding_satoshis)
3857
3819
}
3858
3820
}
3859
3821
@@ -8435,14 +8397,22 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
8435
8397
pub fn new<ES: Deref, F: Deref, L: Deref>(
8436
8398
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
8437
8399
counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
8438
- their_features: &InitFeatures, msg: &msgs::OpenChannelV2, funding_satoshis: u64,
8400
+ their_features: &InitFeatures, msg: &msgs::OpenChannelV2,
8439
8401
funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>, user_id: u128, config: &UserConfig,
8440
8402
current_chain_height: u32, logger: &L,
8441
8403
) -> Result<InboundV2Channel<SP>, ChannelError>
8442
8404
where ES::Target: EntropySource,
8443
8405
F::Target: FeeEstimator,
8444
8406
L::Target: Logger,
8445
8407
{
8408
+ let funding_satoshis = calculate_our_funding_satoshis(
8409
+ false, &funding_inputs, &[], msg.funding_feerate_sat_per_1000_weight,
8410
+ msg.common_fields.dust_limit_satoshis
8411
+ ).map_err(|_| ChannelError::Close(
8412
+ (
8413
+ "Failed to accept channel".to_string(),
8414
+ ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
8415
+ )))?;
8446
8416
let channel_value_satoshis = funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
8447
8417
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
8448
8418
channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
0 commit comments