Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 83 additions & 12 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2192,6 +2192,11 @@ impl FundingScope {
self.channel_transaction_parameters.make_funding_redeemscript()
}

#[cfg(splicing)]
fn holder_funding_pubkey(&self) -> &PublicKey {
&self.get_holder_pubkeys().funding_pubkey
}

fn counterparty_funding_pubkey(&self) -> &PublicKey {
&self.get_counterparty_pubkeys().funding_pubkey
}
Expand Down Expand Up @@ -2335,8 +2340,16 @@ impl FundingScope {
};

let local_owned = self.value_to_self_msat / 1000;

SharedOwnedInput::new(input, prev_output, local_owned)
let holder_sig_first = self.holder_funding_pubkey().serialize()[..]
< self.counterparty_funding_pubkey().serialize()[..];

SharedOwnedInput::new(
input,
prev_output,
local_owned,
holder_sig_first,
self.get_funding_redeemscript(),
)
}
}

Expand Down Expand Up @@ -7969,9 +7982,38 @@ where
}

pub fn funding_transaction_signed(
&mut self, witnesses: Vec<Witness>,
&mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>,
) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), APIError> {
let (funding_tx_opt, tx_signatures_opt) = self
if !self.context.channel_state.is_interactive_signing() {
let err =
format!("Channel {} not expecting funding signatures", self.context.channel_id);
return Err(APIError::APIMisuseError { err });
}
if self.context.channel_state.is_our_tx_signatures_ready() {
let err =
format!("Channel {} already received funding signatures", self.context.channel_id);
return Err(APIError::APIMisuseError { err });
}
#[cfg(splicing)]
if let Some(pending_splice) = self.pending_splice.as_ref() {
if !pending_splice
.funding_negotiation
.as_ref()
.map(|funding_negotiation| {
matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures(_))
})
.unwrap_or(false)
{
debug_assert!(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this be reached?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it could? I was thinking it was already covered by the state checks above, so the assert here is really to make sure we catch a mismatch in the splice state.

let err = format!(
"Channel {} with pending splice is not expecting funding signatures yet",
self.context.channel_id
);
return Err(APIError::APIMisuseError { err });
}
}

let (tx_signatures_opt, funding_tx_opt) = self
.interactive_tx_signing_session
.as_mut()
.ok_or_else(|| APIError::APIMisuseError {
Expand All @@ -7981,12 +8023,41 @@ where
),
})
.and_then(|signing_session| {
let tx = signing_session.unsigned_tx().build_unsigned_tx();
if funding_txid_signed != tx.compute_txid() {
return Err(APIError::APIMisuseError {
err: "Transaction was malleated prior to signing".to_owned(),
});
}

let shared_input_signature = if let Some(splice_input_index) =
signing_session.unsigned_tx().shared_input_index()
{
let sig = match &self.context.holder_signer {
ChannelSignerType::Ecdsa(signer) => signer.sign_splice_shared_input(
&self.funding.channel_transaction_parameters,
&tx,
splice_input_index as usize,
&self.context.secp_ctx,
),
#[cfg(taproot)]
ChannelSignerType::Taproot(_) => todo!(),
};
Some(sig)
} else {
None
};
#[cfg(splicing)]
debug_assert_eq!(self.pending_splice.is_some(), shared_input_signature.is_some());

let tx_signatures = msgs::TxSignatures {
channel_id: self.context.channel_id,
tx_hash: funding_txid_signed,
witnesses,
shared_input_signature,
};
signing_session
.provide_holder_witnesses(
&self.context.secp_ctx,
self.context.channel_id,
witnesses,
)
.provide_holder_witnesses(tx_signatures, &self.context.secp_ctx)
.map_err(|err| APIError::APIMisuseError { err })
})?;

Expand All @@ -8004,7 +8075,7 @@ where
}

#[rustfmt::skip]
pub fn tx_signatures(&mut self, msg: &msgs::TxSignatures) -> Result<(Option<Transaction>, Option<msgs::TxSignatures>), ChannelError> {
pub fn tx_signatures(&mut self, msg: &msgs::TxSignatures) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), ChannelError> {
if !self.context.channel_state.is_interactive_signing()
|| self.context.channel_state.is_their_tx_signatures_sent()
{
Expand Down Expand Up @@ -8035,7 +8106,7 @@ where
}
}

