Make commitment transaction signing a part of ChannelKeys.
[rust-lightning] / lightning / src / ln / channel.rs
index ca4dc89c32e67e7dac0ed41805228d40e74c12a8..36a42d0cec4e3a7e5b8f3182f651017bf8dc720d 100644 (file)
@@ -833,7 +833,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                let mut local_htlc_total_msat = 0;
                let mut value_to_self_msat_offset = 0;
 
-               log_trace!(self, "Building commitment transaction number {} for {}, generated by {} with fee {}...", commitment_number, if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw);
+               log_trace!(self, "Building commitment transaction number {} (really {} xor {}) for {}, generated by {} with fee {}...", commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number), self.get_commitment_transaction_number_obscure_factor(), if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw);
 
                macro_rules! get_htlc_in_commitment {
                        ($htlc: expr, $offered: expr) => {
@@ -1518,10 +1518,11 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
 
                let remote_keys = self.build_remote_transaction_keys()?;
                let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
-               let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
+               let remote_signature = self.local_keys.sign_remote_commitment(self.channel_value_satoshis, &self.get_funding_redeemscript(), self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), self.our_to_self_delay, &self.secp_ctx)
+                               .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0;
 
                // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
-               Ok((remote_initial_commitment_tx, local_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key()), local_keys))
+               Ok((remote_initial_commitment_tx, local_initial_commitment_tx, remote_signature, local_keys))
        }
 
        pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> {
@@ -3222,14 +3223,10 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
 
        /// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created)
        fn get_outbound_funding_created_signature(&mut self) -> Result<(Signature, Transaction), ChannelError> {
-               let funding_script = self.get_funding_redeemscript();
-
                let remote_keys = self.build_remote_transaction_keys()?;
                let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
-               let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
-
-               // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
-               Ok((self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key()), remote_initial_commitment_tx))
+               Ok((self.local_keys.sign_remote_commitment(self.channel_value_satoshis, &self.get_funding_redeemscript(), self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), self.our_to_self_delay, &self.secp_ctx)
+                               .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0, remote_initial_commitment_tx))
        }
 
        /// Updates channel state with knowledge of the funding transaction's txid/index, and generates
@@ -3519,8 +3516,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
        /// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation
        /// when we shouldn't change HTLC/channel state.
        fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> {
-               let funding_script = self.get_funding_redeemscript();
-
                let mut feerate_per_kw = self.feerate_per_kw;
                if let Some(feerate) = self.pending_update_fee {
                        if self.channel_outbound {
@@ -3530,27 +3525,37 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
 
                let remote_keys = self.build_remote_transaction_keys()?;
                let remote_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, true, feerate_per_kw);
-               let remote_commitment_txid = remote_commitment_tx.0.txid();
-               let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]);
-               let our_sig = self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key());
-               log_trace!(self, "Signing remote commitment tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&remote_commitment_tx.0), encode::serialize_hex(&funding_script), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize()), log_bytes!(our_sig.serialize_compact()[..]));
+               let (signature, htlc_signatures);
 
-               let mut htlc_sigs = Vec::with_capacity(remote_commitment_tx.1);
-               for &(ref htlc, _) in remote_commitment_tx.2.iter() {
-                       if let Some(_) = htlc.transaction_output_index {
-                               let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw);
-                               let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys);
-                               let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
-                               let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, self.local_keys.htlc_base_key()), "Derived invalid key, peer is maliciously selecting parameters");
-                               htlc_sigs.push(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key));
-                               log_trace!(self, "Signing remote HTLC tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&htlc_tx), encode::serialize_hex(&htlc_redeemscript), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key).serialize()), log_bytes!(htlc_sigs.last().unwrap().serialize_compact()[..]));
+               {
+                       let mut htlcs = Vec::with_capacity(remote_commitment_tx.2.len());
+                       for &(ref htlc, _) in remote_commitment_tx.2.iter() {
+                               htlcs.push(htlc);
+                       }
+
+                       let res = self.local_keys.sign_remote_commitment(self.channel_value_satoshis, &self.get_funding_redeemscript(), feerate_per_kw, &remote_commitment_tx.0, &remote_keys, &htlcs, self.our_to_self_delay, &self.secp_ctx)
+                               .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?;
+                       signature = res.0;
+                       htlc_signatures = res.1;
+
+                       log_trace!(self, "Signed remote commitment tx {} with redeemscript {} -> {}",
+                               encode::serialize_hex(&remote_commitment_tx.0),
+                               encode::serialize_hex(&self.get_funding_redeemscript()),
+                               log_bytes!(signature.serialize_compact()[..]));
+
+                       for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) {
+                               log_trace!(self, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {}",
+                                       encode::serialize_hex(&chan_utils::build_htlc_transaction(&remote_commitment_tx.0.txid(), feerate_per_kw, self.our_to_self_delay, htlc, &remote_keys.a_delayed_payment_key, &remote_keys.revocation_key)),
+                                       encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &remote_keys)),
+                                       log_bytes!(remote_keys.a_htlc_key.serialize()),
+                                       log_bytes!(htlc_sig.serialize_compact()[..]));
                        }
                }
 
                Ok((msgs::CommitmentSigned {
                        channel_id: self.channel_id,
-                       signature: our_sig,
-                       htlc_signatures: htlc_sigs,
+                       signature,
+                       htlc_signatures,
                }, (remote_commitment_tx.0, remote_commitment_tx.2)))
        }