Skip to content

Commit 2772bfd

Browse files
authored
Merge pull request #4024 from wpaulino/sign-splice-shared-input
Support splice shared input signing
2 parents d55b4f8 + e664b7e commit 2772bfd

File tree

7 files changed

+308
-115
lines changed

7 files changed

+308
-115
lines changed

lightning/src/ln/channel.rs

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2207,6 +2207,11 @@ impl FundingScope {
22072207
self.channel_transaction_parameters.make_funding_redeemscript()
22082208
}
22092209

2210+
#[cfg(splicing)]
2211+
fn holder_funding_pubkey(&self) -> &PublicKey {
2212+
&self.get_holder_pubkeys().funding_pubkey
2213+
}
2214+
22102215
fn counterparty_funding_pubkey(&self) -> &PublicKey {
22112216
&self.get_counterparty_pubkeys().funding_pubkey
22122217
}
@@ -2353,8 +2358,16 @@ impl FundingScope {
23532358
};
23542359

23552360
let local_owned = self.value_to_self_msat / 1000;
2356-
2357-
SharedOwnedInput::new(input, prev_output, local_owned)
2361+
let holder_sig_first = self.holder_funding_pubkey().serialize()[..]
2362+
< self.counterparty_funding_pubkey().serialize()[..];
2363+
2364+
SharedOwnedInput::new(
2365+
input,
2366+
prev_output,
2367+
local_owned,
2368+
holder_sig_first,
2369+
self.get_funding_redeemscript(),
2370+
)
23582371
}
23592372
}
23602373

@@ -8285,9 +8298,38 @@ where
82858298
}
82868299

82878300
pub fn funding_transaction_signed(
8288-
&mut self, witnesses: Vec<Witness>,
8301+
&mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>,
82898302
) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), APIError> {
8290-
let (funding_tx_opt, tx_signatures_opt) = self
8303+
if !self.context.channel_state.is_interactive_signing() {
8304+
let err =
8305+
format!("Channel {} not expecting funding signatures", self.context.channel_id);
8306+
return Err(APIError::APIMisuseError { err });
8307+
}
8308+
if self.context.channel_state.is_our_tx_signatures_ready() {
8309+
let err =
8310+
format!("Channel {} already received funding signatures", self.context.channel_id);
8311+
return Err(APIError::APIMisuseError { err });
8312+
}
8313+
#[cfg(splicing)]
8314+
if let Some(pending_splice) = self.pending_splice.as_ref() {
8315+
if !pending_splice
8316+
.funding_negotiation
8317+
.as_ref()
8318+
.map(|funding_negotiation| {
8319+
matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures(_))
8320+
})
8321+
.unwrap_or(false)
8322+
{
8323+
debug_assert!(false);
8324+
let err = format!(
8325+
"Channel {} with pending splice is not expecting funding signatures yet",
8326+
self.context.channel_id
8327+
);
8328+
return Err(APIError::APIMisuseError { err });
8329+
}
8330+
}
8331+
8332+
let (tx_signatures_opt, funding_tx_opt) = self
82918333
.interactive_tx_signing_session
82928334
.as_mut()
82938335
.ok_or_else(|| APIError::APIMisuseError {
@@ -8297,12 +8339,41 @@ where
82978339
),
82988340
})
82998341
.and_then(|signing_session| {
8342+
let tx = signing_session.unsigned_tx().build_unsigned_tx();
8343+
if funding_txid_signed != tx.compute_txid() {
8344+
return Err(APIError::APIMisuseError {
8345+
err: "Transaction was malleated prior to signing".to_owned(),
8346+
});
8347+
}
8348+
8349+
let shared_input_signature = if let Some(splice_input_index) =
8350+
signing_session.unsigned_tx().shared_input_index()
8351+
{
8352+
let sig = match &self.context.holder_signer {
8353+
ChannelSignerType::Ecdsa(signer) => signer.sign_splice_shared_input(
8354+
&self.funding.channel_transaction_parameters,
8355+
&tx,
8356+
splice_input_index as usize,
8357+
&self.context.secp_ctx,
8358+
),
8359+
#[cfg(taproot)]
8360+
ChannelSignerType::Taproot(_) => todo!(),
8361+
};
8362+
Some(sig)
8363+
} else {
8364+
None
8365+
};
8366+
#[cfg(splicing)]
8367+
debug_assert_eq!(self.pending_splice.is_some(), shared_input_signature.is_some());
8368+
8369+
let tx_signatures = msgs::TxSignatures {
8370+
channel_id: self.context.channel_id,
8371+
tx_hash: funding_txid_signed,
8372+
witnesses,
8373+
shared_input_signature,
8374+
};
83008375
signing_session
8301-
.provide_holder_witnesses(
8302-
&self.context.secp_ctx,
8303-
self.context.channel_id,
8304-
witnesses,
8305-
)
8376+
.provide_holder_witnesses(tx_signatures, &self.context.secp_ctx)
83068377
.map_err(|err| APIError::APIMisuseError { err })
83078378
})?;
83088379

@@ -8320,7 +8391,7 @@ where
83208391
}
83218392

