Skip to content

Commit f20a477

Browse files
committed
Persist witnesses in InteractiveTxSigningSession
InteractiveTxSigningSession currently persists holder witnesses directly, but persists counterparty witnesses as part of its unsigned ConstructedTransaction. This makes the ConstructedTransaction actually partially signed even though it is held in a field named unsigned_tx. Instead, persists the counterparty witnesses alongside the holder witnesses directly in InteractiveTxSigningSession, leaving the transaction it holds unsigned.
1 parent 105c686 commit f20a477

File tree

1 file changed

+71
-71
lines changed

1 file changed

+71
-71
lines changed

lightning/src/ln/interactivetxs.rs

Lines changed: 71 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use bitcoin::constants::WITNESS_SCALE_FACTOR;
1717
use bitcoin::ecdsa::Signature as BitcoinSignature;
1818
use bitcoin::key::Secp256k1;
1919
use bitcoin::policy::MAX_STANDARD_TX_WEIGHT;
20-
use bitcoin::secp256k1::ecdsa::Signature;
2120
use bitcoin::secp256k1::{Message, PublicKey};
2221
use bitcoin::sighash::SighashCache;
2322
use bitcoin::transaction::Version;
@@ -339,11 +338,54 @@ impl ConstructedTransaction {
339338
.sum()
340339
}
341340

