@@ -1461,29 +1461,10 @@ pub(super) trait InteractivelyFunded<SP: Deref> where SP::Target: SignerProvider
14611461 fn is_initiator(&self) -> bool;
14621462
14631463 fn begin_interactive_funding_tx_construction<ES: Deref>(
1464- &mut self, signer_provider: &SP, entropy_source: &ES,
1464+ &mut self, entropy_source: &ES,
14651465 ) -> Result<Option<InteractiveTxMessageSend>, APIError>
14661466 where ES::Target: EntropySource
14671467 {
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-
14871468 let mut funding_outputs = Vec::new();
14881469 if self.is_initiator() {
14891470 funding_outputs.push(TxOut {
@@ -1492,11 +1473,6 @@ pub(super) trait InteractivelyFunded<SP: Deref> where SP::Target: SignerProvider
14921473 });
14931474 }
14941475
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-
15001476 let (tx_constructor, msg) = InteractiveTxConstructor::new(
15011477 entropy_source, self.context().channel_id(),
15021478 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:
36703646}
36713647
36723648#[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+ }));
36903670
36913671 // If we are the initiator, we must pay for weight of all common fields in the funding transaction.
36923672 if is_initiator {
3693- our_contributed_weight += TX_COMMON_FIELDS_WEIGHT;
3673+ our_contributed_weight = our_contributed_weight.saturating_add( TX_COMMON_FIELDS_WEIGHT) ;
36943674 }
36953675
3696- let remaining_value = total_input_satoshis
3697- .saturating_sub(our_funding_satoshis)
3676+ let funding_satoshis = total_input_satoshis
36983677 .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)
37023680 } 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)
37203682 }
37213683}
37223684
@@ -8423,14 +8385,22 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
84238385 pub fn new<ES: Deref, F: Deref, L: Deref>(
84248386 fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
84258387 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,
84278389 funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>, user_id: u128, config: &UserConfig,
84288390 current_chain_height: u32, logger: &L,
84298391 ) -> Result<InboundV2Channel<SP>, ChannelError>
84308392 where ES::Target: EntropySource,
84318393 F::Target: FeeEstimator,
84328394 L::Target: Logger,
84338395 {
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+ )))?;
84348404 let channel_value_satoshis = funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
84358405 let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
84368406 channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
0 commit comments