Skip to content

Commit 0c66c80

Browse files
committed
Add funding_transaction_signed, handle tx_complete
1 parent 8a835e5 commit 0c66c80

File tree

4 files changed

+181
-37
lines changed

4 files changed

+181
-37
lines changed

Diff for: lightning/src/ln/channel.rs

+78-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ use bitcoin::hash_types::{Txid, BlockHash};
2424
use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
2525
use bitcoin::secp256k1::{PublicKey,SecretKey};
2626
use bitcoin::secp256k1::{Secp256k1,ecdsa::Signature};
27-
use bitcoin::{secp256k1, sighash};
27+
use bitcoin::{secp256k1, sighash, Witness};
2828
#[cfg(splicing)]
29-
use bitcoin::{Sequence, Witness};
29+
use bitcoin::Sequence;
3030

3131
use crate::ln::types::ChannelId;
3232
use crate::types::payment::{PaymentPreimage, PaymentHash};
@@ -1546,6 +1546,29 @@ impl<SP: Deref> Channel<SP> where
15461546
}
15471547
}
15481548

1549+
pub fn funding_transaction_signed(&mut self, witnesses: Vec<Witness>) -> Result<Option<msgs::TxSignatures>, APIError> {
1550+
match &mut self.phase {
1551+
ChannelPhase::Funded(chan) => {
1552+
chan.funding_transaction_signed(witnesses)
1553+
}
1554+
#[cfg(splicing)]
1555+
ChannelPhase::RefundingV2(chan) => {
1556+
if let Some(ref mut post_funded) = &mut chan.post_funded {
1557+
post_funded.funding_transaction_signed(witnesses)
1558+
} else {
1559+
Err(APIError::APIMisuseError {
1560+
err: "No negotiation in progress, called in wrong state".to_owned()
1561+
})
1562+
}
1563+
}
1564+
_ => {
1565+
return Err(APIError::APIMisuseError {
1566+
err: "Got a funding_transaction_signed call with no funding negotiation in-progress".to_owned()
1567+
});
1568+
}
1569+
}
1570+
}
1571+
15491572
pub fn force_shutdown(&mut self, should_broadcast: bool, closure_reason: ClosureReason) -> ShutdownResult {
15501573
let (funding, context) = self.funding_and_context_mut();
15511574
context.force_shutdown(funding, should_broadcast, closure_reason)
@@ -6598,6 +6621,59 @@ impl<SP: Deref> FundedChannel<SP> where
65986621
return Ok(self.push_ret_blockable_mon_update(monitor_update));
65996622
}
66006623

6624+
/// Check is a splice is currently in progress
6625+
/// Can be called regardless of `splicing` configuration. TODO: remove this note once `cfg(splicing)` is being removed
6626+
fn is_splice_pending(&self) -> bool {
6627+
#[cfg(splicing)]
6628+
return self.pending_splice_post.is_some();
6629+
#[cfg(not(splicing))]
6630+
false
6631+
}
6632+
6633+
pub(super) fn funding_transaction_signed(&mut self, witnesses: Vec<Witness>) -> Result<Option<msgs::TxSignatures>, APIError> {
6634+
self.verify_interactive_tx_signatures(&witnesses);
6635+
let is_splice = self.is_splice_pending();
6636+
if let Some(ref mut signing_session) = self.interactive_tx_signing_session {
6637+
// Shared signature (used in splicing): holder signature on the prev funding tx input should have been saved.
6638+
// include it in tlvs field
6639+
let tlvs = if is_splice {
6640+
if let Some(s) = signing_session.shared_signature {
6641+
Some(s)
6642+
} else {
6643+
panic!("TODO error!");
6644+
}
6645+
} else {
6646+
None
6647+
};
6648+
let (tx_signatures_opt, funding_tx_opt) =
6649+
signing_session.provide_holder_witnesses(self.context.channel_id(), witnesses, tlvs)
6650+
.map_err(|_| APIError::APIMisuseError {
6651+
err: "Internal error in funding_transaction_signed, provide_holder_witnesses".to_owned(),
6652+
})?;
6653+
if funding_tx_opt.is_some() {
6654+
self.funding.funding_transaction = funding_tx_opt.clone();
6655+
/* TODO
6656+
#[cfg(splicing)]
6657+
{
6658+
self.context.funding_transaction_saved = funding_tx_opt.clone();
6659+
}
6660+
*/
6661+
}
6662+
Ok(tx_signatures_opt)
6663+
} else {
6664+
Err(APIError::APIMisuseError {
6665+
err: format!("Channel with id {} has no pending signing session, not expecting funding signatures", self.context.channel_id())
6666+
})
6667+
}
6668+
}
6669+
6670+
fn verify_interactive_tx_signatures(&mut self, _witnesses: &Vec<Witness>) {
6671+
if let Some(ref mut _signing_session) = self.interactive_tx_signing_session {
6672+
// Check that sighash_all was used:
6673+
// TODO(dual_funding): Check sig for sighash
6674+
}
6675+
}
6676+
66016677
/// Public version of the below, checking relevant preconditions first.
66026678
/// If we're not in a state where freeing the holding cell makes sense, this is a no-op and
66036679
/// returns `(None, Vec::new())`.