341+
fn finalize(
342+
&self, holder_tx_signatures: &TxSignatures, counterparty_tx_signatures: &TxSignatures,
343+
shared_input_sig: Option<&SharedInputSignature>,
344+
) -> Option<Transaction> {
345+
let mut tx = self.tx.clone();
346+
self.add_local_witnesses(&mut tx, holder_tx_signatures.witnesses.clone());
347+
self.add_remote_witnesses(&mut tx, counterparty_tx_signatures.witnesses.clone());
348+
349+
if let Some(shared_input_index) = self.shared_input_index {
350+
let holder_shared_input_sig =
351+
holder_tx_signatures.shared_input_signature.or_else(|| {
352+
debug_assert!(false);
353+
None
354+
})?;
355+
let counterparty_shared_input_sig =
356+
counterparty_tx_signatures.shared_input_signature.or_else(|| {
357+
debug_assert!(false);
358+
None
359+
})?;
360+
361+
let shared_input_sig = shared_input_sig.or_else(|| {
362+
debug_assert!(false);
363+
None
364+
})?;
365+
366+
let mut witness = Witness::new();
367+
witness.push(Vec::new());
368+
let holder_sig = BitcoinSignature::sighash_all(holder_shared_input_sig);
369+
let counterparty_sig = BitcoinSignature::sighash_all(counterparty_shared_input_sig);
370+
if shared_input_sig.holder_signature_first {
371+
witness.push_ecdsa_signature(&holder_sig);
372+
witness.push_ecdsa_signature(&counterparty_sig);
373+
} else {
374+
witness.push_ecdsa_signature(&counterparty_sig);
375+
witness.push_ecdsa_signature(&holder_sig);
376+
}
377+
witness.push(&shared_input_sig.witness_script);
378+
tx.input[shared_input_index as usize].witness = witness;
379+
}
380+
381+
Some(tx)
382+
}
383+
342384
/// Adds provided holder witnesses to holder inputs of unsigned transaction.
343385
///
344386
/// Note that it is assumed that the witness count equals the holder input count.
345-
fn add_local_witnesses(&mut self, witnesses: Vec<Witness>) {
346-
self.tx
387+
fn add_local_witnesses(&self, transaction: &mut Transaction, witnesses: Vec<Witness>) {
388+
transaction
347389
.input
348390
.iter_mut()
349391
.zip(self.input_metadata.iter())
@@ -362,8 +404,8 @@ impl ConstructedTransaction {
362404
/// Adds counterparty witnesses to counterparty inputs of unsigned transaction.
363405
///
364406
/// Note that it is assumed that the witness count equals the counterparty input count.
365-
fn add_remote_witnesses(&mut self, witnesses: Vec<Witness>) {
366-
self.tx
407+
fn add_remote_witnesses(&self, transaction: &mut Transaction, witnesses: Vec<Witness>) {
408+
transaction
367409
.input
368410
.iter_mut()
369411
.zip(self.input_metadata.iter())
@@ -392,13 +434,11 @@ impl ConstructedTransaction {
392434
pub(crate) struct SharedInputSignature {
393435
holder_signature_first: bool,
394436
witness_script: ScriptBuf,
395-
counterparty_signature: Option<Signature>,
396437
}
397438

398439
impl_writeable_tlv_based!(SharedInputSignature, {
399440
(1, holder_signature_first, required),
400441
(3, witness_script, required),
401-
(5, counterparty_signature, required),
402442
});
403443

404444
/// The InteractiveTxSigningSession coordinates the signing flow of interactively constructed
@@ -413,9 +453,9 @@ pub(crate) struct InteractiveTxSigningSession {
413453
unsigned_tx: ConstructedTransaction,
414454
holder_sends_tx_signatures_first: bool,
415455
has_received_commitment_signed: bool,
416-
has_received_tx_signatures: bool,
417456
shared_input_signature: Option<SharedInputSignature>,
418457
holder_tx_signatures: Option<TxSignatures>,
458+
counterparty_tx_signatures: Option<TxSignatures>,
419459
}
420460

421461
impl InteractiveTxSigningSession {
@@ -432,7 +472,7 @@ impl InteractiveTxSigningSession {
432472
}
433473

434474
pub fn has_received_tx_signatures(&self) -> bool {
435-
self.has_received_tx_signatures
475+
self.counterparty_tx_signatures.is_some()
436476
}
437477

438478
pub fn holder_tx_signatures(&self) -> &Option<TxSignatures> {
@@ -457,7 +497,7 @@ impl InteractiveTxSigningSession {
457497
pub fn received_tx_signatures(
458498
&mut self, tx_signatures: &TxSignatures,
459499
) -> Result<(Option<TxSignatures>, Option<Transaction>), String> {
460-
if self.has_received_tx_signatures {
500+
if self.has_received_tx_signatures() {
461501
return Err("Already received a tx_signatures message".to_string());
462502
}
463503
if self.remote_inputs_count() != tx_signatures.witnesses.len() {
@@ -470,26 +510,15 @@ impl InteractiveTxSigningSession {
470510
return Err("Unexpected shared input signature".to_string());
471511
}
472512

473-
self.unsigned_tx.add_remote_witnesses(tx_signatures.witnesses.clone());
474-
if let Some(ref mut shared_input_sig) = self.shared_input_signature {
475-
shared_input_sig.counterparty_signature = tx_signatures.shared_input_signature.clone();
476-
}
477-
self.has_received_tx_signatures = true;
513+
self.counterparty_tx_signatures = Some(tx_signatures.clone());
478514

479515
let holder_tx_signatures = if !self.holder_sends_tx_signatures_first {
480516
self.holder_tx_signatures.clone()
481517
} else {
482518
None
483519
};
484520

485-
// Check if the holder has provided its signatures and if so,
486-
// return the finalized funding transaction.
487-
let funding_tx_opt = if self.holder_tx_signatures.is_some() {
488-
Some(self.finalize_funding_tx())
489-
} else {
490-
// This means we're still waiting for the holder to provide their signatures.
491-
None
492-
};
521+
let funding_tx_opt = self.maybe_finalize_funding_tx();
493522

494523
Ok((holder_tx_signatures, funding_tx_opt))
495524
}
@@ -516,15 +545,15 @@ impl InteractiveTxSigningSession {
516545

517546
self.verify_interactive_tx_signatures(secp_ctx, &tx_signatures.witnesses)?;
518547

519-
self.unsigned_tx.add_local_witnesses(tx_signatures.witnesses.clone());
520548
self.holder_tx_signatures = Some(tx_signatures);
521549

522-
let funding_tx_opt = self.has_received_tx_signatures.then(|| self.finalize_funding_tx());
523-
let holder_tx_signatures =
524-
(self.holder_sends_tx_signatures_first || self.has_received_tx_signatures).then(|| {
525-
debug_assert!(self.has_received_commitment_signed);
526-
self.holder_tx_signatures.clone().expect("Holder tx_signatures were just provided")
527-
});
550+
let funding_tx_opt = self.maybe_finalize_funding_tx();
551+
let holder_tx_signatures = (self.holder_sends_tx_signatures_first
552+
|| self.has_received_tx_signatures())
553+
.then(|| {
554+
debug_assert!(self.has_received_commitment_signed);
555+
self.holder_tx_signatures.clone().expect("Holder tx_signatures were just provided")
556+
});
528557

529558
Ok((holder_tx_signatures, funding_tx_opt))
530559
}
@@ -576,43 +605,15 @@ impl InteractiveTxSigningSession {
576605
})
577606
}
578607

579-
fn finalize_funding_tx(&mut self) -> Transaction {
580-
if let Some(shared_input_index) = self.unsigned_tx.shared_input_index {
581-
if let Some(holder_shared_input_sig) = self
582-
.holder_tx_signatures
583-
.as_ref()
584-
.and_then(|holder_tx_sigs| holder_tx_sigs.shared_input_signature)
585-
{
586-
if let Some(ref shared_input_sig) = self.shared_input_signature {
587-
if let Some(counterparty_shared_input_sig) =
588-
shared_input_sig.counterparty_signature
589-
{
590-
let mut witness = Witness::new();
591-
witness.push(Vec::new());
592-
let holder_sig = BitcoinSignature::sighash_all(holder_shared_input_sig);
593-
let counterparty_sig =
594-
BitcoinSignature::sighash_all(counterparty_shared_input_sig);
595-
if shared_input_sig.holder_signature_first {
596-
witness.push_ecdsa_signature(&holder_sig);
597-
witness.push_ecdsa_signature(&counterparty_sig);
598-
} else {
599-
witness.push_ecdsa_signature(&counterparty_sig);
600-
witness.push_ecdsa_signature(&holder_sig);
601-
}
602-
witness.push(&shared_input_sig.witness_script);
603-
self.unsigned_tx.tx.input[shared_input_index as usize].witness = witness;
604-
} else {
605-
debug_assert!(false);
606-
}
607-
} else {
608-
debug_assert!(false);
609-
}
610-
} else {
611-
debug_assert!(false);
612-
}
613-
}
614-
615-
self.unsigned_tx.tx.clone()
608+
fn maybe_finalize_funding_tx(&mut self) -> Option<Transaction> {
609+
let holder_tx_signatures = self.holder_tx_signatures.as_ref()?;
610+
let counterparty_tx_signatures = self.counterparty_tx_signatures.as_ref()?;
611+
let shared_input_signature = self.shared_input_signature.as_ref();
612+
self.unsigned_tx.finalize(
613+
holder_tx_signatures,
614+
counterparty_tx_signatures,
615+
shared_input_signature,
616+
)
616617
}
617618

618619
fn verify_interactive_tx_signatures<C: bitcoin::secp256k1::Verification>(
@@ -781,7 +782,7 @@ impl_writeable_tlv_based!(InteractiveTxSigningSession, {
781782
(1, unsigned_tx, required),
782783
(3, has_received_commitment_signed, required),
783784
(5, holder_tx_signatures, required),
784-
(7, has_received_tx_signatures, required),
785+
(7, counterparty_tx_signatures, required),
785786
(9, holder_sends_tx_signatures_first, required),
786787
(11, shared_input_signature, required),
787788
});
@@ -1372,7 +1373,6 @@ macro_rules! define_state_transitions {
13721373
.as_ref()
13731374
.map(|shared_input| SharedInputSignature {
13741375
holder_signature_first: shared_input.holder_sig_first,
1375-
counterparty_signature: None,
13761376
witness_script: shared_input.witness_script.clone(),
13771377
});
13781378
let holder_node_id = context.holder_node_id;
@@ -1394,9 +1394,9 @@ macro_rules! define_state_transitions {
13941394
unsigned_tx: tx,
13951395
holder_sends_tx_signatures_first,
13961396
has_received_commitment_signed: false,
1397-
has_received_tx_signatures: false,
13981397
shared_input_signature,
13991398
holder_tx_signatures: None,
1399+
counterparty_tx_signatures: None,
14001400
};
14011401
Ok(NegotiationComplete(signing_session))
14021402
}
@@ -3319,9 +3319,9 @@ mod tests {
33193319
unsigned_tx,
33203320
holder_sends_tx_signatures_first: false, // N/A for test
33213321
has_received_commitment_signed: false, // N/A for test
3322-
has_received_tx_signatures: false, // N/A for test
33233322
shared_input_signature: None,
33243323
holder_tx_signatures: None,
3324+
counterparty_tx_signatures: None,
33253325
}
33263326
.verify_interactive_tx_signatures(
33273327
&secp_ctx,

0 commit comments

Comments
 (0)