Merge pull request #2536 from waterson/test-channel-signer
[rust-lightning] / lightning / src / chain / channelmonitor.rs
index cb267524fb0ff18d1c2f312a8a5741efaa3300a9..47f5605edbb3cbeaa45ff3dfed8609baa6a422fa 100644 (file)
@@ -31,8 +31,9 @@ use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
 
 use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
 use bitcoin::secp256k1::{SecretKey, PublicKey};
-use bitcoin::secp256k1;
+use bitcoin::{secp256k1, EcdsaSighashType};
 
+use crate::ln::channel::INITIAL_COMMITMENT_NUMBER;
 use crate::ln::{PaymentHash, PaymentPreimage};
 use crate::ln::msgs::DecodeError;
 use crate::ln::chan_utils;
@@ -888,6 +889,14 @@ pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
 
        /// The node_id of our counterparty
        counterparty_node_id: Option<PublicKey>,
+
+       /// Initial counterparty commmitment data needed to recreate the commitment tx
+       /// in the persistence pipeline for third-party watchtowers. This will only be present on
+       /// monitors created after 0.0.117.
+       ///
+       /// Ordering of tuple data: (their_per_commitment_point, feerate_per_kw, to_broadcaster_sats,
+       /// to_countersignatory_sats)
+       initial_counterparty_commitment_info: Option<(PublicKey, u32, u64, u64)>,
 }
 
 /// Transaction outputs to watch for on-chain spends.
@@ -1078,6 +1087,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signe
                        (11, self.confirmed_commitment_tx_counterparty_output, option),
                        (13, self.spendable_txids_confirmed, required_vec),
                        (15, self.counterparty_fulfilled_htlcs, required),
+                       (17, self.initial_counterparty_commitment_info, option),
                });
 
                Ok(())
@@ -1228,6 +1238,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
 
                        best_block,
                        counterparty_node_id: Some(counterparty_node_id),
+                       initial_counterparty_commitment_info: None,
                })
        }
 
@@ -1236,11 +1247,31 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
                self.inner.lock().unwrap().provide_secret(idx, secret)
        }
 
+       /// A variant of `Self::provide_latest_counterparty_commitment_tx` used to provide
+       /// additional information to the monitor to store in order to recreate the initial
+       /// counterparty commitment transaction during persistence (mainly for use in third-party
+       /// watchtowers).
+       ///
+       /// This is used to provide the counterparty commitment information directly to the monitor
+       /// before the initial persistence of a new channel.
+       pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
+               &self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
+               commitment_number: u64, their_cur_per_commitment_point: PublicKey, feerate_per_kw: u32,
+               to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, logger: &L,
+       )
+       where L::Target: Logger
+       {
+               self.inner.lock().unwrap().provide_initial_counterparty_commitment_tx(txid,
+                       htlc_outputs, commitment_number, their_cur_per_commitment_point, feerate_per_kw,
+                       to_broadcaster_value_sat, to_countersignatory_value_sat, logger);
+       }
+
        /// Informs this monitor of the latest counterparty (ie non-broadcastable) commitment transaction.
        /// The monitor watches for it to be broadcasted and then uses the HTLC information (and
        /// possibly future revocation/preimage information) to claim outputs where possible.
        /// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers.