Diff for: lightning/src/ln/channelmanager.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -5532,9 +5532,36 @@ where
55325532
/// Do NOT broadcast the funding transaction yourself. When we have safely received our
55335533
/// counterparty's signature(s) the funding transaction will automatically be broadcast via the
55345534
/// [`BroadcasterInterface`] provided when this `ChannelManager` was constructed.
5535-
pub fn funding_transaction_signed(&self, _channel_id: &ChannelId, _counterparty_node_id: &PublicKey,
5536-
_transaction: Transaction) -> Result<(), APIError> {
5537-
// TODO(splicing) TODO(dual_funding)
5535+
pub fn funding_transaction_signed(
5536+
&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, transaction: Transaction)
5537+
-> Result<(), APIError> {
5538+
let per_peer_state = self.per_peer_state.read().unwrap();
5539+
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
5540+
.ok_or_else(|| APIError::ChannelUnavailable {
5541+
err: format!("Can't find a peer matching the passed counterparty node_id {}",
5542+
counterparty_node_id) })?;
5543+
5544+
let witnesses: Vec<_> = transaction.input.into_iter().filter_map(|input| {
5545+
if input.witness.is_empty() { None } else { Some(input.witness) }
5546+
}).collect();
5547+
5548+
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
5549+
let peer_state = &mut *peer_state_lock;
5550+
5551+
if let Some(channel) = peer_state.channel_by_id.get_mut(channel_id) {
5552+
let tx_signatures_opt = channel.funding_transaction_signed(witnesses)?;
5553+
if let Some(tx_signatures) = tx_signatures_opt {
5554+
peer_state.pending_msg_events.push(MessageSendEvent::SendTxSignatures {
5555+
node_id: *counterparty_node_id,
5556+
msg: tx_signatures,
5557+
});
5558+
}
5559+
} else {
5560+
return Err(APIError::ChannelUnavailable { err: format!(
5561+
"Channel with ID {} and counterparty_node_id {} not found", channel_id, counterparty_node_id
5562+
)});
5563+
}
5564+
55385565
Ok(())
55395566
}
55405567

@@ -8565,6 +8592,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
85658592
update_fee: None,
85668593
},
85678594
});
8595+
// channel.set_next_funding_txid(&funding_txid); // TODO ?
85688596
}
85698597
Ok(())
85708598
},

Diff for: lightning/src/ln/interactivetxs.rs

