- pub(super) fn get_fully_signed_htlc_tx(&mut self, txid: Sha256dHash, htlc_index: u32, preimage: Option<PaymentPreimage>) -> Option<Transaction> {
- //TODO: store preimage in OnchainTxHandler
- if let Some(ref mut local_commitment) = self.local_commitment {
- if local_commitment.txid() == txid {
- self.key_storage.sign_htlc_transaction(local_commitment, htlc_index, preimage, self.local_csv, &self.secp_ctx);
- return local_commitment.htlc_with_valid_witness(htlc_index).clone();
+ fn extract_holder_sigs(holder_commitment: &HolderCommitmentTransaction, sigs: Vec<Signature>) -> Vec<Option<(usize, Signature)>> {
+ let mut ret = Vec::new();
+ for (htlc_idx, (holder_sig, htlc)) in sigs.iter().zip(holder_commitment.htlcs().iter()).enumerate() {
+ let tx_idx = htlc.transaction_output_index.unwrap();
+ if ret.len() <= tx_idx as usize { ret.resize(tx_idx as usize + 1, None); }
+ ret[tx_idx as usize] = Some((htlc_idx, holder_sig.clone()));
+ }
+ ret
+ }
+
+ //TODO: getting lastest holder transactions should be infallible and result in us "force-closing the channel", but we may
+ // have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created,
+ // before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing
+ // to monitor before.
+ pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction {
+ let (sig, htlc_sigs) = self.signer.sign_holder_commitment_and_htlcs(&self.holder_commitment, &self.secp_ctx).expect("signing holder commitment");
+ self.holder_htlc_sigs = Some(Self::extract_holder_sigs(&self.holder_commitment, htlc_sigs));
+ self.holder_commitment.add_holder_sig(funding_redeemscript, sig)
+ }
+
+ #[cfg(any(test, feature="unsafe_revoked_tx_signing"))]
+ pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction {
+ let (sig, htlc_sigs) = self.signer.unsafe_sign_holder_commitment_and_htlcs(&self.holder_commitment, &self.secp_ctx).expect("sign holder commitment");
+ self.holder_htlc_sigs = Some(Self::extract_holder_sigs(&self.holder_commitment, htlc_sigs));
+ self.holder_commitment.add_holder_sig(funding_redeemscript, sig)
+ }
+
+ pub(crate) fn get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
+ let mut htlc_tx = None;
+ let commitment_txid = self.holder_commitment.trust().txid();
+ // Check if the HTLC spends from the current holder commitment
+ if commitment_txid == outp.txid {
+ self.sign_latest_holder_htlcs();
+ if let &Some(ref htlc_sigs) = &self.holder_htlc_sigs {
+ let &(ref htlc_idx, ref htlc_sig) = htlc_sigs[outp.vout as usize].as_ref().unwrap();
+ let trusted_tx = self.holder_commitment.trust();
+ let counterparty_htlc_sig = self.holder_commitment.counterparty_htlc_sigs[*htlc_idx];
+ htlc_tx = Some(trusted_tx
+ .get_signed_htlc_tx(&self.channel_transaction_parameters.as_holder_broadcastable(), *htlc_idx, &counterparty_htlc_sig, htlc_sig, preimage));