-       pub(crate) fn provide_latest_counterparty_commitment_tx<L: Deref>(
+       #[cfg(test)]
+       fn provide_latest_counterparty_commitment_tx<L: Deref>(
                &self,
                txid: Txid,
                htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
@@ -1376,6 +1407,22 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
                ret
        }
 
+       /// Gets the counterparty's initial commitment transaction. The returned commitment
+       /// transaction is unsigned. This is intended to be called during the initial persistence of
+       /// the monitor (inside an implementation of [`Persist::persist_new_channel`]), to allow for
+       /// watchtowers in the persistence pipeline to have enough data to form justice transactions.
+       ///
+       /// This is similar to [`Self::counterparty_commitment_txs_from_update`], except
+       /// that for the initial commitment transaction, we don't have a corresponding update.
+       ///
+       /// This will only return `Some` for channel monitors that have been created after upgrading
+       /// to LDK 0.0.117+.
+       ///
+       /// [`Persist::persist_new_channel`]: crate::chain::chainmonitor::Persist::persist_new_channel
+       pub fn initial_counterparty_commitment_tx(&self) -> Option<CommitmentTransaction> {
+               self.inner.lock().unwrap().initial_counterparty_commitment_tx()
+       }
+
        /// Gets all of the counterparty commitment transactions provided by the given update. This
        /// may be empty if the update doesn't include any new counterparty commitments. Returned
        /// commitment transactions are unsigned.
@@ -1383,7 +1430,8 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
        /// This is provided so that watchtower clients in the persistence pipeline are able to build
        /// justice transactions for each counterparty commitment upon each update. It's intended to be
        /// used within an implementation of [`Persist::update_persisted_channel`], which is provided
-       /// with a monitor and an update.
+       /// with a monitor and an update. Once revoked, signing a justice transaction can be done using
+       /// [`Self::sign_to_local_justice_tx`].
        ///
        /// It is expected that a watchtower client may use this method to retrieve the latest counterparty
        /// commitment transaction(s), and then hold the necessary data until a later update in which
@@ -1399,6 +1447,27 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
                self.inner.lock().unwrap().counterparty_commitment_txs_from_update(update)
        }
 
+       /// Wrapper around [`EcdsaChannelSigner::sign_justice_revoked_output`] to make
+       /// signing the justice transaction easier for implementors of
+       /// [`chain::chainmonitor::Persist`]. On success this method returns the provided transaction
+       /// signing the input at `input_idx`. This method will only produce a valid signature for
+       /// a transaction spending the `to_local` output of a commitment transaction, i.e. this cannot
+       /// be used for revoked HTLC outputs.
+       ///
+       /// `Value` is the value of the output being spent by the input at `input_idx`, committed
+       /// in the BIP 143 signature.
+       ///
+       /// This method will only succeed if this monitor has received the revocation secret for the
+       /// provided `commitment_number`. If a commitment number is provided that does not correspond
+       /// to the commitment transaction being revoked, this will return a signed transaction, but
+       /// the signature will not be valid.
+       ///
+       /// [`EcdsaChannelSigner::sign_justice_revoked_output`]: crate::sign::EcdsaChannelSigner::sign_justice_revoked_output
+       /// [`Persist`]: crate::chain::chainmonitor::Persist
+       pub fn sign_to_local_justice_tx(&self, justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64) -> Result<Transaction, ()> {
+               self.inner.lock().unwrap().sign_to_local_justice_tx(justice_tx, input_idx, value, commitment_number)
+       }
+
        pub(crate) fn get_min_seen_secret(&self) -> u64 {
                self.inner.lock().unwrap().get_min_seen_secret()
        }
@@ -2255,6 +2324,25 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                Ok(())
        }
 
+       pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
+               &mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
+               commitment_number: u64, their_per_commitment_point: PublicKey, feerate_per_kw: u32,
+               to_broadcaster_value: u64, to_countersignatory_value: u64, logger: &L
+       )
+       where L::Target: Logger
+       {
+               self.initial_counterparty_commitment_info = Some((their_per_commitment_point.clone(),
+                       feerate_per_kw, to_broadcaster_value, to_countersignatory_value));
+
+               #[cfg(debug_assertions)] {
+                       let rebuilt_commitment_tx = self.initial_counterparty_commitment_tx().unwrap();
+                       debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), txid);
+               }
+
+               self.provide_latest_counterparty_commitment_tx(txid, htlc_outputs, commitment_number,
+                               their_per_commitment_point, logger);
+       }
+
        pub(crate) fn provide_latest_counterparty_commitment_tx<L: Deref>(&mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>, commitment_number: u64, their_per_commitment_point: PublicKey, logger: &L) where L::Target: Logger {
                // TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction
                // so that a remote monitor doesn't learn anything unless there is a malicious close.
@@ -2554,7 +2642,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                                }
                                        } else if !self.holder_tx_signed {
                                                log_error!(logger, "WARNING: You have a potentially-unsafe holder commitment transaction available to broadcast");
-                                               log_error!(logger, "    in channel monitor for channel {}!", log_bytes!(self.funding_info.0.to_channel_id()));
+                                               log_error!(logger, "    in channel monitor for channel {}!", &self.funding_info.0.to_channel_id());
                                                log_error!(logger, "    Read the docs for ChannelMonitor::get_latest_holder_commitment_txn and take manual action!");
                                        } else {
                                                // If we generated a MonitorEvent::CommitmentTxConfirmed, the ChannelManager
@@ -2684,6 +2772,17 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                ret
        }
 
