Skip to content

Commit 7958dd9

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 a415c7a commit 7958dd9

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;
@@ -337,11 +336,54 @@ impl ConstructedTransaction {
337336
self.tx().compute_txid()
338337
}
339338

339+
fn finalize(
340+
&self, holder_tx_signatures: &TxSignatures, counterparty_tx_signatures: &TxSignatures,
341+
shared_input_sig: Option<&SharedInputSignature>,
342+
) -> Option<Transaction> {
343+
let mut tx = self.tx.clone();
344+
self.add_local_witnesses(&mut tx, holder_tx_signatures.witnesses.clone());
345+
self.add_remote_witnesses(&mut tx, counterparty_tx_signatures.witnesses.clone());
346+
347+
if let Some(shared_input_index) = self.shared_input_index {
348+
let holder_shared_input_sig =
349+
holder_tx_signatures.shared_input_signature.or_else(|| {
350+
debug_assert!(false);
351+
None
352+
})?;
353+
let counterparty_shared_input_sig =
354+
counterparty_tx_signatures.shared_input_signature.or_else(|| {
355+
debug_assert!(false);
356+
None
357+
})?;
358+
359+
let shared_input_sig = shared_input_sig.or_else(|| {
360+
debug_assert!(false);
361+
None
362+
})?;
363+
364+
let mut witness = Witness::new();
365+
witness.push(Vec::new());
366+
let holder_sig = BitcoinSignature::sighash_all(holder_shared_input_sig);
367+
let counterparty_sig = BitcoinSignature::sighash_all(counterparty_shared_input_sig);
368+
if shared_input_sig.holder_signature_first {
369+
witness.push_ecdsa_signature(&holder_sig);
370+
witness.push_ecdsa_signature(&counterparty_sig);
371+
} else {
372+
witness.push_ecdsa_signature(&counterparty_sig);
373+
witness.push_ecdsa_signature(&holder_sig);
374+
}
375+
witness.push(&shared_input_sig.witness_script);
376+
tx.input[shared_input_index as usize].witness = witness;
377+
}
378+
379+
Some(tx)
380+
}
381+
340382
/// Adds provided holder witnesses to holder inputs of unsigned transaction.
341383
///
342384
/// Note that it is assumed that the witness count equals the holder input count.
343-
fn add_local_witnesses(&mut self, witnesses: Vec<Witness>) {
344-
self.tx
385+
fn add_local_witnesses(&self, transaction: &mut Transaction, witnesses: Vec<Witness>) {
386+
transaction
345387
.input
346388
.iter_mut()
347389
.zip(self.input_metadata.iter())
@@ -360,8 +402,8 @@ impl ConstructedTransaction {
360402
/// Adds counterparty witnesses to counterparty inputs of unsigned transaction.
361403
///
362404
/// Note that it is assumed that the witness count equals the counterparty input count.
363-
fn add_remote_witnesses(&mut self, witnesses: Vec<Witness>) {
364-
self.tx
405+
fn add_remote_witnesses(&self, transaction: &mut Transaction, witnesses: Vec<Witness>) {
406+
transaction
365407
.input
366408
.iter_mut()
367409
.zip(self.input_metadata.iter())
@@ -390,13 +432,11 @@ impl ConstructedTransaction {
390432
pub(crate) struct SharedInputSignature {
391433
holder_signature_first: bool,
392434
witness_script: ScriptBuf,
393-
counterparty_signature: Option<Signature>,
394435
}
395436

396437
impl_writeable_tlv_based!(SharedInputSignature, {
397438
(1, holder_signature_first, required),
398439
(3, witness_script, required),
399-
(5, counterparty_signature, required),
400440
});
401441

402442
/// The InteractiveTxSigningSession coordinates the signing flow of interactively constructed
@@ -411,9 +451,9 @@ pub(crate) struct InteractiveTxSigningSession {
411451
unsigned_tx: ConstructedTransaction,
412452
holder_sends_tx_signatures_first: bool,
413453
has_received_commitment_signed: bool,
414-
has_received_tx_signatures: bool,
415454
shared_input_signature: Option<SharedInputSignature>,
416455
holder_tx_signatures: Option<TxSignatures>,
456+
counterparty_tx_signatures: Option<TxSignatures>,
417457
}
418458

419459
impl InteractiveTxSigningSession {
@@ -430,7 +470,7 @@ impl InteractiveTxSigningSession {
430470
}
431471

432472
pub fn has_received_tx_signatures(&self) -> bool {
433-
self.has_received_tx_signatures
473+
self.counterparty_tx_signatures.is_some()
434474
}
435475

436476
pub fn holder_tx_signatures(&self) -> &Option<TxSignatures> {
@@ -455,7 +495,7 @@ impl InteractiveTxSigningSession {
455495
pub fn received_tx_signatures(
456496
&mut self, tx_signatures: &TxSignatures,
457497
) -> Result<(Option<TxSignatures>, Option<Transaction>), String> {
458-
if self.has_received_tx_signatures {
498+
if self.has_received_tx_signatures() {
459499
return Err("Already received a tx_signatures message".to_string());
460500
}
461501
if self.remote_inputs_count() != tx_signatures.witnesses.len() {
@@ -468,26 +508,15 @@ impl InteractiveTxSigningSession {
468508
return Err("Unexpected shared input signature".to_string());
469509
}
470510

471-
self.unsigned_tx.add_remote_witnesses(tx_signatures.witnesses.clone());
472-
if let Some(ref mut shared_input_sig) = self.shared_input_signature {
473-
shared_input_sig.counterparty_signature = tx_signatures.shared_input_signature.clone();
474-
}
475-
self.has_received_tx_signatures = true;
511+
self.counterparty_tx_signatures = Some(tx_signatures.clone());
476512

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

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

492521
Ok((holder_tx_signatures, funding_tx_opt))
493522
}
@@ -514,15 +543,15 @@ impl InteractiveTxSigningSession {
514543

515544
self.verify_interactive_tx_signatures(secp_ctx, &tx_signatures.witnesses)?;
516545

517-
self.unsigned_tx.add_local_witnesses(tx_signatures.witnesses.clone());
518546
self.holder_tx_signatures = Some(tx_signatures);
519547

520-
let funding_tx_opt = self.has_received_tx_signatures.then(|| self.finalize_funding_tx());
521-
let holder_tx_signatures =
522-
(self.holder_sends_tx_signatures_first || self.has_received_tx_signatures).then(|| {
523-
debug_assert!(self.has_received_commitment_signed);
524-
self.holder_tx_signatures.clone().expect("Holder tx_signatures were just provided")
525-
});
548+
let funding_tx_opt = self.maybe_finalize_funding_tx();
549+
let holder_tx_signatures = (self.holder_sends_tx_signatures_first
550+
|| self.has_received_tx_signatures())
551+
.then(|| {
552+
debug_assert!(self.has_received_commitment_signed);
553+
self.holder_tx_signatures.clone().expect("Holder tx_signatures were just provided")
554+
});
526555

527556
Ok((holder_tx_signatures, funding_tx_opt))
528557
}
@@ -574,43 +603,15 @@ impl InteractiveTxSigningSession {
574603
})
575604
}
576605

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

616617
fn verify_interactive_tx_signatures<C: bitcoin::secp256k1::Verification>(
@@ -779,7 +780,7 @@ impl_writeable_tlv_based!(InteractiveTxSigningSession, {
779780
(1, unsigned_tx, required),
780781
(3, has_received_commitment_signed, required),
781782
(5, holder_tx_signatures, required),
782-
(7, has_received_tx_signatures, required),
783+
(7, counterparty_tx_signatures, required),
783784
(9, holder_sends_tx_signatures_first, required),
784785
(11, shared_input_signature, required),
785786
});
@@ -1370,7 +1371,6 @@ macro_rules! define_state_transitions {
13701371
.as_ref()
13711372
.map(|shared_input| SharedInputSignature {
13721373
holder_signature_first: shared_input.holder_sig_first,
1373-
counterparty_signature: None,
13741374
witness_script: shared_input.witness_script.clone(),
13751375
});
13761376
let holder_node_id = context.holder_node_id;
@@ -1390,9 +1390,9 @@ macro_rules! define_state_transitions {
13901390
unsigned_tx: tx,
13911391
holder_sends_tx_signatures_first,
13921392
has_received_commitment_signed: false,
1393-
has_received_tx_signatures: false,
13941393
shared_input_signature,
13951394
holder_tx_signatures: None,
1395+
counterparty_tx_signatures: None,
13961396
};
13971397
Ok(NegotiationComplete(signing_session))
13981398
}
@@ -3317,9 +3317,9 @@ mod tests {
33173317
unsigned_tx,
33183318
holder_sends_tx_signatures_first: false, // N/A for test
33193319
has_received_commitment_signed: false, // N/A for test
3320-
has_received_tx_signatures: false, // N/A for test
33213320
shared_input_signature: None,
33223321
holder_tx_signatures: None,
3322+
counterparty_tx_signatures: None,
33233323
}
33243324
.verify_interactive_tx_signatures(
33253325
&secp_ctx,

0 commit comments

Comments
 (0)