@@ -1954,11 +1954,19 @@ where
19541954
19551955 let funding_tx_signed = if !has_local_contribution {
19561956 let funding_txid = signing_session.unsigned_tx().tx().compute_txid();
1957- if let ChannelPhase::Funded(chan) = &mut self.phase {
1958- chan.funding_transaction_signed(funding_txid, vec![], 0, fee_estimator, logger).ok()
1959- } else {
1960- None
1961- }
1957+ Some(
1958+ self.funding_transaction_signed(funding_txid, vec![], 0, fee_estimator, logger)
1959+ .map_err(|err| {
1960+ log_error!(
1961+ logger,
1962+ "Failed signing funding transaction without local contribution: {err:?}"
1963+ );
1964+ self.fail_interactive_tx_negotiation(
1965+ AbortReason::InternalError("Signing failed"),
1966+ logger,
1967+ )
1968+ })?,
1969+ )
19621970 } else {
19631971 None
19641972 };
@@ -2137,6 +2145,181 @@ where
21372145 Ok(())
21382146 }
21392147
2148+ pub fn funding_transaction_signed<F: Deref, L: Deref>(
2149+ &mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>, best_block_height: u32,
2150+ fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L,
2151+ ) -> Result<FundingTxSigned, APIError>
2152+ where
2153+ F::Target: FeeEstimator,
2154+ L::Target: Logger,
2155+ {
2156+ let (context, funding, pending_splice) = match &mut self.phase {
2157+ ChannelPhase::Undefined => unreachable!(),
2158+ ChannelPhase::UnfundedV2(channel) => (&mut channel.context, &channel.funding, None),
2159+ ChannelPhase::Funded(channel) => {
2160+ (&mut channel.context, &channel.funding, channel.pending_splice.as_ref())
2161+ },
2162+ _ => {
2163+ return Err(APIError::APIMisuseError {
2164+ err: format!(
2165+ "Channel with id {} not expecting funding signatures",
2166+ self.context().channel_id
2167+ ),
2168+ });
2169+ },
2170+ };
2171+
2172+ let signing_session = if let Some(signing_session) =
2173+ context.interactive_tx_signing_session.as_mut()
2174+ {
2175+ if let Some(pending_splice) = pending_splice.as_ref() {
2176+ debug_assert!(pending_splice
2177+ .funding_negotiation
2178+ .as_ref()
2179+ .map(|funding_negotiation| matches!(
2180+ funding_negotiation,
2181+ FundingNegotiation::AwaitingSignatures { .. }
2182+ ))
2183+ .unwrap_or(false));
2184+ }
2185+
2186+ if signing_session.holder_tx_signatures().is_some() {
2187+ // Our `tx_signatures` either should've been the first time we processed them,
2188+ // or we're waiting for our counterparty to send theirs first.
2189+ return Ok(FundingTxSigned {
2190+ commitment_signed: None,
2191+ counterparty_initial_commitment_signed_result: None,
2192+ tx_signatures: None,
2193+ funding_tx: None,
2194+ splice_negotiated: None,
2195+ splice_locked: None,
2196+ });
2197+ }
2198+
2199+ signing_session
2200+ } else {
2201+ if Some(funding_txid_signed) == funding.get_funding_txid() {
2202+ // We may be handling a duplicate call and the funding was already locked so we
2203+ // no longer have the signing session present.
2204+ return Ok(FundingTxSigned {
2205+ commitment_signed: None,
2206+ counterparty_initial_commitment_signed_result: None,
2207+ tx_signatures: None,
2208+ funding_tx: None,
2209+ splice_negotiated: None,
2210+ splice_locked: None,
2211+ });
2212+ }
2213+ let err = format!("Channel {} not expecting funding signatures", context.channel_id);
2214+ return Err(APIError::APIMisuseError { err });
2215+ };
2216+
2217+ let tx = signing_session.unsigned_tx().tx();
2218+ if funding_txid_signed != tx.compute_txid() {
2219+ return Err(APIError::APIMisuseError {
2220+ err: "Transaction was malleated prior to signing".to_owned(),
2221+ });
2222+ }
2223+
2224+ let shared_input_signature =
2225+ if let Some(splice_input_index) = signing_session.unsigned_tx().shared_input_index() {
2226+ let sig = match &context.holder_signer {
2227+ ChannelSignerType::Ecdsa(signer) => signer.sign_splice_shared_input(
2228+ &funding.channel_transaction_parameters,
2229+ tx,
2230+ splice_input_index as usize,
2231+ &context.secp_ctx,
2232+ ),
2233+ #[cfg(taproot)]
2234+ ChannelSignerType::Taproot(_) => todo!(),
2235+ };
2236+ Some(sig)
2237+ } else {
2238+ None
2239+ };
2240+ debug_assert_eq!(pending_splice.is_some(), shared_input_signature.is_some());
2241+
2242+ let tx_signatures = msgs::TxSignatures {
2243+ channel_id: context.channel_id,
2244+ tx_hash: funding_txid_signed,
2245+ witnesses,
2246+ shared_input_signature,
2247+ };
2248+ let (tx_signatures, funding_tx) = signing_session
2249+ .provide_holder_witnesses(tx_signatures, &context.secp_ctx)
2250+ .map_err(|err| APIError::APIMisuseError { err })?;
2251+
2252+ let logger = WithChannelContext::from(logger, &context, None);
2253+ if tx_signatures.is_some() {
2254+ log_info!(
2255+ logger,
2256+ "Sending tx_signatures for interactive funding transaction {funding_txid_signed}"
2257+ );
2258+ }
2259+
2260+ let funding = pending_splice
2261+ .as_ref()
2262+ .and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
2263+ .and_then(|funding_negotiation| funding_negotiation.as_funding())
2264+ .unwrap_or(funding);
2265+ let commitment_signed = context.get_initial_commitment_signed_v2(funding, &&logger);
2266+
2267+ // For zero conf channels, we don't expect the funding transaction to be ready for broadcast
2268+ // yet as, according to the spec, our counterparty shouldn't have sent their `tx_signatures`
2269+ // without us having sent our initial commitment signed to them first. However, in the event
2270+ // they do, we choose to handle it anyway. Note that because of this behavior not being
2271+ // spec-compliant, we're not able to test this without custom logic.
2272+ let (splice_negotiated, splice_locked) = if let Some(funding_tx) = funding_tx.clone() {
2273+ debug_assert!(tx_signatures.is_some());
2274+ let funded_channel = self.as_funded_mut().expect(
2275+ "Funding transactions ready for broadcast can only exist for funded channels",
2276+ );
2277+ funded_channel.on_tx_signatures_exchange(funding_tx, best_block_height, &logger)
2278+ } else {
2279+ (None, None)
2280+ };
2281+
2282+ // If we have a pending splice with a buffered initial commitment signed from our
2283+ // counterparty, process it now that we have provided our signatures.
2284+ let counterparty_initial_commitment_signed_result =
2285+ if let Some(funded_channel) = self.as_funded_mut() {
2286+ if let Some(commit_sig) = funded_channel
2287+ .pending_splice
2288+ .as_mut()
2289+ .and_then(|pending_splice| pending_splice.funding_negotiation.as_mut())
2290+ .and_then(|funding_negotiation| {
2291+ if let FundingNegotiation::AwaitingSignatures {
2292+ ref mut initial_commitment_signed_from_counterparty,
2293+ ..
2294+ } = funding_negotiation
2295+ {
2296+ initial_commitment_signed_from_counterparty.take()
2297+ } else {
2298+ None
2299+ }
2300+ }) {
2301+ Some(funded_channel.splice_initial_commitment_signed(
2302+ &commit_sig,
2303+ fee_estimator,
2304+ &&logger,
2305+ ))
2306+ } else {
2307+ None
2308+ }
2309+ } else {
2310+ None
2311+ };
2312+
2313+ Ok(FundingTxSigned {
2314+ commitment_signed,
2315+ counterparty_initial_commitment_signed_result,
2316+ tx_signatures,
2317+ funding_tx,
2318+ splice_negotiated,
2319+ splice_locked,
2320+ })
2321+ }
2322+
21402323 pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
21412324 let (funding, context) = self.funding_and_context_mut();
21422325 context.force_shutdown(funding, closure_reason)
@@ -2206,7 +2389,7 @@ where
22062389 .unwrap_or(false);
22072390
22082391 // We delay processing this until the user manually approves the splice via
2209- // [`FundedChannel ::funding_transaction_signed`], as otherwise, there would be a
2392+ // [`Channel ::funding_transaction_signed`], as otherwise, there would be a
22102393 // [`ChannelMonitorUpdateStep::RenegotiatedFunding`] committed that we would
22112394 // need to undo if they no longer wish to proceed.
22122395 if has_holder_tx_signatures {
@@ -2710,7 +2893,7 @@ enum FundingNegotiation {
27102893 is_initiator: bool,
27112894 /// The initial [`msgs::CommitmentSigned`] message received for the [`FundingScope`] above.
27122895 /// We delay processing this until the user manually approves the splice via
2713- /// [`FundedChannel ::funding_transaction_signed`], as otherwise, there would be a
2896+ /// [`Channel ::funding_transaction_signed`], as otherwise, there would be a
27142897 /// [`ChannelMonitorUpdateStep::RenegotiatedFunding`] committed that we would need to undo
27152898 /// if they no longer wish to proceed.
27162899 ///
@@ -9117,149 +9300,6 @@ where
91179300 }
91189301 }
91199302
9120- pub fn funding_transaction_signed<F: Deref, L: Deref>(
9121- &mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>, best_block_height: u32,
9122- fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L,
9123- ) -> Result<FundingTxSigned, APIError>
9124- where
9125- F::Target: FeeEstimator,
9126- L::Target: Logger,
9127- {
9128- let signing_session =
9129- if let Some(signing_session) = self.context.interactive_tx_signing_session.as_mut() {
9130- if let Some(pending_splice) = self.pending_splice.as_ref() {
9131- debug_assert!(pending_splice
9132- .funding_negotiation
9133- .as_ref()
9134- .map(|funding_negotiation| matches!(
9135- funding_negotiation,
9136- FundingNegotiation::AwaitingSignatures { .. }
9137- ))
9138- .unwrap_or(false));
9139- }
9140-
9141- if signing_session.holder_tx_signatures().is_some() {
9142- // Our `tx_signatures` either should've been the first time we processed them,
9143- // or we're waiting for our counterparty to send theirs first.
9144- return Ok(FundingTxSigned {
9145- commitment_signed: None,
9146- counterparty_initial_commitment_signed_result: None,
9147- tx_signatures: None,
9148- funding_tx: None,
9149- splice_negotiated: None,
9150- splice_locked: None,
9151- });
9152- }
9153-
9154- signing_session
9155- } else {
9156- if Some(funding_txid_signed) == self.funding.get_funding_txid() {
9157- // We may be handling a duplicate call and the funding was already locked so we
9158- // no longer have the signing session present.
9159- return Ok(FundingTxSigned {
9160- commitment_signed: None,
9161- counterparty_initial_commitment_signed_result: None,
9162- tx_signatures: None,
9163- funding_tx: None,
9164- splice_negotiated: None,
9165- splice_locked: None,
9166- });
9167- }
9168- let err =
9169- format!("Channel {} not expecting funding signatures", self.context.channel_id);
9170- return Err(APIError::APIMisuseError { err });
9171- };
9172-
9173- let tx = signing_session.unsigned_tx().tx();
9174- if funding_txid_signed != tx.compute_txid() {
9175- return Err(APIError::APIMisuseError {
9176- err: "Transaction was malleated prior to signing".to_owned(),
9177- });
9178- }
9179-
9180- let shared_input_signature =
9181- if let Some(splice_input_index) = signing_session.unsigned_tx().shared_input_index() {
9182- let sig = match &self.context.holder_signer {
9183- ChannelSignerType::Ecdsa(signer) => signer.sign_splice_shared_input(
9184- &self.funding.channel_transaction_parameters,
9185- tx,
9186- splice_input_index as usize,
9187- &self.context.secp_ctx,
9188- ),
9189- #[cfg(taproot)]
9190- ChannelSignerType::Taproot(_) => todo!(),
9191- };
9192- Some(sig)
9193- } else {
9194- None
9195- };
9196- debug_assert_eq!(self.pending_splice.is_some(), shared_input_signature.is_some());
9197-
9198- let tx_signatures = msgs::TxSignatures {
9199- channel_id: self.context.channel_id,
9200- tx_hash: funding_txid_signed,
9201- witnesses,
9202- shared_input_signature,
9203- };
9204- let (tx_signatures, funding_tx) = signing_session
9205- .provide_holder_witnesses(tx_signatures, &self.context.secp_ctx)
9206- .map_err(|err| APIError::APIMisuseError { err })?;
9207-
9208- let logger = WithChannelContext::from(logger, &self.context, None);
9209- if tx_signatures.is_some() {
9210- log_info!(
9211- logger,
9212- "Sending tx_signatures for interactive funding transaction {funding_txid_signed}"
9213- );
9214- }
9215-
9216- let (splice_negotiated, splice_locked) = if let Some(funding_tx) = funding_tx.clone() {
9217- debug_assert!(tx_signatures.is_some());
9218- self.on_tx_signatures_exchange(funding_tx, best_block_height, &logger)
9219- } else {
9220- (None, None)
9221- };
9222-
9223- let funding = self
9224- .pending_splice
9225- .as_ref()
9226- .and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
9227- .and_then(|funding_negotiation| funding_negotiation.as_funding())
9228- .unwrap_or(&self.funding);
9229- let commitment_signed = self.context.get_initial_commitment_signed_v2(funding, &&logger);
9230-
9231- // If we have a pending splice with a buffered initial commitment_signed from our
9232- // counterparty, process it now that we have provided our signatures.
9233- let counterparty_initial_commitment_signed_result = if let Some(commit_sig) = self
9234- .pending_splice
9235- .as_mut()
9236- .and_then(|pending_splice| pending_splice.funding_negotiation.as_mut())
9237- .and_then(|funding_negotiation| {
9238- if let FundingNegotiation::AwaitingSignatures {
9239- ref mut initial_commitment_signed_from_counterparty,
9240- ..
9241- } = funding_negotiation
9242- {
9243- initial_commitment_signed_from_counterparty.take()
9244- } else {
9245- None
9246- }
9247- }) {
9248- Some(self.splice_initial_commitment_signed(&commit_sig, fee_estimator, &&logger))
9249- } else {
9250- None
9251- };
9252-
9253- Ok(FundingTxSigned {
9254- commitment_signed,
9255- counterparty_initial_commitment_signed_result,
9256- tx_signatures,
9257- funding_tx,
9258- splice_negotiated,
9259- splice_locked,
9260- })
9261- }
9262-
92639303 pub fn tx_signatures<L: Deref>(
92649304 &mut self, msg: &msgs::TxSignatures, best_block_height: u32, logger: &L,
92659305 ) -> Result<FundingTxSigned, ChannelError>
0 commit comments