83228393
#[rustfmt::skip]
8323-
pub fn tx_signatures(&mut self, msg: &msgs::TxSignatures) -> Result<(Option<Transaction>, Option<msgs::TxSignatures>), ChannelError> {
8394+
pub fn tx_signatures(&mut self, msg: &msgs::TxSignatures) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), ChannelError> {
83248395
if !self.context.channel_state.is_interactive_signing()
83258396
|| self.context.channel_state.is_their_tx_signatures_sent()
83268397
{
@@ -8351,7 +8422,7 @@ where
83518422
}
83528423
}
83538424

8354-
let (holder_tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg.clone())
8425+
let (holder_tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg)
83558426
.map_err(|msg| ChannelError::Warn(msg))?;
83568427

83578428
// Set `THEIR_TX_SIGNATURES_SENT` flag after all potential errors.
@@ -8366,7 +8437,7 @@ where
83668437
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
83678438
}
83688439

8369-
Ok((funding_tx_opt, holder_tx_signatures_opt))
8440+
Ok((holder_tx_signatures_opt, funding_tx_opt))
83708441
} else {
83718442
let msg = "Unexpected tx_signatures. No funding transaction awaiting signatures";
83728443
let reason = ClosureReason::ProcessingError { err: msg.to_owned() };

lightning/src/ln/channelmanager.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5967,13 +5967,14 @@ where
59675967
match peer_state.channel_by_id.get_mut(channel_id) {
59685968
Some(channel) => match channel.as_funded_mut() {
59695969
Some(chan) => {
5970+
let txid = transaction.compute_txid();
59705971
let witnesses: Vec<_> = transaction
59715972
.input
59725973
.into_iter()
59735974
.map(|input| input.witness)
5974-
.filter(|witness| witness.is_empty())
5975+
.filter(|witness| !witness.is_empty())
59755976
.collect();
5976-
match chan.funding_transaction_signed(witnesses) {
5977+
match chan.funding_transaction_signed(txid, witnesses) {
59775978
Ok((Some(tx_signatures), funding_tx_opt)) => {
59785979
if let Some(funding_tx) = funding_tx_opt {
59795980
self.broadcast_interactive_funding(chan, &funding_tx);
@@ -9004,10 +9005,13 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
90049005
}
90059006
}
90069007

9007-
if let Some(signing_session) = &mut channel.interactive_tx_signing_session {
9008-
if signing_session.local_inputs_count() > 0
9009-
&& signing_session.holder_tx_signatures().is_none()
9010-
{
9008+
if let Some(signing_session) = (!channel.is_awaiting_monitor_update())
9009+
.then(|| ())
9010+
.and_then(|_| channel.interactive_tx_signing_session.as_mut())
9011+
.filter(|signing_session| signing_session.holder_tx_signatures().is_none())
9012+
{
9013+
let local_inputs_count = signing_session.local_inputs_count();
9014+
if local_inputs_count > 0 {
90119015
let mut pending_events = self.pending_events.lock().unwrap();
90129016
let unsigned_transaction = signing_session.unsigned_tx().build_unsigned_tx();
90139017
let event_action = (
@@ -9020,13 +9024,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
90209024
None,
90219025
);
90229026

9023-
if pending_events.contains(&event_action) {
9024-
debug_assert!(false, "FundingTransactionReadyForSigning should not have been queued already");
9025-
} else {
9027+
if !pending_events.contains(&event_action) {
90269028
pending_events.push_back(event_action);
90279029
}
9028-
} else if signing_session.local_inputs_count() == 0 && signing_session.holder_tx_signatures().is_none() {
9029-
match channel.funding_transaction_signed(vec![]) {
9030+
} else {
9031+
let txid = signing_session.unsigned_tx().compute_txid();
9032+
match channel.funding_transaction_signed(txid, vec![]) {
90309033
Ok((Some(tx_signatures), funding_tx_opt)) => {
90319034
if let Some(funding_tx) = funding_tx_opt {
90329035
self.broadcast_interactive_funding(channel, &funding_tx);
@@ -9039,7 +9042,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
90399042
Ok((None, _)) => {
90409043
debug_assert!(false, "If our tx_signatures is empty, then we should send it first!");
90419044
},
9042-
Err(err) => debug_assert!(false, "We should not error here but we got: {:?}", err),
9045+
Err(err) => {
9046+
log_warn!(logger, "Failed signing interactive funding transaction: {err:?}");
9047+
},
90439048
}
90449049
}
90459050
}
@@ -10026,7 +10031,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1002610031
hash_map::Entry::Occupied(mut chan_entry) => {
1002710032
match chan_entry.get_mut().as_funded_mut() {
1002810033
Some(chan) => {
10029-
let (funding_tx_opt, tx_signatures_opt) = try_channel_entry!(self, peer_state, chan.tx_signatures(msg), chan_entry);
10034+
let (tx_signatures_opt, funding_tx_opt) = try_channel_entry!(self, peer_state, chan.tx_signatures(msg), chan_entry);
1003010035
if let Some(tx_signatures) = tx_signatures_opt {
1003110036
peer_state.pending_msg_events.push(MessageSendEvent::SendTxSignatures {
1003210037
node_id: *counterparty_node_id,

0 commit comments

Comments
 (0)