+32-30
Original file line numberDiff line numberDiff line change
@@ -302,19 +302,8 @@ pub(crate) struct InteractiveTxSigningSession {
302302
impl InteractiveTxSigningSession {
303303
pub fn received_commitment_signed(&mut self) -> Option<TxSignatures> {
304304
self.received_commitment_signed = true;
305-
if self.holder_sends_tx_signatures_first {
306-
self.holder_tx_signatures.clone()
307-
} else {
308-
None
309-
}
310-
}
311305

312-
pub fn get_tx_signatures(&self) -> Option<TxSignatures> {
313-
if self.received_commitment_signed {
314-
self.holder_tx_signatures.clone()
315-
} else {
316-
None
317-
}
306+
self.get_tx_signatures()
318307
}
319308

320309
/// Handles a `tx_signatures` message received from the counterparty.
@@ -337,22 +326,7 @@ impl InteractiveTxSigningSession {
337326
self.unsigned_tx.add_remote_witnesses(tx_signatures.witnesses.clone());
338327
self.counterparty_sent_tx_signatures = true;
339328

340-
let holder_tx_signatures = if !self.holder_sends_tx_signatures_first {
341-
self.holder_tx_signatures.clone()
342-
} else {
343-
None
344-
};
345-
346-
// Check if the holder has provided its signatures and if so,
347-
// return the finalized funding transaction.
348-
let funding_tx_opt = if self.holder_tx_signatures.is_some() {
349-
Some(self.finalize_funding_tx())
350-
} else {
351-
// This means we're still waiting for the holder to provide their signatures.
352-
None
353-
};
354-
355-
Ok((holder_tx_signatures, funding_tx_opt))
329+
Ok((self.get_tx_signatures(), self.get_finalized_funding_tx()))
356330
}
357331

358332
/// Provides the holder witnesses for the unsigned transaction.
@@ -362,7 +336,7 @@ impl InteractiveTxSigningSession {
362336
pub fn provide_holder_witnesses(
363337
&mut self, channel_id: ChannelId, witnesses: Vec<Witness>,
364338
shared_input_signature: Option<Signature>,
365-
) -> Result<(), ()> {
339+
) -> Result<(Option<TxSignatures>, Option<Transaction>), ()> {
366340
if self.local_inputs_count() != witnesses.len() {
367341
return Err(());
368342
}
@@ -375,7 +349,35 @@ impl InteractiveTxSigningSession {
375349
shared_input_signature,
376350
});
377351

378-
Ok(())
352+
Ok((self.get_tx_signatures(), self.get_finalized_funding_tx()))
353+
}
354+
355+
/// Decide if we need to send `TxSignatures` at this stage or not
356+
fn get_tx_signatures(&mut self) -> Option<TxSignatures> {
357+
if self.holder_tx_signatures.is_none() {
358+
return None; // no local signature yet
359+
}
360+
if !self.received_commitment_signed {
361+
return None; // no counterparty commitment received yet
362+
}
363+
if (!self.holder_sends_tx_signatures_first && self.counterparty_sent_tx_signatures)
364+
|| (self.holder_sends_tx_signatures_first && !self.counterparty_sent_tx_signatures)
365+
{
366+
self.holder_tx_signatures.clone()
367+
} else {
368+
None
369+
}
370+
}
371+
372+
/// Decide if we have the funding transaction signed from both parties
373+
fn get_finalized_funding_tx(&mut self) -> Option<Transaction> {
374+
if self.holder_tx_signatures.is_none() {
375+
return None; // no local signature yet
376+
}
377+
if !self.counterparty_sent_tx_signatures {
378+
return None; // no counterparty signature received yet
379+
}
380+
Some(self.finalize_funding_tx())
379381
}
380382

381383
pub fn remote_inputs_count(&self) -> usize {

Diff for: lightning/src/ln/splicing_tests.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ fn test_v1_splice_in() {
5050
let expect_inputs_in_reverse = true;
5151
let expected_pre_funding_txid =
5252
"4f128bedf1a15baf465ab1bfd6e97c8f82628f4156bf86eb1cbc132cda6733ae";
53+
let expected_splice_funding_txid =
54+
"0a6d624a6a6ec0f72e50317856cb8169c1a2272559ba84f20fbb37838c13bf82";
5355

5456
// ==== Channel is now ready for normal operation
5557

@@ -257,7 +259,7 @@ fn test_v1_splice_in() {
257259
};
258260
let (input_idx_prev_fund, input_idx_second_input) =
259261
if expect_inputs_in_reverse { (0, 1) } else { (1, 0) };
260-
if let Event::FundingTransactionReadyForSigning {
262+
let _channel_id1 = if let Event::FundingTransactionReadyForSigning {
261263
channel_id,
262264
counterparty_node_id,
263265
mut unsigned_transaction,
@@ -286,8 +288,44 @@ fn test_v1_splice_in() {
286288
.node
287289
.funding_transaction_signed(&channel_id, &counterparty_node_id, unsigned_transaction)
288290
.unwrap();
291+
channel_id
289292
} else {
290-
panic!();
293+
panic!("Expected event FundingTransactionReadyForSigning");
294+
};
295+
296+
// check new funding tx
297+
assert_eq!(initiator_node.node.list_channels().len(), 1);
298+
{
299+
let channel = &initiator_node.node.list_channels()[0];
300+
assert!(!channel.is_channel_ready);
301+
assert_eq!(channel.channel_value_satoshis, post_splice_channel_value);
302+
assert_eq!(channel.funding_txo.unwrap().txid.to_string(), expected_splice_funding_txid);
303+
assert_eq!(channel.confirmations.unwrap(), 0);
304+
}
305+
306+
let _res = acceptor_node
307+
.node
308+
.handle_tx_complete(initiator_node.node.get_our_node_id(), &tx_complete_msg);
309+
let msg_events = acceptor_node.node.get_and_clear_pending_msg_events();
310+
// First messsage is commitment_signed, second is tx_signatures (see below for more)
311+
assert_eq!(msg_events.len(), 1);
312+
let _msg_commitment_signed_from_1 = match msg_events[0] {
313+
MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => {
314+
assert_eq!(*node_id, initiator_node.node.get_our_node_id());
315+
let res = updates.commitment_signed.clone();
316+
res
317+
},
318+
_ => panic!("Unexpected event {:?}", msg_events[0]),
319+
};
320+
321+
// check new funding tx (acceptor side)
322+
assert_eq!(acceptor_node.node.list_channels().len(), 1);
323+
{
324+
let channel = &acceptor_node.node.list_channels()[0];
325+
assert!(!channel.is_channel_ready);
326+
assert_eq!(channel.channel_value_satoshis, post_splice_channel_value);
327+
assert_eq!(channel.funding_txo.unwrap().txid.to_string(), expected_splice_funding_txid);
328+
assert_eq!(channel.confirmations.unwrap(), 0);
291329
}
292330

293331
// TODO(splicing): Continue with commitment flow, new tx confirmation

0 commit comments

Comments
 (0)