let (holder_tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg.clone())
let (holder_tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg)
.map_err(|msg| ChannelError::Warn(msg))?;

// Set `THEIR_TX_SIGNATURES_SENT` flag after all potential errors.
Expand All @@ -8050,7 +8121,7 @@ where
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
}

Ok((funding_tx_opt, holder_tx_signatures_opt))
Ok((holder_tx_signatures_opt, funding_tx_opt))
} else {
let msg = "Unexpected tx_signatures. No funding transaction awaiting signatures";
let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
Expand Down
31 changes: 18 additions & 13 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5969,13 +5969,14 @@ where
match peer_state.channel_by_id.get_mut(channel_id) {
Some(channel) => match channel.as_funded_mut() {
Some(chan) => {
let txid = transaction.compute_txid();
let witnesses: Vec<_> = transaction
.input
.into_iter()
.map(|input| input.witness)
.filter(|witness| witness.is_empty())
.filter(|witness| !witness.is_empty())
.collect();
match chan.funding_transaction_signed(witnesses) {
match chan.funding_transaction_signed(txid, witnesses) {
Ok((Some(tx_signatures), funding_tx_opt)) => {
if let Some(funding_tx) = funding_tx_opt {
self.broadcast_interactive_funding(chan, &funding_tx);
Expand Down Expand Up @@ -9006,10 +9007,13 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
}
}

if let Some(signing_session) = &mut channel.interactive_tx_signing_session {
if signing_session.local_inputs_count() > 0
&& signing_session.holder_tx_signatures().is_none()
{
if let Some(signing_session) = (!channel.is_awaiting_monitor_update())
.then(|| ())
.and_then(|_| channel.interactive_tx_signing_session.as_mut())
.filter(|signing_session| signing_session.holder_tx_signatures().is_none())
{
let local_inputs_count = signing_session.local_inputs_count();
if local_inputs_count > 0 {
let mut pending_events = self.pending_events.lock().unwrap();
let unsigned_transaction = signing_session.unsigned_tx().build_unsigned_tx();
let event_action = (
Expand All @@ -9022,13 +9026,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
None,
);

if pending_events.contains(&event_action) {
debug_assert!(false, "FundingTransactionReadyForSigning should not have been queued already");
} else {
if !pending_events.contains(&event_action) {
pending_events.push_back(event_action);
}
} else if signing_session.local_inputs_count() == 0 && signing_session.holder_tx_signatures().is_none() {
match channel.funding_transaction_signed(vec![]) {
} else {
let txid = signing_session.unsigned_tx().compute_txid();
match channel.funding_transaction_signed(txid, vec![]) {
Ok((Some(tx_signatures), funding_tx_opt)) => {
if let Some(funding_tx) = funding_tx_opt {
self.broadcast_interactive_funding(channel, &funding_tx);
Expand All @@ -9041,7 +9044,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
Ok((None, _)) => {
debug_assert!(false, "If our tx_signatures is empty, then we should send it first!");
},
Err(err) => debug_assert!(false, "We should not error here but we got: {:?}", err),
Err(err) => {
log_warn!(logger, "Failed signing interactive funding transaction: {err:?}");
},
}
}
}
Expand Down Expand Up @@ -10028,7 +10033,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
hash_map::Entry::Occupied(mut chan_entry) => {
match chan_entry.get_mut().as_funded_mut() {
Some(chan) => {
let (funding_tx_opt, tx_signatures_opt) = try_channel_entry!(self, peer_state, chan.tx_signatures(msg), chan_entry);
let (tx_signatures_opt, funding_tx_opt) = try_channel_entry!(self, peer_state, chan.tx_signatures(msg), chan_entry);
if let Some(tx_signatures) = tx_signatures_opt {
peer_state.pending_msg_events.push(MessageSendEvent::SendTxSignatures {
node_id: *counterparty_node_id,
Expand Down
Loading