Skip to content

Commit 1512cd9

Browse files
committed
Implement async signing of splice shared input
We get async for free since the user already has to call back into LDK via `funding_transaction_signed`. If the signer fails to sign, they can simply retry the call once it is available.
1 parent accfc26 commit 1512cd9

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

lightning/src/ln/channel.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7983,6 +7983,34 @@ where
79837983
pub fn funding_transaction_signed(
79847984
&mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>,
79857985
) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), APIError> {
7986+
if !self.context.channel_state.is_interactive_signing() {
7987+
let err =
7988+
format!("Channel {} not expecting funding signatures", self.context.channel_id);
7989+
return Err(APIError::APIMisuseError { err });
7990+
}
7991+
if self.context.channel_state.is_our_tx_signatures_ready() {
7992+
let err =
7993+
format!("Channel {} already received funding signatures", self.context.channel_id);
7994+
return Err(APIError::APIMisuseError { err });
7995+
}
7996+
if let Some(pending_splice) = self.pending_splice.as_ref() {
7997+
if !pending_splice
7998+
.funding_negotiation
7999+
.as_ref()
8000+
.map(|funding_negotiation| {
8001+
matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures(_))
8002+
})
8003+
.unwrap_or(false)
8004+
{
8005+
debug_assert!(false);
8006+
let err = format!(
8007+
"Channel {} with pending splice is not expecting funding signatures yet",
8008+
self.context.channel_id
8009+
);
8010+
return Err(APIError::APIMisuseError { err });
8011+
}
8012+
}
8013+
79868014
let (tx_signatures_opt, funding_tx_opt) = self
79878015
.interactive_tx_signing_session
79888016
.as_mut()
@@ -8000,11 +8028,34 @@ where
80008028
});
80018029
}
80028030

8031+
let shared_input_signature = if let Some(splice_input_index) =
8032+
signing_session.unsigned_tx().shared_input_index()
8033+
{
8034+
let sig = match &self.context.holder_signer {
8035+
ChannelSignerType::Ecdsa(signer) => signer
8036+
.sign_splicing_funding_input(
8037+
&self.funding.channel_transaction_parameters,
8038+
&tx,
8039+
splice_input_index as usize,
8040+
&self.context.secp_ctx,
8041+
)
8042+
.map_err(|_| APIError::ChannelUnavailable {
8043+
err: "Signer unavailable".to_string(),
8044+
})?,
8045+
#[cfg(taproot)]
8046+
ChannelSignerType::Taproot(_) => todo!(),
8047+
};
8048+
Some(sig)
8049+
} else {
8050+
None
8051+
};
8052+
debug_assert_eq!(self.pending_splice.is_some(), shared_input_signature.is_some());
8053+
80038054
let tx_signatures = msgs::TxSignatures {
80048055
channel_id: self.context.channel_id,
80058056
tx_hash: funding_txid_signed,
80068057
witnesses,
8007-
shared_input_signature: None,
8058+
shared_input_signature,
80088059
};
80098060
signing_session
80108061
.provide_holder_witnesses(tx_signatures, &self.context.secp_ctx)

lightning/src/ln/channelmanager.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9044,7 +9044,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
90449044
Ok((None, _)) => {
90459045
debug_assert!(false, "If our tx_signatures is empty, then we should send it first!");
90469046
},
9047-
Err(err) => debug_assert!(false, "We should not error here but we got: {:?}", err),
9047+
Err(err) => {
9048+
log_warn!(logger, "Failed signing interactive funding transaction: {err:?}");
9049+
},
90489050
}
90499051
}
90509052
}

lightning/src/sign/ecdsa.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,10 @@ pub trait EcdsaChannelSigner: ChannelSigner {
254254
/// `input_index`: The index of the input within the new funding transaction `tx`,
255255
/// spending the previous funding transaction's output
256256
///
257-
/// This method is *not* asynchronous. If an `Err` is returned, the channel will be immediately
258-
/// closed.
257+
/// An `Err` can be returned to signal that the signer is unavailable/cannot produce a valid
258+
/// signature and should be retried later via [`ChannelManager::funding_transaction_signed`].
259+
///
260+
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
259261
fn sign_splicing_funding_input(
260262
&self, channel_parameters: &ChannelTransactionParameters, tx: &Transaction,
261263
input_index: usize, secp_ctx: &Secp256k1<secp256k1::All>,

0 commit comments

Comments
 (0)