- pub(super) fn provide_latest_local_tx(&mut self, tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), ()> {
- // To prevent any unsafe state discrepancy between offchain and onchain, once local
- // commitment transaction has been signed due to an event (either block height for
- // HTLC-timeout or channel force-closure), don't allow any further update of local
- // commitment transaction view to avoid delivery of revocation secret to counterparty
- // for the aformentionned signed transaction.
- if let Some(ref local_commitment) = self.local_commitment {
- if local_commitment.has_local_sig() { return Err(()) }
- }
- self.prev_local_commitment = self.local_commitment.take();
- self.local_commitment = Some(tx);
- self.prev_htlc_cache = self.current_htlc_cache.take();
- let mut per_htlc = HashMap::with_capacity(htlc_outputs.len());
- for htlc in htlc_outputs {
- if htlc.0.transaction_output_index.is_some() { // Discard dust HTLC as we will never have to generate onchain tx for them
- per_htlc.insert(htlc.0.transaction_output_index.unwrap(), (htlc.0, htlc.1));
+ pub(super) fn provide_latest_holder_tx(&mut self, tx: HolderCommitmentTransaction) {
+ self.prev_holder_commitment = self.holder_commitment.take();
+ self.holder_commitment = Some(tx);
+ }
+
+ fn sign_latest_holder_htlcs(&mut self) {
+ if let Some(ref holder_commitment) = self.holder_commitment {
+ if let Ok(sigs) = self.key_storage.sign_holder_commitment_htlc_transactions(holder_commitment, &self.secp_ctx) {
+ self.holder_htlc_sigs = Some(Vec::new());
+ let ret = self.holder_htlc_sigs.as_mut().unwrap();
+ for (htlc_idx, (holder_sig, &(ref htlc, _))) in sigs.iter().zip(holder_commitment.per_htlc.iter()).enumerate() {
+ if let Some(tx_idx) = htlc.transaction_output_index {
+ 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.expect("Did not receive a signature for a non-dust HTLC")));
+ } else {
+ assert!(holder_sig.is_none(), "Received a signature for a dust HTLC");
+ }
+ }
+ }
+ }
+ }
+ fn sign_prev_holder_htlcs(&mut self) {
+ if let Some(ref holder_commitment) = self.prev_holder_commitment {
+ if let Ok(sigs) = self.key_storage.sign_holder_commitment_htlc_transactions(holder_commitment, &self.secp_ctx) {
+ self.prev_holder_htlc_sigs = Some(Vec::new());
+ let ret = self.prev_holder_htlc_sigs.as_mut().unwrap();
+ for (htlc_idx, (holder_sig, &(ref htlc, _))) in sigs.iter().zip(holder_commitment.per_htlc.iter()).enumerate() {
+ if let Some(tx_idx) = htlc.transaction_output_index {
+ 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.expect("Did not receive a signature for a non-dust HTLC")));
+ } else {
+ assert!(holder_sig.is_none(), "Received a signature for a dust HTLC");
+ }
+ }
+ }
+ }
+ }
+
+ //TODO: getting lastest holder transactions should be infaillible 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(super) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
+ if let Some(ref mut holder_commitment) = self.holder_commitment {
+ match self.key_storage.sign_holder_commitment(holder_commitment, &self.secp_ctx) {
+ Ok(sig) => Some(holder_commitment.add_holder_sig(funding_redeemscript, sig)),
+ Err(_) => return None,