Move local commitment tx generation in OnchainTxHandler
[rust-lightning] / lightning / src / ln / channelmonitor.rs
index 2ac113b9845eef43391f5758ebad8335f82af453..b3cff4c2b42065406cd7b4b568700de0d80a81f9 100644 (file)
@@ -443,6 +443,9 @@ pub(crate) enum InputMaterial {
                sigs: (Signature, Signature),
                preimage: Option<PaymentPreimage>,
                amount: u64,
+       },
+       Funding {
+               channel_value: u64,
        }
 }
 
@@ -472,6 +475,10 @@ impl Writeable for InputMaterial  {
                                sigs.1.write(writer)?;
                                preimage.write(writer)?;
                                writer.write_all(&byte_utils::be64_to_array(*amount))?;
+                       },
+                       &InputMaterial::Funding { ref channel_value } => {
+                               writer.write_all(&[3; 1])?;
+                               channel_value.write(writer)?;
                        }
                }
                Ok(())
@@ -521,6 +528,12 @@ impl Readable for InputMaterial {
                                        preimage,
                                        amount
                                }
+                       },
+                       3 => {
+                               let channel_value = Readable::read(reader)?;
+                               InputMaterial::Funding {
+                                       channel_value
+                               }
                        }
                        _ => return Err(DecodeError::InvalidValue),
                };
@@ -1098,7 +1111,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        onchain_detection: onchain_detection,
                        their_htlc_base_key: Some(their_htlc_base_key.clone()),
                        their_delayed_payment_base_key: Some(their_delayed_payment_base_key.clone()),
-                       funding_redeemscript: Some(funding_redeemscript),
+                       funding_redeemscript: Some(funding_redeemscript.clone()),
                        channel_value_satoshis: Some(channel_value_satoshis),
                        their_cur_revocation_points: None,
 
@@ -1121,7 +1134,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        onchain_events_waiting_threshold_conf: HashMap::new(),
                        outputs_to_watch: HashMap::new(),
 
-                       onchain_tx_handler: OnchainTxHandler::new(destination_script.clone(), keys, logger.clone()),
+                       onchain_tx_handler: OnchainTxHandler::new(destination_script.clone(), keys, funding_redeemscript, logger.clone()),
 
                        last_block_hash: Default::default(),
                        secp_ctx: Secp256k1::new(),
@@ -1241,6 +1254,14 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                if self.their_to_self_delay.is_none() {
                        return Err(MonitorUpdateError("Got a local commitment tx info update before we'd set basic information about the channel"));
                }
+               // Returning a monitor error before updating tracking points means in case of using
+               // a concurrent watchtower implementation for same channel, if this one doesn't
+               // reject update as we do, you MAY have the latest local valid commitment tx onchain
+               // for which you want to spend outputs. We're NOT robust again this scenario right
+               // now but we should consider it later.
+               if let Err(_) = self.onchain_tx_handler.provide_latest_local_tx(commitment_tx.clone()) {
+                       return Err(MonitorUpdateError("Local commitment signed has already been signed, no further update of LOCAL commitment transaction is allowed"));
+               }
                self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take();
                self.current_local_signed_commitment_tx = Some(LocalSignedTx {
                        txid: commitment_tx.txid(),
@@ -1806,7 +1827,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                // tracking state and panic!()ing if we get an update after force-closure/local-tx signing.
                log_trace!(self, "Getting signed latest local commitment transaction!");
                if let &mut Some(ref mut local_tx) = &mut self.current_local_signed_commitment_tx {
-                       local_tx.tx.add_local_sig(&self.onchain_detection.keys.funding_key(), self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
+                       self.onchain_detection.keys.sign_local_commitment(&mut local_tx.tx, self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
                }
                if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
                        let mut res = vec![local_tx.tx.with_valid_witness().clone()];
@@ -1886,15 +1907,11 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                let should_broadcast = if let Some(_) = self.current_local_signed_commitment_tx {
                        self.would_broadcast_at_height(height)
                } else { false };
-               if let Some(ref mut cur_local_tx) = self.current_local_signed_commitment_tx {
-                       if should_broadcast {
-                               cur_local_tx.tx.add_local_sig(&self.onchain_detection.keys.funding_key(), self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
-                       }
+               if should_broadcast {
+                       claimable_outpoints.push(ClaimRequest { absolute_timelock: height, aggregable: false, outpoint: BitcoinOutPoint { txid: self.onchain_detection.funding_info.as_ref().unwrap().0.txid.clone(), vout: self.onchain_detection.funding_info.as_ref().unwrap().0.index as u32 }, witness_data: InputMaterial::Funding { channel_value: self.channel_value_satoshis.unwrap() }});
                }
                if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
                        if should_broadcast {
-                               log_trace!(self, "Broadcast onchain {}", log_tx!(cur_local_tx.tx.with_valid_witness()));
-                               broadcaster.broadcast_transaction(&cur_local_tx.tx.with_valid_witness());
                                let (txs, new_outputs, _) = self.broadcast_by_local_state(&cur_local_tx);
                                if !new_outputs.is_empty() {
                                        watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));