+       pub(crate) fn initial_counterparty_commitment_tx(&mut self) -> Option<CommitmentTransaction> {
+               let (their_per_commitment_point, feerate_per_kw, to_broadcaster_value,
+                       to_countersignatory_value) = self.initial_counterparty_commitment_info?;
+               let htlc_outputs = vec![];
+
+               let commitment_tx = self.build_counterparty_commitment_tx(INITIAL_COMMITMENT_NUMBER,
+                       &their_per_commitment_point, to_broadcaster_value, to_countersignatory_value,
+                       feerate_per_kw, htlc_outputs);
+               Some(commitment_tx)
+       }
+
        fn build_counterparty_commitment_tx(
                &self, commitment_number: u64, their_per_commitment_point: &PublicKey,
                to_broadcaster_value: u64, to_countersignatory_value: u64, feerate_per_kw: u32,
@@ -2733,6 +2832,31 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                }).collect()
        }
 
+       pub(crate) fn sign_to_local_justice_tx(
+               &self, mut justice_tx: Transaction, input_idx: usize, value: u64, commitment_number: u64
+       ) -> Result<Transaction, ()> {
+               let secret = self.get_secret(commitment_number).ok_or(())?;
+               let per_commitment_key = SecretKey::from_slice(&secret).map_err(|_| ())?;
+               let their_per_commitment_point = PublicKey::from_secret_key(
+                       &self.onchain_tx_handler.secp_ctx, &per_commitment_key);
+
+               let revocation_pubkey = chan_utils::derive_public_revocation_key(
+                       &self.onchain_tx_handler.secp_ctx, &their_per_commitment_point,
+                       &self.holder_revocation_basepoint);
+               let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx,
+                       &their_per_commitment_point,
+                       &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
+               let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
+                       self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
+
+               let sig = self.onchain_tx_handler.signer.sign_justice_revoked_output(
+                       &justice_tx, input_idx, value, &per_commitment_key, &self.onchain_tx_handler.secp_ctx)?;
+               justice_tx.input[input_idx].witness.push_bitcoin_signature(&sig.serialize_der(), EcdsaSighashType::All);
+               justice_tx.input[input_idx].witness.push(&[1u8]);
+               justice_tx.input[input_idx].witness.push(revokeable_redeemscript.as_bytes());
+               Ok(justice_tx)
+       }
+
        /// Can only fail if idx is < get_min_seen_secret
        fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
                self.commitment_secrets.get_secret(idx)
@@ -3265,7 +3389,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
                                if prevout.txid == self.funding_info.0.txid && prevout.vout == self.funding_info.0.index as u32 {
                                        let mut balance_spendable_csv = None;
                                        log_info!(logger, "Channel {} closed by funding output spend in txid {}.",
-                                               log_bytes!(self.funding_info.0.to_channel_id()), txid);
+                                               &self.funding_info.0.to_channel_id(), txid);
                                        self.funding_spend_seen = true;
                                        let mut commitment_tx_to_counterparty_output = None;
                                        if (tx.input[0].sequence.0 >> 8*3) as u8 == 0x80 && (tx.lock_time.0 >> 8*3) as u8 == 0x20 {
@@ -4195,6 +4319,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
                let mut confirmed_commitment_tx_counterparty_output = None;
                let mut spendable_txids_confirmed = Some(Vec::new());
                let mut counterparty_fulfilled_htlcs = Some(HashMap::new());
+               let mut initial_counterparty_commitment_info = None;
                read_tlv_fields!(reader, {
                        (1, funding_spend_confirmed, option),
                        (3, htlcs_resolved_on_chain, optional_vec),
@@ -4204,6 +4329,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
                        (11, confirmed_commitment_tx_counterparty_output, option),
                        (13, spendable_txids_confirmed, optional_vec),
                        (15, counterparty_fulfilled_htlcs, option),
+                       (17, initial_counterparty_commitment_info, option),
                });
 
                Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl {
@@ -4259,6 +4385,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
 
                        best_block,
                        counterparty_node_id,
+                       initial_counterparty_commitment_info,
                })))
        }
 }