pub fn get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
log_trace!(self, "Getting signed latest local commitment transaction!");
if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) {
+ let txid = commitment_tx.txid();
let mut res = vec![commitment_tx];
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
- let mut htlc_txn = self.broadcast_by_local_state(res.get(0).unwrap(), local_tx).0;
- res.append(&mut htlc_txn);
+ for htlc in local_tx.htlc_outputs.iter() {
+ if let Some(htlc_index) = htlc.0.transaction_output_index {
+ let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None };
+ if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) {
+ res.push(htlc_tx);
+ }
+ }
+ }
// We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
// The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
}
pub fn unsafe_get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
log_trace!(self, "Getting signed copy of latest local commitment transaction!");
if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx(self.channel_value_satoshis.unwrap()) {
+ let txid = commitment_tx.txid();
let mut res = vec![commitment_tx];
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
- let mut htlc_txn = self.broadcast_by_local_state(res.get(0).unwrap(), local_tx).0;
- res.append(&mut htlc_txn);
+ for htlc in local_tx.htlc_outputs.iter() {
+ if let Some(htlc_index) = htlc.0.transaction_output_index {
+ let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None };
+ if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) {
+ res.push(htlc_tx);
+ }
+ }
+ }
}
return res
}
use ln::msgs::DecodeError;
use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest};
-use ln::channelmanager::HTLCSource;
+use ln::channelmanager::{HTLCSource, PaymentPreimage};
use ln::chan_utils;
use ln::chan_utils::{HTLCType, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment};
use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
}
None
}
+
+ 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 local_commitment) = self.local_commitment {
+ if local_commitment.txid() == txid {
+ if let Some(ref htlc_cache) = self.current_htlc_cache {
+ if let Some(htlc) = htlc_cache.per_htlc.get(&htlc_index) {
+ if !htlc.0.offered && preimage.is_none() { return None; }; // If we don't have preimage for HTLC-Success, don't try to generate
+ let htlc_secret = if !htlc.0.offered { preimage } else { None }; // If we have a preimage for a HTLC-Timeout, don't use it that's likely a duplicate HTLC hash
+ let mut htlc_tx = chan_utils::build_htlc_transaction(&txid, htlc_cache.feerate_per_kw, self.local_csv, &htlc.0, &htlc_cache.local_keys.a_delayed_payment_key, &htlc_cache.local_keys.revocation_key);
+ self.key_storage.sign_htlc_transaction(&mut htlc_tx, htlc.1.as_ref().unwrap(), &htlc_secret, &htlc.0, &htlc_cache.local_keys.a_htlc_key, &htlc_cache.local_keys.b_htlc_key, &htlc_cache.local_keys.revocation_key, &htlc_cache.local_keys.per_commitment_point, &self.secp_ctx);
+ return Some(htlc_tx);
+
+ }
+ }
+ }
+ }
+ None
+ }
}